which thread processes messages of a spesific hwnd - c++

I have two threads and I call CreateWindowEx function from different processes. The two threads are MainThread and Action.dlu.
Action.dlu creates a window and holds a buffer associated with the window. Whenever I resize the window, window messages are acumulated untill I process and deleted them from queue with the fallowing lines.
while(PeekMessage(&msg, mHWnd, 0U, 0U, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Action.dlu uses the buffer associated with the window so I process messages when I finish using buffers. However, when I create the window from MainThread, WM_SIZE message gets immediately triggered. I mean it doesn't wait for me to process messages. My WNDPROC calback function gets called from MainThread. Is there a way to make a specific process the owner of the window ? This way I can keep processing messages wherever I want.

Related

Determine which window the message was sent (SetWindowsHookEx & WH_KEYBOARD)

I need to be able to determine which window the message is intended for, but I don’t understand how to do it correctly. In WH_MOUSE has a special structure (MOUSEHOOKSTRUCT) that stores the hwnd of the window, but where to get the hwnd in WH_KEYBOARD?
LRESULT CALLBACK messageHandler(int nCode, WPARAM wParam, LPARAM lParam)
{
// ???
}
DWORD WINAPI messageDispatcher(LPVOID thread)
{
hookHandle = SetWindowsHookEx(WH_KEYBOARD, messageHandler, GetModuleHandle(nullptr), *reinterpret_cast<DWORD*>(thread));
if (!hookHandle)
{
return GetLastError();
}
MSG message{};
while (GetMessage(&message, 0, 0, 0) > 0)
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return 0;
}
In theory, I could use GetForegroundWindow, but it seems to me that this is a terrible option, because the window can receive a keyboard message from some other process (if another process sends a SendMessage to this window) and not the fact that the current window will be exactly the one for which the message was intended.
At the time a keyboard action is generated, the OS doesn't know yet which window will eventually receive the message. That is why the WH_KEYBOARD hook doesn't provide a target HWND, like a WH_MOUSE hook does (since a mouse message carries window-related coordinates).
When a keyboard message is being routed to a target, the message gets delivered to the window that currently has input focus.
Per About Keyboard Input:
The system posts keyboard messages to the message queue of the foreground thread that created the window with the keyboard focus. The keyboard focus is a temporary property of a window. The system shares the keyboard among all windows on the display by shifting the keyboard focus, at the user's direction, from one window to another. The window that has the keyboard focus receives (from the message queue of the thread that created it) all keyboard messages until the focus changes to a different window.
Since your hook runs inside of the message queue of the target thread, you can use GetFocus() to get the target HWND at that time:
Retrieves the handle to the window that has the keyboard focus, if the window is attached to the calling thread's message queue.
Otherwise, you can use a WH_CALLWNDPROC/RET hook instead, which gets called when the message is actually delivered to a window. However, you can't block messages with this hook (as you were asking about in your previous question).
I think what you might be looking for is a hook of type WH_JOURNALRECORD.
With this, the callback procedure that Windows will call in response to the various events that this hook intercepts is of type JournalRecordProc, and the lparam parameter passed to this function points to an EVENTMSG structure, which looks like this:
typedef struct tagEVENTMSG {
UINT message;
UINT paramL;
UINT paramH;
DWORD time;
HWND hwnd;
} EVENTMSG;
And there is your hwnd!

WinAPI timer callback not called while child window is in focus

I'm working on a 3D editor app using Direct3D and WinAPI. I create a main window, which has a child window that takes up a portion of the main window's client area. This is used by D3D as the render target. I then also create a separate window with CreateWindow, which is built the same way as the main window (i.e a "main window" and an internal child used as a render target), and I make this window a child of the main application window (to ensure that they are minimized/restored/closed together).
The D3D rendering is executed by the render target child windows processing their WM_PAINT messages. To reduce unnecessary overhead, I set the window procedures to only render on WM_PAINT if GetForegroundWindow and GetFocus match the respective window handles. In other words, I only want a window's rendering to be refreshed if it's on top and is focused.
This is my main message loop:
HWND mainWnd;
HWND mainRenderWnd;
HWND childWnd;
HWND childRenderWnd;
// ...
MSG msg = {};
while (WM_QUIT != msg.message)
{
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
if (!TranslateAccelerator(mainWnd, accel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
// Run non-UI code...
}
}
When the main window gets WM_SETFOCUS, I have it set the focus to its render target child window, since I'll want to process inputs there (e.g camera controls):
// ...
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
//...
case WM_SETFOCUS:
{
SetFocus(mainRenderWnd);
return 0;
}
//...
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
I do the same in the window procedure for childWnd, setting the focus to childRenderWnd. This window is opened and closed by the user, i.e at any one time it may or may not exist, but when it does and is not minimized, it needs to be the foreground window with focus. Also, to control the framerate for the child window, I use a Timer to refresh it:
static constexpr UINT_PTR RENDER_TIMER_ID = (UINT_PTR)0x200;
void TimerCallback(HWND Arg1, UINT Arg2, UINT_PTR Arg3, DWORD Arg4)
{
if (IsIconic(childWnd) || !(GetFocus() == childRenderWnd))
return;
// Invalidate the render area to make sure it gets redrawn
InvalidateRect(childRenderWnd, nullptr, false);
}
// ...
SetTimer(childWnd, RENDER_TIMER_ID, 16, (TIMERPROC)TimerCallback);
With all this set up, mainWnd and mainRenderWnd seem to work just fine. However, childRenderWnd refuses to have anything rendered to it when it is in the foreground and in focus. While debugging, I found that while this is the case, the timer callback never gets executed, nor does a WM_TIMER message get dispatched to the child window.
On the other hand, the moment I deliberately move focus out of the child window and onto the main window (while keeping both open), the timer message gets sent, and the callback is executed. Another problem is that when I minimize the app while both windows are open, and then restore them both, the render target of neither of the windows is refreshed. Instead, it seems like the focus got "flipped", as I have to click on my child window first, then my main window, and that makes it refresh properly (while the child still refuses to render anything).
What am I missing? I searched for others having problem, e.g an incorrect message pump setup blocking WM_TIMER, but nothing seems to explain what's going on here.
Thanks in advance for the help!
IInspectable and Raymond Chen's comments have helped lead me to the answer. I tried to reproduce the error in a minimal app and finally came upon the source of my trouble. Originally, the main window would just call InvalidateRect in the message loop if there were no messages to be dispatched, effectively redrawing itself every chance it got. This originally did not seem to cause any harm, the scene was rendered just fine, and the window responded to inputs. Once I introduced a second window, however, it must have flooded the message loop with paint messages, making it impossible for any timer messages to get through.
The solution, quite simply, was to give a timer to both windows to set the rate at which they would refresh their D3D render targets. Coupled with focus checks, I can now easily alternate between both windows, with only one refreshing itself at any given time.
The question remains whether the WinAPI timer system is the best choice. My bad code aside, people have mentioned that the timer's messages are low-priority, which might make it a poor choice for framerate control in the long run.
EDIT: I ended up going with IInspectable's suggestion to use a while loop within the main message loop to process to dispatch all messages, and once those are processed, I perform a frame update. This allows me to consistently update all windows and control the frame rate without risking the issue of window messages being stuck.

Why can't I get a WM_DESTROY or WM_CLOSE message outside a window procedure?

I wanted to read out messages in my message loop right before I dispatch them to my window procedure. Most messages I tried reading like this were read correctly, but when I close the window, a WM_CLOSE or WM_DESTROY message could not be read as it seems as if they were never received. Here's what i do:
void Framework::Run(){
while(running){
MSG msg;
while(PeakMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
switch(msg.message){
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_QUIT:
running = false;
break;
//...other cases...
}
DispatchMessage(&msg);
}
//...
}
}
I put a breakpoint at the first case, but even when I close the window (by clicking the 'X') the breakpoint is never hit. Though, when I check for WM_DESTROY in the window procedure, it gets read and every thing goes fine. Why not outside it?
Are such messages sent directly to the window proc? How?
A message loop only sees messages that are posted to the calling thread's message queue. Not all messages go through the message queue. WM_DESTROY is one such message. What you should be doing instead is handling the messages in the window procedure so you see every message that the window receives, whether the message went through the message queue or not.
If you need to look at messages for a window you are not creating yourself, or for a standard window that has a system-provided window procedure, you can subclass the window using SetWindowLongPtr(GWLP_WNDPROC) or SetWindowSubclass(). See Subclassing Controls for more details.

DLL crashes app after reuse

I use an application that uses mdi and a script can be attached to, and detached from, a mdi window to be run/stopped on demand; this script loads my dll that does some work; it does fine so; however, when I detach the script still all is fine and the application should unload the dll (and it calls dllmain with the appropriate thread_attach/detach and process_attach/detach operations). Now if I try to re-attach the script to the winow, or to attach it to another window, after the dll has been in use once - the main application crashes. I have isloated the problem to a thread that is created by the dll; the tread crates a window; so, I create the thread like so:
if (!hThread) hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
and, when the script is detached it shuts down the thread like so (no matter if the commented-out lines are uncommented-out):
SendMessage(hWnd, WM_DESTROY, 0, 0);
//TerminateThread(hThread, 0);
//WaitForSingleObject(hWndThread, INFINITE);
CloseHandle(hThread);
hThread = NULL;
I'm at a loss here as to why the main app crashes. A different thread (i.e. one that would simply sleep for a second and loop, will do no harm. What gives?
Ok, here are some ideas:
You said your thread opens a window. Do you run a message loop in the thread function, or you expect your window to be serviced by some other message loop?
If you are running your own message loop in the thread, then exiting the loop may or may not happen, depending on how you have written it. If you use something like:
while(GetMessage(&msg, ...) // msg loop in the thread function
{
....
}
DestroyWindow(hWnd); // see comment below
then this requires a WM_QUIT and not WM_DESTROY to exit. Anyway, the best is to send your window a WM_QUIT and after exiting the message loop then call DestroyWindow() to destroy it properly.
Quoting from MSDN:
DestroyWindow function
Destroys the specified window. The function sends WM_DESTROY and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus from it. The function also destroys the window's menu, flushes the thread message queue, destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if the window is at the top of the viewer chain
After posting WM_QUIT message to your window, your main thread should wait for the window thread to exit. Here is some relevant code:
SendMessage(hWnd, WM_QUIT, 0, 0); // send your quit message to exit the msg loop
if (WaitForSingleObject(hThread, 5000) != WAIT_OBJECT_0) // wait up to 5 seconds
{
TerminateThread(hThread, -1); // bad! try to never end here
}
I hope this helps. I use this in a threaded log viewer that uses a window to display log messages.

CDialog not Receiving Windows Messages in ActiveX Control

I have an ActiveX control in MFC that manipulates images and I am trying to add TWAIN scanning functionality to it.
I need to be able to receive a Windows Message back from the TWAIN driver that tells my control when an image has been scanned, so I have created a CDialog and I pass the HWND of the Dialog to the driver.
ALl the sample code I have seen on the net then uses PreTranslateMessage to capture the message from TWAIN, but in my ActiveX control this method is never being called.
Does anyone know how I can get the messages for that Dialog? I have also tried using PeekMessage with no success.
Many Thanks
You don't need to create a CDialog. You just need any window to process the messages. Anything dealing with TWAIN is best handled in its own thread. So, create a new thread for MFC (via CWinThread or AfxBeginThread). In that thread, create a CWnd. The HWND of this CWnd is the one you will pass with all the calls to the DSM, etc. Each thread has its own message queue, so set one up in there. Communicate with that thread via PostMessage, SendMessage, PostThreadMessage, etc. Assuming you post a message MY_SPECIAL_MESSAGE to signal to being acquiring an image, your message loop should look something like this:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (msg.message == MY_SPECIAL_MESSAGE)
{
GetImageFromTWAIN();
}
else if (!ProcessTWAINMessage(&msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Definitely look at the source code in the TWAIN development kit to see how this all works in detail. TWAIN is a tricky creature.
Trust me, this is the best approach. You can do it all in a single thread using your main thread's message queue, but it's to be avoided.