How to implement your own double buffering (Views: 28)
Problem/Question/Abstract: In order to give a control the appearance of being "transparent", in the WM_EraseBkgnd message processing section I'm invalidating the rectangle the control covers in the parent control's context and then having the parent control repaint itself in the rectangle that's hidden behind the control. However, this doesn't work when the control's DoubleBuffer property is set to true. Does anyone know how to get this working with double buffered controls? Answer: VCL double-buffering is ineffective and limited. If you need double-buffering, you will need to implement it yourself. To do this process the WM_PAINT message and do something like this: 1) Do your own effective double-buffering: procedure TCustomElPanel.WMPaint(var Msg: TWMPaint); var DC, MemDC: HDC; MemBitmap, OldBitmap: HBITMAP; PS: TPaintStruct; R: TRect; ARgn: HRGN; begin if (Msg.DC <> 0) then PaintHandler(Msg) else begin DC := GetDC(0); MemBitmap := CreateCompatibleBitmap(DC, ClientRect.Right, ClientRect.Bottom); ReleaseDC(0, DC); MemDC := CreateCompatibleDC(0); OldBitmap := SelectObject(MemDC, MemBitmap); try DC := BeginPaint(Handle, PS); GetClipBox(DC, R); if IsRectEmpty(R) then R := ClientRect else begin InflateRect(R, 1, 1); end; with R do ARgn := CreateRectRgn(Left, Top, right, Bottom); SelectClipRgn(MemDC, ARgn); Perform(WM_ERASEBKGND, MemDC, MemDC); Msg.DC := MemDC; WMPaint(Msg); SelectClipRgn(MemDC, 0); DeleteObject(ARgn); Msg.DC := 0; with R do BitBlt(DC, Left, Top, Right, Bottom, MemDC, Left, Top, SRCCOPY); EndPaint(Handle, PS); finally SelectObject(MemDC, OldBitmap); DeleteDC(MemDC); DeleteObject(MemBitmap); end; end; end; 2) When painting, ask your parent to draw on your canvas or do the following: { ... } if Transparent then begin GetClipBox(Canvas.Handle, Rect); OffsetRect(Rect, Left, Top); RedrawWindow(Parent.Handle, @Rect, 0, RDW_ERASE or RDW_INVALIDATE or RDW_NOCHILDREN or RDW_UPDATENOW); begin OffsetRect(Rect, -Left, -Top); DC := GetDC(Handle); bitblt(Canvas.Handle, 0, 0, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top, DC, Rect.Left, Rect.Top, SRCCOPY); ReleaseDC(Handle, DC); end; end; { ... } |