Where to group-catch thread messages WINAPI/MFC - winapi

Does anyone know where is the best place to forward thread messages to child controls?
Basically, app has to catch registered thread messages in range msg_frst...msg_last and forward them to active frame/view.
There are 3 overload points in MFC, or so it seems:
DefWndProc
OnWndMessage
PreTranslateMessage
Which is the correct one to override?

A message posted with PostThreadMessage() has a NULL window handle. So forget about any of the window methods, DispatchMessage() isn't going to deliver them. All you got is CWinThread::PreTranslateMessage().
But there's a big hazard here, this isn't going to be called anymore when any code in that thread start pumping its own message loop. Your messages now fall in the bit bucket because other code is now calling Peek/GetMessage(). That's a lot more likely then you think, MessageBox() is enough. Or the COM modal loop. Etcetera.
You can only safely use PostThreadMessage() to send messages to a thread that does not create any windows of its own. The workaround is simple enough, provide the thread with a window handle so it can call PostMessage() instead. That could be a hidden window, dedicated to handling these messages for example.

Related

Is it safe to call PeekMessage/GetMessage from a DirectShow filter FillBuffer() call?

I have a DirectShow filter written in Delphi 6 using the DSPACK component library. It is a push source video filter that receives its source frames from an external cooperating process that I also wrote.
When the worker thread that calls my Filters' FillBuffer() call is created and ran, when the graph starts up, the first thing I do from that worker thread is create a hidden window using AllocateHWND() to process WM_COPYDATA messages that contain the externally generated frames. Right before the thread is destroyed I destroy the hidden window. In other words the hidden window is created and destroyed in the execution context of the worker thread that calls FillBuffer(). My intention is to let FillBuffer() block as it waits for a WM_COPYDATA or a WM_QUIT message. The external cooperating process will submit frames to my filter using a WM_COPYDATA message and the handle to my hidden windows' WndProcc(). I will post a WM_QUIT message in my override of the pin's Inactive() method (thanks for that tip #RomanR), to unblock the FillBuffer() call before the filter is shut down.
My question is, is it safe to call PeekMessage() or GetMessage() from the FillBuffer() call given this scenario? Or are there potential pitfalls that may arise from this occurring in the context of a DirectShow graph executing? Also, do you see any flaws in my overall approach here that I need to consider?
Safe, but not so reasonable too. FillBuffer is being called on a background worker thread which is typically have no windows on it. It would be perhaps only your window which you are going to implement message loop for. And the window is here only for the purpose of receiving WM_COPYDATA messages. It sounds like it can work out, but you would perhaps could do much easier without helper windows by passing your data between applications via named file mappings and events. In case of video (you have audio, right?) you would also be able to appreciate a smaller performance overhead.

how to create a blocking function

I have a thread that needs to dispatch a message (a simulated mouse event that it sends using SendInput) as soon as it's generated. I want this to happen in a loop where there is no sleep; adding any sleep hurts performance as I basically want the events to go in to the event loop immediately once they have been generated. Of course I also don't want the loop in the consumer thread to hog all the cpu so I can't just keep it running, although this gives me good performance.
As far as I understand this, the task is to make the consuming thread to wait for something that signals that the producing thread has provided something to dispatch (?) but how to best do this? I think I need something like two mutexes if I want to make the two threads mutually exclusive; consumer waits for the producer and the producer continues as soon as the consumer resumes running? Didn't really get this working so far and I'm really not sure how to best do this; CriticalSections vs. mutexes, something entirely different?
The reason I don't want to call SendInput from the producer thread is that that thread (the 'main thread'?) actually runs in response to a mouse move message, intercepted by a mouse hook, and sending more mouse messages from that thread didn't allow the thread to finnish before the simulated mouse move event was processed, messing things for me. As I suspected, moving the SendInput call to another thread so that the original thread could finish out of the way fixed the problem but now I need to make the consumer more responsive; mouse messages keep coming at a good pace I suppose since just a 1 ms Sleep made the loop too slow and message processing started lagging; all works well if I have no sleep.
Thanks.
Sounds like you want to use win32 event objects instead of mutexes or critical sections. See the docs here. The event functions allow a thread to wait on a condition that can be signaled from another thread.
Windows threads support message queues - usually used for windows messages but completely usable for messaging between worker threads. PostThreadMessage can be used in the Hook Proc to post messages to another thread for processing.
The worker thread can do a normal GetMessage loop to extract messages to process - rather than passing them on to DispatchMessage as you would in a UI thread you simply check the HWND is NULL in the message structure indicating its a thread message, then process the message yourself. In the case of potential message flooding PeekMessage can be used to cull any outstanding messages from the queue.

