The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: NoCforMe on October 04, 2011, 07:36:55 PM

Title: Of Mice and Messages
Post by: NoCforMe on October 04, 2011, 07:36:55 PM
OK, rookie conceptual questions here. I hope you'll be kind to this n00b.

So say a guy wants to create a simple window, with a very small window inside it, just for proof-of-concept purposes. The parent window will create the "client area", within which the small window is free to move. The idea is to be able to drag the small window around inside the parent, like placing an object with a drawing program, say.

OK, so far so good. I've created the parent and the child(*) windows. I started playing around with intercepting mouse-move and button messages. But I'm very confused about a basic point that I need to get cleared up before I go further.

I tried making the child window the message-interceptor, using RegisterClassEx() to set up a message-handling procedure (let's call it "ChildProc"). On left-button-down messages, I checked for signs of dragging, using DragDetect(), at which point I captured the mouse with SetCapture(). After this, I watched for WM_MOUSEMOVE messages, thinking I could use them to actually move my window around.

Let me back this up to a more conceptual level. I'm confused about who should handle what in this situation.

Because I'm looking at mouse coordinates from the child's point of view, (0, 0) is at the upper-left of the child window, correct? But I want to move this window within the client area (=parent window). So should I be looking for mouse moves within the parent instead of the child?

Using pseudocode:


[ParentProc]
case WM_MOUSEMOVE:
if (DragFlag)
- move child window to (mouseX, mouseY)

case WM_LBUTTONUP:
- DragFlag = FALSE
- ReleaseCapture()

...


[ChildProc]
case WM_LBUTTONDOWN:
- if (DragDetect())
- DragFlag = TRUE
- SetCapture()

case WM_LBUTTONUP:
- DragFlag = FALSE
- ReleaseCapture()

...


The basic idea is that the signal to capture the mouse comes from the user clicking and dragging within the child, but of tracking mouse movements from the parent's point of view, so that the child can be moved within the parent (that is, relative to (0,0) of the parent). Both parent and child must monitor for WM_LBUTTONUP to know when the user releases the left button (DragFlag is a global variable).

Will this work? Is this the way to do this? Remember, all I want to do is be able to drag this little child around in the client area.

But I'm confused about who gets (and handles) what messages when. Is there some clear explanation of this out there in web-land? There's some good stuff at MSDN, but it's not basic enough to clear this up for me.

Other questions: should I use SetWindowPos() or MoveWindow() to move the window?
What about repainting, invalidating rectangles, etc.? What are the minimal requirements for being able to drag this child around and have it visible and with underlying stuff repainted as needed?
* Do I need to create the child as an actual child (that is, with the Windows child property)?

Probably more questions later.
Title: Re: Of Mice and Messages
Post by: jj2007 on October 04, 2011, 07:47:44 PM
Your idea looks suspiciously like \masm32\examples\exampl02\mdidemo  :bg
Title: Re: Of Mice and Messages
Post by: dedndave on October 04, 2011, 07:52:03 PM
if the mouse is moved outside the main window, i believe you no longer get WM_MOUSEMOVE messages
you may want to use "mouse capture"
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645601%28v=VS.85%29.aspx#_win32_Mouse_Capture

if you create an MDI child, you may not have this problem, but it has it's own quirks, too - lol
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 04, 2011, 07:54:59 PM
Quote from: jj2007 on October 04, 2011, 07:47:44 PM
Your idea looks suspiciously like \masm32\examples\exampl02\mdidemo  :bg

Yes, something like what happens if you click the first button, except that I don't want the scroll bars to appear when the child is dragged to the extremes. So close, but no cigar.
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 04, 2011, 07:57:20 PM
Quote from: dedndave on October 04, 2011, 07:52:03 PM
if the mouse is moved outside the main window, i believe you no longer get WM_MOUSEMOVE messages
you may want to use "mouse capture"
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645601%28v=VS.85%29.aspx#_win32_Mouse_Capture

Look at my pseudocode; I'm already capturing the mouse. The question is, who captures it, the parent or the child?

Quoteif you create an MDI child, you may not have this problem, but it has it's own quirks, too - lol

Yes, looks like maybe too many quirks for me. I'd like a robust, elegant solution I can use from now on.
Title: Re: Of Mice and Messages
Post by: dedndave on October 04, 2011, 08:04:00 PM
i don't think you are using the SetCapture function   :P
if you were, you probably wouldn't ask that question
QuoteThe system typically posts a mouse message to the window that contains the cursor hot spot when a mouse event
occurs. An application can change this behavior by using the SetCapture function to route mouse messages to a
specific window. The window receives all mouse messages until the application calls the ReleaseCapture function
or specifies another capture window, or until the user clicks a window created by another thread.
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 04, 2011, 08:10:18 PM
I am using SetCapture(). Here's my code:


MOV EAX, uMsg
CMP EAX, WM_LBUTTONDOWN
JE lbuttondown

...

lbuttondown:
; Left button down: see if user dragged:
MOV EAX, lParam
MOV EDX, EAX ;Make a copy
AND EAX, 0FFFFH ;Mask off high word
MOV pt.x, EAX
SHR EDX, 16 ;High word--> low word
MOV pt.y, EDX
INVOKE DragDetect, hWin, pt.x, pt.y
OR EAX, EAX ;Did we detect dragging?
JZ cp999
MOV Dragging, TRUE ;Yes, set flag.
INVOKE SetCapture, hWin
JMP cp999 ;Exit
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 04, 2011, 11:21:05 PM
I went ahead and tried what I  described above in pseudocode. My hunch seems to have been right: it works pretty well. I can pick up and drag my child window all over the inside of the parent window.

Few weird things, though:

Clearly I've got a lot to learn here. But I'm making progress.

I would still very much appreciate a general explanation of how this all works, without too many of the actual implementation details. (There's always time for them later!)
Title: Re: Of Mice and Messages
Post by: dedndave on October 04, 2011, 11:41:15 PM
the child window should clip inside the client of the main window - that's a good thing   :bg
(in fact, i strongly recommend using the WS_CLIPCHILDREN flag when creating the main window)
but, you shouldn't be able to drag the cursor outside the main window client

attached is a small MDI window that i use
i don't use IF/ELSEIF/ELSE/ENDIF structures in my code, so it doesn't make a wonderful example for newbies   :P
but, it does demonstrate proper dragging behaviour of a child window
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 05, 2011, 12:23:22 AM
Quote from: dedndave on October 04, 2011, 11:41:15 PM
the child window should clip inside the client of the main window - that's a good thing   :bg
(in fact, i strongly recommend using the WS_CLIPCHILDREN flag when creating the main window)
but, you shouldn't be able to drag the cursor outside the main window client

attached is a small MDI window that i use

That still exhibits the problem I described with my test, except that your mouse cursor is constrained within the parent window. It's still possible to drag part of the child over the edge of the parent so it clips. I'd like my window to stop when it "bumps into" the parent window. (Not a huge problem, but still ...)

Quotei don't use IF/ELSEIF/ELSE/ENDIF structures in my code, so it doesn't make a wonderful example for newbies   :P

Well, I'm a n00b to Win32 only. Been writing 16-bit code for decades now. I also don't care much for those "streamlined" directives. Hell, why not just write C, if that's what you want your code to look like?
Title: Re: Of Mice and Messages
Post by: dedndave on October 05, 2011, 01:49:28 AM
yes - the child window will be clipped inside the main window
that is always true for child windows and is generally considered desirable
however, if you do not want that, then you do not want a child window
you want an independant window, or more likely, a dialog box
no more SetCapture, either   :U

QuoteWell, I'm a n00b to Win32 only. Been writing 16-bit code for decades now. I also don't care much for
those "streamlined" directives. Hell, why not just write C, if that's what you want your code to look like?

a man after my own heart - lol
my thoughts exactly - if i wanted my program to look like a C program, i'd probably write it in C   :bg
btw - i also wrote 16-bit asm for years
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 05, 2011, 01:53:10 AM
More progress to report. Got clipping working correctly, using a page from MSDN (http://msdn.microsoft.com/en-us/library/windows/desktop/ms648380%28v=vs.85%29.aspx#_win32_Confining_a_Cursor):


PrevRect RECT <>

ChildProc PROC hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
LOCAL pt:POINT

MOV EAX, uMsg
CMP EAX, WM_LBUTTONUP
JE lbuttonup

...

lbuttonup:
CMP MouseCaptured, TRUE ;Are we watching the mouse?
JNE cddodef ;Nope.
INVOKE ReleaseCapture
INVOKE ClipCursor, ADDR PrevRect ;Un-clip to our window.
INVOKE SetWindowText, mousebtnhandle, ADDR upmsg
MOV MouseCaptured, FALSE ;Clear flag.
JMP cddodef

...

WindowProc PROC hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
LOCAL pt:POINT, clipRect:RECT

MOV EAX, uMsg
CMP EAX, WM_MOUSEMOVE
JE domousemove
CMP EAX, WM_LBUTTONUP
JE buttonup

...

domousemove:
CMP MouseCaptured, TRUE ;Are we watching the mouse?
JE dm10 ;Yes, move child window.
CMP DragFlag, TRUE ;No; did child report dragging?
JNE dodefault ;Nope, do nothing.
MOV DragFlag, FALSE ;Clear flag
MOV MouseCaptured, TRUE
INVOKE SetCapture, hWin
INVOKE GetClipCursor, ADDR PrevRect ;Get current clip rectangle
INVOKE GetWindowRect, hWin, ADDR clipRect
INVOKE ClipCursor, ADDR clipRect
dm10: INVOKE MoveWindow, ChildHandle, pt.x, pt.y, $childWidth, $childHeight, TRUE

buttonup:
CMP MouseCaptured, TRUE ;Are we watching the mouse?
JNE dodefault ;Nope.
INVOKE ReleaseCapture ;Yep, stop capture.
INVOKE ClipCursor, ADDR PrevRect ;Un-clip to our window.
INVOKE SetWindowText, mousebtnhandle, ADDR upmsg
MOV MouseCaptured, FALSE ;Clear flag.
JMP dodefault


Notice that PrevRect is a global so it is preserved across calls.
Title: Re: Of Mice and Messages
Post by: dedndave on October 05, 2011, 01:54:48 AM
here's a thread you might like   :P
http://www.masm32.com/board/index.php?topic=12092.0
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 05, 2011, 02:03:52 AM
Next question: I've got this window-dragging stuff working reasonably well. For one window. But what if one has dozens of windows that one wants to be able to drag around? I can see this turning into a real nightmare, unless one comes up with a clever organization scheme.

Hmm, I wonder if I could create an array of structures to keep track of all of these windows wandering all over the place?

Any thoughts?

Wait, wait! I think I just figured it out.

You might have dozens of windows, even active windows within a parent. But since the user can only drag one window at a time, it should actually be easy. (I'm leaving aside the ability to move more than one window at a time aside, like with marquee-selecting.) There will always be at most one window being dragged to keep track of.

In fact, it'll work fine the way I have things set up now. The window proc for the child window simply detects whether the user clicked and dragged in that window (using DragDetect()), then sets a flag. The parent window proc checks this flag, and if set, starts mouse capture. To move the child window (following the mouse), it needs the handle to the child window. So all the child window has to do is to copy its handle into a global variable, which the parent proc can use. Easy!

I'll have to try this to see if it's as easy as it looks ...

Problem: Each child window still requires its own window proc. That could still make the code pretty bloat-y. Any way to funnel all this through a single window proc? I don't see how you'd know which child window the user tried to drag. Any way to retrieve the ID of the window?
Title: Re: Of Mice and Messages
Post by: dedndave on October 05, 2011, 03:31:08 AM
it's probably given to you in wParam or lParam   :P
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 05, 2011, 04:48:15 AM
Nope. WM_LBUTTONDOWN (http://msdn.microsoft.com/en-us/library/ms645607%28v=VS.85%29.aspx) has a bunch of flags in wParam,  and of course the mouse X and Y in lParam. Same for WM_LBUTTONUP and WM_MOUSEMOVE.

By the way, enjoyed that thread on C++ very much. I don't hate it (never really learned it myself, just C), but I can see why people do.
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 06, 2011, 04:14:31 AM
It works!

Figured out how to have multiple windows share a common window proc.

Was wondering up above, hmm, how could I tell which window I'm handling this time around? lParam? No. wParam? No.

Well, duh! Just look at the window handle, dummy! (Talking to myself here.) After all, it's guaranteed to be unique.

It works. On creating a child window, store its handle in a global variable. Inside the childProc(), compare the handle passed to the routine to the stored one. If it matches, bingo! that's the child.

So I can just build me an array of structures, storing the handles there, plus all the interesting stuff I need for each child (text to paint, colors, sizes, etc., etc.). Search the list, matching the Windows handle to the stored ones, use the index to access the other stuff.

I think that's pretty slick ... of course, I'm sure some of you figured this out long ago.
Title: Re: Of Mice and Messages
Post by: dedndave on October 06, 2011, 02:10:40 PM
the trick is to design the code so that each window is treated the same
that way, you don't care which one it is   :bg
of course, that can't always be a good solution
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 06, 2011, 06:06:00 PM
Quote from: dedndave on October 06, 2011, 02:10:40 PM
the trick is to design the code so that each window is treated the same
that way, you don't care which one it is   :bg
of course, that can't always be a good solution

Yes, I've learned that. My childProc() doesn't discriminate at all against any of its children. I guess you could say it's "orthogonal".

It works fine now; I'm wondering how well it'll work with lots and lots of children. Theoretically, it should be fine. Have to try it.

Hey, I'm still having some basic problems with my child windows, like cursor position whle dragging, repainting, etc. Would you be willing to take a look at my program if I posted it here (in a .zip)? or should I post code snippets?

Also, if you're  interested, I could post the essentials of my multiple-children-on-one-proc method, including a really easy way to generate lots and lots of windows using only one subroutine and some data structures.
Title: Re: Of Mice and Messages
Post by: dedndave on October 06, 2011, 06:08:43 PM
attach the complete program
i'll have a look
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 06, 2011, 06:44:11 PM
OK, done.

Couple warnings: I use different INCLUDE paths (didn't like the default position of MASM32 in my folder structure).

A good deal of commented-out code.

If anything doesn't make sense to you, ask me. Hopefully you'll find it pretty straightforward.

Things I'm not happy with:

Title: Re: Of Mice and Messages
Post by: dedndave on October 06, 2011, 06:54:05 PM
at first glance, things look pretty good, for the most part

there are a couple things i notice right away, however

1) i see that you do not have the masm32 folder in the drive root
this is likely to cause you problems in the future - it can be on any drive, but should be in the root
also, it is helpful to put the "[drive]:\masm32\bin" folder in the PATH system environment variable
let me know if you need guidance, there

2) i notice the mouse position at the bottom of the window
it is pretty easy to create a status bar and use SendMessage to set the text
i will find or make a simple example after i get out of the shower   :P
then, time permitting, i will look at the program again in more detail
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 06, 2011, 07:04:31 PM
Quote from: dedndave on October 06, 2011, 06:54:05 PM
1) i see that you do not have the masm32 folder in the drive root
this is likely to cause you problems in the future - it can be on any drive, but should be in the root
also, it is helpful to put the "[drive]:\masm32\bin" folder in the PATH system environment variable
let me know if you need guidance, there

Thanks, but I think I've got that covered. I'm using 4DOS, my old-time favorite Windows shell (so much better than the default "command window"!).

Why on earth would I want to put that stuff in my root? I can easily set paths with 4DOS (or modify them on the fly if needed). My path to MASM is f:\techstuff\masm32\bin. 4DOS has no problems finding my executables. Seems like different strokes for different folks, no? (Unless there's some potential problem with programs finding DLLs?)

Of course, there are problems with other people's code, but I can always edit (or, my preference, lift out the "good parts" and copy them into my code).

Anyway, thanks for your help.
Title: Re: Of Mice and Messages
Post by: dedndave on October 06, 2011, 07:19:18 PM
lol
well - have a look at masm32\include\masm32rt.inc
you will see what issues may arise
at any rate - it is a simple thing
you can just move the folder and change the path setting
no need to completely re-install masm32
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 06, 2011, 07:25:11 PM
Quote from: dedndave on October 06, 2011, 07:19:18 PM
lol
well - have a look at masm32\include\masm32rt.inc
you will see what issues may arise

I see what you mean. The solution is simple: don't use masm32rt.inc. I think I can figure out which include files I need in my projects. (Or I could edit the include files to tailor them to my liking.)
Title: Re: Of Mice and Messages
Post by: dedndave on October 06, 2011, 07:26:36 PM
just make a copy of it, name it "MyMasm32rt.inc", and edit the paths   :U

that way, when you want to assemble an example, you just add 2 letters "My"   :P
Title: Re: Of Mice and Messages
Post by: jj2007 on October 06, 2011, 07:31:11 PM
Quote from: dedndave on October 06, 2011, 07:26:36 PM
just make a copy of it, name it "MyMasm32rt.inc", and edit the paths   :U

that way, when you want to assemble an example, you just add 2 letters "My"   :P

ça peut crèer pas mal de problèmes si tout le monde parle une autre langue... il y'à de bonnes raisons pq on a une certaine standardisation: ça marche!
Title: Re: Of Mice and Messages
Post by: dedndave on October 06, 2011, 07:33:33 PM
all may be well if he runs under 4dos, and "techstuff" becomes the root
not sure how that program works
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 06, 2011, 08:16:27 PM
Well, yes, all is fine and dandy under 4DOS (a product of JP Software (http://jpsoft.com/) if you're interested; it's now morphed into something called "Take Command"). It's just a command shell, just like the default Windows "Command prompt". But so much nicer; has memory-based batch files (.BTMs), customizeable everything, editable PATHs, lots of other goodies. I've used it since the 1990s.

And no, I didn't make \techstuff the root; why would I want to do that? I simply set my path to point to the MASM "bin" folder (Path=F:\TECHSTUFF\MASM32\BIN). Easy peasy. All the "makeit.bat" files in the MASM32 examples work fine.

I hope I haven't opened a can of worms here; after reading jj's Masm32 page, I can see why he suggests people use the standard locations for things (so that other people can test their code). So I pledge that if I post code here that might actually be used by others, I'll take care that the path names for include files, etc., are the standard ones. For my own projects, however, I really like to be able to put things where I want them.
Title: Re: Of Mice and Messages
Post by: dedndave on October 06, 2011, 08:49:43 PM
it's ok - you're bound to bump into problems at some point
when you do, it's an easy fix   :P

here is a status bar that displays mouse position
the stuff i added to make the status bar is surrounded by "$$$$$$"
Title: Re: Of Mice and Messages
Post by: jj2007 on October 06, 2011, 08:51:23 PM
Quote from: NoCforMe on October 06, 2011, 08:16:27 PMFor my own projects, however, I really like to be able to put things where I want them.

It is a can of worms indeed. Reflect what you gain by not having masm32 in one of your roots (you have several drives, don't you?). We use English not because everybody likes English but because it makes life so much easier...
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 06, 2011, 08:57:26 PM
Hey, what can I say? I don't like to be like everyone else. (I'm a 'Merkin, after all.)
Title: Re: Of Mice and Messages
Post by: dedndave on October 06, 2011, 09:01:13 PM
i can see another problem with not using the standard location
your programs are going to require modification if other members want to assemble them
that means, when you ask for help, you may not get the response you would like   :P
Title: Re: Of Mice and Messages
Post by: jj2007 on October 06, 2011, 09:09:41 PM
Quote from: NoCforMe on October 06, 2011, 08:57:26 PM
Hey, what can I say? I don't like to be like everyone else. (I'm a 'Merkin, after all.)

Merkin (http://www.urbandictionary.com/define.php?term=merkin), that sounds good ::)
Jokes apart: We are all very different from everyone else here. Honestly :thumbu
But over time we have learnt that include \masm32\include\masm32rt.inc is a fantastic start into the World of Assembly :bg
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 06, 2011, 09:22:16 PM
Hey, Dave,  I tried adding a window to my test bed by calling CreateStatusWindow(), just like in your example, but the linker complained "undefined symbol : CreateStatusWindowA". (I copied all the INCLUDELIBs from masm32rt into my program.) Where is this object?
Title: Re: Of Mice and Messages
Post by: dedndave on October 06, 2011, 09:26:20 PM
it can also be done using CreateWindowEx, using a class name of 'msctls_statusbar32'
but, CreateStatusWindowA is in comctl32.inc / lib
that means you should probably use InitCommonControlsEx
my little window program had that already (first thing executed)
it may not be necessary for a status bar
Title: Re: Of Mice and Messages
Post by: jj2007 on October 06, 2011, 09:38:26 PM
Assembles and links perfectly. You seem to have a problem with your includes and/or paths.

include \masm32\include\masm32rt.inc

.code
AppName db "Masm32:", 0

start: MsgBox 0, "Hello World", addr AppName, MB_OK
exit
invoke CreateStatusWindow, 0, 0, 0, 0

end start
Title: Re: Of Mice and Messages
Post by: dedndave on October 06, 2011, 09:42:39 PM
 :lol
i see Jochen is in a good mood, today   :P
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 06, 2011, 09:58:39 PM
Well, I got it working (needed the comctl32 stuff).

So Dave, basically that whole example you linked boiled down to this, so far as setting up the status window goes:



StatusMessage DB "Mouse: X: "
StatusXpos DB "#### Y: "
StatusYpos DB "####"
NullString DB 0

...

; Create the status bar:
INVOKE CreateStatusWindow, WS_CHILD or WS_VISIBLE, OFFSET NullString, WindowHandle, $statusbarID
MOV StatusHandle, EAX

...

(in parent WndProc:)

domousemove:
; First, show current mouse position:
IF 1
        PUSH    EDI
        MOVZX EAX, WORD PTR lParam ;EAX = X position (lParam low word)
        MOV     EDI, OFFSET StatusXpos + 3
        CALL    B2Asc
        MOVZX EAX, WORD PTR lParam +  2 ;EAX = Y position (lParam high word)
        MOV EDI, OFFSET StatusYpos + 3
        CALL    B2Asc
        INVOKE  SendMessage, StatusHandle, SB_SETTEXT, 0, offset StatusMessage
        POP     EDI



(I left out the stuff for resizing the window, which just goes in the handler for WM_SIZE.) That's pretty much it.

I will say it's a heck of a lot nicer display than what I had. I'll keep it.

By the way, I got "gotcha!"-d by the weird way you do your binary-to-ASCII conversion. Couldn't figure out why it looked so funky until I saw that you start at the right side of the number and work leftwards. (Hence the + 3s in the code.)

Regarding the resizing stuff, it's kind of funny to watch what happens when you resize the window without that code. The status bar just hangs there, orphaned.
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 06, 2011, 10:36:47 PM
So I added zero-suppression to your binary-to-ASCII routine (I don't like leading zeroes):



;====================================================================
; B2A4
;
; Converts binary value to ASCII numeric digits (4 digits, limited to
; maximum value of 9999). Result is leading-zero suppressed.
;
; On entry,
; EAX = value to convert
; EDI--> place to store digits (4)
;
; Return value: (none)
;
;====================================================================

B2A4 PROC
        MOV ECX, 4 ;4 digits

b2a10: PUSH ECX
MOV ECX, 10
XOR EDX, EDX
DIV ECX
OR DL, '0' ;Binary--> ASCII
POP ECX
MOV [EDI], DL
DEC EDI
LOOP b2a10
; Now do leading-zero suppression:
MOV ECX, 3 ;Look @ 1st 3 digits
b2a20: INC EDI
CMP BYTE PTR [EDI], '0'
JNE b2a499 ;Stop on 1st non-zero digit.
MOV BYTE PTR [EDI], ' '
LOOP b2a20
b2a499: RET

B2A4 ENDP



(Edit: fixed bad code. Hate bad code!)
Title: Re: Of Mice and Messages
Post by: qWord on October 06, 2011, 10:43:15 PM
[interjection] use a text editor which allows convertion of tabs to spaces -> before posting code, make a convertion ... just for reasons of readability  :8)[/[interjection]
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 06, 2011, 10:43:55 PM
Uh oh; bigger problem.

Adding your status bar (which works) makes all my child windows go "Poof!" when I click on them.

WTF?????

I'm starting to think that there's something fundamentally wrong with the way I'm creating these little windows. Probably something having to do with the window styles, or the extended window style.

Thinking about it, in a "normal" window--that is, one with a title bar--you can only grab the window with the cursor by the title bar. But my windows can be moved by dragging inside them (I guess because that's the way I detect that the user wants to move them, by using DragDetect() and then capturing the mouse). But as I indicated earlier, the cursor always jumps to the upper-left corner when they're being dragged. So the "hot spot" must be that corner. Which makes me unsure just what kinds of windows these really are.
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 06, 2011, 10:47:11 PM
Quote from: qWord on October 06, 2011, 10:43:15 PM
[interjection] use a text editor which allows convertion of tabs to spaces -> before posting code, make a convertion ... just for reasons of readability  :8)[/[interjection]

Is that the convention around here? I personally hate spaces (they're just "empty calories" in text files), but I notice that all the code examples here seem to use them. I'm guessing the reason is that there's no agreed-upon convention for tab spacing (I use 8, others use 4).

Is this really a problem?

Like I wrote earlier, I'm willing to follow conventions if I ever post any code worthy of other people using it.
Title: Re: Of Mice and Messages
Post by: dedndave on October 07, 2011, 03:34:42 AM
well - i don't see anything that hits me in the face as far as the problems you describe
i do have a few helpful tips, though

first, the use of the $defStatTxt macro is a bit confusing, and probably unnecessary
you define the structure:
$ST STRUCT ;Static text structure
  $st_X DD ?
  $st_Y DD ?
  $st_w DD ?
  $st_h DD ?
  $st_text DD ?
  $st_ID DD ?
$ST ENDS

all is good, there, although i would probably reduce the names a little
$ST STRUCT ;Static text structure
  X       DD ?
  Y       DD ?
  w       DD ?
  h       DD ?
  text    DD ?
  ID      DD ?
$ST ENDS

in the macro...
$defStatTxt MACRO tname, txt, x, y, w, h, ID
LOCAL sname

sname DB &txt, 0 ;Declare the string
tname $ST <x, y, w, h, OFFSET sname, ID> ;Declare the structure
ENDM

not sure i would use a macro for this
anyways - the structure is all dwords - nice if they were dword aligned
by placing a variable-length string at the beginning, it doesn't happen
you already have a structure member that is a pointer to the string
if the array were all $ST structures, and the string data was seperate, everyone would be aligned
another way might be to align the structure definition and place the string at the end
$ST STRUCT 4 ;Static text structure
  X       DD ?
  Y       DD ?
  w       DD ?
  h       DD ?
  text    DD ?
  ID      DD ?
$ST ENDS

notice the "$ST STRUCT 4"
that means everyone is dword aligned
then, in the macro, place the string after the structure

personally, i would probably seperate the string data from the dword structure array
it makes it easy to index mathematically (even easier if each struct had 8 dword members  :P )
@ST_Font $ST <10, 14, 40, 20, szFont, 401>
@ST_mouse $ST <10, 250, 300, 20, szMouse, 402>
@ST_mousebtn $ST <109, 250, 30, 20, szMouseBtn, 403>
@ST_mouseX $ST <205, 250, 40, 20, szMouseX, 404>
@ST_mouseY $ST <265, 250, 40, 20, szMouseY, 405>

szFont db 'Font:',0
szMouse db 'Mouse: lbutton down  pos: x:       y:     ',0
szMouseBtn db 'up',0
szMouseX db '#####',0
szMouseY db '#####',0


at any rate, addressing structure members can be simplified
CreateStaticText    PROC     stPtr:DWORD
; Returns window handle in EAX.

    MOV    EBX, stPtr
    INVOKE    CreateWindowEx, WS_EX_LEFT, ADDR STclassName, [EBX + OFFSET $ST.$st_text], $STattrs,
             [EBX + OFFSET $ST.$st_X], [EBX + OFFSET $ST.$st_Y],
        [EBX + OFFSET $ST.$st_w], [EBX + OFFSET $ST.$st_h], WindowHandle,
        [EBX + OFFSET $ST.$st_ID], InstanceHandle, 0
    RET

CreateStaticText    ENDP

for example,
[EBX + OFFSET $ST.$st_text]
can be
[EBX].$ST.$st_text
or, you can use ASSUME
CreateStaticText    PROC     stPtr:DWORD
; Returns window handle in EAX.

        ASSUME  EBX:Ptr $ST

    MOV    EBX, stPtr
    INVOKE    CreateWindowEx, WS_EX_LEFT, ADDR STclassName, [EBX].$st_text, $STattrs,
             [EBX].$st_X, [EBX].$st_Y,
        [EBX].$st_w, [EBX].$st_h, WindowHandle,
        [EBX].$st_ID, InstanceHandle, 0
    RET

        ASSUME  EBX:Nothing

CreateStaticText    ENDP


i also notice that the main window has the WS_EX_OVERLAPPEDWINDOW style
not really needed if you use WS_OVERLAPPEDWINDOW
for the main window, i would also use WS_CLIPCHILDREN - that helps paint - keeps the thing from flickering, too

not sure why you enumerate fonts
it is easy to use SystemParametersInfo with SPI_NONCLIENTMETRICS to get the user-selected fonts
then, set the size you want and CreateFont using the LOGFONT in the NONCLIENTMETRICS structure

i will look at the program some more tomorrow
you said you had trouble when you added a status bar
perhaps you could post the updated program for me to work with
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 07, 2011, 05:44:24 AM
Hey, thanks for looking at my code.

1. Re: structure member names: I guess I got so used to naming the members the same as the structure (like $ST_text) that I didn't realize this was totally unnecessary, as you never use just the member name alone. So thanks for the tip. (You can see I like descriptive names, but why not save some typing?)

2. Re: my scheme for declaring structures containing text with a macro: Yes, having variable-length text embedded in what would otherwise be a nice DWORD-aligned structure is not good. I thought about that too. The reason I did things this way was to try to do the whole declaration thing in one fell swoop. The macro allocates the text, declares the structure, plugs in the elements, and uses the first macro argument as the name of the finished structure. Makes declaring lots of static-text items really easy.

Couple things come to mind: one is to declare the strings separately from the structures, put them in a heap, and let the structures line up nicely.
Another way would be to insert alignment statements after the string, to bring the next element to a WORD or DWORD boundary. Of course, that wastes a little space, not much.

3. Turns out there are at least 3 ways to reference structure members with a pointer register:



MOV EAX, [EBX + OFFSET $ST.text]
MOV EAX, [EBX + $ST.text]
MOV EAX, [EBX.$ST.text]



I've settled on the 2nd one. Don't like the last one 'cause the dot between reg and struct name just looks plain weird to me.  But not having to include OFFSET in every dang one is an improvement. (This, of course, is a matter of style, not of programming accuracy.) I like the "+" operator. By the way, you'll notice that I combine bitwise flag values with "+" instead of "OR", just because it's more intuitive for me (OR looks to me like "hmm, I either get this value or that value or that value"). Of course, the result is exactly the same, and it's my program, so I'll keep on doing it that way, thank you very much.

4. I'm listing fonts as part of another project, where I want to be able to select from any installed font. Actually, that was the first Windoze thing I got working (ever!), and was pretty happy when it all came together. Are you saying there's an easier way to do font enumeration than EnumFontFamiliesEx()?

5. That business of the status bar killing my child windows was, of course, just a stupid error on my part (I wasn't computing the mouse X and Y before trying to move the window, so of course it just went into the bit bucket). Fixed now.

I want to wait until  I get the resize code working before I give you another copy. Speaking of which, could you please explain the following from that program (SmallWin) you attached?



SizeWin:
        mov     ecx,[esp+8]                            ;ECX = hWnd
        sub     esp,sizeof RECT
        INVOKE  GetClientRect,ecx,esp
        pop     eax
        pop     edx
        pop     ecx
        sub     eax,ecx                                ;EAX = client height
        pop     ecx
        sub     edx,ecx                                ;EDX = client width
        mov     ecx,StbHeight
        sub     eax,ecx
        INVOKE  MoveWindow,hStatus,0,eax,edx,ecx,TRUE



I have no idea what's going on with all that stuff pulled off the stack. How can you keep track of that stuff? It's totally non-intuitive. (I can see that you're getting the client RECT structure, then doing some arithmetic with the window size, then passing it to MoveWindow()). If you could explain what's what in there, I'd appreciate it. I  really do not have the patience to try to unravel the stack to see which register corresponds to which parameter.

Anyhow, thanks again for all the help.
Title: Re: Of Mice and Messages
Post by: dedndave on October 07, 2011, 05:58:17 AM
3. yah - this is really a matter of personal taste   :P
i have gotten used to [reg].structtype.member
a habit i picked up from qWord, i think

4. well - there are a number of caveats to enumerating fonts - good you got it working, actually   :U
you may also want to look into ChooseFont - there are 1 or 2 examples in masm32\examples
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646914%28v=vs.85%29.aspx

5. well - i create a temporary RECT structure on the stack (without using LOCAL)
        sub     esp,sizeof RECT
after the call, i pop the RECT members into registers - it makes for small code
what i am really after, there, is the position and size for the status bar
so - i get the RECT for the client
the X position for the status bar is always 0
the Y position is the client height minus the status bar height (client height = bottom minus top)
the width is the same as the client width (client width = right minus left)
the height is the height of a status bar (measured and stored in StbHeight during WM_CREATE)

now that i think about it, that code could be simpler
because the left and top are always 0   :P
so - the first 2 SUB instructions could be removed, i guess

as for the stack stuff, you'll get used to it
the win32 API always passes parameters on the stack
so - it is something you'll see a lot of
also, the stack is a great place for small temporary allocations
fast - small code to access it
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 07, 2011, 06:50:47 AM
New .zip of source & exe is attached.

You'll notice there's still the problem of the child window borders getting messed up. Since you can drag them over the status bar, try that and see what happens to them.

Speaking of the status bar, it's working fine (including resizing--piece of cake). However, one thing I don't like: I tried to adjust the clipping rectangle I used to clip the cursor by subtracting the height of the status bar, but it doesn't seem to work correctly:



INVOKE GetWindowRect, hWin, ADDR gpRect
; Adjust clipping rectangle to exclude status bar:
MOV EAX, SBheight
SUB gpRect.bottom, EAX
INVOKE ClipCursor, ADDR gpRect



I can't be sure, but it looks as if the clip area may be correct, but the child windows can extend below it by their height (in other words, since the window is being dragged by the upper-left corner (0,0), the rest of the window goes out of the clip area. Or something like that. Yet more evidence that I'm doing something wrong with the children.
Title: Re: Of Mice and Messages
Post by: dedndave on October 07, 2011, 01:50:14 PM
it appears that you attached the old version   :P
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 07, 2011, 05:27:37 PM
whoops, sorry 'bout that.

Regarding the problems I'm having with constraining the mouse (ClipRect() and all that), seems to me that it's probably working correctly, but the problem lies elsewhere. The cursor is being correctly constrained; it cannot go beyond the client area. But since the child window is being dragged by its ear (0,0), it extends beyond the bottom and right of the client area.

What I want is an object that will be constrained within the client area. In other words, when any edge of the object bumps into the edge of the client area, I want the object to stop moving.
Title: Re: Of Mice and Messages
Post by: dedndave on October 07, 2011, 06:52:25 PM
; Now do leading-zero suppression:
MOV ECX, 3 ;Look @ 1st 3 digits
b2a20: INC DI
CMP BYTE PTR [EDI], '0'
JNE b2a499 ;Stop on 1st non-zero digit.
MOV BYTE PTR [EDI], ' '
LOOP b2a20


i am a little surprised this assembles   :bg
b2a20: INC DI
i guess it just puts a size override byte in there - hope we don't wrap a 64 kb boundry   :P

one solution that comes to mind would be to create a large child window that does not include the drop-down and status bar
then, create the little windows under that one
i have done this in the past to prevent scroll bar flicker
Title: Re: Of Mice and Messages
Post by: dedndave on October 07, 2011, 07:01:01 PM
B2A4 PROC

        MOV ECX, 4 ;4 digits

b2a10: CMP     CL,4
        JZ      b2a11

        OR      EAX,EAX
        JZ      b2a12

b2a11:  PUSH ECX
MOV CL, 10
XOR EDX, EDX
DIV ECX
OR DL, '0' ;Binary--> ASCII
POP ECX
MOV [EDI], DL
DEC EDI
LOOP b2a10

        RET

b2a12:  MOV BYTE PTR [EDI],20h
        DEC     EDI
        LOOP    b2a12

        RET

B2A4 ENDP


i should mention - the LOOP instruction is slow in 32-bit world
we generally use DEC ECX/JNZ
however - speed isn't super critical here
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 07, 2011, 07:09:54 PM
Quote from: dedndave on October 07, 2011, 06:52:25 PM
one solution that comes to mind would be to create a large child window that does not include the drop-down and status bar
then, create the little windows under that one
i have done this in the past to prevent scroll bar flicker

So like this?

Main window--> big child window--> little kid windows?

The big child window would have no title bar, no resizeable borders, just a big (borderless?) "playground" for the small children.
Would respond to resize messages just like the status bar (handled in parent).

Seems to make sense.

By the way, I think your latest B2A routine needs a little work ...
Title: Re: Of Mice and Messages
Post by: dedndave on October 07, 2011, 07:13:35 PM
it seems to work ok - i just tried it for the first go - lol
i may have missed something
the point was, though, why convert them after the fact ?
if the dividend is 0, fill the rest in with spaces
of course, you want the first 0, in case the value is 0
there are far more efficient ways to do this - it was a down-and-dirty approach   :P

yes - a child window with no border or title - the style would be "WS_VISIBLE or WS_CHILD or WS_CLIPCHILDREN"
which, btw - i see you using "+" to add flags together
this will byte you in the ass - lol
use "OR"   :U

you write a seperate WndProc for it - of course, one more class to register, too
in a way, it makes it nice because you put all the child stuff in one WndProc and the main window in another
should make it a little easier to read
you can combine them into one, but it's not worth the effort

when the main window is resized, you set the size for the "master" child
that code can be combined with the status bar size code
Title: Re: Of Mice and Messages
Post by: dedndave on October 07, 2011, 07:25:42 PM
the problem with the little windows seems to be that they are not being redrawn entirely
we must be missing a style bit someplace   :bg
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 07, 2011, 07:27:20 PM
Quote from: dedndave on October 07, 2011, 07:13:35 PM
yes - a child window with no border or title - the style would be "WS_VISIBLE or WS_CHILD or WS_CLIPCHILDREN"
which, btw - i see you using "+" to add flags together
this will byte you in the ass - lol

Side issue, but I disagree: how do you suppose that there's any difference between 'X or Y or Z" and "X + Y + Z" when they're all unsigned quantities?

I already explained eariler why I do this.

I do realize that there are places where this would byte one in the ass. This isn't one of them. No problems with overflow here.
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 07, 2011, 07:28:52 PM
Quote from: dedndave on October 07, 2011, 07:25:42 PM
the problem with the little windows seems to be that they are not being redrawn entirely
we must be missing a style bit someplace   :bg
\

Yes! I'm sure that's at least part of the problem.

Gotta leave now, but when I come back I'll go through the code and extract all the style settings and put them in a message. There's some kind of conflict somewhere, I'm sure.
Title: Re: Of Mice and Messages
Post by: dedndave on October 07, 2011, 07:32:00 PM
ok - rock on   :P

let me think of an example....

try this...
       mov     eax,WS_OVERLAPPEDWINDOW+WS_SYSMENU
       print   str$(eax),13,10
       mov     eax,WS_OVERLAPPEDWINDOW or WS_SYSMENU
       print   str$(eax),13,10
Title: Re: Of Mice and Messages
Post by: jj2007 on October 07, 2011, 07:39:13 PM
Quote from: NoCforMe on October 07, 2011, 07:27:20 PM
Side issue, but I disagree: how do you suppose that there's any difference between 'X or Y or Z" and "X + Y + Z" when they're all unsigned quantities?

Good example, Dave. In many cases - see first three below - Windows shows benign behaviour because only 1 bit is set for each constant. It is the exceptions that will let your code go bang. Chasing such bugs is a nightmare...

WS_VISIBLE     =        00010000000000000000000000000000
WS_CHILD       =        01000000000000000000000000000000
WS_CLIPCHILDREN=        00000010000000000000000000000000
WS_OVERLAPPEDWINDOW=    00000000110011110000000000000000
WS_SYSMENU=             00000000000010000000000000000000
Sys or OverLap=         00000000110011110000000000000000
Sys + OverLap=          00000000110101110000000000000000
Title: Re: Of Mice and Messages
Post by: dedndave on October 07, 2011, 08:26:22 PM
well - there are better examples, but that one was easy to come up with - lol
the thing is....
like Jochen says, trying to find this bug will make you pull your hair out
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 07, 2011, 11:33:43 PM
OK, jj, you convinced me. I guess I'm just used to working with single-bit flags in my own code. OR it is.

I'm still having to break myself of my 16-bit habits, like that INC DI in the b2a routine. Still seems strange to type things like EAX, EDX, etc. And realize that PUSH and POP expect 32-bit entities, not 16-bit.

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

Regarding my child-window problem, before I code another layer of window like you suggested, let's think about this a moment. The problem is that the child windows' borders aren't being redrawn (or not redrawn properly): why is this? Is it something I'm doing or not doing in my program? or do I have the wrong styles somewhere?

I'd like to understand what's actually wrong here, rather than just start throwing darts at the dartboard, if you know what I mean.

I'll wait until you (Dave) have had a chance to look at my newest program.
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 08, 2011, 01:05:58 AM
I made a small improvement to your routine:



B2A4 PROC

MOV ECX, 4 ;4 digits
JMP SHORT b2a11
b2a10: OR EAX, EAX
        JZ      b2a12
b2a11: PUSH ECX
MOV CL, 10
XOR EDX, EDX
DIV ECX
OR DL, '0' ;Binary--> ASCII
POP ECX
MOV [EDI], DL
DEC EDI
LOOP b2a10
RET

b2a12: MOV BYTE PTR [EDI],  ' '
DEC EDI
LOOP b2a12
RET

B2A4 ENDP



Do you see what it is? (Hint: it gives a tiny speed improvement as well as code size reduction.)
Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 01:47:28 AM
there ya go   :P

let me find another one...........
Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 01:49:48 AM
some code by drizz...
http://www.masm32.com/board/index.php?topic=12234.msg93949#msg93949
i squeezed 2 clock cycles out of it - lol

B2Asc   PROC

        push    ebx
        mov     edx,4294968          ;2^32/1000
        mov     ebx,10               ;per digit
        mul     edx                  ;extend first digit
        mov     ecx,edx              ;digit 1 in CL
        mul     ebx                  ;second digit
        mov     ch,dl                ;digit 2 in CH
        mul     ebx                  ;third digit
        bswap   ecx                  ;digits 1 & 2 up high
        mov     ch,dl                ;digit 3 in CH
        mul     ebx                  ;digit 4 in DL
        lea     ecx,[edx+ecx+'0000'] ;combine and make ASCII
        bswap   ecx                  ;re-order bytes
        pop     ebx
        ret

B2Asc   ENDP


you'll want to take out the EDI stuff from the calling code
you still call it with the value in EAX, but you have to place the results from ECX when done

        mov     eax,9999
        call    B2Asc
        mov     SomeLabel,ecx


it takes about 30 clock cycles   :bg
Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 02:24:56 AM
MOV EAX, lParam ;Yep, 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 pt.x, EAX
MOV EAX, EDX ;Get back copy
SHR EAX, 16 ;High word--> low word
CWDE
MOV pt.y, EAX


i just noticed your code here   :P
ouch !

replace all of this...
domousemove:
; First, get current mouse position (from lParam):
MOV EAX, lParam ;Yep, 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 pt.x, EAX
MOV EAX, EDX ;Get back copy
SHR EAX, 16 ;High word--> low word
CWDE
MOV pt.y, EAX

; Display current pos:
        PUSH    EDI
        MOV EAX, pt.x
        MOV     EDI, OFFSET StatusXpos + 3
        CALL    B2A4
        MOV EAX, pt.y
        MOV EDI, OFFSET StatusYpos + 3
        CALL    B2A4
        INVOKE  SendMessage, StatusHandle, SB_SETTEXT, 0, offset StatusMessage
        POP     EDI

and this
B2A4 PROC

        MOV ECX, 4 ;4 digits

b2a10: CMP     CL,4
        JZ      b2a11

        OR      EAX,EAX
        JZ      b2a12

b2a11:  PUSH ECX
MOV ECX, 10
XOR EDX, EDX
DIV ECX
OR DL, '0' ;Binary--> ASCII
POP ECX
MOV [EDI], DL
DEC EDI
LOOP b2a10

        RET

b2a12:  MOV BYTE PTR [EDI],20h
        DEC     EDI
        LOOP    b2a12

        RET

B2A4 ENDP


with this
domousemove:
        movzx   eax,word ptr lParam
        push    ebx
        mov     pt.x,eax
        call    B2As4
        movzx   eax,word ptr lParam+2
        mov dword ptr StatusXpos,ecx
        mov     pt.y,eax
        call    B2As4
        mov dword ptr StatusYpos,ecx
        pop     ebx
        INVOKE  SendMessage,StatusHandle,SB_SETTEXT,0,offset StatusMessage

and this
B2As4   PROC

        mov     edx,4294968          ;2^32/1000
        mov     ebx,10               ;per digit
        mul     edx                  ;extend first digit
        mov     ecx,edx              ;digit 1 in CL
        mul     ebx                  ;second digit
        mov     ch,dl                ;digit 2 in CH
        mul     ebx                  ;third digit
        bswap   ecx                  ;digits 1 & 2 up high
        mov     ch,dl                ;digit 3 in CH
        mul     ebx                  ;digit 4 in DL
        lea     ecx,[edx+ecx+'0000'] ;combine and make ASCII
        bswap   ecx                  ;re-order bytes
        ret

B2As4   ENDP

it probably does both strings in about the same time as a single DIV instruction - lol
(not including the SendMessage)

you'll have to use .586 (or .486) instead of .386
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 08, 2011, 02:32:43 AM
Well, OK. But remember that at this point the plan is to get this working, not super-optimizing it. It'll be a while before this goes to market ...
Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 02:56:33 AM
yah - sorry about that - can't help it - lol

i notice the status message stops updating when the cursor is over one of the child windows
that's because the child proc gets the messages
we can fix that, easy enough

at this point, i may take a different tack
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 08, 2011, 03:34:34 AM
As promised, style definitions:

That's it. Pretty vanilla.
Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 03:51:03 AM
my problem up til now has been trying to understand everything you are doing
it is consuming too much time   :P

so - i am going to take one of my little "standard" window programs...
first, i'll confine the mouse movement when it's being dragged
then, i'll put 2 static text boxes on it and make it so you can drag one over the top of the other
after that, i'll make it so the boxes, themselves, are confined to the client area

these are all things that i have not had to do yet - lol
it's sort of a "start at the beginning and make each step work" approach
by using one of my own window programs, i do not have to spend time familiarizing myself with someone elses code
Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 03:54:31 AM
before i start working on that, i added leading zero suppression to the B2As4 routine above...
B2As4   PROC

        mov     edx,4294968          ;2^32/1000
        mov     ebx,10               ;per digit
        mul     edx                  ;extend first digit
        mov     ecx,edx              ;digit 1 in CL
        mul     ebx                  ;second digit
        mov     ch,dl                ;digit 2 in CH
        mul     ebx                  ;third digit
        bswap   ecx                  ;digits 1 & 2 up high
        mov     ch,dl                ;digit 3 in CH
        mul     ebx                  ;digit 4 in DL
        lea     ecx,[edx+ecx+'0000'] ;combine and make ASCII
        bswap   ecx                  ;re-order bytes
        cmp     cl,30h
        jnz     B2As42

        cmp     ch,30h
        jnz     B2As41

        test    ecx,0F0000h
        jnz     B2As40

        and     ecx,03F202020h
        ret

B2As40: mov     cx,2020h
        ret

B2As41: mov     cl,20h

B2As42: ret

B2As4   ENDP
Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 05:34:15 AM
here's a function we can use   :U
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648383%28v=vs.85%29.aspx

btw, i don't think i caught your name ?
Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 06:09:16 AM
and, that's step 1
i even made it stay above the status bar   :P
(only when left button is down, of course)
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 08, 2011, 06:34:05 AM
Quote from: dedndave on October 08, 2011, 05:34:15 AM
here's a function we can use   :U
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648383%28v=vs.85%29.aspx

Already in there. Look in WindowProc, under "domousemove".
Title: Re: Of Mice and Messages
Post by: jj2007 on October 08, 2011, 06:55:16 AM
Quote from: NoCforMe on October 08, 2011, 06:34:05 AM
Already in there. Look in WindowProc, under "domousemove".

Yep, ClipCursor is there. Can't test it, though - Error A2087: Cannot open include file '\techstuff\masm32\include\kernel32.inc'
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 08, 2011, 07:08:51 AM
Well, sorry about that. I guess at this point I had planned on playing this game (learning assembly language forWindows) my way, by my rules, on my computer. I hadn't envisioned joining a "community"  just yet.

You could just change the include statement. The program does assemble and link OK.

OK, here's a copy with the standard includes ("\masm32\include ...") just for you. It should be build-able. Then you can see the problem with moving the child windows.
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 08, 2011, 08:01:31 AM
Interesting.

If anyone out there is actually playing with my little testbed program, notice the difference between using



INVOKE InvalidateRect, ChildHandle, NULL, TRUE



and



INVOKE RedrawWindow, ChildHandle,  NULL, NULL, RDW_FRAME OR RDW_INVALIDATE



immediately after using MoveWindow() on the child window.
Title: Re: Of Mice and Messages
Post by: jj2007 on October 08, 2011, 08:55:24 AM
You can use conditional assembly to make testing easier:
Quotedm10:   INVOKE   MoveWindow, ChildHandle, pt.x, pt.y, $childWidth, $childHeight, TRUE
   UseInvRect = 1
   if UseInvRect
      INVOKE   InvalidateRect, ChildHandle, NULL, TRUE
   else
      INVOKE RedrawWindow, ChildHandle,  NULL, NULL, RDW_FRAME OR RDW_INVALIDATE
   endif

Case 1 redraws the background after moving the child over the status bar, case 0 doesn't.
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 08, 2011, 09:48:15 AM
Thanks; that makes sense, and jibes with what actually happens.

Can someone tell me exactly what kind of windows I've created here? They don't seem to fit the categories of windows that I see described in the references (MSDN). The strangest part of their behavior is how the mouse cursor always attaches itself to the upper-left corner. (Although this may be a side effect of doing something wrong in my window-moving code.) It behaves like there's a one-pixel "handle" at (0,0).

Here's what I actually want: small windows that I can drag by clicking anywhere in the interior of the window, and resizeable. (Resizing is easy: just add the WS_SIZEBOX style. Of course, for some WEIRD reason, this also forces the box to acquire the WS_THICKFRAME style.)

Let me tell you what I'm after here: I thought, perhaps a little grandiosely, that I might create a tool to create resource templates. Like the resource editors in Visual {xxx}, but much simplified. So the child windows could represent fixed-text items, for instance. I want to be able to position them, resize them (by grabbing their frames), and to put stuff in them (like text, maybe even bitmaps). So what kind of child windows do I want? I'm starting to suspect that this will require owner-draw controls to do it properly. Haven't learned that yet ...
Title: Re: Of Mice and Messages
Post by: jj2007 on October 08, 2011, 10:37:24 AM
Quote from: NoCforMe on October 08, 2011, 09:48:15 AM
Can someone tell me exactly what kind of windows I've created here? They don't seem to fit the categories of windows that I see described in the references (MSDN). The strangest part of their behavior is how the mouse cursor always attaches itself to the upper-left corner. (Although this may be a side effect of doing something wrong in my window-moving code.) It behaves like there's a one-pixel "handle" at (0,0).

You need the initial position of the mouse, and then use an offset for MoveWindow.

Quote
for some WEIRD reason, this also forces the box to acquire the WS_THICKFRAME style.)

You can get rid of the thick frame by subclassing and capturing the nc paint message.

BTW, check RDW_FRAME OR RDW_INVALIDATE or RDW_ERASE
Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 01:49:41 PM
the windows are Static Controls
they are a special window because the OS has predefined the class for them
the OS also provides the WndProc for these special control classes
typically, they are used in dialog boxes

you can create them by using CreateWindowEx, just as any other window
but, you do not have to register the class, just use the string 'Static' as the class name

http://msdn.microsoft.com/en-us/library/windows/desktop/bb773173%28v=VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/bb773169%28v=VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/bb760769%28v=VS.85%29.aspx

likewise, you can register your own class and make them any way you like
you then have to provide the WndProc code

once i get my static controls in there, i will be able to constrain the box inside the client
this will be done by using the mouse position when WM_LBUTTONDOWN is received
and by subtracting the complimentary window dimensions from the clip rectange
Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 04:02:43 PM
reading through some of the previous posts, here...

QuoteI guess at this point I had planned on playing this game (learning assembly language forWindows)
my way, by my rules, on my computer. I hadn't envisioned joining a "community"  just yet.

:bg
i look at it this way...
i am in the "learn mode"
once i have learned everything there is to know about windows, i can do it however i like
unfortunately, i probably won't live that long   :P

QuoteI want to be able to position them, resize them (by grabbing their frames), and to put stuff in them
(like text, maybe even bitmaps). So what kind of child windows do I want? I'm starting to suspect
that this will require owner-draw controls to do it properly.

well - we don't want static controls, then
they are meant to be, well, static   :bg
you could almost use an MDI arrangement - a bit clumsy for some of the controls you will want to add
i think if i were doing what you want to do,
i would use a sizable window for each type of control that the user may want to add
that means they will have borders while many of the controls do not
anyways, you put the type of control they ask for inside the sizing window and size the control when they size the window
you could create a class for each control type, each with a special WndProc
they ask for a slider, your "slider-class" WndProc handles all the stuff that is appropriate for a slider
they ask for a button, your "button-class" WndProc handles all the stuff that is appropriate for a button
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 08, 2011, 11:19:59 PM
Just to make things clear (because this thread is starting to get confused, and I'm not sure you really understand what I'm after here, or what my knowledge of assembly language is): are you suggesting that I create these controls as small child windows, like what I have now, but with other controls (text, bitmaps, etc.) inside them? I did want one type to be a static-text control creator (not  a static control in and of itself--get it?) that would allow the user to type text into it.

Currently, the child windows are not static-text windows. (I removed all the static-text stuff when I pulled that font-selection combo box out.)

Again, I need a type of window that:

For now I think I can live with the child window being able to be dragged beneath the status bar; not a huge deal.

I'd really like to get this right from the get-go, both for the sake of my learning, and to get the bugs worked out before I get a big, complicated application going and have to debug it. So it's important that I understand what's going on conceptually, as well as how it's implemented.

I'm almost convinced that this needs to be an owner-draw type of window. Any suggestions in this area appreciated.

I looked through Iczelion's tutorials, but there doesn't seem to be much on this subject specifically. (Bits and pieces here and there.)
Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 11:28:05 PM
yes - i think what you are after is a button that looks like a button
if they ask for an edit box, it looks like an edit box
then, they can size and place them as desired

i have something in works - it only supports buttons and trackbars (sliders)
but, that should be enough to build on by adding the other control types

when they add a slider, it opens a sliderWin
they can size that window however they like
when they do, the slider that is inside it will size with the window (always filling the window)
same for buttons, except it opens a buttonWin

now, let's take buttons as an example
besides the size and location, there are other attributes like text, color, control ID number
you can handle it however you like - i was thinking if they right-click on it, a dialog comes up and lets them set those

Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 11:29:39 PM
i was going to point you at Ketil Olsen's ResEd program, but i am having a hard time finding a link
you might get some ideas from his program

here you go
http://www.oby.ro/rad_asm/resed/index.html
Ketil is a very powerful windows programmer   :U
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 08, 2011, 11:33:54 PM
I'm still not clear what you're suggesting. You're saying make the control a button: is that the containing window? Isn't a button a type of  control?

I thought what you were saying was to create a child window, then put a control (slider, edit control, whatever) inside it. Is that it?

(Regarding your link) Yes, that looks like what I'm after (although I'm thinking of a much more modest program!). It looks like you can download the app for free (which is nice), but not the source. But yes, that's the idea.
Title: Re: Of Mice and Messages
Post by: dedndave on October 08, 2011, 11:45:20 PM
QuoteI thought what you were saying was to create a child window, then
put a control (slider, edit control, whatever) inside it. Is that it?

yes - that's the idea
you could have a right-click context menu, too - they are easy to implement   :P
if they right-click on a button window, it gives them a list of things they can edit for that type of control
just a few thoughts
Title: Re: Of Mice and Messages
Post by: Gunner on October 08, 2011, 11:54:38 PM
The other cool and free Asm IDE is WinASM.  It is now open source, you could DL that and see how they do it. http://www.winasm.net/forum/index.php?showtopic=3713
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 09, 2011, 12:11:52 AM
Dave, I should first say thank you--that was exactly what I was looking for!

OK, I don't have to write this app now; forget everything I said.

Just kidding. I still want to know how to do this. Yes, source is included, but wow: this is one hell of a complicated program.

The controls are EXACTLY what I was looking for. When you create a new control, you get box with the name of the control type (e.g., IDC_CHK) in it, plus a graphic of the control (checkbox, radio button, etc.). When you select the control, you see 9 resize handles, and you can grab it and put it anywhere you want to.

Anyone want to download this and tell me just where this happens in the code? (Hint: I think it's somewhere in the file DlgEdt.asm.)

Anyhow, I'll have fun playing with this and looking through the code.
Title: Re: Of Mice and Messages
Post by: dedndave on October 09, 2011, 12:53:55 AM
oops - wrong thread   :P
Title: Re: Of Mice and Messages
Post by: Gunner on October 09, 2011, 01:02:56 AM
Dave, did you send him the source?  Is he to be trusted to be in our "secret" society  :bdg

I would think it is in CreateCtl but that is as far as I will go.  AFAIK, ResEdit NOR RadASM is open source, so I won't discuss modifying the source here.
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 09, 2011, 01:12:56 AM
Believe me, I have no desire to modify that source! Angels fear to tread and all that.

I'd like to learn how it works, and I might borrow stuff from it for my own code.

So what or where is CreateCtl? Can't find that in any of the .asm files.
Title: Re: Of Mice and Messages
Post by: dedndave on October 09, 2011, 01:15:24 AM
yah - and Ketil's source files are nice to read, too   :P
let me see if i can find his old text editor as an example....

dang - can't find it
Title: Re: Of Mice and Messages
Post by: Gunner on October 09, 2011, 01:16:54 AM
That is why I posted the link to WinASM, it is a similar IDE and became open source recently.
Title: Re: Of Mice and Messages
Post by: dedndave on October 09, 2011, 06:07:07 PM
well, so far, i can make sizable boxes   :P

(http://img525.imageshack.us/img525/3434/re1m.png)

i had to use WS_CLIPSIBLINGS - that may be the problem on your other program
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 09, 2011, 07:40:00 PM
Quote from: dedndave on October 09, 2011, 06:07:07 PM
i had to use WS_CLIPSIBLINGS - that may be the problem on your other program

Well, I tried that, and it didn't fix the problem I'm having.

However: the plot thickens.

Currently my little child windows are resizeable. If I drag one without resizing it, it gets repainted correctly after being drug under the status bar. But if I resize it, then it gets messed up when you do this.

Does this give anyone a clue as to what's going on here?
Title: Re: Of Mice and Messages
Post by: dedndave on October 10, 2011, 12:43:18 AM
i was having problems when creating a new child
the new one was underneath any previously created child (if they overlapped)
instead of using MoveWindow to change the window position, try using SetWindowPos
this function has some flags that allow you to control the Z-order, as well as certain aspects of the redraw process
most notably, a flag for SWP_DRAWFRAME

using SetWindowPos after window creation solved my Z-order problem
i had already tried SetForegroundWindow, SetFocus, SetActiveWindow, EnableWindow   :P

these are the style flags i am using for child windows
WS_CHILD or WS_THICKFRAME or WS_VISIBLE or WS_CLIPSIBLINGS
maybe i am missing one - i would have thought the newly created window would be on top
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 10, 2011, 03:23:36 AM
I tried that (SetWindowPos() instead of MoveWindow()). Interesting: it fixed the border-drawing problem.

But it created a new problem: the text inside the child window isn't redrawn until you release the mouse button. ??????

Further investigation required.

(The flags I used are SWP_DRAWFRAME OR SWP_NOSIZE OR SWP_NOZORDER OR SWP_SHOWWINDOW, since I wasn't changing either the window size or its Z-order.)
Title: Re: Of Mice and Messages
Post by: dedndave on October 10, 2011, 04:18:09 AM
hmmmm - interesting

you might try using HWND_TOP for the hWndInsertAfter parameter
then, play with the uFlags parameter, starting with just the SWP_SHOWWINDOW flag
it sounds as though you have the SWP_NOCOPYBITS flag set, which you do not
maybe the SWP_DRAWFRAME causes it to draw just the frame   :P

i haven't got to the text part yet - lol
i do have boxes that size properly
when you left click on a box (including its sizing border), it comes to the top

i was just working out a strategy for moving the boxes
as far as i can see, there should be no need for DragDetect
when you get a WM_MOUSEMOVE message, bit 0 of wParam tells you if the left button is up or down
if it is up, you simply update the cursor position in the status bar and exit
if it is down, you do that, then move the box, as well
sounds simple enough   :bg
Title: Re: Of Mice and Messages
Post by: dedndave on October 10, 2011, 04:22:02 AM
oh - you might check your display settings - just to make sure...

Display Properties
Appearance tab
Effects button
be sure you have the "Show window contents while dragging" box checked
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 10, 2011, 04:37:07 AM
Quote from: dedndave on October 10, 2011, 04:18:09 AM
you might try using HWND_TOP for the hWndInsertAfter parameter

Tried it, no improvement.

Quotethen, play with the uFlags parameter, starting with just the SWP_SHOWWINDOW flag
it sounds as though you have the SWP_NOCOPYBITS flag set, which you do not
maybe the SWP_DRAWFRAME causes it to draw just the frame   :P

Yep, that flag fixed the no-text problem, but now the messed-up borders are back!

Quoteas far as i can see, there should be no need for DragDetect
when you get a WM_MOUSEMOVE message, bit 0 of wParam tells you if the left button is up or down
if it is up, you simply update the cursor position in the status bar and exit
if it is down, you do that, then move the box, as well
sounds simple enough   :bg

But what if you just click in the window without moving the mouse? I guess no harm, no foul, eh? Although I don't think DragDetect() is my problem.

Quoteoh - you might check your display settings - just to make sure...

Display Properties
Appearance tab
Effects button
be sure you have the "Show window contents while dragging" box checked

In Win2K, it's in the Effects tab, but it's checked in any case.
Title: Re: Of Mice and Messages
Post by: dedndave on October 10, 2011, 04:42:29 AM
well - it was worth a shot   :P
notice that the hWndInsertAfter parameter is only valid without the SWP_NOZORDER flag set
SetWindowPos is like MoveWindow on steroids - lol

tomorrow, i should have a sizable, movable button
i will be able to see how it behaves with text, then
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 10, 2011, 05:54:11 PM
Hey, Dave, wondering if you could do me a flavor: Could you go through the source  for ResEd and find out where the code is that creates controls (like, say, when you add a text control to a dialog)? Whatever is done in there works 100%, so it might be useful to find out just how it's being done.

I've looked through the code, and MEGO. How could you say that that's good code? There's hardly a single comment in it (the only ones I could find were labels when data types were being defined). Since we can't read the author's mind, it's very difficult to figure out what's being done.
Title: Re: Of Mice and Messages
Post by: dedndave on October 10, 2011, 06:20:44 PM
there are a number of programs named "ResEd" and "ResEdit"
are you refering to Ketil's program ?
where did you get the source ?

btw, here are a couple others...
http://www.resedit.net/
http://www.wilsonc.demon.co.uk/d10resourceeditor.htm
the later has source, but it's in Delphi   :P
still, you can see what functions are called
Title: Re: Of Mice and Messages
Post by: NoCforMe on October 10, 2011, 06:34:54 PM
Quote from: dedndave on October 10, 2011, 06:20:44 PM
there are a number of programs named "ResEd" and "ResEdit"
are you refering to Ketil's program ?
where did you get the source ?

It's the one you pointed me to in post #82 (http://www.masm32.com/board/index.php?topic=17487.msg147123#msg147123l). The package includes all the source. (Or I guess I downloaded the source separately, but it's all there.)
Title: Re: Of Mice and Messages
Post by: dedndave on October 10, 2011, 06:47:38 PM
ok - that is Ketil's program
his own site is down, but someone set up a mirror for him (Bogdan, i think)
let me have a look....
Title: Re: Of Mice and Messages
Post by: dedndave on October 10, 2011, 07:09:43 PM
well - a quick glance
what i did was search for files that contain the text "CreateWindowEx"
here is that list...
DlgEdit.asm
FileIO.asm
Project.asm
Property.asm
RAResEd.Asm
RCDataEdit.asm
ResEd.Asm
ToolbarEdit.asm
ToolBox.asm
XPManifestEdit.asm


of course, not all controls are created that way
you may also search for anything with the word "dialog", for example

some of the stuff you want to see may be in his DLL or LIB's, too
Title: Re: Of Mice and Messages
Post by: dedndave on October 10, 2011, 07:13:04 PM
some of the other functions that can create dialogs or controls...
CreateDialog
CreateDialogIndirect
CreateDialogIndirectParam
CreateDialogParam
DialogBox
DialogBoxIndirect
DialogBoxIndirectParam
DialogBoxParam
MessageBox
MessageBoxEx
MessageBoxIndirect

Title: Re: Of Mice and Messages
Post by: NoCforMe on October 10, 2011, 07:26:51 PM
I really do not have the patience to go through 4,400 lines of almost totally uncommented assembly language (DlgEdit.asm) to find out where these controls are created.
Title: Re: Of Mice and Messages
Post by: dedndave on October 10, 2011, 07:42:15 PM
oh - and i do ?   :lol

that particular file isn't so bad
i opened it with Notepad and used Find to locate "CreateWindow"

a coupled popped right up...
.if hCur
invoke CreateWindowEx,0,
addr szStaticClass,0,
WS_CHILD or WS_VISIBLE or SS_WHITERECT or WS_BORDER or SS_NOTIFY,
xP,yP,6,6,
hPar,0,hInstance,0
.else
invoke CreateWindowEx,0,
addr szStaticClass,0,
WS_CHILD or WS_VISIBLE or SS_GRAYRECT or WS_BORDER or SS_NOTIFY or WS_CLIPSIBLINGS or WS_CLIPCHILDREN,
xP,yP,6,6,
hPar,0,hInstance,0
.endif

i would have used a register to hold the style bits, then a single CreateWindowEx in that case   :P
        .if hCur
                mov eax,WS_CHILD or WS_VISIBLE or SS_WHITERECT or WS_BORDER or SS_NOTIFY
        .else
                mov eax,WS_CHILD or WS_VISIBLE or SS_GRAYRECT or WS_BORDER or SS_NOTIFY or WS_CLIPSIBLINGS or WS_CLIPCHILDREN
        .endif
        invoke CreateWindowEx,0,
        addr szStaticClass,0,eax,
        xP,yP,6,6,
        hPar,0,hInstance,0


there are many more lines that use "CreateWindow"

i see he also uses CreateDialogIndirectParam several times in that file
Title: Re: Of Mice and Messages
Post by: qWord on October 10, 2011, 07:45:11 PM
NoCforMe,
what are you exactly trying to do? - what is so hard on creating child controls?
Title: Re: Of Mice and Messages
Post by: dedndave on October 11, 2011, 12:43:25 AM
i didn't get much time to play, today - back to it tomorrow   :P
Title: Re: Of Mice and Messages
Post by: dedndave on October 11, 2011, 10:27:39 PM
my move window code seems to have a bug - well, at least one   :bg
my head hurts - lol
i am going to set it aside for the moment and put together a "display messages" window
that should go better
Title: Re: Of Mice and Messages
Post by: dedndave on October 12, 2011, 04:52:53 PM
ok - i got one bug fixed - the main one
for window move, however, you must move slowly - lol
i know what is happening and how to fix it
the mouse gets outside the child window before the window move happens
then, that proc no longer gets WM_MOUSEMOVE messages
but, i thought you might like to play with what i have so far....