2009-11-18 55 views
1

我正在研究OpenGL的可移植性层(抽象出Linux和Windows的glX和wgl)...总之,它有一个创建窗口的方法...如果你没有传入父级,你得到一个真正的窗口与框架...如果你通过父母,你会得到一个无国界,无框架的窗口...Win32 CreateWindow()调用在子线程中挂起?

这工作正常,只要我在1个线程上做...所有一旦另一个线程尝试创建子窗口,应用程序就会在win32调用“CreateWindow()”中死锁。有任何想法吗?

回答

5

这不是一个真正的答案,但既然有这么多的人似乎认为,Win32的禁止创建其他线程比父母的子女,我觉得有责任发布示范相反。

下面的代码演示了在属于不同进程的父级上创建子窗口。它接受一个窗口句柄值作为命令行参数并在该父窗口上创建一个子窗口。

// t.cpp 

#include <windows.h> 
#include <stdio.h> 

#define CLASS_NAME L"fykshfksdafhafgsakr452" 


static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (msg) 
    { 
     case WM_DESTROY: 
      PostQuitMessage(0); 
      break; 

     case WM_PAINT: 
     { 
      PAINTSTRUCT ps; 
      BeginPaint(hwnd, &ps); 
      EndPaint(hwnd, &ps); 
      break; 
     } 
    } 
    return DefWindowProc(hwnd, msg, wParam, lParam); 
} 



int main(int argc, char* argv[]) 
{ 
    HWND parent = (argc >= 2) ? (HWND)strtoul(argv[1], 0, 0) : (HWND)0; 
    printf("parent: 0x%x\n", parent); 

    WNDCLASS wc = {}; 
    wc.lpfnWndProc = WindowProc; 
    wc.hInstance = (HINSTANCE)GetModuleHandle(NULL); 
    wc.lpszClassName = CLASS_NAME; 
    wc.hbrBackground = (HBRUSH)(COLOR_ACTIVECAPTION + 1); 
    if (!RegisterClass(&wc)) 
    { 
     printf("%d: error %d\n", __LINE__, GetLastError()); 
     return 0; 
    } 

    const DWORD style = WS_CHILD | WS_VISIBLE; 

    HWND hwnd = CreateWindow(CLASS_NAME, L"Test", style, 50, 50, 100, 100, 
          parent, 0, wc.hInstance, 0); 

    if (!hwnd) 
    { 
     printf("%d: error %d\n", __LINE__, GetLastError()); 
     return 0; 
    } 

    MSG msg; 
    while (GetMessage(&msg, 0, 0, 0)) 
     DispatchMessage(&msg); 

    return 0; 
} 

使用下面的命令编译该(使用MSVC命令行环境):

cl /EHsc /DUNICODE /D_UNICODE t.cpp user32.lib 

然后使用间谍++或其他工具,以获得任何窗口的句柄值 - 例如记事本或浏览本网站的浏览器。让我们假设它是0x000。然后用t.exe 0x1234运行编译后的示例。使用Ctrl-C来终止t.exe(或者关闭控制台窗口)。

-1

窗口绑定到创建它的线程(更具体地说,是该线程的消息队列)。父窗口不能驻留在与其子窗口不同的线程中。

+0

这不是我想要做的。我希望每个线程只处理它创建的窗口......我只需要创建一个由另一个线程创建的父窗口... – dicroce 2009-11-18 21:47:32

+0

这不会工作。您不能在一个线程中创建父窗口,然后在另一个线程中创建一个子窗口。他们必须在同一个线程中。 – 2009-11-18 22:39:24

+0

嗯...嗯,我确实让它工作了......基本上,我只需要让父母消息泵抽......然后一切都开始工作......但是你的评论让我担心......你有多确定这是一件坏事? – dicroce 2009-11-19 02:44:14

1

当创建子窗口时,它可以通过SendMessage与父窗口进行交互。但是,请注意,线程边界块线程中的SendMessagePostMessage不同。如果父窗口的线程正在等待子线程,并且子线程正在尝试创建父窗口在该线程中的窗口,那么这是一个死锁。

一般来说,我认为在线程间建立子女父母关系并不是一个好主意。它很容易造成僵局。

+0

父母和孩子之间没有互动...所以我不知道SendMessage和PostMessage的用途是什么......你对第二段的确信如何?这是Win32的一般限制吗? – dicroce 2009-11-18 21:48:37

+0

是的,这是一个Win32限制。父子窗口关系不应该跨越线程边界。另一个症状是DestroyWindow()在销毁其子窗口在其他线程中创建的父窗口时将无法正确工作。 – 2009-11-18 22:58:11

+0

Dicroce,父和子之间有一个隐含的SendMessage调用。所以,你最好避免它。 – minjang 2009-11-19 00:35:12

0

这是一个有趣的问题:许多老派的win32家伙告诉我你不能这样做。在研究这个时候,我发现这个论坛:SendMessage()。我目前的理论是,CreateWindowEx()必须发送一条消息(通过SendMessage(),所以它阻止)到父窗口以请求存在权限(或至少通知其存在)......无论如何,只要那个父线程可以自由地处理这些消息,它一切正常...

1

这里有很多答复,说你不应该试图在不同的线程上有子窗口和父窗口,而是强调说它会不行。

如果是这样,将视窗放一些保障措施,只是失败了,当你试图调用CreateWindow的。 现在,肯定存在可能导致重大问题的线程耦合问题,但是,这些约束表示这是一种受支持的方案。