News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Of Mice and Messages

Started by NoCforMe, October 04, 2011, 07:36:55 PM

Previous topic - Next topic

jj2007

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...

NoCforMe

Hey, what can I say? I don't like to be like everyone else. (I'm a 'Merkin, after all.)

dedndave

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

jj2007

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, 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

NoCforMe

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?

dedndave

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

jj2007

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

dedndave

 :lol
i see Jochen is in a good mood, today   :P

NoCforMe

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.

NoCforMe

#39
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!)

qWord

[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]
FPU in a trice: SmplMath
It's that simple!

NoCforMe

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.

NoCforMe

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.

dedndave

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

NoCforMe

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.