请考虑下面的代码:TBitmap后不相关的图形代码失去裁剪区域
type
TBaseControl = class(TWinControl)
private
FBitmap : TBitmap;
public
constructor Create(AOwner : TComponent); override;
procedure DrawBorder;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
NewC : TBaseControl;
implementation
{$R *.dfm}
constructor TBaseControl.Create(AOwner : TComponent);
begin
inherited Create(AOwner);
FBitmap := TBitmap.Create;
FBitmap.PixelFormat := pf24bit;
FBitmap.SetSize(100,100);
end;
procedure TBaseControl.DrawBorder;
var
Region : HRGN;
ContentRect : TRect;
begin
// Almost like a Client Area of a control
ContentRect := Rect(10,10,FBitmap.Width - 10,FBitmap.Height - 10);
// Create clipping region on FBitmap with ContentRect being excluded
Region := CreateRectRgnIndirect(Rect(0,0,Width,Height));
SelectClipRgn(FBitmap.Canvas.Handle,Region);
ExcludeClipRect(FBitmap.Canvas.Handle,ContentRect.Left,ContentRect.Top,
ContentRect.Right,ContentRect.Bottom);
DeleteObject(Region);
// Do Pre-drawing
FBitmap.Canvas.Brush.Style := bsSolid;
FBitmap.Canvas.Brush.Color := clRed;
FBitmap.Canvas.FillRect(Rect(0,0,FBitmap.Width,FBitmap.Height));
// Will comment out one of these statements
// The graphics one (.Caption) will cause the clipping to be lost. Any
// graphics code will do it as long as it is not related to FBitmap
// ========================================================================
Form1.Caption := 'You have just lost your Bitmap''s clipping';
// -----
Form1.Tag := Random(1000);
// ========================================================================
// Do some drawing afterwards
FBitmap.Canvas.Brush.Color := clGreen;
FBitmap.Canvas.FillRect(Rect(5,5,FBitmap.Width - 5,FBitmap.Height - 5));
// Want to see what it looks like
FBitmap.SaveToFile('d:\test.bmp');
// Test the tag setting
ShowMessage(InttoStr(Form1.Tag));
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// Create an instance of TBaseControl
NewC := TBaseControl.Create(Self);
NewC.SetBounds(0,0,200,200);
NewC.Parent := Self;
// Tell it to draw
NewC.DrawBorder;
end;
在DrawBorder
,如果我只设置Form1的标签没有字幕被设置,那么FBitmap的剪辑区域保持和在整个绘图代码中受到尊重。 FBitmap看起来就像这样:
但如果Form1的标题设置然后FBitmap将失去它的剪切区域,看起来像这样:
如此看来,后Form1的标题是设置FBitmap失去了它的剪辑区域。当发生这种情况时,WindowOrigins(通过SetWindowOrgEx设置)也会丢失。
该位图丢失了其画布(在D2009中该表单标题更改后,其句柄将变为0)。控制权未被重新创建。你有没有试图牺牲一只小棕松鼠或类似的树木动物?这真的没有意义。 – Victoria
@Victoria当你考虑到VCL缓存GDI资源并且经常(在消息处理期间)释放未被主动锁定的画布HDC时,它是有意义的。不要指望GDI设置随着时间的推移而被保留下来。只要你需要画东西就重置它们。由'DrawBorder'设置的区域在执行返回主消息循环后可能无效(例如由于'Caption'更改触发重绘) –