2010. január 1., péntek
How to implement your own double buffering
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;
{ ... }
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése