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?
Read masm64 help file. .WHILE
ml64 complains on this piece of code
.BREAK .IF (!eax)
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
Excellent info!
thanks a lot
PS in case my app does not have accelerators - I guess the block of TranslateAccelerator might be omitted..
Yes, you don't need TranslateAccelerator unless you someday want to add Accelerator Resource to your Window. Just remove pieces that are not useful.
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.
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
;#############################################################################################################
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 (https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessage):
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
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
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 (https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-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?
> If there is an error ........
Don't make errors. :icon_idea: