副标题#e#
这篇文章提及内容大概各人已经在许多处所看到过了,作者也是如此,只不外还看了许多VCL源代码,加上本身实际编写元件的履历,拼凑了这么一篇文章。所以所有言论都是小我私家概念、履历的描写,仅供参考。
你可转载,拷贝,但必需插手作者署名Aweay,假如用于贸易目标,必需颠末作者同意。
系统要求
假如你想一起随着做的话,那么你应该看看这里,不然你可以直接跳过。
C++ Builder6 + updata4 (上帝造人的东西,以下简称BCB)
Windows2k or higher (须要)
作者强烈发起你利用WinNT,BCB在Win9x下有很是多的问题,并且很是不不变,就算你不在乎这个,尚有一个很是致命的问题,BCB的辅佐文件在Win9x下显示不完全(因为BCB的辅佐索引要害字数量高出Win9x的限制),这样很是难于参考辅佐。
Delphi6 🙁 (须要)
什么?是不是写错了,完全没有写错,假如你要深入VCL查察源代码的话,在没有比用Delphi6更符合的了,在全部安装Delphi6后,把VCL Source的目次插手Search Path中,这样你可以在编辑器中按住Ctrl键,点击鼠标直接跳转到源代码处很是利便,比什么grep好用多了。
起步
对付VCL的动静机制,各人可以参考CKER的
http://www.csdn.net/develop/read_article.asp?id=8131
反复的内容我就不先容了,可是对付编写元件来说上面的动静机制照旧很恍惚,并且许多时候并不是用那些要领来处理惩罚动静的,尚有就是元件特有的CM_XXXXXXXX动静如那里理惩罚呢?如何插手本身的事件呢?这些问题我会在后头的接头中做具体先容。
站在巨人的肩膀
编写元件的第一件工作就是确定我们从哪里担任的问题,选取一个好的祖先类是编写一个好的元件的第一步,那么到底如何选取他山之石呢?一般性的法则是这样的:
1.对付有界面的显示的,需要处理惩罚键盘事件的,又不是容器的组件从TCustomControl担任
2.对付有界面的显示的,需要不处理惩罚键盘事件的,需要处理惩罚鼠标事件的从TGraphicsControl担任
3.对付没有界面显示的,雷同与TOpenDialog/TXpMenu这样的控件从TComponent担任
#p#副标题#e#
4.假如你想扩展某个指定的控件,好比TPanel,你最好从TCustomPanel担任,而不要从TPanel直接担任。
留意上面第4条法则,根基上所有组件都有TCustomXXX的父类,这也是VCL勉励的担任工具,原因在于你可以定制元件属性的可见性,最重要的是他们的结构函数和析构函数是虚拟的。
这篇文章主要针对1,2法则的元件举办先容,3,4相对简朴就不作深入接头了。
画出本身
元件要显示在窗体上,必需以必然的样子呈现,那么可定要画出本身,各人都知道处理惩罚WM_PAINT动静就可以了,从CKER的文章里,我们可以得出许多要领来处理惩罚这个动静,好比:
__fastcall WndProc(TMessage msg)
{
switch(msg->msg)
{
case WM_PAINT:
//我们的处理惩罚代码
…
}
可能爽性用动静映射的宏,但这些都不是最好的要领。
从TControl今后的组件都有Paint这个虚拟要领,我们只要重载这个要领就可以自动绘制,相当于处理惩罚了WM_PAINT,这是因为:
procedure TGraphicControl.WMPaint(var Message: TWMPaint);
begin
if Message.DC <> 0 then
begin
Canvas.Lock;
try
Canvas.Handle := Message.DC;
try
Paint;
finally
Canvas.Handle := 0;
end;
finally
Canvas.Unlock;
end;
end;
end;
以上代码片段说明白这一点,据我所研究过的专业级组件都是通过重载这个函数来绘制本身的。
留意上面的代码片段就是用我上面提到的要领(装delphi6)按了屡次鼠标左键获得的,是不是很实惠,^_^。
在Paint方里我们可以自由绘制,在后头的文章里我会交各人如何高效率绘制。
在许多时候,我们需要重绘本身,好比我前几天给网友做的划线的组件,当线的宽度改变时我们必需重绘本身,不然无法反应属性的改变,我见许多伴侣利用repaint()要领,这也不是最好的要领,我们应该用Invalidate(),为什么?留给各人看源代码吧,就算温习上面的常识了。
代码演示:
void __fastcall TLine::SetLineWidth(int value)
{
//TODO: Add your source code here
if(FLineWidth!=value)
{
FLineWidth=value;
Invalidate();
}
}