大家好
我创建了一个派生自TWinControl
的新组件。
我把它放在TPanel
上,我试着调用面板的PaintTo
程序。结果是面板及其标题,我的组件根本没有画在画布上。我该怎么办呢?
来源的一部分(亲爱的大卫问道):
Procedure TApListBox.Paint;
var
C: TCanvas;
B: TBitmap;
ItemClient: TPoint;
Begin
Try
If (FUpdating > 0) Then
Exit;
Try
BeginUpdate;
B := TBitmap.Create;
B.Width := Width;
B.Height := Height;
With B.Canvas Do Begin
Lock;
// Begin :
ItemClient := Point(IVisPanel + 3, 2);
// Draw Items
PaintItems(B.Canvas, ItemClient);
Unlock;
End;
C := TCanvas.Create;
C.Handle := GetWindowDC(Self.Handle);
C.Lock;
inherited;
C.Draw(1, 1, B);
If (RenameEdit.Visible) Then
RenameEdit.Repaint;
Finally
C.Unlock;
ReleaseDC(0, C.Handle);
C.Free;
B.Free;
Dec(FUpdating);
End;
Except
End;
End;
答案 0 :(得分:2)
你真的不需要调用或覆盖PaintTo。
相反,您应该在重写的Paint方法中完成100%的绘画。绘画可以随时发生,一个组件需要能够按需绘画。发生的方式是Windows发送一条WM_PAINT消息,VCL将该消息转换为对组件的Paint方法的调用。
因此,请确保您的组件可以随时绘制所需的内容,并且在重写的“Paint Method”中执行所有绘制。
答案 1 :(得分:1)
在处理WM_PAINT消息的方法中,不能直接使用Canvas,因为WM_PAINT在Message.DC参数中指定了GDI句柄(HDC)。
例如,看一下TGraphicControl的代码片段,它按预期处理它:
procedure TGraphicControl.WMPaint(var Message: TWMPaint);
begin
if Message.DC <> 0 then
begin
Canvas.Lock;
try
Canvas.Handle := Message.DC;
try
Paint; // this is where the painting is done, using a "locked" Canvas
finally
Canvas.Handle := 0;
end;
finally
Canvas.Unlock;
end;
end;
end;
请检查您的WM_PAINT实现方法,并遵循此代码方案。
使用Canvas属性放置您自己的绘图代码,而不是上面的“Paint”方法。
“PaintTo”方法将按预期工作。
另一种可能性是使用直接的Windows API绘图,使用Message.DC句柄...但我想上面的方法,允许使用常规的Canvas,对我们大多数人来说更容易! ;)
在所有情况下,WM_PAINT不应该是Delphi组件实现绘制的地方,而只是一个重写的Paint方法。因此,让您的组件继承自TGraphicControl,并将所有绘图代码放入一个重写的Paint方法中。
答案 2 :(得分:1)
您的基类应该是TCustomControl
,而不是TWinControl
。前者设置控件的画布,以便您可以通过覆盖Paint
来正确绘制它。
如果您坚持自己处理wm_Paint
,请确保使用WParam
参数作为显示上下文(如果已提供)。形式上,该参数未使用,但VCL(以及一些常用控件)使用该参数,这使得实现wm_PrintClient
消息更容易。