2.调试自定义控件

Posted crystal_lz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2.调试自定义控件相关的知识,希望对你有一定的参考价值。

2.调试自定义控件

原文请看我博客:http://clzf.co/blog.php?id=2

上一篇说了如何创建一个自定义控件 这一篇介绍一下怎么去调试一个自定义控件 其实吧我觉得这一篇没有多大意义 因为我感觉我不说大家都知道要怎么去调试 直接点就是 弄到窗体上去用用看就行了

在上一篇中忘了说 其实在新建项目的时候直接有个 【窗体控件库(Windows Forms Control Library)】:


新建好后右键工程 然后属性里面可以看到 他的输出类型是 Class Library  如果你做过Dll就会知道 到时候编译的时候是一个Dll文件而不是exe文件

新建好后 右边默认会给你新建一个 UserControl1 在这种环境下 你可以 直接F5 会弹出一个VS自带的那个啥  我也不知道该咋说不经常用这东西 就像这样:


可以看到这东西 和窗体设计时 右下角的属性窗口很像 是的 就是那个东西 用这个东西你可以在上面设置你控件的属性啥的 来调试你的控件 而在上面 你可以选择你要调试那个控件 而且你也看到了 我把第一篇文章里面写的MyControl没有在上面显示出来 至于这个问题是为什么 我只能说 我不知道 因为我不常用这东西 姑且理解为 这个东西只能调试容器控件吧那在这种情况下要怎么去调试MyControl?

很简单 对着解决方案 右键然后再新建一个WinForm工程 把它设为启动项目就行了:

而且我也经常这样干  如果你的控件本就在一个WinForm项目中 那就好办了 不用我说 你也知道该怎么办

注意:如果你在你的WinForm项目中 打开你的窗体 左边工具栏没有看到控件的话 不要害怕 不要惊慌 自己对着你WinForm工程的引用 右键 ->添加引用 在弹出来的窗体选【项目】选项卡 里面 把呢个Dll文件引用就可以了

这里说一点题外话吧  如果平时在做项目的时候 要用到自定义控件的话 如果你只有一两个控件的话 和你的WinForm项目写在一起 倒也无所谓 如果本来就要写很多个自定义控件 还是建议把控件单独一个Library工程写 当然 这个Library 不一定就是 Control Library 、 Class Libaray 也可以 脑子里面千万不要以为要写控件库就只能新建Control Library 要写普通Dll文件就只能新建 Class Library 你新建一个Class Library照样写控件 只是麻烦点 因为Class Library不会为你添加 System.Windows.Forms.Dll 的引用 自己在引用里面添加就可以 注意 我说的不是 代码里面的 using 的应用 是dll文件的引用

下面来看一个有趣的现象 依然那MyControl说事:

public class MyControl : Control

    protected override void OnPaint(PaintEventArgs e) 
        this.Controls[1].Text = "- -!";
        base.OnPaint(e);
    

如果在里面写上这样的代码会有啥后果? 编译肯定是能通过的 额不要说 你不知道this.Controls是啥 就是当前控件的子控件的一个集合

比如 如果是一个Form  那么 Form.Controls里面就是 窗体上的那些button textbox啥的被包涵在Form里面的控件 而控件又可以有子控件

比如 Panel 我们可以在Panel上面放一个Button  注意此时Button是属于Panel的 在Panel.Controls里面 如果这个Panel在Form上那么你在Form.Controls里面只能找到Panel找不到那个Button 如果你要找那个Button你可以这样 Form.Controls["Your Panel Name" or Index].Controls["Your Button Name" or Index];  好了扯远了

从上面那句代码来看 是没有错的前提是 确实在MyControl里面有至少两个控件的时候这句代码才算对 但是 当我们在左边工具栏上双击把它添加到窗体上的时候:

恭喜你 中奖了 不过注意啊  千万不要看到弹出一个错误框 弹了一大堆东西 而且还是一个XX就觉得不知所措了 这种情况可能以后会经常遇到 没有人能保证自己的代码一次写正确

分析一下为什么报错?在MyControl控件中 不排除以后可能会存在子控件 但是当控件才添加到窗体上的时候 它是没有子控件的 然而当控件在绘制的时候会执行Paint事件 由于控件才添加到窗体上去 控件会绘制一次自身 然后去执行Paint事件 而我们在Paint里面又出现了悲剧的代码 所以就悲剧了 这种问题没啥 好处理 直接去改控件代码就是了

再来看一种:

public class MyControl : Control

    protected override void OnPaint(PaintEventArgs e) 
        ((Form)this.Parent).Close();
        base.OnPaint(e);
    
这个样子把它放到窗体上去看看会有啥后果?

孩子 要是你以为这是最最糟糕的情况 那你就错了 我不会告诉你 至少我知道还有两种比这个更糟糕的情况

第一种列举的是控件自身出现的问题 这个是因为MyControl的出现导致了Form出现了问题 这种情况下 还好 至少你还在IDE里面 你还有机会去改代码 遇到这种情况 你还是去Form的Designer.cs里面把和你控件相关的东西 删除吧 然后重新编译一下就好了

