Delphi 为什么画布是;“隐藏的”;在所有VCL控件中?
我想做一个基本的过程,在任何控件(按钮、面板等)的画布上绘制一些东西(为了简单起见,让我们说一个三角形): 在这个函数中,我需要使用Control.Width&Control.Height来知道控件有多大。 事实证明,这比想象的要困难,因为画布是受保护的 一种解决方案是获取过程中控件的画布:Delphi 为什么画布是;“隐藏的”;在所有VCL控件中?,delphi,canvas,vcl,lazarus,Delphi,Canvas,Vcl,Lazarus,我想做一个基本的过程,在任何控件(按钮、面板等)的画布上绘制一些东西(为了简单起见,让我们说一个三角形): 在这个函数中,我需要使用Control.Width&Control.Height来知道控件有多大。 事实证明,这比想象的要困难,因为画布是受保护的 一种解决方案是获取过程中控件的画布: VAR ParentControl: TWinControl; canvas: TCanvas; begin ParentControl:= Control.Parent; Canvas:=
VAR
ParentControl: TWinControl;
canvas: TCanvas;
begin
ParentControl:= Control.Parent;
Canvas:= TCanvas.Create;
TRY
Canvas.Handle:= GetWindowDC(ParentControl.Handle);
WITH Canvas DO
xyz
FINALLY
FreeAndNil(canvas);
END;
end;
但是每次我想画一些东西的时候,创建和破坏画布似乎是对CPU的浪费
因此,我的问题是:
interposer
类,则无需安装组件
您也可以考虑重写<代码>油漆>代码>方法,并将您的绘图代码放在那里。
< P>在对该问题的评论中发现TCustomControl
子体就足够了,并且//
//所需基础设施
//
类型
TCustomControlCracker=类(TCustomControl)
结束;
函数CustomControlCanvas(AControl:TCustomControl):TCanvas;
开始
结果:=TCustomControlCracker(AControl).Canvas;
结束;
//
//我的可重用绘图功能
//(只能在TCustomControl子体中使用)
//
程序控制(A控制:TCustomControl);
变量
画布:TCanvas;
开始
画布:=CustomControlCanvas(AControl);
TextOut(10,10,'Frog');
结束;
请注意,DrawFrog
只接受一个参数,即控件本身。然后,它可以使用一个简单的函数调用获得控件的画布,而CPU开销非常小
完整示例:
单元1;
接口
使用
Winapi.Windows、Winapi.Messages、System.SysUtils、System.Variants、System.Classes、Vcl.Graphics、,
控件、窗体、对话框、ExtCtrls、StdCtrls;
类型
TForm1=类(TForm)
过程表单创建(发送方:ToObject);
私有的
{私有声明}
公众的
{公开声明}
结束;
变量
表1:TForm1;
实施
{$R*.dfm}
类型
TTestControl=类(TCustomControl)
受保护的
程序漆;推翻
结束;
类型
TCustomControlCracker=类(TCustomControl)
结束;
函数CustomControlCanvas(AControl:TCustomControl):TCanvas;
开始
结果:=TCustomControlCracker(AControl).Canvas;
结束;
程序控制(A控制:TCustomControl);
变量
画布:TCanvas;
开始
画布:=CustomControlCanvas(AControl);
TextOut(10,10,'Frog');
结束;
过程TForm1.FormCreate(发送方:TObject);
开始
使用TTestControl.Create(Self)do
开始
父母:=自我;
顶部:=100;
左:=100;
宽度:=400;
高度:=200;
结束;
结束;
{TTestControl}
程序控制。油漆;
开始
继承;
Canvas.Brush.Color:=clSkyBlue;
Canvas.FillRect(ClientRect);
牵引蛙(自身);//使用我的可重用青蛙绘图功能
结束;
结束。
尽管如此,我个人仍然会使用传递
TCanvas
(甚至是HDC
)的标准方法,而不是控件,以及一些维度:
procedure DrawFrog(ACanvas: TCanvas; const ARect: TRect);
这将允许我将其用于其他控件(不仅是
TCustomControl
子体),以及打印机画布等。您不应该这样做。控件应该自己绘制。恐怕Olivier是对的。你什么时候在控件上绘图?通常,只有在收到窗口的WM_PAINT
消息时,才能在其上绘制窗口。在其他时间(例如在OnClick
事件处理程序中)在画布上绘制是不可行的(没有很多问题)。据我们所知,控件可能会在添加三角形后的毫秒内选择重新绘制自身。此外,许多Win32控件在一开始就很难自定义绘制。这里的想法是,如果我有一个包含大量代码的绘制过程,我需要在几个自定义控件中复制所有这些代码。。。。这与“代码的可重用性”的概念不符。@InNameofScience:现在我明白你的意思了。然后,解决方案是使用一个过程DrawTriangle(ACanvas:TCanvas;const-ARect:TRect)
,它在ARect
处的ACanvas
画布中绘制三角形。事实上,这就是所有GDI在Win32中的幕后工作方式。例如,请参见函数:它采用HDC,这在功能上相当于TCanvas
。(本质上说:你不是在控件上画画,而是在“画布”上画画。)我通常有s FCN,以便能够在scn和打印机的简历上画画。@以科学的名义:我理解。我可以想出一些“解决方案”,但它们都需要比简单地传递两个附加参数更多的工作:)仅供参考,VCL有一个用于在任何t控件上绘图的类。因此,您不需要手动打开TCustomControl.Canvas
。如果我出于其他原因需要画布,该怎么办?不是为了在上面画画吗?例如,我想截断带有省略号的文本。为此,我需要访问画布来测量文本大小
procedure DrawFrog(ACanvas: TCanvas; const ARect: TRect);