5

我正在尝试做简单的事情:在 TScrollBox 后代上添加 Canvas 属性。我读过这篇文章

但我的 ScrollBox 后代根本不在画布上绘制。有人可以告诉我,有什么问题吗?

  TfrmScrollContainer = class (TScrollBox)
  private
    FCanvas: TCanvas; 
    FControlState:TControlState;
    procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  protected
    procedure Paint;
    procedure PaintWindow(DC: HDC); override;
    property Canvas: TCanvas read FCanvas;
  public
    constructor Create(AOwner: TComponent);  override;
    destructor Destroy; override;
  end;

...这是精确的副本,TWincontrol 如何转向 TCustomControl(但它在某处失败)

constructor TfrmScrollContainer.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FCanvas := TControlCanvas.Create;
  TControlCanvas(FCanvas).Control := Self;
end;

destructor TfrmScrollContainer.Destroy;
begin
  FCanvas.Free;
  inherited Destroy;
end;

procedure TfrmScrollContainer.WMPaint(var Message: TWMPaint);
begin
  Include(FControlState, csCustomPaint);
  inherited;
  Exclude(FControlState, csCustomPaint);
end;

procedure TfrmScrollContainer.PaintWindow(DC: HDC);
begin
  FCanvas.Lock;
  try
    FCanvas.Handle := DC;
    try
      TControlCanvas(FCanvas).UpdateTextFlags;
      Paint;
    finally
      FCanvas.Handle := 0;
    end;
  finally
    FCanvas.Unlock;
  end;
end;

procedure TfrmScrollContainer.Paint;    // this is not executed (I do not see any ellipse)
begin
  Canvas.Brush.Color:=clRed;
  Canvas.Ellipse(ClientRect);
end;

谢谢

4

1 回答 1

7

您不包括csCustomPaintto ControlState,而是将其包括在您声明的类似名称的字段中。你的字段没有被检查,上位控制对此一无所知。解决,更换

procedure TfrmScrollContainer.WMPaint(var Message: TWMPaint);
begin
  Include(FControlState, csCustomPaint);
  inherited;
  Exclude(FControlState, csCustomPaint);
end;

procedure TfrmScrollContainer.WMPaint(var Message: TWMPaint);
begin
  ControlState := ControlState + [csCustomPaint];
  inherited;
  ControlState := ControlState - [csCustomPaint];
end;


或者,您的滚动框可以作为自定义绘画工作的任何控件的父级。继承的WM_PAINT处理程序检查控制计数,如果它不为 0,它会调用绘制处理程序,而不是将消息传递给默认处理程序。

于 2013-08-15T00:50:41.467 回答