Originally Posted by
novacain
Drawing is slow, so have to try and create the GDIs only once.
We also try to do the drawing offscreen and when finished, post to screen with a paint msg.
If you declare a variable in the callback (and want it to retain the value each msg) you must declare the variable as a static.
I use something like....
Code:
static HDC hdcScr = NULL;
static HBITMAP hbmpScr = NULL, hbmpOrig = NULL;
//WM_CREATE
//create our DC, BMP and set it up
//get the size of the whole screen [GetDeviceCaps() with HORZRES|VERTRES]
//create a mem DC [CreateCompatibleDC( NULL )]
//create a BMP [CreateCompatibleBitmap( memDC)]
//select the BMP into mem DC, catching return [SelectObject]
//fill the DC with a solid colour [FillRect GetStockObject(WHITE_BRUSH)]
//WM_DESTROY
//clean up our DC and BMP
//Select original BMP back into mem DC
//delete comp BMP
//delete mem DC
//WM_PAINT
//draw our mem DC to the paint DC
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd, &ps);
BitBlt(hdc,
ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, //only redraw the invalid area, not the whole screen.
hdcScr, //from mem DC
ps.rcPaint.left, ps.rcPaint.top, //assuming no offset for the image
SRCCOPY);
EndPaint(hwnd, &ps);
//MSG to draw new line (ie mouse click)
//draw a new line as required
//draw line (you have the code to do this)
//call for a paint msg to draw line to screen
InvalidateRect( hWnd, NULL, FALSE); //redraw whole client area but not background
UpdateWindow( hWnd); //bypass the OS msg queue and send directly tothis callback (is faster)
Thanks. I tried implementing that stuff, and got it to draw a load of random lines which stayed on the screen. Here's my code so far.
Code:
int x,y;
static HDC hdcScr = NULL;
static HBITMAP hbmpScr = NULL, hbmpOrig = NULL;
static RECT r;
Code:
case WM_CREATE:
try
{
pCtrl = new Controller (hwnd, reinterpret_cast<CREATESTRUCT *> (lParam));
// Store pointer to Controller inside Window
WinSetLong<Controller *> (hwnd, pCtrl);
SetTimer(hwnd, IDT_TIMER1, 500, (TIMERPROC) NULL); // no timer callback
// Text output stuff.
hdc = GetDC(hwnd);
ReleaseDC(hwnd, hdc);
hdcScr = CreateCompatibleDC(NULL);
x = GetDeviceCaps (hdcScr, HORZRES);
y = GetDeviceCaps (hdcScr, VERTRES);
hbmpOrig = CreateCompatibleBitmap(hdcScr, x, y);
hbmpScr=(HBITMAP)SelectObject(hdcScr,hbmpOrig);
SetRect(&r, 0, 0, x, y);
Rectangle(hdcScr, r.left, r.top, r.right, r.bottom);
FillRect(hdcScr, &r, (HBRUSH)GetStockObject(WHITE_BRUSH));
}
Code:
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
BitBlt(hdc,
ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top, //only redraw the invalid area, not the whole screen.
hdcScr, //from mem DC
ps.rcPaint.left, ps.rcPaint.top, //assuming no offset for the image
SRCCOPY);
EndPaint(hwnd, &ps);
return 0;
Code:
case WM_TIMER:
switch (wParam)
case IDT_TIMER1:
{
hdc = GetDC(hwnd);
::MoveToEx (hdcScr, rand() % 300, rand() % 300, 0);
::LineTo (hdcScr, rand() % 300, rand() % 300);
ReleaseDC(hwnd, hdc);
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);
}
return 0;
Does some of that seem ok? I know I haven't deleted stuff properly but I'm just trying to get the basics going first. It seems to do what it's supposed to, but there's something I don't understand.
Say I comment out everything after "ReleaseDC(hwnd, hdc);" in WM_CREATE, and comment out everything between "BeginPaint" and "EndPaint" in WM_PAINT. Then, if I change the hdcScr's in MoveToEx and LineTo to hdc, the lines will still draw, and stay on the screen.
Surely they should just appear and then disappear each time WM_PAINT gets called though? If stuff's not being copied to/from hdcSrc, why do they still stay on the screen?
This stuff is really bloody confusing, so thanks for your help- it's appreciated.