Hello.
When you use getmessage, it waits until a message is available, and then you naturally dispatch the message to the windows message handler function which you passed in the structure when you registered the window.
My question is why do we need such a function when you can handle the messages in a messageloop directly, using peekmessage? I don't get it why this function is so important. I find myself handling some important messages just beneath the peekmessage call and the rest in the callback function, it seems rather messy. Can anyone explain the purpose of that callback function?
EDIT: I think I got the answer with a little bit of thinking. Perhaps its important to get messages right there when they are available? Important messages may need instant handling? (But then again, thats nothing you cant do in a loop or just beneath getmessage or peekmessage)
Would it work if you didnt mention lpfnWndProc in WNDCLASSEX? Well, i think you'll need to accept the fact that windows is designed this way. I'm with you all the way i think. It's not a very programmer friendly platform, but hey, there's even more confusing things than that. So bare with it.
Courage zemtex.
Bye
Raymond Chen has a number of blog entries detailing the common mistakes that programmers make in their message loops (http://blogs.msdn.com/b/oldnewthing/archive/2005/04.aspx?PageIndex=1). It's a two page monthly listing,... you have to scroll through the stuff that doesn't apply.
The MSDN page that explains Using Messages and Message Queues (http://msdn.microsoft.com/en-us/library/ms644928) also has lots of information.
Quote from: MSDNYou can use the PeekMessage function to examine a message queue during a lengthy operation. PeekMessage is similar to the GetMessage function; both check a message queue for a message that matches the filter criteria and then copy the message to an MSG structure. The main difference between the two functions is that GetMessage does not return until a message matching the filter criteria is placed in the queue, whereas PeekMessage returns immediately regardless of whether a message is in the queue.
Message queues are associated with a particular thread, and a particular thread may create any number of Windows. With your method, it would require parsing the returned message to figure out which window it was destined for, and then having logic within each message type for each window; a programming nightmare. For example
PeekMessage()
if message = Click
if Window = a
Do_Something_on_Window_A
if Window = b
Do_Something_on_Window_B
if message = Key
if Window = a
Do_Something_Else_on_Window_A
if Window = b
Do_Something_Else_on_Window_B
Now scale that to 50, and you can see the problem. With the current way, each window has it's own, encapsulated procedure, and only has to worry about messages destined for it.
-r
zemtex,
Congratulations about "non-standard" thinking but it is very old "invention" (see the link) :green
redskull is right about different windows but don't worry
coz you will not use two slow API's - TranslateMessage and DispatchMessage
and you have a lot of time in the main loop to create the logic about each message type for each window...
It is not mandatory to have main AND callback functions too.
So, you can work with EBX,EBP,ESI and EDI registers without preservation too,
coz you have main proc only (and it is not a callback proc).
I just did a copy of the old example from link (http://www.asmcommunity.net/board/index.php?topic=5702.30) :U
.386 ; minimum processor needed for 32 bit
.model flat, stdcall ; FLAT memory model & STDCALL calling
option casemap :none ; set code to case sensitive
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\gdi32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\kernel32.lib
.data
szDisplayName db "Test",0
szClassName db "Test_Class",0
szTest db "I don't want to feel guilty if my programs"
db " don't start with :",13,10
db " Start:",13,10
db " invoke GetModuleHandle,NULL",10,13
db " mov hInstance, eax",10,13
db " invoke WinMain,eax,0,0,0",10,13
db " invoke ExitProcess,eax",10,13
db " END Start",0
szConfirm db "Please Confirm Exit",0
wc WNDCLASSEX <sizeof WNDCLASSEX, CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW, \
offset WndProc, 0, 0,0,0,0,COLOR_WINDOW +1, 0, szClassName, 0>
.data?
hWnd dd ?
dStack dd ?
ps PAINTSTRUCT <?>
rect RECT <?>
.code
start:
mov esi, 0FFFF0000h
mov dStack, esp ; save the stack
and esi, $ ; esi->instance handle
invoke LoadIcon, 0, IDI_APPLICATION
mov wc.hIcon, eax
invoke LoadCursor, 0,IDC_ARROW
mov wc.hCursor, eax
mov wc.hInstance, esi ; esi->instance handle
invoke RegisterClassEx, addr wc
invoke CreateWindowEx, WS_EX_OVERLAPPEDWINDOW,
addr szClassName,
addr szDisplayName,
WS_OVERLAPPEDWINDOW or WS_VISIBLE,
100,100,500,350,
0, 0, esi, 0 ; esi->instance handle
;...............................................;
WndProc:
cmp esp, dStack
je WinGetMessage
WinMain:
mov eax, [esp+2*4] ; eax->uMsg
mov esi, [esp+1*4] ; esi->hwnd
cmp eax,WM_CLOSE
je OnDestroy
cmp eax, WM_PAINT
je OnPaint
cmp eax, WM_CREATE
jne DefWindowProc ; call API
;...................................................................;
OnCreate:
mov hWnd, esi
jmp DefWindowProc
;...................................................................;
OnPaint:
invoke BeginPaint, esi, ADDR ps
mov edi, eax ; edi->hDC
invoke GetClientRect, esi, addr rect
invoke DrawText, edi, addr szTest,-1,\ ; edi->hDC
addr rect, DT_VCENTER
invoke EndPaint, esi, addr ps
jmp DefWindowProc ; call API
;...................................................................;
OnDestroy:
invoke MessageBox, esi, \
addr szConfirm, \
addr szDisplayName,\
MB_YESNO
cmp eax, IDNO
jne ExitProcess ; Exit
;...................................................................;
mov esp, dStack
WinGetMessage:
lea eax, [esp-4*4]
mov [esp-5*4], offset WndProc ; return address -> WndProc
mov dword ptr [esp-6*4], 0 ; zeros are parameters
mov dword ptr [esp-7*4], 0 ; of GetMessage
mov dword ptr [esp-8*4], 0
mov [esp-9*4], eax ; eax-> offset MSG struct
mov [esp-10*4], offset WinMain ; return-> WinMain
sub esp, 10*4
jmp GetMessage ; call API
;...................................................................;
end start
Anyway, I always use GetQueueStatus for quick hint if there is messages available before i pass the execution to the slow (5 push) peekmessage function. GetQueueStatus only has 1 push and it checks a few flags. If the message loop runs 1 million times in 10 ms, that means peekmessage is pushing and popping 5 million times (Thats alot of memory reading) Microsoft SDK also mentions that getqueuestatus is the fastest possible way to check if there are available messages.
zemtex,
you are worrying about about some push's while calling API-functions that end up in an syscall :P
Quote from: qWord on September 05, 2010, 11:03:50 AM
zemtex,
you are worrying about about some push's while calling API-functions that end up in an syscall :P
Microsoft says its faster, you reduce overhead in the message loop. if you produce inputs, one every 50,000 iterations, lets say by a keystroke, you would have avvoided peekmessage for 50,000 iterations. peekmessage pushes 20 bytes of data per iteration and performs a long execution afterwards to filter messages, remove unwanted messages, fill inn the msg structure. When you use getqueuestatus you push 4 bytes of data and the system checks a few flags and returns. Thats much faster.
Syscall or no syscall. If the syscall have a delay of 10 ms, that doesnt matter because you would have to substitute the delay of the message function and you get a lower overhead no matter how intensive the syscall is. This is simple math. :U
Quote from: zemtex on September 06, 2010, 10:55:19 AM
Microsoft says its faster, you reduce overhead in the message loop. if you produce inputs, one every 50,000 iterations, lets say by a keystroke, you would have avvoided peekmessage for 50,000 iterations. peekmessage pushes 20 bytes of data per iteration and performs a long execution afterwards to filter messages, remove unwanted messages, fill inn the msg structure. When you use getqueuestatus you push 4 bytes of data and the system checks a few flags and returns. Thats much faster.
Syscall or no syscall. If the syscall have a delay of 10 ms, that doesnt matter because you would have to substitute the delay of the message function and you get a lower overhead no matter how intensive the syscall is. This is simple math. :U
I was going to point out that when there are messages a message loop that calls GetQueueStatus and PeekMessage actually has higher overhead, but now that I test, at least on my Windows 2000 system GetQueueStatus is much slower than PeekMessage even when there are no messages. Specifically, a million loops of the message loop took ~1140ms when the loop called GetQueueStatus(QS_ALLINPUT), or ~140ms when it did not.
;==============================================================================
; Build as a console app.
;==============================================================================
;----------------------------------------------------------------------------
; This macro more or less duplicates the functionality of the BASIC language
; TIMER function, returning the elapsed seconds since the system was started
; as a floating-point value at the top of the FPU stack. The elapsed seconds
; are derived from the high-resolution performance counter, so the effective
; resolution is on the order of a few microseconds.
;----------------------------------------------------------------------------
timer MACRO
IFNDEF _timer_pc_frequency_
.data
align 8
_timer_pc_frequency_ dq 0
_timer_pc_count_ dq 0
_timer_elapsed_seconds_ dq 0
_timer_initialized_ dd 0
.code
ENDIF
.IF _timer_initialized_ == 0
invoke QueryPerformanceFrequency, ADDR _timer_pc_frequency_
inc _timer_initialized_
.ENDIF
invoke QueryPerformanceCounter, ADDR _timer_pc_count_
fild _timer_pc_count_
fild _timer_pc_frequency_
fdiv
fstp _timer_elapsed_seconds_
EXITM <_timer_elapsed_seconds_>
ENDM
;==============================================================================
include \masm32\include\masm32rt.inc
;==============================================================================
.data
hInstance dd 0
hDlg dd 0
loopcount dd 0
pmcount dd 0
gqscount dd 0
time REAL8 ?
seconds REAL8 ?
msg MSG <>
.code
;==============================================================================
DialogProc proc hwndDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
SWITCH uMsg
CASE WM_CLOSE
invoke DestroyWindow, hwndDlg
CASE WM_DESTROY
invoke PostQuitMessage, NULL
ENDSW
xor eax, eax
ret
DialogProc endp
;==============================================================================
start:
;==============================================================================
invoke GetModuleHandle, NULL
mov hInstance, eax
Dialog 0, \
"FixedSys",11, \
WS_VISIBLE or WS_OVERLAPPED or WS_SYSMENU or DS_CENTER, \
0, \
0,0,50,40, \
1024
CallModelessDialog hInstance, 0, DialogProc, NULL
mov hDlg, eax
fld timer()
fstp time
msgLoop:
inc loopcount
.IF loopcount > 1000000
;--------------------------------------------------------
; Calc and display the elapsed seconds for 1000000loops,
; along with the message counts.
;--------------------------------------------------------
fld time
fld timer()
fst time
fsubr
fstp seconds
invoke crt_printf, cfm$("%f\t%d\t%d\n"), seconds, pmcount, gqscount
mov loopcount, 0
mov pmcount, 0
mov gqscount, 0
.ENDIF
IncludeGetQueueStatus equ 1
IFDEF IncludeGetQueueStatus
invoke GetQueueStatus, QS_ALLINPUT
.IF eax
inc gqscount
ENDIF
invoke PeekMessage, ADDR msg, NULL, 0, 0, PM_REMOVE
.IF eax != 0
inc pmcount
.IF msg.message == WM_QUIT
invoke ExitProcess, 0
.ENDIF
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDIF
IFDEF IncludeGetQueueStatus
.ENDIF
ENDIF
jmp msgLoop
;==============================================================================
end start
Quote from: MichaelW on September 06, 2010, 06:16:35 PM
I was going to point out that when there are messages a message loop that calls GetQueueStatus and PeekMessage actually has higher overhead, but now that I test, at least on my Windows 2000 system GetQueueStatus is much slower than PeekMessage even when there are no messages. Specifically, a million loops of the message loop took ~1140ms when the loop called GetQueueStatus(QS_ALLINPUT), or ~140ms when it did not.
All I can say is microsofts own words: "GetQueueStatus returns an array of flags that indicates the types of messages in the queue; using it is the fastest way to discover whether the queue contains any messages."
And also, keep in mind that if your message queue is always filled up, you are basically running getqueuestatus and peekmessage both at the same time per message. The getqueuestatus is really only fastest if it is used a single time or if there are few messages available. You have to weight it and see which option is better based on what program you have.
If your program is always having messages it just might be that you would do better with dropping getqueuestatus entirely. :U
EDIT: It might be that what microsoft means by "fastest way" is that its the most easy function call to "USE", and that its not actualyl the fastest in execution. I can't really tell. The timing was interesting though. Try to run it a few more times and see if it is consistent.
Test it. The speed difference exists whether there are messages or not. Unless I intentionally trigger messages by pressing keys when the window has the focus, moving the mouse within the window, moving the window, etc, then there are no messages. I would be interested to see the timings for Windows XP and later.
Windows XP:
IncludeGetQueueStatus equ 1
0.282236 14 1
0.284462 21 2
0.291163 11 1
0.281626 0 0
0.276215 0 0
0.271831 0 0
0.285561 0 0
0.275448 0 0
0.277165 0 0
0.275120 0 0
0.281987 0 0
0.277742 0 0
0.279168 0 0
0.282788 0 0
0.274141 0 0
IncludeGetQueueStatus equ 0
0.297155 10 11
0.269335 24 24
0.280158 12 12
0.258623 0 0
0.260007 0 0
0.253857 0 0
0.267360 0 0
0.271125 0 0
0.252812 0 0
0.265616 0 0
0.271749 0 0
0.255088 0 0
0.260941 0 0
0.260837 0 0
0.271073 0 0
On my computer with Windows 7 the getqueuestatus runs with numbers like 0.22 most of the time, and peekmessage runs with 0.23-24 most of the time when there is 0 messages available in the queue.
When there was the same amount messages available, getqueuestatus ran with 0.231 and peekmessage run slightly slower at 0.239
I DONT KNOW GUYS, what do you think. Should this method be expelled or what? You guys deside. :cheekygreen:
I see now that I should have used a different way of controlling the conditional assembly. Because I'm testing with IFDEF, the GetQueueStatus code will be included if IncludeGetQueueStatus is defined, whatever the value assigned to it. I intended that the entire statement be commented out to remove the GetQueueStatus code. To use it the way that my equate value suggests it should be used, the:
IFDEF IncludeGetQueueStatus
statement should be:
IF IncludeGetQueueStatus EQ 1
You would also have to remove peekmessage to time both of them individually. You include peekmessage when getqueuestatus runs. You increase gqscount but the incresage will be wrong because it waits until peekmessage increases too, the timing will be wrong.
Quote from: MichaelW on September 06, 2010, 08:00:28 PM
I see now that I should have used a different way of controlling the conditional assembly.
:lol I thought I saw a bug in my interpretation but I couldnt find it
Quote from: zemtex on September 06, 2010, 08:19:46 PM
You would also have to remove peekmessage to time both of them individually. You include peekmessage when getqueuestatus runs. You increase gqscount but the incresage will be wrong because it waits until peekmessage increases too, the timing will be wrong.
This only happens a maximum of 20/100,000 times it wont addmuch weight to the result
My new results (commenting instead of 0ing) are much different.... When commented my results are....
0.048902 34 0
0.031764 0 0
0.057923 11 0
0.053695 0 0
0.030719 0 0
0.028572 0 0
0.034822 1 0
0.030796 0 0
0.028341 0 0
0.027664 0 0
0.040897 0 0
0.027688 0 0
0.027359 0 0
0.029990 0 0
0.035721 0 0
(10 times faster without GetQueueStatus)
Quote from: zemtex on September 06, 2010, 07:28:27 PM
Should this method be expelled or what? You guys deside. :cheekygreen:
The better question is why use a non-blocking version in the first place? Unless you are writing something like a game that must "run all the time", spinning your wheels checking for non-existant messages is a waste of the CPU.
-r
Quote from: zemtex on September 06, 2010, 08:19:46 PM
You would also have to remove peekmessage to time both of them individually. You include peekmessage when getqueuestatus runs. You increase gqscount but the incresage will be wrong because it waits until peekmessage increases too, the timing will be wrong.
What would be the point of timing GetQueueStatus separately, when it is not intended for freestanding use? I was attempting to time what I thought you were describing, and expecting different results than what I got. On my system the combination of GetQueueStatus and PeekMessage is ~8 times slower than PeekMessage alone. I use gqscount to track the number of times per timed interval that GetQueueStatus indicates one or more messages in the queue, and pmcount to track the number of times per timed interval that PeekMessage returns a message. Neither of these values have anything to do with the computation of the timed interval.
Quote from: MichaelW on September 06, 2010, 08:47:02 PM
What would be the point of timing GetQueueStatus separately, when it is not intended for freestanding use?
If you are timing (A+B) against (A) then there is no point to remove it. However, if you intend to use getqueuestatus to run 100,000 times when there are no messages, it is relevant because you would be stuck with no messages for 100,000 iterations. :wink
Quote from: redskull on September 06, 2010, 08:41:48 PM
The better question is why use a non-blocking version in the first place? Unless you are writing something like a game that must "run all the time", spinning your wheels checking for non-existant messages is a waste of the CPU.
Yes, the difference in CPU utilization is large. If I comment out the display code to prevent it from further loading the CPU, I get essentially a 100% utilization for the non-blocking loop, and 0 to ~10% utilization (depending on the number of messages being queued) for the blocking loop.
Quote from: MichaelW on September 06, 2010, 09:00:42 PM
Quote from: redskull on September 06, 2010, 08:41:48 PM
The better question is why use a non-blocking version in the first place? Unless you are writing something like a game that must "run all the time", spinning your wheels checking for non-existant messages is a waste of the CPU.
Yes, the difference in CPU utilization is large. If I comment out the display code to prevent it from further loading the CPU, I get essentially a 100% utilization for the non-blocking loop, and 0 to ~10% utilization (depending on the number of messages being queued) for the blocking loop.
May I also suggest you dont use PM_REMOVE as when getqueuestatus runs, it doesnt remove the messages, but it does in peekmessage. When you're done, report the numbers back to me again :U
Quote from: zemtex on September 06, 2010, 08:55:33 PM
If you are timing (A+B) against (A) then there is no point to remove it. However, if you intend to use getqueuestatus to run 100,000 times when there are no messages, it is relevant because you would be stuck with no messages for 100,000 iterations. :wink
PeekMessage and everything below it runs only if GetQueueStatus returns non-zero, so in the absence of messages GetQueueStatus is being called a million times per timed interval, and PeekMessage is being called zero times. If I comment out the PeekMessage call and the IF block below it, there is essentially no change in the timings. Your idea of using GetQueueStatus to test for messages was good, but it turns out that GetQueueStatus is just too slow to be useful for this.
Quote from: MichaelW on September 06, 2010, 09:17:39 PM
Quote from: zemtex on September 06, 2010, 08:55:33 PM
If you are timing (A+B) against (A) then there is no point to remove it. However, if you intend to use getqueuestatus to run 100,000 times when there are no messages, it is relevant because you would be stuck with no messages for 100,000 iterations. :wink
PeekMessage and everything below it runs only if GetQueueStatus returns non-zero, so in the absence of messages GetQueueStatus is being called a million times per timed interval, and PeekMessage is being called zero times. If I comment out the PeekMessage call and the IF block below it, there is essentially no change in the timings. Your idea of using GetQueueStatus to test for messages was good, but it turns out that GetQueueStatus is just too slow to be useful for this.
Replace PM_REMOVE with PM_NOREMOVE and report the numbers back to me again :U
Change 2 I want you to do as well: Run the peekmessage in a while loop until the message buffer is emptied.
Quote
Replace PM_REMOVE with PM_NOREMOVE and report the numbers back to me again :U
I had already tested that and there was no change in the timings that I could see, but it's not really meaningful because then you have a non-functional message loop. For the blocking loop in my test above I used GetMessage.
Quote from: MichaelW on September 06, 2010, 09:27:04 PM
Quote
Replace PM_REMOVE with PM_NOREMOVE and report the numbers back to me again :U
I had already tested that and there was no change in the timings that I could see, but it's not really meaningful because then you have a non-functional message loop. For the blocking loop in my test above I used GetMessage.
It makes all the difference. You get second delays when you replace it. GetQueueStatus is way faster here. And if you run that loop in a true program, you will miss alot of messages if the traffic is heavy because you dont use a while loop.
I hope you see the difference. GetQueueStatus does not remove the message, but peekmessage does, so only the very first iteration is qualified to time the two functions. (UNLESS you are willing to replace PM_REMOVE with PM_NOREMOVE, if you do that you will discover huge delays using peekmessage)
Quote from: zemtex on September 06, 2010, 09:28:44 PM
It makes all the difference. You get second delays when you replace it. GetQueueStatus is way faster here. And if you run that loop in a true program, you will miss alot of messages if the traffic is heavy because you dont use a while loop.
I hope you see the difference. GetQueueStatus does not remove the message, but peekmessage does, so only the very first iteration is qualified to time the two functions. (UNLESS you are willing to replace PM_REMOVE with PM_NOREMOVE, if you do that you will discover huge delays using peekmessage)
I have no idea what you mean. If there is a valid point buried in there some where, post code that demonstrates it.
Quote from: MichaelW on September 07, 2010, 01:26:33 AM
Quote from: zemtex on September 06, 2010, 09:28:44 PM
It makes all the difference. You get second delays when you replace it. GetQueueStatus is way faster here. And if you run that loop in a true program, you will miss alot of messages if the traffic is heavy because you dont use a while loop.
I hope you see the difference. GetQueueStatus does not remove the message, but peekmessage does, so only the very first iteration is qualified to time the two functions. (UNLESS you are willing to replace PM_REMOVE with PM_NOREMOVE, if you do that you will discover huge delays using peekmessage)
I have no idea what you mean. If there is a valid point buried in there some where, post code that demonstrates it.
What you seem not to understand is that peekmessage removes the message and runs 99.9% with an empty message queue, while getquestatus runs with a full message queue all the time when you should have emptied it when it discover a message.
Replace PM_REMOVE with PM_NOREMOVE and report the numbers back again. Copy the numbers and report them in again. :cheekygreen:
Here is from your code: invoke PeekMessage, ADDR msg, NULL, 0, 0, PM_REMOVE
Replace the last argument with PM_NOREMOVE. (tip for you)
Here is your real numbers: (http://i54.tinypic.com/2yke3j6.png)
About 5 times slower than GetQueueStatus. (OFFTopic joke: Whats funny about that is that peekmessage also uses 5 times the amount of arguments :lol)
QuoteWhat you seem not to understand is that peekmessage removes the message and runs 99.9% with an empty message queue, while getquestatus runs with a full message queue all the time when you should have emptied it when it discover a message.
I understand what PeekMessage does. My code removes the messages, whether it's configured to run PeekMessage alone, or run PeekMessage after GetQueueStatus indicates that there are messages in the queue. It does what you describe here:
Quote from: zemtex on September 05, 2010, 10:11:24 AM
Anyway, I always use GetQueueStatus for quick hint if there is messages available before i pass the execution to the slow (5 push) peekmessage function. GetQueueStatus only has 1 push and it checks a few flags. If the message loop runs 1 million times in 10 ms, that means peekmessage is pushing and popping 5 million times (Thats alot of memory reading) Microsoft SDK also mentions that getqueuestatus is the fastest possible way to check if there are available messages.
And the results show that GetQueueStatus slows the message loop down. There is no point in testing GetQueueStatus alone because it will not be used alone. There is no point in testing PeekMessage with PM_NOREMOVE because without some way to remove the messages, the message loop and application will not function correctly.
Here is a sampling of my results without the GetQueueStatus code:
0.140525 13 0
0.140405 14 0
0.140311 8 0
0.140667 13 0
0.139825 7 0
0.140351 9 0
0.139806 0 0
0.140035 0 0
0.139867 0 0
0.140347 0 0
And a sampling with the GetQueueStatus code:
1.142921 9 9
1.140578 0 0
1.140418 6 6
1.138636 15 15
1.143593 3 3
1.144531 0 0
1.137575 0 0
1.143059 0 0
1.140317 0 0
1.142379 0 0
I'm done here.
Quote from: MichaelW on September 07, 2010, 04:18:50 PM
QuoteWhat you seem not to understand is that peekmessage removes the message and runs 99.9% with an empty message queue, while getquestatus runs with a full message queue all the time when you should have emptied it when it discover a message.
I understand what PeekMessage does. My code removes the messages, whether it's configured to run PeekMessage alone, or run PeekMessage after GetQueueStatus indicates that there are messages in the queue. It does what you describe here:
You forgot the while loop my man, you forgot the while loop. :bdg
Quote from: MichaelW on September 07, 2010, 04:18:50 PM
And the results show that GetQueueStatus slows the message loop down. There is no point in testing GetQueueStatus alone because it will not be used alone. There is no point in testing PeekMessage with PM_NOREMOVE because without some way to remove the messages, the message loop and application will not function correctly.
There is nothing that forces you to use peekmessage, keep in mind the different filters available to getqueuestatus. And its twin-cousin getinputstatus can be used effectively in combinations as well.
The point of using PM_NOREMOVE is to test the individual functions up against each other. Peekmessage have an "exit strategy" in your 1 million time iteration loop. GetQueueStatus has no "exit strategy". Once peekmessage discovers a message it removes it instantly while GetQueueStatus is not able to do that while in a real program GetQueueStatus would not be stuck in such a position to not be able to do that and PeekMessage would never run once with an empty buffer.
GetQueueStatus is much faster in checking a message buffer than what peekmessage is. And this proves my point and microsoft as well that GetQueueStatus is faster, but you have to be careful where you use it. Bad implementation is your own responsibility.
One usage could be to run GetQueueStatus once per second and then run PeekMessage in a while loop.
Another usage could be to look for paint messages, which would be too time consuming to do in peekmessage.
Whatever the usage is, as long as it gives positive progress in the program, it should be used.
I'm out of here myself.
Quote