0

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);

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 ?

Neel Basu
  • 12,638
  • 12
  • 82
  • 146

1 Answers1

0

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

Outside of that, you may be able to use plain GetDC/ReleaseDC instead of BeginPaint/EndPaint pair.

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).

BrendanMcK
  • 14,252
  • 45
  • 54
  • If `BeginPaint` doesn't work without a `WM_PAINT` message How can `DGRect::draw(HWND hwnd)` when called from `DGRDPServer::DGRDPServer() ` – Neel Basu Apr 12 '11 at 04:54
  • 1
    What the docs are saying is: if you call BeginPaint from within a WM_PAINT, you'll be fine. They say you *shouldn't* call it from outside BeginPaint; but don't guarantee that it will fail. Maybe it will fail consistently; maybe it wont. Maybe it will work, but only under certain constraints. And maybe it will work for now, but fail on the next OS release. Go against the docs, and you do so at your peril. My guess is that BeginPaint has thread affinity: so if you call it from the same thread, you just might 'luck out'. – BrendanMcK Apr 12 '11 at 05:05
  • See also answers to: http://stackoverflow.com/questions/5631937/use-textout-in-wm-command – BrendanMcK Apr 12 '11 at 10:07