News:

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

Main Menu

Message loop in masm64

Started by greenozon, November 22, 2022, 12:45:47 AM

Previous topic - Next topic

greenozon

A question regarding message loop

in masm32 one could write the following one:

    .WHILE TRUE
                invoke GetMessage, ADDR msg,NULL,0,0
                .BREAK .IF (!eax)
                invoke TranslateMessage, ADDR msg
                invoke DispatchMessage, ADDR msg
    .ENDW

but it doesn't compile in masm64

any hints why?

BugCatcher


greenozon

ml64  complains on this piece of code

.BREAK .IF (!eax)

C3

Hi greenozon,

I'll answer your both questions, this is how I use .while/.endw and how I have implemented message-loop:


    .while TRUE
        invoke GetMessage,ADDR msg,NULL,0,0
        .break .if (rax==0)
        invoke TranslateAccelerator,hwnd,hAccel,ADDR msg
        .if (rax==0)
            invoke TranslateMessage,ADDR msg
            invoke DispatchMessage,ADDR msg
        .endif
    .endw


I think you have problem with the macros, use lowercase for .while and .endw

greenozon

Excellent info!
thanks a lot

PS in case my app does not have accelerators - I guess the block of TranslateAccelerator might be omitted..

C3

Yes, you don't need TranslateAccelerator unless you someday want to add Accelerator Resource to your Window. Just remove pieces that are not useful.

C3

Reading thru the MASM64 Examples (awesome content)..
There is a other view of how to build MSG loop.


msgloop proc

    LOCAL msg   :MSG
    LOCAL pmsg  :QWORD
    LOCAL .r15  :QWORD
    LOCAL .r14  :QWORD

    mov .r15, r15
    mov .r14, r14

    lea r15, msg                                    ; load msg address into r15
    xor r14, r14                                    ; set r14 to zero

    jmp gmsg                                        ; jump directly to GetMessage()

  mloop:
    rcall TranslateMessage,r15
    rcall DispatchMessage,r15
  gmsg:
    test rax, rvcall(GetMessage,r15,r14,r14,r14)    ; loop until GetMessage returns zero
    jnz mloop

  mquit:
    mov r15, .r15
    mov r14, .r14

    ret

msgloop endp


Assembly is awsome, you can build things so many way. Thank you for this! Mine example were bit like C-syntax loop.

Caché GB

This works for me.

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

WinMainW proc public

     local  wMsg:MSG

            add  rsp,-28h
            and  rsp,-10h

         FNINIT

         invoke  GetModuleHandle, null
            mov  hInstance, rax

         invoke  InitializeWindow

         invoke  RtlZeroMemory, &wMsg, sizeof(MSG)
            mov  rax, g_hwnd
            mov  wMsg.hwnd, rax

        MsgLoop:

         invoke  GetMessage, &wMsg, null, 0, 0
             or  eax, eax
             je  short  MainExit
         invoke  TranslateMessage, &wMsg
         invoke  DispatchMessage, &wMsg
            jmp  short MsgLoop
 
       MainExit:

            mov  rcx, null
           call  ExitProcess

            ret

WinMainW endp

;#############################################################################################################
Caché GB's 1 and 0-nly language:MASM

jj2007

There are several variants to code a message loop. Most do not care for...
a) CreateWindowEx failure (which means you have a zombie running)
b) GetMessage error:
QuoteIf the function retrieves the WM_QUIT message, the return value is zero.
If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle

Here is a fool-proof variant:
  invoke RegisterClassEx, rbx ; the window class needs to be registered
  wsStyle=WS_OVERLAPPEDWINDOW or WS_VISIBLE or WS_CLIPCHILDREN
  invoke CreateWindowEx, 0, wc.lpszClassName, Chr$("Hello World"), wsStyle, 600, 127, 300, 200, NULL,\
rv(LoadMenu, wc.hInstance, 100), wc.hInstance, NULL

msgLoop: inc eax
shr eax, 1
je @F ; quit if GetMessage returned 0 (exit OK) or -1 (error), or if CwEx failed
  invoke TranslateMessage, addr msg ; translates virtual-key messages into character messages
invoke DispatchMessage, addr msg ; dispatches a message to a window procedure
invoke GetMessage, addr msg, 0, 0, 0 ; retrieve a message from the queue, and return a BOOL
  jmp msgLoop
@@: invoke ExitProcess, msg.wParam

hutch--

Minimal, authodox, reliable.

msgloop proc

    LOCAL msg    :MSG
    LOCAL pmsg   :QWORD

    mov pmsg, ptr$(msg)                     ; get the msg structure address
    jmp gmsg                                ; jump directly to GetMessage()

  mloop:
    rcall TranslateMessage,pmsg
    rcall DispatchMessage,pmsg
  gmsg:
    test rax, rvcall(GetMessage,pmsg,0,0,0) ; loop until GetMessage returns zero
    jnz mloop

    ret

msgloop endp

jj2007

Quote from: hutch-- on December 19, 2022, 01:50:40 PMtest rax, rvcall(GetMessage,pmsg,0,0,0) ; loop until GetMessage returns zero
    jnz mloop

Quote from: jj2007 on December 19, 2022, 12:05:11 PM
GetMessage:
If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle

\Masm64\Examples\Simple\progress_win\progress.asm
    mov classname, "x" ; create an error in line 100
    invoke CreateWindowEx,WS_EX_LEFT or WS_EX_ACCEPTFILES, \


And, voilà, you have a zombie - check your Task Manager :tongue:

RichMasm:
Quote\Masm64\Examples\Simple\progress_win\progress.exe
(ID 11252) is running or open in debugger
Try to kill it?

hutch--

> If there is an error ........

Don't make errors.  :icon_idea: