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 ...
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
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.
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
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.
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
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?
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)
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?
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.chm2. You will find this function in the source code - this function create the subclass (ok - may be the name is inappropriate)
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 ...)
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
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.)
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
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.)
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
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?
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
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
nice example, qWord :U
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.
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?
can you show us the resulting value of STHandle ?
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.
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
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
ahhhh :U
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.
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
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 ...
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
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
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.
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
@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
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.
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
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