好吧你不用找了 打开Designer文件 你是找不到MyControl的东西的 因为那个控件压根就还没有添加上去 执行添加控件的时候 由于控件里面的代码直接把窗体关了 导致后面的工作还没有做完窗体没了 所以才报出的那个错来 因为我实在是想不出了一个合适的办法 来引发一个让设计器崩掉的错误 我又不是每天闲的蛋疼专门想办法把程序搞崩的 - -!、、我只是在列举 到时候在开发过程中可能出现的问题而已 如果出现了这种让设计器蹦掉的情况 去Designer文件里面把那个控件的东西删了再重新编译一下就可以了

上面说了两种情况了 一个是自己出了问题的  一个是让设计器崩了的 下面我要说的是 直接让IDE崩的情况 好吧这种情况我只遇到过两次我也不知道要怎么引发那种情况 但我能引发一个最蛋疼的情况 最后来说 先来说说这种情况 由于我没法做一个效果出来看 我就描述一

你现在暂且这样理解 你在控件里面写的代码当控件被添加到窗体上去的时候 会由于IDE去执行一部分 而不是F5运行出来的时候才会去执行 感觉就像此时此刻 窗体就是桌面 而你的控件就是窗体 然后你脑子再YY一些做WinForm项目的时候 就像上一篇MyControl里面看到的Hello World一样 还有上面列举的两个错误一样 一添加到窗体上去的时候 就开始想正常的程序一样执行了 所以可能会存在这样一个问题 你写代码 逻辑上出现了冲突之类的啥的 然后一添加到窗体上IDE去执行那些代码的时候就悲剧了 是的崩掉了 就想写你普通程序的时候 F5 运行出来除了问题 崩掉了一样 只是这里崩的是IDE 这还没完 IDE蹦了之后 你再去打开IDE 恭喜你由于IDE又会去加载那些代码 然后继续崩、、、恭喜你中了大奖 没事VS也不是那么傻不拉唧的 根据我两次的情况来看 你重启了那么一两次都没有正常的时候 再次打开的时候 vs会提示你多次打开都没有成功 然后就这样直接打开文件不去执行那些了 恭喜你 赶紧去改代码重新编译吧、、或者用下面要说的这种方式

下面来看最后一个 也是最蛋疼的一个情况如果 在MyControl里面写这样的代码:

public class MyControl : Control

    protected override void OnPaint(PaintEventArgs e) 
        while(true)
        base.OnPaint(e);
    
让后再把控件添加到窗体上是啥效果?


恭喜你中了特等奖(当然这个框也可能是在上面的一个情况里面出现 如果是上面那种情况出现多半是自己跳出来的 因为环境确认了是你程序有问题 而我这里的这个是我手动点出来的 因为我发现vs没有反映了 鼠标点击什么的 vs变白了 然后我就想着要关闭他 然后点XX 就出来了 之所以不是自动跳出来是因为 严格来说 死循环不算是错误 谁说while(true)就不能通过编译?只是我们没有在循环里面跳出而已 所以环境就一直在执行死循环) 如果是上面那种情况还好 你折腾几下vs也不会让你折腾了、、你来几次都一样vs一打开就卡死 正如上面所说的 那句代码不算是错的 死循环怎么了?平时写代码的时候也经常用到死循环的写法 只是这里的代码没有在里面写逻辑而已  所以 无论你怎么折腾vs vs都会是一打开就卡死 别指望vs会嫌你折腾累了就不玩了  自己老老实实用记事本之类的去找到你得窗体的Designer把里面的 控件相关的代码删除吧 因为vs启动的时候回去加载那些文件 发现Designer文件里面 有要向窗体上添加你的控件的代码 于是就添加 结果一添加就悲剧 所以你去删了就没事了

可能你会觉得我上面的是吃饱了撑着 没事干了 没错 我上面确实是故意那样去写的  难道你就敢保证 你今后写的代码一定不会出现上面的情况?你的代码里面绝对不会因为一个不小心出现死循环?

一般出错的方式有两种 一种是你控件本来就有问题 然后添加到窗体上出错 还有一种情况是 你控件已经添加到窗体上了 你也没有删除控件 然后继续去修改控件的代码 编译 结果一切换回来发现 悲剧了

上面我列举的前三种情况是属于第一种 为什么最后一个不是?如果最后一个也属于第一种的话 那么你的IDE只会挂一次 因为就像上面列举的第二个情况一样 控件压根就还没有添加上去 因为在添加的过程中 就出现了悲剧 上面的第二种情况是把窗体关了 最后一个是死循环 那个时候控件还没有算正真添加到窗体上 所以最后一个的错误 是我先把控件添加到了窗体上 让Designer里面有了我的控件 我再去写的死循环

至于调试 怎么调试 就暂时写到这里吧 因为我也就能想到这些可写了、、、


以上是关于2.调试自定义控件的主要内容,如果未能解决你的问题,请参考以下文章

5.处理自定义控件焦点

5.处理自定义控件焦点

自定义控件

自定义控件 - 如何将聚合封装在另一个控件中

在设计期间在 VS(10) 中调试 C# .NET 自定义组件/控件

带有自定义控件的 MPMoviePlayerController