Multithreading 来自不同线程的hwnd线程关联绘制

Multithreading 来自不同线程的hwnd线程关联绘制,multithreading,winapi,qt,sockets,gdi,Multithreading,Winapi,Qt,Sockets,Gdi,我有一个DGRect::draw(HWND-HWND),它只是在HWND窗口句柄上绘制一个空白的HBITMAP。 如果我从main()调用它,我可以正常工作。如果从DGRDPServer::DGRDPServer()构造函数调用,它甚至可以正常工作,该构造函数是qtcserver派生的。它在DGRDPServer::listen(qint64端口)中也能正常工作。hwnd在DGRDPServer构造函数中传递。当我从DGRDPServer::incomingConnection(int-sock

我有一个
DGRect::draw(HWND-HWND)
,它只是在
HWND
窗口句柄上绘制一个空白的
HBITMAP
。 如果我从
main()
调用它,我可以正常工作。如果从
DGRDPServer::DGRDPServer()
构造函数调用,它甚至可以正常工作,该构造函数是
qtcserver
派生的。它在
DGRDPServer::listen(qint64端口)
中也能正常工作。hwnd在
DGRDPServer
构造函数中传递。当我从
DGRDPServer::incomingConnection(int-socketDescriptor)
调用它时,问题出现了。我已经得到了
qDebug()
hwnd的ed值,并且没有问题。是什么导致抽签失败的?? 下面是我的
DGRect::draw(HWND-HWND)

更新
似乎只能从主线程绘制
hwnd
。然而,
UpdateWindow
调用从不同的线程工作。类似于
DGRDPServer::incomingConnection(intsocketdescriptor)
这样的函数是从不同的线程调用的。那么,如何从不同的线程绘制
hwnd
呢?

我的猜测是,这里的问题是您使用BeginPaint::应用程序不应该调用BeginPaint,除非响应WM_paint消息

除此之外,您还可以使用普通的GetDC/ReleaseDC,而不是BeginPaint/EndPaint对


然而,做这类事情的“windows方法”是只使用工作线程适当地更新内部数据,然后使用或类似的方法告诉windows需要更新窗口,windows稍后将发送WM_PAINT。UpdateWindow本质上是一个更直接的版本:它将WM_PAINT发送到窗口,然后(这导致实际的绘制在hwnd的线程上进行)。

如果
BeginPaint
没有
WM_PAINT
消息,则如何
dRect::draw(hwnd-hwnd)
当从
DGRDPServer::DGRDPServer()调用时,
文档所说的是:如果您从WM_PAINT中调用BeginPaint,您会没事的。他们说你不应该从外面开始叫它油漆;但不要保证它会失败。也许它会一直失败;也许不会。也许它会起作用,但只有在某些限制条件下。也许它现在可以工作,但在下一个操作系统版本中失败。违反文件规定,你这样做是危险的。我的猜测是BeginPaint具有线程关联性:因此,如果您从同一线程调用它,您可能会“运气不佳”。另请参见以下内容的答案:所有接收HWND的函数都必须从创建窗口的线程生成。这些就是规则。
QByteArray ba;
HDC hdc = GetWindowDC(hwnd);
HBITMAP scrn = CreateCompatibleBitmap(hdc,/*width*/200,/*height*/200);
SetBitmapBits(scrn, /*size()*/200*200*4, ba.data());

BITMAP bm;
PAINTSTRUCT ps;
HDC whdc = BeginPaint(hwnd, &ps);
HDC hdcMem = CreateCompatibleDC(whdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, scrn);
GetObject(scrn, sizeof(bm), &bm);
BitBlt(whdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);