C#剖析系列――控件继承

分类: C#   出处:iocblog整理  更新时间:2009-05-21   添加到收藏  

    首先想要告诉大家的是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();[来源www.iocblog.net]

     }

}

    很好,现在是不是你可以随心所欲地加上你自已想要的东东了。

    方法知道了,想知道原理么?

    程序员是追求真理的人群。老办法,还是请出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.

[1] [2] 下一页



文章整理:iocblog
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。