Window moving and resizing interferes with MsgWaitForMultipleObjects

I have an application that message-loops using MsgWaitForMultipleObjects to catch additional events while pumping ui messages. It seems that as soon as a window is being moved or resized, DefWindowProc begins it's own message loop until the mouse is being released. This situation prevents from the outer loop to catch the additional messages in the meantime.
I'd hate to multi-thread the application just because of this. Is there any other way to solve it?
MsgWaitForMultipleObjects has very few uses in a traditional multi threaded program. It has some use in Games - where traditional non client frame elements are omitted and APIs like "MessageBox" and "DoDragDrop" are avoided...
Usually it finds its best use in "UI worker" threads that don't host visible windows, but use the message queue as an inter thread messaging system and also need to wait on kernel handles.
In your case, making a second thread does not seem avoidable. Ironically, PostThreadMessage + MsgWaitForMultipleObjects will probably be the easiest way to set up a reliable communication mechanism between the GUI thread and your "ui" worker thread.
There are several additional places in the Windows API that will enter their own message loop. If you need to continue handling your messages during these times then you'll need a separate thread.

How can I handle window messages from a separate thread?

I wish to launch a separate thread for handling window messages (via a blocking GetMessage loop), but still create the windows in the initial thread, afterward.
Within the separate thread, as soon as it launches, I am calling PeekMessage with PM_NOREMOVE to ensure a message queue exists (is this necessary?), followed by..
AttachThreadInput(initial thread id,GetCurrentThreadId(),true)
..before finally entering the message loop
I am not yet using a mutex or cs to ensure this is happening in time, but am merely using a Sleep statement in my initial thread for the sake of simplicity.
Regardless, window messages do not appear to be intercepted by the separate thread.
I am a little unsure as to whether I am doing this correctly, and would appreciate any possible guidance. Both threads are in the same process
Thank you all
That's not what AttachThreadInput does. Even after you attach your input queue to another thread, Windows still have thread affinity. Messages in the queue for a given window can only be removed from the queue by that window's thread.
What AttachTheadInput does is to make two threads share an input queue. This allows them to query information about the input state and know that the other thread will get the same answer for the same query. For instance, one thread could call GetAsyncKeyState and know that the answer reflected the key state for the other thread.
It allows two or more threads to have the same relationship to the input queue and each other as processes had in Windows 3x. This is the reason that this API exists; so that complex multiprocess applications could be ported from Win 3x to Win95/WinNT.
It seems the best way to instigate window creation from the main thread, while having messages for them handled in a separate, looping thread is to use a custom message, that can be sent to the separate thread - Thus allowing it to create the window, but still allowing that action to be invoked from the initial thread:
1) Allocate a custom message, and create a structure to hold the window initialisation parameters:
message_create_window = WM_USER + 0;
class Message_create_window{
Message_create_window(...);
};
2) Instead of calling CreateWindow(Ex), use something similiar to the following, passing in the relavant window creation parameters:
PostThreadMessage(
thread.id,
message_create_window,
new Message_create_window(...),
0
);
3) Handle the custom message in the message pump of your ui handling thread, extract the creation parameters, & free afterwards:
MSG msg;
GetMessage(&msg,0,0,0);
...
switch(msg->message){
...
case message_create_window:{
Message_create_window *data=msg->wParam;
CreateWindowEx(data->...);
delete data;
}break;
...
This does, however, have the following side-effects:
The window will be created asynchronously. If it is required that the initial thread block until the window is created (or, indeed, that the window's existence can ever be asserted) then a thread synchronisation tool must be used (such as an event)
Care should be taken when interacting with the window (it is a multithreaded application, after all)
If there are any major holes in this answer, or this seems like a terrible approach, please correct me.
(This is still my question, & I am trying to find the best way to accomplish this)

How is Win32 event-driven programming implemented under the hood?

In a Win32 C++ application, we start a message loop that fetches messages from a queue, translates them and then dispatches them. Eventually, each message reaches our WndProc where the associated event can be handled.
I understand that part. What I don't understand is the in between goings-on. Specifically:
Different kinds of OS interrupt handlers must be placing messages in the said 'message queue', but where within the process address space does this queue reside? How is it exposed to the interrupt handler code?
What does it mean to 'translate' the message? What does the call to TranslateMessage() really do?
Once dispatched by DispatchMessage(), what all places does the message swing by before reaching my WndProc (i.e. what does the OS do with it)?
If anyone knows the answers to the above, kindly satisfy my curiosity. Thanks.
The OS maintains a message queue, where it puts the events (e.g., from interrupts or other sources). It then sends the messages from that queue to all windows, depending on the message (e.g., it won't send key messages to a window that doesn't have focus).
Applications can have their own queue to process messages. Those queues are created on request (only if needed).
Translating a message is used to create messages that are not 'real' events. For example, the WM_CONTEXTMENU message is 'translated' from either a mouse right-click, or the context menu key, or shift-F10. The WM_CHAR is translated from WM_KEYDOWN messages. And of course many other messages are 'translated' that way.
A message is posted to every window that should receive it. The OS decides depending on the type of message whether a window should receive that message or not. Most messages are waited for by the system, i.e., the message won't get posted to another window until it was processed by the window. This has a great impact for broadcast messages: if one window doesn't return when handling that message, the queue is blocked and other windows won't receive the message anymore.
It depends on how your message is sent and how it's handled.
When you call SendMessage, if the target window is owned by the current thread, the call bypasses the message queue for the window and the window manager directly calls the windowproc on the target window. If the target window is owned by another thread, the window manager effectively calls PostMessage and pumps window messages until the target window returns from the window proc.
When you call PostMessage, the window manager marshals the message parameters and inserts the corresponding object onto the message queue for the target window. When it next calls GetMessage the message is removed from the message queue.
The window manager also registers for raw input events from the input devices (keyboard and/or mouse) and it generates messages for those input events. It then inserts those messages in the queue as appropriate (the processing of input events is complicated because it depends on what messages are already in the message queue for the window).
As Stefan indicated, TranslateMessage just translates accelerator keys - for instance it converts key sequences to WM_COMMAND messages.
Different kinds of OS interrupt handlers must be placing messages in the said 'message queue', but where within the process address space does this queue reside? How is it exposed to the interrupt handler code?
Windows are associated with threads. Each thread with a window has a thread queue in the process's address space. The OS has an internal queue in its own address space for the hardware-generated events. Using details of the event and other state information (e.g., which window has the focus), the OS translates the hardware events into messages that are then placed in the appropriate thread queue.
Messages that are posted are placed directly in the thread queue for the target window.
Messages that are sent are usually processed directly (bypassing the queue).
The details get hairy. For example, the thread queues are more than lists of messages--they also maintain some state information. Some messages (like WM_PAINT) aren't really queued, but synthesized from the additional state information when you query the queue and it's empty. Messages sent to windows owned by other threads are actually posted to the receiver's queue rather than being processed directly, but the system makes it appear like a regular blocking send from the caller's point of view. Hilarity ensues if this can cause deadlock (because of circular sends back to the original thread).
The Jeffrey Richter books have a lot (all?) of the gory details. My edition is old (Advanced Windows). The current edition seems to be called Windows via C/C++.
The OS does a LOT of work to make the message stream appear rational (and relatively simple) to the caller.
What does it mean to 'translate' the message? What does the call to TranslateMessage() really do?
It watches for virtual key messages and, when it recognizes a key-down/key-up combination, it adds character messages. If you don't call TranslateMessage, you won't receive character messages like WM_CHAR.
I suspect it sends the character message directly before returning (as opposed to posting them). I've never checked, but I seem to recall that the WM_CHAR messages arrive just before the WM_KEYUP.
Once dispatched by DispatchMessage(), what all places does the message swing by before reaching my WndProc (i.e. what does the OS do with it)?
DispatchMessage passes the message to the WndProc for the target window. Along the way, it some hooks may get a chance to see the message (and possibly interfere with it).
To address the last subquestion, a dispatched message will go to your WindowProc after it's been piped through all hooks (WH_CALLWNDPROC)
Not absolutely positive about this but my best guess says:
The queue is a system object that you access with Win32 API calls. It is not in your process address space at all. So the interrupt handlers can access it (probably through the HAL (Hardware Abstraction Layer) of the kernel).
In Win16, that call took the various subparts of a bigger message and mashed them into a whole. So TranslateMessage would add the WM_KEYPRESS when it found the corresponding WM_KEYDOWN WM_KEYUP sequence. It would also turn various button click messages into doubleclick messages based on internal setting and the timestamps of the messages. Whether it still does this in Win32, I don't know.
DispatchMessage is probably where Window message hooks get processed. So if there's a hook on your window, it is either called here or when the GetMessage is called. I'm not sure. Other than that, DispatchMessage just looks up the WndProc address associated with the window and calls it. There's not much else for it to do.
Hope that helps.

Resources