News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Win32 My First Window

Started by tda0626, April 24, 2024, 11:05:19 AM

Previous topic - Next topic

zedd151

#15
Quote from: tda0626 on April 25, 2024, 10:20:46 AM@sudoku Updated source file added to original post
Change your WM_DESTROY to WM_CLOSE... that should do it.
Never mind. That was incorrect. Something else is wrong.

NoCforMe

Quote from: tda0626 on April 25, 2024, 10:20:46 AMExactly. Once I get the basics of creating a window out of the way, I can just make a default window and pass parameters to it.

Wellll, not quite: you don't really "pass parameters" to a window. Windows does that for you (the standard "window procedure" is <proc name> hWin, uMsg, wParam, lParam). Windows passes the "parameters" to you. Remember, Windows is a message-driven (or event-driven) OS.

What you do is populate your window with other windows, generally Windows "controls":
  • Static control: displays text
  • Button control: Buttons in several flavors (pushbutton, radio button, checkbox button)
  • Edit control: A window that accepts user input typed into it
  • Listbox control: A box that displays rows of items (text) that can be selected by the user

There are lots more kinds of controls. You would create these as "child windows" of your main window, with the main window as the "parent".

And your window can respond to lots of different events, like the mouse being moved, clicked or double-clicked, keystrokes entered, files being dragged and dropped over the window, lots more.

Oh, and don't forget menus. You can add a menu bar to your window and put all kinds of items in it.

I think you've got a lot of fun ahead of you here.
Assembly language programming should be fun. That's why I do it.

tda0626

Quote from: sudoku on April 25, 2024, 10:23:55 AM
Quote from: tda0626 on April 25, 2024, 10:20:46 AM@sudoku Updated source file added to original post
Change your WM_DESTROY to WM_CLOSE... that should do it.

Yep that did it! Thanks! So happy right now! YAY!  :eusa_dance:

zedd151

#18
Quote from: tda0626 on April 25, 2024, 10:44:35 AMYep that did it! Thanks! So happy right now! YAY!  :eusa_dance:
:thumbsup:

I think you will do fine.
Now you need to do something a little more interesting with it. :smiley:

added later...
While that may have worked once or twice,, it is not a valid fix for your code.
An error on my part.

zedd151

I noticed in your new attachment
greeting db "Hello There!"

You need to terminate that string with a zero. Like so...
greeting db "Hello There!", 0

NoCforMe

If you use my skeleton code, or at least the parts of it that create a status bar at the bottom of the window, you can use the following to display messages there without forcing the user to respond to them as MessageBox() does:

