C#剖析系列――控件继承
首先想要告诉大家的是ms一个龌龊的行为,一个人所共知的行为。而这个问题在所有ms提供的基本控件里都存在,比如我们想要对combobox这个控件稍微的扩展一下,加上一点点我们自已的东东。结果是很麻烦,很麻烦,甚至你都没办法使用继承来重载onpaint.因为正常情况下,onpaint在这个控件里永远不会调用,当然ms告诉你可以用this.setstyle(controlstyles.userpaint)来激活这个方法,很好,不过当你运行了一下,发觉好象不是这么简单,
protected override void onpaint(painteventargs e)
{
base.onpaint (e);
}
什么东东都没有了,就是一个白板,这时候你除了自已重新绘制,别无它法。
当然聪明的程序员不会被ms的小伎俩难倒。既然你不让我从onpaint重载,你总得使用消息吧,那我重载wndproc
private static int wm_paint =0x000f;
protected override void wndproc(ref message m)
{
base.wndproc (ref m);
if(m.msg == wm_paint)
{
graphics g =this.creategraphics();
//g.drawline(new pen(color.blue), 0,0,100,100);
string str =this.getstyle(controlstyles.userpaint).tostring();
g.drawstring(str,new font("宋体",10),brushes.blue,new rectangle(0,0,100,100));
g.dispose();
}
}
很好,现在是不是你可以随心所欲地加上你自已想要的东东了。
方法知道了,想知道原理么?
程序员是追求真理的人群。老办法,还是请出reflector,分析分析源码,因为所有的控件都是从control继承的,基本控件也不例外,那么我们来看看onpaint方法是如何调用的? control类中的核心是wndproc,呵呵,这就是上篇也提到过的窗口过程,从这里跟踪起就象抓住了鱼网的拉纤。
因为wm_paint常数值是15,很快我们就来了这一小段
case 15:
if (this.getstyle(controlstyles.userpaint))
{
this.wmpaint(ref m);
return;
}
this.defwndproc(ref m);
return;
当wm_paint消息进入队列时,注意如果是userpaint就会调用wmpaint,否则就由系统默认的过程处理。那么wmpaint里有些什么东东呢,太长了,不过总而言之,它会调用paintwitherrorhandling这个方法,然后这个方法又会调用onpaint,而onpaint才会激发paint事件。而control和form的userpaint位都会默认设为true,因此才能够进行简单的重载onpaint,而象基本控件其userpaint都会是false,象上面重载wndproc而进行绘制的代码段,会打印出一个蓝色的false.
文章整理:iocblog
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。