The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: NoCforMe on October 16, 2011, 10:11:00 AM

Title: Moving child windows, revisited
Post by: NoCforMe on October 16, 2011, 10:11:00 AM
A follow-up to my earlier thread about my troubles getting child windows to be able to be dragged around inside another window.

The attached code & executable shows what I've been able to do. My original aim was to try to replicate some of the functionality of the typical resource editor. Along the way someone turned me on to ResEd (by KetilO). I've managed to figure out how he did some things.

The attached program (resizing) doesn't actually resize anything (yet), so I guess the name is a lie. But it does what I think are some pretty cool things. I've created a child window with 8 attached resize handles (each a small sibling window), just like in his editor (same size, too, 6x6, a nice-looking size). You can drag the child around.

You can also right-click (outside the child, since the code is in the parent's window proc) and add a control from a pop-up menu. (The only thing that doesn't work right is the static text choice: for some reason, it doesn't show up in the window at all.) You'll notice that the controls are actually semi-functional; you can click the checkbox and type into the edit control.

There's a bug (at least I'd call it that) in his editor that I've fixed in this little program. If you fire up RedEd and create a dialog with a control in it, try dragging the control out of the dialog; it lets you do that. With the result that you cannot grab it back (if you let go of the mouse button while you're outside the dialog); the control is just stranded. I fixed this by capturing the mouse (using SetCapture() - ReleaseCapture() ) to confine the cursor to the containing client area. I'm surprised he didn't do that. Also, his controls move kind of jerkily, sometime leaving lots of nasty artifacts behind; perhaps he's doing a lot of processing that's slowing things down.

Anyhow, just wanted to put this out there. Comments welcome as always. (Dave, check out my table-driven handle-window moving & cursor-setting code; notice how you get the correct resizing arrows, even though they don't actually do anything yet.)

==========================================================

Aaaargh. I can see the dangers of capturing the mouse. I don't know if this version of the program does this, but I made a few changes, and now the mouse is always confined to the program window, even after releasing the mouse button after dragging the child. When this happened before, I couldn't reach any controls to kill the program, so I had to Alt-Tab to another app to restore the cursor! At least now I can reach the window's close button.

Further research is needed ...
Title: Re: Moving child windows, revisited
Post by: dedndave on October 16, 2011, 11:50:22 AM
i figured out wht i need to do on my little version
but, i had to sit it aside to take care of some other things
at any rate, i also wanted to add the dialog box, which would be sizable, as well

not sure how you confine the cursor, but i use ClipCursor (during WM_LBUTTONDOWN)
to release that rectangle, i use ClipCursor,NULL during WM_LBUTTONUP
thing is - it has to do the same in the parent window, in case the cursor is outside the box
Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 16, 2011, 06:03:55 PM
Well, yes, that's the way to confine the cursor. I fixed that problem: I was forgetting to call ClipCursor() again to clip it back to the original setting. The proper sequence is


INVOKE SetCapture, hWin
INVOKE GetClipCursor, ADDR PrevRect ;Get current clip rectangle
INVOKE GetWindowRect, hWin, ADDR gpRect
INVOKE ClipCursor, ADDR gpRect


to capture the mouse, followed by


INVOKE ReleaseCapture
INVOKE ClipCursor, ADDR PrevRect ;Un-clip to our window.


to return things to normal.

So there's still a basic problem with this program: if you run it, you'll see that the child window is only "sensitive" at its boundaries. You can't click in its interior and move it: the cursor must be moved to any edge, at which point it starts moving.

It's a little tricky, because you need to track the origins of left-button-down and mouse movement in the child, but you have to do the mouse capture in the parent. What I'm doing is setting a global flag in the child and checking it in the parent.

Similar thing for implementing the pop-up ("shortcut") menu: the version I posted doesn't work correctly, in that the position of the menu is where I want it if you click outside the child, but wrong if you click inside the child. This has to do with the X and Y positions in the mouse-button messages (in lParam). If the user clicks in the child, I send a message (the same message I receive, WM_RBUTTONDOWN) to the parent. But since the child and parent see X/Y coordinates from different points of view, I had to adjust things for the child. This ended up doing the trick:

In the child:

MOV EAX, lParam
MOV EDX, EAX
AND EAX, 0FFFFH
MOV pt.x, EAX
SHR EDX, 16
MOV pt.y, EDX
INVOKE ClientToScreen, hWin, ADDR pt ;Where is our client in the "real world"?
INVOKE ScreenToClient, MainWinHandle, ADDR pt
MOV EAX, pt.y
SHL EAX, 16
MOV AX, WORD PTR pt.x
INVOKE PostMessage, MainWinHandle, WM_RBUTTONDOWN, wParam, EAX


and in the parent

MOV EAX, lParam
MOV EDX, EAX
AND EAX, 0FFFFH
CWDE
MOV pt.x, EAX
SHR EDX, 16
CWDE
MOV pt.y, EDX
INVOKE ClientToScreen, hWin, ADDR pt ;Where is our client in the "real world"?
INVOKE TrackPopupMenuEx, hMenu,
TPM_LEFTALIGN OR TPM_TOPALIGN OR TPM_RETURNCMD OR TPM_RIGHTBUTTON OR TPM_VERNEGANIMATION OR TPM_VERTICAL,
pt.x, pt.y, hWin, NULL


TrackPopupMenuEx() displays and gets a selection from the popup menu. It works correctly no matter where you click.

(Yeah, I know, I should use MOVZX or MOVSX to save an operation up there. What can I say?--those instructions are new to me.
Title: Re: Moving child windows, revisited
Post by: dedndave on October 16, 2011, 06:17:51 PM
yah - if you put a control in the box, the WndProc for the control gets the messages
you can get around that by subclassing the control - give it your own WndProc
use SetWindowLong to set the address of the new WndProc and get the old one (the old one is the return value)
then, you can intercept mouse activity for the control, and send the other messages to the original WndProc
Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 16, 2011, 06:26:04 PM
That doesn't matter here, as I'm not actually using the controls (which work, by the way). I'm using the same class for the child window and the controls, so all the messages go to the same window proc. I can easily distinguish who the message is for by looking at handles.
Title: Re: Moving child windows, revisited
Post by: dedndave on October 16, 2011, 06:29:16 PM
well - having controls that function like controls is a bit much to ask for - lol
you have to think about how the program is going to be used
the programmer is going to use it to set up a dialog box - functional controls is somewhat superfluous
he wants to see how it looks - not test it   :bg
Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 16, 2011, 06:32:16 PM
Right. You seem to have missed the point; I didn't want the controls to work, only to look like what they actually look like. They're just place-holders. That they work is just a little added bonus. It's not like I'm actually handling any messages from them.

In any case, I don't think that has anything to do with the latest problem we were discussing, that you can't "grab" the child window in its interior. It happens even if there's no control in it. (Maybe I need to add a "delete" function to that little pop-up menu.) Any ideas?
Title: Re: Moving child windows, revisited
Post by: qWord on October 16, 2011, 06:43:49 PM
hi,

I've create an advanced example using subclasses. AFAICS, you can use any control and add the 'container'-subclass to it (function: BindContainer)
The controls can be resized and moved (hold the CONTROL-key down and click the little white boxes for moving ;-) )
(http://www.masm32.com/board/index.php?action=dlattach;topic=17569.0;id=9847)


Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 16, 2011, 07:49:25 PM
Interesting; I'll have to study that.

About subclassing: that's basically Windows jargon for "intercepting calls to objects for the purpose of manipulating them", isn't it?

Question about your code:


fn CreateWindowEx,0,"Edit","xyz",WS_CHILD or WS_VISIBLE,120,10,100,100,hWnd,0,hInstance,0
invoke BindContainer,eax,HANDHOLDS_SIZE,hInstance


1. Dunno what "fn" does. Is this a MASM32 macro or something?
2. I couldn't find any documentation on MSDN for BindContainer(). Is this also MASM32? What does it do? What does it bind to what?
Title: Re: Moving child windows, revisited
Post by: qWord on October 16, 2011, 08:05:19 PM
Quote from: NoCforMe on October 16, 2011, 07:49:25 PMAbout subclassing: that's basically Windows jargon for "intercepting calls to objects for the purpose of manipulating them", isn't it?
'yes' - subcalssing means to replace the original windows procedure with your own. This allows to get all messages that the window gets, thus you can use, redirect or filter them.
Quote from: NoCforMe on October 16, 2011, 07:49:25 PM1. Dunno what "fn" does. Is this a MASM32 macro or something?
2. I couldn't find any documentation on MSDN for BindContainer(). Is this also MASM32? What does it do? What does it bind to what?
1. This macro extents the INVOKE-directive - it adds support for string literals (e.g. "edit") -> see \masm32\help\hlhelp.chm
2. You will find this function in the source code - this function create the subclass (ok - may be the name is inappropriate)
Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 16, 2011, 08:06:19 PM
Hmm:


SubCalssTrampoline:
mov edx,02BADF00Dh ; edx = pOrgWndProc
mov ecx,02BADF00Dh  ; ecx = ptr CSCI
mov eax,02BADF00Dh ; eax = pWndProcSubCalss
jmp eax
SubCalssTrampoline_end:


Isn't this what's called a "thunik"? Sure looks like one. (Jiump address is plugged in at run time; kind of like the dreaded "computed GOTO" of olden days ...)
Title: Re: Moving child windows, revisited
Post by: dedndave on October 16, 2011, 08:09:02 PM
QuoteAbout subclassing: that's basically Windows jargon for "intercepting calls to objects for the purpose of manipulating them", isn't it?

that's more-or-less correct
to put it simply, you are replacing the standard WndProc function with your own

Quote1. Dunno what "fn" does. Is this a MASM32 macro or something?

yah - it's a fancy macro for INVOKE   :P
you can see what it does by looking in masm32\macros\macros.asm

Quote2. I couldn't find any documentation on MSDN for BindContainer(). Is this also MASM32? What does it do? What does it bind to what?

i'll let qWord get that one - lol
new to me   :P
i was just going to subclass the control and take over the mouse and keyboard messages, rendering it non-functional
but still leave the other messages "as is" so it gets painted, sized, moved, and so on
Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 16, 2011, 08:12:39 PM
Thanks for all the info on "subcalssing", folks. But for the time being I think I'll concentrate on doing things the plain old boring conventional Windows way. I think there must be an answer to my problem that doesn't involve this level of complexity.

Later on, of course, I want to learn all about it ...

So Dave, I assume this is in reference to my problem? Why do you think it's necessary to render the controls non-functional? After all, as I already stated, the problem occurs even with no controls in the child window, so I don't think they're to blame. (Unless you just want to figure out how to do this anyhow.)
Title: Re: Moving child windows, revisited
Post by: dedndave on October 16, 2011, 08:28:44 PM
well - that has to do with how you capture the mouse
i wasn't going to use that function, nor DragDetect, either   :P

my game-plan was to just...
1) set the clip rectangle on left button down
this step takes a little preperation, as you want to clip so the window stays inside the boundry - not just the mouse
2) move the window with the mouse cursor as long as the left button is down
3) reset the clip rectangle on left button up

that method works, unless the cursor happens to get ahead of the moving window
a problem that can be overcome by catching the parent window mouse messages when the left button is down

i posted that code in the other thread
Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 16, 2011, 08:38:19 PM
Quote from: dedndave on October 16, 2011, 08:28:44 PM
my game-plan was to just...
1) set the clip rectangle on left button down
this step takes a little preperation, as you want to clip so the window stays inside the boundry - not just the mouse
2) move the window with the mouse cursor as long as the left button is down
3) reset the clip rectangle on left button up

Actually, I've changed my requirements a bit. Remember how I was bothered by the child window being able to be partially drug outside the client area? how I wanted it to "bump up against" the edge of the client rectangle? Well, after looking at lots of other apps, nobody does it that way, so I'm OK with it being able to "go under" the client border. That should simplify things.

So I have that part (mouse capture/client clipping) pretty well down. Can you suggest why I can't drag the child from its interior? That's my main problem here. (To be clear: If I click inside the child and try to drag, nothing happens until the mouse cursor hits the nearest edge, at which point it bounces back to the initial drag point and dragging commences. Works, but it's kind of annoying, and not at all how other apps work.)
Title: Re: Moving child windows, revisited
Post by: dedndave on October 16, 2011, 09:39:54 PM
well - for some reason, the WndProc function for the child window is not seeing the mouse button message
i haven't looked at your code, but i would say that it has to be designed that way
Title: Re: Moving child windows, revisited
Post by: jj2007 on October 16, 2011, 09:44:38 PM
Quote from: dedndave on October 16, 2011, 09:39:54 PM
well - for some reason, the WndProc function for the child window is not seeing the mouse button message
i haven't looked at your code, but i would say that it has to be designed that way

You looked for it in the loword of WM_PARENTNOTIFY?
Title: Re: Moving child windows, revisited
Post by: dedndave on October 18, 2011, 02:25:31 AM
here is a simple example of what i was talking about
it does have a small issue - one that could be fixed
that is, if you size the main window so that it clips part of the child, then cursor clipping doesn't work anymore
that can be overcome by limiting the main window sizing so that it does not clip the child
i.e., they wouldn't be able to size the main window so small that the child gets clipped
Title: Re: Moving child windows, revisited
Post by: qWord on October 18, 2011, 08:38:00 PM
hi,
In the attachment a simple solution using a container, which holds the actual control.
I like the idea, that the user has the option to rearrange and resize the controls - maybe I will continue work on this idea.

qWord
Title: Re: Moving child windows, revisited
Post by: dedndave on October 18, 2011, 08:45:42 PM
nice example, qWord   :U
Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 19, 2011, 04:40:12 AM
Well, folks, I got it all working--pretty well, too. And it wasn't all that complicated.

The whole thing (window resizing/moving/resize-handle handling) is table-driven, one of my favorite ways of coding.

First, some data structures and a fairly scary-looking array of structs:



$handleInfo STRUCT
  ID DD ?
  X DD ?
  Y DD ?
  flags DD ?
  handle HWND ?
  cursor HCURSOR ?
$handleInfo ENDS

;===== Move handle flag bits: =====
$Vconstrain EQU 100H
$Hconstrain EQU 200H
$dX0 EQU 400H
$dY0 EQU 800H
$dXneg EQU 1000H
$dXpos EQU 2000H
$dYneg EQU 4000H
$dYpos EQU 8000H
$dW EQU 10000H
$dH EQU 20000H

HandleInfo LABEL DWORD
  $handleInfo <2000, $Xc - $Wh, $Yc - $Hh, 11111110B OR $dX0 OR $dY0 OR $dW OR $dH OR $dXneg OR $dYneg>
  $handleInfo <2001, $Xc + ($Wc / 2) + ($Wh / 2), $Yc - $Hh, 11111000B OR $Vconstrain OR $dY0 OR $dH OR $dYneg>
  $handleInfo <2002, $Xc + $Wc, $Yc - $Hh, 11111011B OR $dY0 OR $dH OR $dW OR $dXpos OR $dYneg>
  $handleInfo <2003, $Xc - $Wh, $Yc + ($Hc / 2) - ($Hh / 2), 11010110B OR $Hconstrain OR $dX0 or $dW OR $dXneg>
  $handleInfo <2004, $Xc + $Wc, $Yc + ($Hc / 2) - ($Hh / 2), 01101011B OR $Hconstrain OR $dW OR $dXpos>
  $handleInfo <2005, $Xc - $Wh, $Yc + $Hc, 11011111B OR $dX0 OR $dW OR $dH OR $dXneg OR $dYpos>
  $handleInfo <2006, $Xc + ($Wc / 2) + ($Wh / 2), $Yc + $Hc, 00011111B OR $Vconstrain OR $dH OR $dYpos>
  $handleInfo <2007, $Xc + $Wc, $Yc + $Hc, 01111111B OR $dW OR $dH OR $dXpos OR $dYpos>



OK, that's a bit on the ugly side. But the good news is that it makes coding the routines that move all those littlle resizing handles much simpler. Far fewer "if-then-else" tests. The flags make a lot of the decisions.

Moving or resizing the child window is detected and initiated in the child-window's proc, by setting a global flag:



lbuttondown:
CMP MovingChild, TRUE
JE dodefault
CMP ResizingChild, TRUE
JE dodefault

; Get current mouse position, save as initial move/resize offset:
MOV EAX, lParam ;Get new X & Y pos.
MOV EDX, EAX ;Make a copy for later
AND EAX, 0FFFFH ;Mask off high word
CWDE ;Sign-extend to DWORD
MOV MM_Xoffset, EAX
MOV EAX, EDX ;Get back copy
SHR EAX, 16 ;High word--> low word
CWDE
MOV MM_Yoffset, EAX

; See which child window (main child or handles) generated the message:
MOV EAX, hWin
CMP EAX, ChildWinHandle
JE lbutton_child
CALL FindHandleWindow
OR EAX, EAX
JZ dodefault ;No match, do the default thang.
MOV HandleWinHandle, EAX
MOV HandlePtr, EDX
MOV ResizingChild, TRUE
call putresizing
; Compute starting position from child's POV:
MOV EAX, MM_Xoffset
MOV pt.x, EAX
MOV EAX, MM_Yoffset
MOV pt.y, EAX
INVOKE ClientToScreen, hWin, ADDR pt
INVOKE ScreenToClient, MainWinHandle, ADDR pt
; Calculate pos. from parent's POV:
MOV EAX, pt.x
MOV StartResizePosX, EAX
MOV EAX, pt.y
MOV StartResizePosY, EAX
JMP SHORT cwp_capture

lbutton_child:
; Capture that rodent!
MOV MovingChild, TRUE
cwp_capture:
INVOKE SetCapture, MainWinHandle
INVOKE GetClipCursor, ADDR PrevRect ;Get current clip rectangle
INVOKE GetWindowRect, MainWinHandle, ADDR gpRect
MOV EAX, SBheight
SUB gpRect.bottom, EAX ;Clip out status bar.
INVOKE ClipCursor, ADDR gpRect
JMP SHORT cwp_commonexit



while the actual moving/resizing work is done by the parent, since they've captured the mouse.

Here's the code for resizing the window. A good deal of this is just for checking the resulting size to make sure it doesn't get smaller than the minimum size:



ResizeChild PROC x:DWORD, y:DWORD
LOCAL deltaX:DWORD, deltaY:DWORD, pt:POINT

; Compute delta-X and delta-Y of move:
MOV EAX, x
SUB EAX, StartResizePosX
MOV deltaX, EAX
MOV EAX, y
SUB EAX, StartResizePosY
MOV deltaY, EAX

; Check that resulting new child window size is above minimum:
MOV EAX, deltaX
TEST ResizeFlag, $dXneg
JZ rcw3
NEG EAX
rcw3: MOV EDX, ChildWidth
ADD EDX, EAX
CMP EDX, $childMinW
JBE rcw99 ;No good, too small.
MOV EAX, deltaY
TEST ResizeFlag, $dYneg
JZ rcw6
NEG EAX
rcw6: MOV EDX, ChildHeight
ADD EDX, EAX
CMP EDX, $childMinH
JBE rcw99
MOV EAX, deltaX
ADD StartResizePosX, EAX
MOV EAX, deltaY
ADD StartResizePosY, EAX

; Get current (0,0) of child window:
XOR EAX, EAX
MOV pt.x, EAX
MOV pt.y, EAX
INVOKE ClientToScreen, ChildWinHandle, ADDR pt
INVOKE ScreenToClient, MainWinHandle, ADDR pt

; Determine whether & how to change origin of child:
MOV EAX, deltaX
MOV EDX, deltaY
TEST ResizeFlag, $dX0
JZ rcw10
ADD pt.x, EAX
rcw10: TEST ResizeFlag, $dY0
JZ rcw20
ADD pt.y, EDX


; Determine how to change child's size:
rcw20: TEST ResizeFlag, $dXneg
JZ rcw22
NEG EAX
rcw22: TEST ResizeFlag, $dYneg
JZ rcw24
NEG EDX
rcw24: TEST ResizeFlag, $dW
JZ rcw30
ADD ChildWidth, EAX
rcw30: TEST ResizeFlag, $dH
JZ rcw40
ADD ChildHeight, EDX
rcw40:
INVOKE SetWindowPos, ChildWinHandle, HWND_BOTTOM, pt.x, pt.y, ChildWidth, ChildHeight, SWP_SHOWWINDOW
INVOKE UpdateWindow, ChildWinHandle
INVOKE MoveHandleWindows, pt.x, pt.y
rcw99: RET

ResizeChild ENDP



The rest of it uses the current value of ResizieFlag to direct program flow (whether to add or subtract the delta-X and -Ys, whether to change the window's origin, whether to resize the window width and height, etc.).

A really handy trick is to use this sequence to map an (x,y) point in one window to another one:



INVOKE ClientToScreen, ChildWinHandle, ADDR pt
INVOKE ScreenToClient, MainWinHandle, ADDR pt



The code looks complicated, but it really isn't.

By the way, speaking of complicated, qWord, I looked at your sample (DragContainer), saw some interesting thing in there, but I really couldn't figure out what you were doing, as it's almost completely uncommented.

Another thing mine does that yours doesn't is to display the resizing-arrow cursors. That's actually really easy to do, and of course is table-driven as well:



LoadArrowCursors PROC
LOCAL cursorNS:HCURSOR, cursorEW:HCURSOR, cursorLdiag:HCURSOR, cursorRdiag:HCURSOR

; Load 4 resizing cursors:
INVOKE LoadCursor, NULL, IDC_SIZENS
MOV cursorNS, EAX
INVOKE LoadCursor, NULL, IDC_SIZEWE
MOV cursorEW, EAX
INVOKE LoadCursor, NULL, IDC_SIZENWSE
MOV cursorLdiag, EAX
INVOKE LoadCursor, NULL, IDC_SIZENESW
MOV cursorRdiag, EAX

; Store cursor handles in handle window table:
PUSH ESI
PUSH EBX
LEA ESI, HandleInfo
MOV EAX, cursorLdiag
MOV EBX, cursorEW
MOV ECX, cursorRdiag
MOV EDX, cursorNS
; 1:
MOV [ESI + $handleInfo.cursor], EAX
; 2:
MOV [ESI + (SIZEOF $handleInfo) + $handleInfo.cursor], EDX
; 3:
MOV [ESI + (SIZEOF $handleInfo * 2) + $handleInfo.cursor], ECX
; 4:
MOV [ESI + (SIZEOF $handleInfo * 3) + $handleInfo.cursor], EBX
; 5:
MOV [ESI + (SIZEOF $handleInfo * 4) + $handleInfo.cursor], EBX
; 6:
MOV [ESI + (SIZEOF $handleInfo * 5) + $handleInfo.cursor], ECX
; 7:
MOV [ESI + (SIZEOF $handleInfo * 6) + $handleInfo.cursor], EDX
; 8:
MOV [ESI + (SIZEOF $handleInfo * 7) + $handleInfo.cursor], EAX

POP EBX
POP ESI
RET

LoadArrowCursors ENDP



Then each cursor gets automagically loaded in the child window proc:



CMP EAX, WM_SETCURSOR
JE setcursor

setcursor:
MOV EAX, hWin
CALL FindHandleWindow ;See if handle matches any handle window's:
OR EAX, EAX ;Any match?
JZ dodefault ;Nope, do nothing.
INVOKE SetCursor, [EDX + $handleInfo.cursor]
XOR EAX, EAX
RET



Of course, I noticed that you're simply drawing little boxes instead of creating little windows. Probably less overhead that way, but then you don't get the nice functionality of the windows. Anyhow, thanks for posting your code.
Title: Why no static text?
Post by: NoCforMe on October 19, 2011, 06:26:54 PM
Question: one small thing still bugs me; my static-text control isn't showing up. Here's how I create it:



StaticClassName DB "static"
StaticText DB "Some text", 0

makeStaticText:
CALL DestroyExistingControl
INVOKE CreateWindowEx, WS_EX_LEFT, ADDR StaticClassName, ADDR StaticText,
SS_LEFT OR WS_VISIBLE OR WS_CHILD, $STX, $STY,
$STWidth, $STHeight, ChildWinHandle, $STID, InstanceHandle, NULL
MOV STHandle, EAX
MOV ControlHandle, EAX
INVOKE UpdateWindow, EAX



which is basically the same code I use to create the other controls (checkbox, radio button, etc.), all of which work. Can anyone see the stupid mistake I made here? Is this the way to create static text in a Windows app?
Title: Re: Moving child windows, revisited
Post by: dedndave on October 19, 2011, 06:55:14 PM
can you show us the resulting value of STHandle ?
Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 19, 2011, 07:08:32 PM
Sure; it's 1,050,206. In other words, not zero, so no error. Why would there be an error here and not in any of the other control-creation code, which is just about identical?

How do you create static text (like in dialogs)? This should work.
Title: Re: Moving child windows, revisited
Post by: dedndave on October 19, 2011, 07:19:35 PM
        INVOKE  CreateWindowEx, NULL, ADDR StaticClassName, ADDR StaticText,
                WS_VISIBLE OR WS_CHILD or WS_CLIPSIBLINGS,
                $STX, $STY, $STWidth, $STHeight, ChildWinHandle, $STID, InstanceHandle, NULL


those are the style bits i would normally use - that is probably not the issue

to set the text, i would probably use SendMessage - never tried it that way
that text generally applies to a title bar, but seems like it ought to work here, too

that leaves the parameters on the last line
i assume the ChildWinHandle is for a child that is to be the parent of the static, and it is non-zero
make sure the X and Y parameters are inside the ChildWinHandle window
make sure the width and height are something logical
Title: Re: Why no static text?
Post by: jj2007 on October 19, 2011, 07:28:46 PM
Quote from: NoCforMe on October 19, 2011, 06:26:54 PM
Question: one small thing still bugs me; my static-text control isn't showing up.

OR WS_CHILD OR WS_BORDER ... and voilà it shows up in all its beauty :bg
Title: Re: Moving child windows, revisited
Post by: dedndave on October 19, 2011, 07:31:38 PM
ahhhh   :U
Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 19, 2011, 07:36:43 PM
Not so fast, jj. True, the control shows up--I see a little box--but not the text. (And besides, I don't want a border anyway.)

How do I get the TEXT to show up?

I tried this



INVOKE  SendMessage, ControlHandle, WM_SETTEXT, 0, ADDR StaticText



but still no joy.
Title: Re: Moving child windows, revisited
Post by: dedndave on October 19, 2011, 07:40:44 PM
hang on, Jochen   :bg
a text static should not require a border

but - style bits do seem to be the issue, afterall

try these bits   :U
WS_CHILD or WS_VISIBLE or SS_EDITCONTROL

i know that makes no sense, but those are the bits that MessageBox uses (along with WS_NOPREFIX and WS_GROUP)

you can add WS_CLIPSIBLINGS if you like, as you are moving things around
normally, static conrtrols are static, so that bit is not applicable

btw - your SendMessage parms look ok
Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 19, 2011, 07:44:05 PM
OK, this works: make the control a read-only edit control:



INVOKE CreateWindowEx, WS_EX_LEFT, ADDR EditClassName, ADDR StaticText,
WS_VISIBLE OR WS_CHILD OR ES_LEFT OR ES_READONLY, $STX, $STY,
$STWidth, $STHeight, ChildWinHandle, $STID, InstanceHandle, NULL



Seems like a stupid way to do it, but it works (look ma, no border!).

Dave: I tried what you suggested (I think):



INVOKE CreateWindowEx, WS_EX_LEFT, ADDR StaticClassName, ADDR StaticText,
WS_VISIBLE OR WS_CHILD OR SS_EDITCONTROL, $STX, $STY,
$STWidth, $STHeight, ChildWinHandle, $STID, InstanceHandle, NULL



but it didn't work. I guess I'll go with the edit control.

Unless someone else has some method that actually works ...
Title: Re: Moving child windows, revisited
Post by: dedndave on October 19, 2011, 07:46:46 PM
a while back, i wrote a little program to find out which style bits the MessageBox function uses for different controls...

;     button style = 50030001

WS_CHILD                             equ 40000000h
WS_VISIBLE                           equ 10000000h
WS_GROUP                             equ 00020000h ;control
WS_TABSTOP                           equ 00010000h ;control
BS_DEFPUSHBUTTON                     equ 00000001h

;static icon style = 50020003

WS_CHILD                             equ 40000000h
WS_VISIBLE                           equ 10000000h
WS_GROUP                             equ 00020000h ;control
SS_RIGHT                             equ 00000002h
SS_CENTER                            equ 00000001h

;static text style = 50022080

WS_CHILD                             equ 40000000h
WS_VISIBLE                           equ 10000000h
WS_GROUP                             equ 00020000h ;control
SS_EDITCONTROL                       equ 00002000h
SS_NOPREFIX                          equ 00000080h


the WS_GROUP and WS_TABSTOP bits are used to control how the tab key moves around
Title: Re: Moving child windows, revisited
Post by: jj2007 on October 19, 2011, 07:47:26 PM
The border was just to demonstrate that the window is there. To see the text, make a little change around line 200:
ChildClassName DB "OneShouldNotUseReservedWords", 0
BtnClassName DB "button", 0
EditClassName DB "edit", 0
StaticClassName DB "static", 0
Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 19, 2011, 07:53:03 PM
jj, thank you for delving so deeply into my n00b code. That fixed it.

The problem wasn't using "reserved words" so much as mis-using them. I don't know why I made the class of the child window "static", but that was boogering up the whole class thing. Class warfare, dontcha know. Static text works just fine.

See, I told you it was just a stupid mistake on my part!

One more question, if you don't mind: What's the easiest way to change the font of  the static text? Do I need to change it at the class ("static") level, or on a per-control basis, or what? Don't like that ugly blocky font.
Title: Re: Moving child windows, revisited
Post by: dedndave on October 19, 2011, 08:02:32 PM
that makes no sense   :(

if he used a class name string of...
StaticClassName  DB "static"
StaticText DB "Some text", 0


i.e., the class name is actually
StaticClassName  DB "staticSome text", 0

then it seems like CreateWindowEx should have returned an error telling you the class name is not registered
Title: Re: Moving child windows, revisited
Post by: jj2007 on October 19, 2011, 08:05:05 PM
@Dave: it's ChildClassName :thumbu

MOV ControlHandle, EAX
; INVOKE UpdateWindow, EAX not needed
invoke SendMessage, STHandle, WM_SETTEXT, 0, chr$("Hey, why not another text?")
invoke SendMessage, STHandle, WM_SETFONT, rv(GetStockObject, ANSI_VAR_FONT), 0


rv and chr$ are Masm32 macros that you'll get if you replace the boring stuff between
; UNSOLVED PROBLEMS:
and
; Defines, macros, prototypes, etc.
with
include \masm32\include\masm32rt.inc
or, much better,
include \masm32\MasmBasic\MasmBasic.inc
Title: Re: Moving child windows, revisited
Post by: NoCforMe on October 19, 2011, 08:08:32 PM
Thank you, jj, you're what they used to call a gentleman and a scholar.

Keep bugging me. One day I might even change my old ways and use that cover-all include file.
Title: Re: Moving child windows, revisited
Post by: dedndave on October 19, 2011, 08:13:53 PM
Quote from: jj2007 on October 19, 2011, 08:05:05 PM
@Dave: it's ChildClassName  :U

gotcha   ::)
Title: Re: Moving child windows, revisited
Post by: jj2007 on October 19, 2011, 08:19:55 PM
Quote from: NoCforMe on October 19, 2011, 08:08:32 PM
Thank you, jj, you're what they used to call a gentleman and a scholar.

That is very kind but incorrect. Dave is a gentleman, and MichaelW, Donkey, Vortex, Tedd (to name a few) are scholars. I am just a cantankerous old hobby programmer who tries to give Hutch a helping hand :thumbu :toothy
Title: Re: Moving child windows, revisited
Post by: oex on October 19, 2011, 08:23:05 PM
Quote from: jj2007 on October 19, 2011, 08:19:55 PM
I am just a cantankerous old hobby programmer who tries to give Hutch a helping hand :thumbu :toothy

Yes.... jj is the handy man