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?
Posted on 2004-02-12 08:27:07 by Mikky
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 ?
Posted on 2004-02-12 14:21:51 by donkey
Hey Donkey,

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?
Posted on 2004-02-12 17:50:06 by Mikky
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:

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
Posted on 2004-02-12 19:51:19 by donkey
You need to clip this static control, it's easy.
in WindowCreateEx ,.... as "style" set "WS_CLIPCHILDREN"
Posted on 2004-02-13 02:33:36 by Ultrano