I tried to use back buffer technique on icezilion "paint text" example, to make flicker free window, and it works. However, when I add some control on that window like static control, flicker shows up again but only withing client area of that static. This is esspecialy the true if static has bitmap/icon in it, rather than just text.
So how can I make control flicker free? I tried sending WM_PAINT to control, and specifying hdc of main window this works well except that static image is drawn on 0,0 starting point of main window which is not what I want.
Any other ideas? Is subclassing way to go?
So how can I make control flicker free? I tried sending WM_PAINT to control, and specifying hdc of main window this works well except that static image is drawn on 0,0 starting point of main window which is not what I want.
Any other ideas? Is subclassing way to go?
Hi Mikky,
Getting rid of flicker is a big problem. Alot of the time it is not the WM_PAINT handler but the WM_ERASEBKGND of the main window that is causing the flicker in controls. It depends on where the actual flicker is, inside the client area or on the border of the control. Is there a way you can post an example of a window that is doing this ?
Getting rid of flicker is a big problem. Alot of the time it is not the WM_PAINT handler but the WM_ERASEBKGND of the main window that is causing the flicker in controls. It depends on where the actual flicker is, inside the client area or on the border of the control. Is there a way you can post an example of a window that is doing this ?
Hey Donkey,
I just readed that tutorial from icezilion site about flickering and applied it to icezilion example about painting text
and the PaintScreen proc is
But this code works just fine, the problem arise when I add static control with CreateWindowEx somewhere on window in which I want to show text/bitmap/icon. Then flicker is visible inside client area of that static control, when I resize main window. I dunno how to solve this, if I could tell static to draw it self on memory Dc and then to copy that DC to its client area, then I think it could solve the problem... What do you think?
I just readed that tutorial from icezilion site about flickering and applied it to icezilion example about painting text
.ELSEIF uMsg == WM_ERASEBKGND
mov eax,1
ret
.ELSEIF uMsg==WM_PAINT
INVOKE BeginPaint, hWnd, ADDR ps
INVOKE PaintScreen,hWnd
INVOKE EndPaint, hWnd, ADDR ps
and the PaintScreen proc is
PaintScreen proc hMainWnd:dword
;============================
; LOCAL VARIABLES
;============================
LOCAL hDC :DWORD
LOCAL hMemDC :DWORD
LOCAL ScreenRect :RECT
LOCAL hBitmap :DWORD
;=================================
; Get the client rectangle
;=================================
INVOKE GetClientRect, hMainWnd, ADDR ScreenRect
;============================
; get the DC
;============================
INVOKE GetDC, hMainWnd
MOV hDC, EAX
;============================
; Create a compatible DC
;============================
INVOKE CreateCompatibleDC, hDC
MOV hMemDC, EAX
;==============================
; Now create a Bitmap for that
; offscreen DC
;==============================
; MOV EAX, ScreenRect.right
; SUB EAX, ScreenRect.left
; MOV EBX, ScreenRect.bottom
; SUB EBX, ScreenRect.top
INVOKE CreateCompatibleBitmap, hDC, ScreenRect.right,ScreenRect.bottom;EAX, EBX
MOV hBitmap, EAX
;=============================
; Select that bitmap into the
; object, preserve old
;=============================
INVOKE SelectObject, hMemDC, hBitmap
PUSH EAX
;=============================
; Erase the Background
;=============================
INVOKE GetSysColor, COLOR_WINDOW
INVOKE CreateSolidBrush, EAX
PUSH EAX
INVOKE FillRect, hMemDC, ADDR ScreenRect, EAX
POP EAX
INVOKE DeleteObject,EAX
INVOKE GetClientRect, hMainWnd, ADDR ScreenRect
invoke GetStockObject,BLACK_BRUSH
invoke FillRect,hMemDC,addr ScreenRect,eax
invoke DrawText, hMemDC,ADDR OurText,-1, ADDR ScreenRect, DT_SINGLELINE or DT_CENTER or DT_VCENTER
;===========================
; Copy buffer to actual
;===========================
MOV EAX, ScreenRect.right
SUB EAX, ScreenRect.left
MOV EBX, ScreenRect.bottom
SUB EBX, ScreenRect.top
INVOKE BitBlt,hDC, ScreenRect.left, ScreenRect.top, EAX, EBX,\
hMemDC, 0, 0, SRCCOPY
;============================
; Select old int hMemDC
;============================
POP EAX
INVOKE SelectObject, hMemDC, EAX
;============================
; Delete the Compatible DC
;============================
INVOKE DeleteDC, hMemDC
;===============================
; Delete the Compatible Bitmap
;===============================
INVOKE DeleteObject, hBitmap
;================================
; release the device context
;================================
INVOKE ReleaseDC, hMainWnd, hDC
ret
PaintScreen endp
But this code works just fine, the problem arise when I add static control with CreateWindowEx somewhere on window in which I want to show text/bitmap/icon. Then flicker is visible inside client area of that static control, when I resize main window. I dunno how to solve this, if I could tell static to draw it self on memory Dc and then to copy that DC to its client area, then I think it could solve the problem... What do you think?
Well, just looking at the routine it has a couple of problems. First off, it should not use EBX without preserving it, it could just as easily use any other register in that place. Second there is no need to get the DC in this case as that is returned in eax from BeginPaint, it should be something like:
Also it is painting the background a couple of times (actually 3 times). There is no need to continually get the client rectangle if you don't change the values in the RECT structure. Also you should use SetTextColor and SetBkMode when painting text or you'll get weird results. There are a few other things. I have included a routine that will replace the static with a bitmap, you can set the offset where the bitmap will be painted to anywhere you like. I tried the code with these modifications and I did not get any flicker.
INVOKE BeginPaint, hWnd, ADDR ps
INVOKE PaintScreen,hWnd,eax
INVOKE EndPaint, hWnd, ADDR ps
PaintScreen proc hMainWnd:dword,hDC:DWORD
Also it is painting the background a couple of times (actually 3 times). There is no need to continually get the client rectangle if you don't change the values in the RECT structure. Also you should use SetTextColor and SetBkMode when painting text or you'll get weird results. There are a few other things. I have included a routine that will replace the static with a bitmap, you can set the offset where the bitmap will be painted to anywhere you like. I tried the code with these modifications and I did not get any flicker.
PaintScreen FRAME hMainWnd,hDC
;============================
; LOCAL VARIABLES
;============================
LOCAL hMemDC :D
LOCAL ScreenRect :RECT
LOCAL hBitmap :D
LOCAL hStatMemDC :D
;=================================
; Get the client rectangle
;=================================
INVOKE GetClientRect, [hMainWnd], ADDR ScreenRect
;============================
; Create a compatible DC
;============================
INVOKE CreateCompatibleDC, [hDC]
MOV [hMemDC], EAX
;==============================
; Now create a Bitmap for that
; offscreen DC
;==============================
INVOKE CreateCompatibleBitmap, [hDC], \
[ScreenRect.right],[ScreenRect.bottom]
MOV [hBitmap], EAX
;=============================
; Select that bitmap into the
; object, preserve old
;=============================
INVOKE SelectObject, [hMemDC], [hBitmap]
PUSH EAX
;=============================
; Erase the Background
;=============================
INVOKE GetSysColor, COLOR_WINDOW
INVOKE CreateSolidBrush, EAX
PUSH EAX
INVOKE FillRect, [hMemDC], ADDR ScreenRect, EAX
POP EAX
INVOKE DeleteObject,EAX
[b] ;=============================
; Paint the bitmap
;=============================
invoke CreateCompatibleDC, [hDC]
mov [hStatMemDC],eax
invoke SelectObject, [hStatMemDC],[hStatBitmap]
push eax
; note 10,10 is the x,y offset of the bitmap
invoke BitBlt,[hMemDC], 10, 10, 100, 100,\
[hStatMemDC], 0, 0, SRCCOPY
pop eax
invoke SelectObject,[hStatMemDC],eax
invoke DeleteDC,[hStatMemDC][/b]
invoke SetTextColor,[hMemDC],00FFFFh
invoke SetBkMode,[hMemDC],TRANSPARENT
invoke DrawText, [hMemDC],ADDR OurText,-1, ADDR ScreenRect,\
DT_SINGLELINE+DT_CENTER +DT_VCENTER
;===========================
; Copy buffer to actual
;===========================
MOV EAX, [ScreenRect.right]
SUB EAX, [ScreenRect.left]
MOV edx, [ScreenRect.bottom]
SUB edx, [ScreenRect.top]
INVOKE BitBlt,[hDC], [ScreenRect.left], [ScreenRect.top],\
EAX, edx,[hMemDC], 0, 0, SRCCOPY
;============================
; Select old int hMemDC
;============================
POP EAX
INVOKE SelectObject, [hMemDC], EAX
;============================
; Delete the Compatible DC
;============================
INVOKE DeleteDC, [hMemDC]
;===============================
; Delete the Compatible Bitmap
;===============================
INVOKE DeleteObject, [hBitmap]
ret
ENDF
You need to clip this static control, it's easy.
in WindowCreateEx ,.... as "style" set "WS_CLIPCHILDREN"
in WindowCreateEx ,.... as "style" set "WS_CLIPCHILDREN"