I wrote some code that should simply draw a rectangle from a given point up to the current mouse location. Everytime the mouse moved the screen flashed white quickly in between and now I wanted to remove it by using a compatible Device context and bitmap but the flickering only got worse now. Does anyone see what is wrong with my code for the WM_PAINT message (I didn't include the code for the other messages) ?
cmp eax,WM_PAINT
jnz __cont0
push ebx
push edi
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
invoke CreateCompatibleDC,hdc
mov memdc,eax
invoke GetClientRect,hWnd, offset rect
invoke CreateCompatibleBitmap,hdc,rect.right,rect.bottom
mov hbm,eax
invoke SelectObject,memdc,eax ; Select the Bitmap
mov hOld,eax
;the following code paints the membc in the same background color as the window
invoke SelectObject,memdc,hbrBkgnd
invoke PatBlt,memdc,0,0,rect.right,rect.bottom,PATCOPY
;The following code draws the rectangle using a brush and a pen created in the WM_CREATE message
invoke SelectObject,memdc,hbr
mov hbrOld,eax
invoke SelectObject,memdc,hpen
mov hpenOld,eax
cmp drawrect,0
jz skiprect
invoke Rectangle,memdc,x1,y1,x2,y2
skiprect:
;Deselect brush and pen
invoke SelectObject,memdc,hbrOld
invoke SelectObject,memdc,hpenOld
; the follow code copys the image in memdc to the hdc
mov edi,ps.rcPaint.left
mov ebx,ps.rcPaint.top
mov ecx,ps.rcPaint.right
mov edx,ps.rcPaint.bottom
sub ecx,edi ;ECX = width
sub edx,ebx
invoke BitBlt,hdc,edi,ebx,ecx,edx,memdc,edi,ebx,SRCCOPY
;clean up
invoke SelectObject,memdc,hOld
invoke DeleteObject,hbm
invoke DeleteDC,memdc
invoke EndPaint,hWnd, ADDR ps
pop edi
pop ebx
jmp __cont
__cont0:
invoke DefWindowProc,hWnd,uMsg,wParam,lParam ; Default message processing
ret
__cont:
xor eax,eax
ret
WndProc endp
Thanks in advance,
Jannes
Often the problem is that GDI is automatically painting your background for you. Ensure hbrBackground is NULL when you register the window.
-r
thanks, that did the trick :icon_exclaim: :redface:
General "avoiding flicker" advice:
- don't use CS_HREDRAW or CS_VREDRAW in the class style;
- use a NULL brush for the window background (and obviously then ensure you paint the full client area);
- add WS_CLIPCHILDREN to the window style (in CreateWindowEx) of your main window (only necessary if you have children/controls in the window);
- using a back-buffer (CreateCompatibleDC) isn't necessarily required (make the above changes, then check).
hbrBackground = NULL solves the flicker problem, as others suggested
but, I do see a little flaw in the code
when you store the original brush that is selected into the memdc, you only need to do it the first time you replace it (when you PatBlt the background)
you do not need to store the returned value when you select the painting brush
when you restore the memdc to original state, you will have the correct brush handle
little things like that can cause GDI memory leaks