GetMessage() loop doesn't get all windows messages? [duplicate] - c

Could someone explain why I never receive a WM_COMMAND message in my GetMessage loop?
I've checked and the WndProc is receiving the WM_COMMAND message, so i'm very confused why this doesn't work.
while (GetMessage(&msg, NULL, 0, 0) != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_COMMAND)
{
// This never happens:
MessageBox(NULL, "WM_COMMAND", "WM_COMMAND", MB_OK);
}
}
OS: Windows 8

Because WM_COMMAND is sent with SendMessage(). Which directly calls the window procedure. Only messages posted with PostMessage() get added to the queue and are retrieved by GetMessage().
You can see this back in a utility like Spy++, it annotates messages that are posted with P and messages that are sent with S.

Related

C - Debug mode won't acknowledge callback event

I'm trying to write a simple UDP transfer program in Labwindows/CVI.
The idea is it creates 2 UDP channels, uses one to write data to a port, and the other to receive the data and print it out.
Here's the receiving end:
//Called whenever data arrives on port
int CVICALLBACK udpCallback(unsigned channel, int eventType, int errCode, void *callbackData)
{
printf("Callback called\n");
//Gets the data from port
readChannel();
return 0;
}
void createReadChannel()
{
//Channel for given port, receiving from any IP address
CreateUDPChannelConfig(port, UDP_ANY_ADDRESS, 0, NULL, NULL, &readerChannel);
//Attach callback to channel (above)
SetUDPAttribute(readerChannel, ATTR_UDP_CALLBACK, udpCallback);
printf("Read channel created\n");
}
My main problem is just that when I run it in debug mode, the shown callback function is never called, i.e. "Callback called" is not printed, not is any data stored or printed in the resulting readChannel() call.
However, when compiled and executed as an .exe, it works as intended. Every time data is received on that port the callback executes.
What difference could there be between the debug and 'release' version that would cause this to happen?
EDIT: After much testing I believe it has to do with waiting for messages using functions like getchar() which caused the main thread to hang up. Why it worked in release mode I don't know, but it probably has something to do with the difference in output window(?). My solution was to remove the callbacks and run the receiving channel on it's own thread.
This way the thread is always waiting for a message, using:
UDPRead(readerChannel, 0, 0, UDP_WAIT_FOREVER, NULL, NULL)) < 0)
And then my main thread can pick up messages as needed.
If anyone has any additional info let me know.

WriteFile hangs the application when using WaitCommEvent

I am encoutering a issues with win32 programming doing a serial port communication using a event-driven approach. I have my communication handle created as:
hComm = CreateFile(lpszCommName, GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, 0, NULL);
and i set my CommTimeouts as:
commTimeout.ReadIntervalTimeout = MAXWORD;
commTimeout.ReadTotalTimeoutConstant = 0;
commTimeout.ReadTotalTimeoutMultiplier = 0;
commTimeout.WriteTotalTimeoutConstant = 0;
commTimeout.WriteTotalTimeoutMultiplier = 0;
I created a thread for ReadFile which looks like this:
SetCommMask(hComm, EV_RXCHAR);
while (isConnected)
{
if (WaitCommEvent(hComm, &dwEvent, NULL)) //If i comment out this block my write file will work fine
{
ClearCommError(hComm, &dwError, &cs);
if ((dwEvent & EV_RXCHAR) && cs.cbInQue)
{
if (!ReadFile(hComm, str, cs.cbInQue, &read_byte, NULL))
/* Process error*/
else if (read_byte)
/* Print to screen */
}
else {
/* Process error*/
}
}
}
PurgeComm(hComm, PURGE_RXCLEAR);
My Wrifile goes into WndProc which sends characters to the communication device when WM_CHAR is triggered:
VOID Write_To_Serial(WPARAM wParam, HWND hwnd){
DWORD write_byte;
char str[10];
sprintf_s(str, "%c", (char)wParam); //Convert wParam to a string
WriteFile(hComm, str, strlen(str), &write_byte, NULL)//Program hangs here
}
My problem is everytime WriteFile() is called my application hangs and I have to force to close it. And if I comment out the WaitCommEvent() in my read thread it works fine, but I can't read then.Any pointers would be appreciated. thanks
This is the expected behavior of Synchronous IO operations.
As per the following description in Serial Communications article in MSDN (https://msdn.microsoft.com/en-us/library/ff802693.aspx),
It is the responsibility of the application to serialize access to the
port correctly. If one thread is blocked waiting for its I/O operation
to complete, all other threads that subsequently call a communications
API will be blocked until the original operation completes. For
instance, if one thread were waiting for a ReadFile function to
return, any other thread that issued a WriteFile function would be
blocked.
WriteFile has to wait until WaitCommEvent function has completed its operation.
A small workaround would be to cancel the pending WaitCommEvent operation (for instance by using CancelIoEx API) when WriteFile needs to be invoked.
VOID Write_To_Serial(WPARAM wParam, HWND hwnd){
DWORD write_byte;
char str[10];
sprintf_s(str, "%c", (char)wParam); //Convert wParam to a string
CancelIoEx(hComm, NULL);
WriteFile(hComm, str, strlen(str), &write_byte, NULL);//Program hangs here
}
WaitCommEvent returns FALSE when canceled. Hence,the code following WaitCommEvent will not be executed.
However, in extreme case, there is a chance, where the thread invoking the ReadFile function, re invokes the WaitCommEvent function, before WndProc gets to WriteFile. If this occurs, it needs to be handled separately. Maybe a small delay when WaitCommEvent returns FALSE would do.

Is there a difference between using `PostQuitMessage` and just processing all messages?

I wonder whether there's a difference between those two snippets:
One:
void main()
{
// ...
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
ExitProcess(0);
}
// ...
void quit()
{
PostQuitMessage(0);
}
Two:
bool quit = false;
void main()
{
// ...
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if(quit)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&_msg);
}
ExitProcess(0);
}
}
// Shouldn't get here
ExitProcess(1);
}
// ...
void quit()
{
quit = true;
PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0);
}
Sorry but I couldn't come up with shorter snippets.
The point of my question is whether calling PostQuitMessage and processing all messages with GetMessage is equivalent to processing all messages with PeekMessage, until it returns FALSE.
According to Raymond, WM_QUIT is "generated only when the message queue is otherwise empty", so it looks like the two methods should do the same, but perhaps there's a subtle difference.
Raymond's blog post says:
Because the system tries not to inject a WM_QUIT message at a "bad
time"; instead it waits for things to "settle down" before generating
the WM_QUIT message, thereby reducing the chances that the program
might be in the middle of a multi-step procedure triggered by a
sequence of posted messages.
So in theory no, there is no difference, because the system won't generate WM_QUIT until the queue is empty. However Raymond doesn't say that it's guaranteed that messages won't arrive after WM_QUIT is generated, only that the system tries to avoid it.
Therefore it's conceivably possible that another thread could post you a message after you've exited your main GetMessage loop, and depending on your application this may be something you have to deal with. For example, if you post messages internally with memory allocations that the receiving thread is expected to free, you may need a separate PeekMessage loop to clean them up before the thread exits completely.
In practice however no one ever writes message loops like your second example.
I don't think the accepted answer addresses the real issue.
Raymond answers this question directly here.
Basically:
You do not have control over every message loop, so you don't have that option.
Oh, and by the way, don't forget to PostQuitMessage inside your own message loops.
Note that even WTL neglects to do this!
It relies on you passing the return value of CMessageLoop::Run to PostQuitMessage.

How to handle all key presses in a parent window

Ive been struggling for a while with a basic UI thing. I have a parent window and several child windows. With child windows such as button (BS_CHECKBOX style) and edit Im not able to process any message for pressing the ESC key event. I could subclass child windows but it seems to be an overkill just to handle one event. I also have a listview child and for some reason I can handle the VK_ESCAPE correctly. I also checked spy++ and noticed there are NO messages sent to the parent window when ESC key is pressed (and the child is focused). If I set spy++ to log child messages only, the correct messages are generated for the key press - they are just not passed to the parent. Any ideas what (not) to do?
Main window loop:
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage (&Msg);
DispatchMessage (&Msg);
}
Working code in parent's WndProc for handling listview key press:
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
case LVN_KEYDOWN:
if (((LPNMLVKEYDOWN)lParam)->wVKey == VK_ESCAPE)
Exit();
break;
}
break;
Thanks,
Kra
One way to do this is to catch it in your message loop before it gets dispatched to the focus window, e.g.:
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0))
{
if (Msg.message == WM_KEYDOWN && Msg.wParam == VK_ESCAPE)
{
// process escape key
}
else
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
There are other ways to do it of course, but this is a very simple solution.

Win32 Message Loops: Quitting after window closes with GetMessage(&msg, NULL, 0, 0)?

If I have the following code below, how do I detect when the window has been closed, so I can quit? r never seems to get the value -1 0, and I need to process messages for the entire thread, not just the current window.
HWND hWnd = CreateWindowExW(0, L"Edit", L"My Window", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 300, 200, NULL, NULL, NULL, NULL);
ShowWindow(hWnd, SW_SHOWDEFAULT);
MSG msg;
BOOL r;
while ((r = GetMessageW(&msg, NULL, 0, 0)) != 0)
{
if (r == -1) { break; }
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
Waiting for r = -1 is not the way you detect that your window has closed. A return value of -1 is not a normal condition: it indicates that an error has occurred in the message loop.
From the documentation:
Return Value
Type: BOOL
If the function retrieves a message other than WM_QUIT, the return value is nonzero.
If 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 or lpMsg is an invalid pointer. To get extended error information, call GetLastError.
When GetMessage retrieves a WM_QUIT message from the queue, it will return a value of 0, and you should end the loop.
If you just want to know when the window has closed, you probably want to handle either the WM_CLOSE or WM_DESTROY messages. For a discussion of these messages, see the answers to this question: What is the difference between WM_QUIT, WM_CLOSE, and WM_DESTROY in a windows program?
I found a solution for this: WM_NULL.
The message loop can handle the matter on its own independently of WndProc:
// written in C#
MSG msg = new MSG();
while (GetMessage(out msg, window, 0, 0))
{
if ((msg.message == WM_NULL) && !IsWindow(window))
break;
TranslateMessage(ref msg);
DispatchMessage(ref msg);
}
Console.WriteLine("yeah, out of loop ^^");
From my observation: When window is destroyed GetMessage retrieves WM_NULL messages without pause (1st hint) and IsWindow can check the window (affirmation).

Resources