PaintTo不适用于我的组件

时间:2011-01-14 22:48:40

标签: delphi

大家好 我创建了一个派生自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;

3 个答案:

答案 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消息更容易。