INVOKE  SendMessage, StatusHandle, SB_SETTEXT, 0, <text ptr.>
where "<text ptr.>" is a pointer to the text you want to show (which as Sudoku pointed out must be terminated by a zero--it's known as "ASCIIZ" text, for "ASCII terminated with a zero byte").
Assembly language programming should be fun. That's why I do it.

zedd151

#21
At least one of my initial assumptions in the original post here was incorrect.

Upon executing your program in windows 7, the 'busy' cursor is showing, when the arrow cursor should be showing. Something else is amiss that is not obvious at first glance.

I will let the assembly code experts here help you figure out what is causing that effect.

Regarding your use of push/call syntax:

Once you start coding more projects, you might find that using the 'invoke' style of procedure calls is a bit easier. It uses prototypes to aid in detecting the correct number of arguments (will not assemble if incorrect number of arguments), for instance.


Take a look through the examples folder in the masm32 directory. Especially \masm32\examples\exampl01\minimum\minimum.asm (it gives an example of push/call versus 'invoke' style of calling procedures)
Here (its a short code, so I'll post it here)
; #########################################################################

      .386
      .model flat, stdcall
      option casemap :none   ; case sensitive

; #########################################################################

      include \masm32\include\windows.inc
      include \masm32\include\user32.inc
      include \masm32\include\kernel32.inc

      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\kernel32.lib

; #########################################################################

    .code

start:

    jmp @F
      szDlgTitle    db "Minimum MASM",0
      szMsg         db "  --- Assembler Pure and Simple ---  ",0
    @@:

    push MB_OK
    push offset szDlgTitle
    push offset szMsg
    push 0
    call MessageBox

    push 0
    call ExitProcess

    ; --------------------------------------------------------
    ; The following are the same function calls using MASM
    ; "invoke" syntax. It is clearer code, it is type checked
    ; against a function prototype and it is less error prone.
    ; --------------------------------------------------------

    ; invoke MessageBox,0,ADDR szMsg,ADDR szDlgTitle,MB_OK
    ; invoke ExitProcess,0

end start

Most members here use the 'invoke' style. Of course, you can always use what you feel more comfortable with.

jj2007

Quote from: tda0626 on April 25, 2024, 08:59:14 AMafter closing the window, it is still showing up in my process list and I have to force close it

It took me a while to find out why. Actually, it has nothing to do with your WM_DESTROY handler - that one is correct, you don't need a WM_CLOSE handler. But your simple...
    call GetMessage
    .break .if !eax
... has a flaw: it doesn't care for errors. Use this message loop, which breaks if GetMessage returns zero or -1. The latter, if not handled, creates the "zombie" that can be killed only via Task Manager. At least, that was what I saw once in the debugger.

Here is a foolproof message loop:

  .While 1
    invoke GetMessage, addr msg, 0, 0, 0
    inc eax
    shr eax, 1
    .Break .if Zero?    ; 0 (OK) or -1 (error)
    invoke TranslateMessage, addr msg
    invoke DispatchMessage, addr msg
  .Endw

P.S.:
Quote from: jj2007 on April 24, 2024, 04:27:10 PMhave a look at this template (93 lines, with a menu, an edit control and a WM_PAINT handler)

TimoVJL

I have used simple message loop about 25 years
while (GetMessage(&msg, NULL, 0, 0)) {
 TranslateMessage(&msg);
 DispatchMessage(&msg);
}
so, why bother that -1 thing, as if it occurs, there might be programming error.
Perhaps someone show an example of that -1 error.

When will GetMessage return -1?
May the source be with you

NoCforMe

Timo, can you please post in assembly language here?
Assembly language programming should be fun. That's why I do it.

sinsi

jj has it right.
push 0
push 0
push hwnd ;<<<<<<<< bad idea,just pass 0
lea eax, msg
push eax
call GetMessage
The dangers of filtering window messages

NoCforMe

Or better yet:
INVOKE GetMessage, ADDR msg, NULL, 0, 0

(same as above, just not push-push-call)
Assembly language programming should be fun. That's why I do it.

jj2007

Here is my personal message loop, merciless optimised for size:

  lea edi, msg
  .While 1
xor eax, eax
invoke GetMessage, edi, eax, eax, eax
inc eax
shr eax, 1
.Break .if Zero? ; 0 (OK) or -1 (error)
invoke TranslateMessage, edi
invoke DispatchMessage, edi
  .Endw

TimoVJL

Quote from: NoCforMe on April 26, 2024, 02:37:49 AMTimo, can you please post in assembly language here?
why not both
1: #define WIN32_LEAN_AND_MEAN
2: #include <windows.h>
3: MSG msg;
4: void __cdecl WinMainCRTStartup(void)

_WinMainCRTStartup:
  [00000000] 55                    push              ebp
  [00000001] 89E5                  mov              ebp,esp
  [00000003] EB16                  jmp              0000001B
5: {
6:    //MSG msg;
7:    while (GetMessage(&msg, NULL, 0, 0)) {
8:      TranslateMessage(&msg);
  [00000005] 6800000000            push              _msg
  [0000000A] FF1500000000          call              dword ptr [__imp__TranslateMessage@4]
9:      DispatchMessage(&msg);
  [00000010] 6800000000            push              _msg
  [00000015] FF1500000000          call              dword ptr [__imp__DispatchMessageA@4]
  [0000001B] 6A00                  push              0
  [0000001D] 6A00                  push              0
  [0000001F] 6A00                  push              0
  [00000021] 6800000000            push              _msg
  [00000026] FF1500000000          call              dword ptr [__imp__GetMessageA@16]
  [0000002C] 85C0                  test              eax,eax
  [0000002E] 75D5                  jne              00000005
10:    }
11:    ExitProcess(0);
  [00000030] 6A00                  push              0
  [00000032] FF1500000000          call              dword ptr [__imp__ExitProcess@4]
  [00000038] 0F0B                  ud2             
  [0000003A] 89EC                  mov              esp,ebp
  [0000003C] 5D                    pop              ebp
  [0000003D] C3                    ret             
1: #define WIN32_LEAN_AND_MEAN
2: #include <windows.h>
3: MSG msg;
4: void __cdecl WinMainCRTStartup(void)

WinMainCRTStartup:
  [0000000000000000] 4883EC28                     sub               rsp,28
  [0000000000000004] EB24                         jmp               000000000000002A
  [0000000000000006] 90                           nop               
  [0000000000000007] 660F1F840000000000           nop               [rax+rax+0]
5: {
6: //MSG msg;
7: while (GetMessage(&msg, NULL, 0, 0)) {
8: TranslateMessage(&msg);
  [0000000000000010] 488D0D00000000               lea               rcx,[msg]
  [0000000000000017] FF1500000000                 call              qword ptr [__imp_TranslateMessage]
9: DispatchMessage(&msg);
  [000000000000001D] 488D0D00000000               lea               rcx,[msg]
  [0000000000000024] FF1500000000                 call              qword ptr [__imp_DispatchMessageA]
  [000000000000002A] 488D0D00000000               lea               rcx,[msg]
  [0000000000000031] 31D2                         xor               edx,edx
  [0000000000000033] 4531C0                       xor               r8d,r8d
  [0000000000000036] 4531C9                       xor               r9d,r9d
  [0000000000000039] FF1500000000                 call              qword ptr [__imp_GetMessageA]
  [000000000000003F] 85C0                         test              eax,eax
  [0000000000000041] 75CD                         jne               0000000000000010
10: }
11: ExitProcess(0);
  [0000000000000043] 31C9                         xor               ecx,ecx
  [0000000000000045] FF1500000000                 call              qword ptr [__imp_ExitProcess]
  [000000000000004B] 0F0B                         ud2               
  [000000000000004D] 4883C428                     add               rsp,28
  [0000000000000051] C3                           ret               
May the source be with you

NoCforMe

Nice try, but what you posted is disassembly, not assembly.
Don't you ever write assembly language yourself? Or only C?
Assembly language programming should be fun. That's why I do it.