来自其他线程的hwnd线程亲和力绘画 [英] hwnd thread affinity painting from a different thread
问题描述
我有一个DGRect::draw(HWND hwnd)
,它简单地在hwnd
窗口句柄上绘制了空白HBITMAP
.
如果我从main()
调用它,我可以正常工作.如果从QTcpServer
派生的DGRDPServer::DGRDPServer()
构造函数调用,它甚至可以正常工作.从DGRDPServer::listen(qint64 port)
也可以很好地工作. hwnd在DGRDPServer
构造函数中传递.当我从DGRDPServer::incomingConnection(int socketDescriptor)
调用它时,出现了问题,我已经qDebug()
修改了hwnd
的值,并且还可以.是什么导致平局失败. ??
这是我的DGRect::draw(HWND hwnd)
I've a DGRect::draw(HWND hwnd)
which simply draws a Blank HBITMAP
on hwnd
window Handle.
I works fine If I call it from main()
. It even works correctly If called from DGRDPServer::DGRDPServer()
constructor which is QTcpServer
Derived. It also works well from DGRDPServer::listen(qint64 port)
. The hwnd is passed in DGRDPServer
constructor. The Problem appears when I call it from DGRDPServer::incomingConnection(int socketDescriptor)
I've qDebug()
ed value of hwnd
and its Okay. Whats Causing the draw for failing. ??
Here goes my code for DGRect::draw(HWND 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);
更新
看起来像hwnd
只能从主线程绘制.但是,UpdateWindow
调用是从其他线程进行的.看起来像DGRDPServer::incomingConnection(int socketDescriptor)
这样的函数是从其他线程调用的.那么如何从不同的线程绘制hwnd
呢?
Update
Seems like hwnd
can be painted from main thread only. However UpdateWindow
Call works from a different thread. and looks like functions like DGRDPServer::incomingConnection(int socketDescriptor)
are called from a different thread. So What can be done to paint hwnd
from a different thread ?
推荐答案
My guess is that the problem here is your use of BeginPaint: as per docs: An application should not call BeginPaint except in response to a WM_PAINT message
除此之外,您还可以使用普通的GetDC/ReleaseDC而不是BeginPaint/EndPaint对.
Outside of that, you may be able to use plain GetDC/ReleaseDC instead of BeginPaint/EndPaint pair.
但是,做这种事情的"Windows方式"是只使用工作线程来适当地更新内部数据,然后使用
The 'windows way' of doing this sort of thing, however, is to just use the worker thread to update the internal data appropriately, and then use InvalidateRect or similar to tell Windows that the window needs to be updated, and Windows will send a WM_PAINT later. UpdateWindow is essentially a more immediate version of this: it sends WM_PAINT to the window right there and then (which causes the actual painting to take place on that hwnd's thread).
这篇关于来自其他线程的hwnd线程亲和力绘画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!