3
votes

Using the Win32 APIs, is it possible to create a Window or Dialog in one thread then collect events for it from another thread?

Are HWNDs tied to threads?

Trying the contrived example below I never see GetMessage() fire.

HWND g_hWnd;

DWORD WINAPI myThreadProc(LPVOID lpParam)
{
    while(GetMessage(&msg, hWnd, 0, 0) > 0)
    {
       ...
    }

}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 
{
    hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_MYDIALOG), 0, myDlgProc);
    CreateThread(NULL, 0 myThreadProc, NULL, 0, NULL);
    ...
}

But here, I do.

HWND g_hWnd;
HINSTANCE g_hInstance;

DWORD WINAPI myThreadProc(LPVOID lpParam)
{
    hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_MYDIALOG), 0, myDlgProc);

    while(GetMessage(&msg, hWnd, 0, 0) > 0)
    {
       ...
    }

}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 
{
    g_hInstance = hInstance;
    CreateThread(NULL, 0 myThreadProc, NULL, 0, NULL);
    ...
}

Can somebody explain what I'm seeing?

7

7 Answers

5
votes

No.

GetMessage returns messages on the current thread's input queue. The HWND parameter is a filter, so that GetMessage only returns messages in the current thread's input queue intended for that window.

Windows have thread affinity - messages intended for a window get handled on the thread that created and therefore owns the window.

2
votes

From the MSDN:

The GetMessage function retrieves a message from the calling thread's message queue

So no, what you describe is not directly possible.

2
votes

In your first example the Dialog and GetMessage are in separate threads. And the documentation says:

The GetMessage function retrieves a message from the calling thread's message queue.

The second example works since the calling thread (for GetMessage) also owns the Dialog.

0
votes

In your example programm finish after create window.

But anyway in win32 all threads have own message queue.

And all message queues get messages for windows created in this thread.

see:

http://msdn.microsoft.com/en-us/library/ms644928(VS.85).aspx (Using Messages and Message Queues)

http://msdn.microsoft.com/en-us/library/ms644936(VS.85).aspx (GetMessage Function)

0
votes

You can of course change the window procedure that handles messages for any window. Check the SetWindowLong function - http://msdn.microsoft.com/en-us/library/ms633591(VS.85).aspx - there are some rules as to what address space the new proc is. I suggest using a dll. Another way is to sub class the window message queue.

-3
votes

Of course you can !

Just use remote code injection ! (very classic !)