Vs自定义控件设计第一例(直线控件的设计)

目录

一、 杨老师是个热情的人

二、 开始喽

三、 还需要些解释什么吗

四、 OK了吗

五、最终代码

一、杨老师是个热情的人

我们的项目开源有一段时间了,我一直以为我有一个很不错的胸怀把自己花了很多精力做出来的项目贡献出来了,我以为同学们会很开心,会像“一个饥饿的人看到面包”一样的扑到了我的项目代码上面快乐的研究起来,但是事实上我们的群里面却异常的冷清。我想应该是大家都还在研究代码来不及说话或者是不爱说话吧,直到今天杨老师给我打电话,说了一些情况,似乎是说大家还不太懂数据库等等,我才知道是我错了,生活往往是这样:你没想到的太多了……。杨老师是我最佩服的老师,他是一个充满热情的人。电话里面一直邀请我再和同学们去讲个课帮助大家看懂这些代码,可以让这个项目学习继续下去,这样也不枉费当初的一番好的初衷。但是我想,我可能不是一个会讲课的人,再去讲课也太正规了一点,我跟杨老师商量一个折中的办法:利用大家已经加入的QQ群,我尝试着写几个教程,跟大家一起从零开始介绍一些我的项目里面可能会用到的知识,但愿这样可以帮到大家。

我不确定我能不能坚持下去(可能这也是我不敢去和同学们讲课的原因之一吧。人有时是没办法太了解自己的),但是不管怎么样,大家一起努力,今天就从第一个开始吧。

在Microsoft Visual Studio 2012(以下简称VS)里面,有许多的控件可供日常窗体设计的需求。但是很多时候,我们需要的控件却找不到,比如:画一条直线。当然,我们也不能太苛求Microsoft,毕竟他们已经做得够好。更何况有时我们还会忘记支付他们软件使用费……。

在多年前(你们可能还不是小学生的时候,估计应该是人了)我有一个项目做得很好,我以为业主会很满意,事实上他们也真的很满意。只有在最后我要交货,他们要付款(这个是我当时最看重的一个环节)之前,老板很轻描淡写的说了一句,那么复杂的界面(真的很复杂吗,如下图。但是伦家是付款的资本方,顾客就是上帝呀,以后你们会知道的),你就不能画几条线分割一下吗?

我想也对,可是回去后我在工具栏里面却怎么也找不到可以画一条线的控件,多简单的一件事情,Microsoft竟然不能帮我,我曾经无比崇拜的Bill,你到哪里去了……。后来我用Ps做了二条线解决了问题(那时候我还不会自定义控件,错怪了Bill),但是这个事情让我在很长的一段时间里面感到惭愧,认为自己不是一个合格的程序员。当然,今天我做到了,就像下面这个图所示:

二、开始喽

好吧,言归正传。要做这件事(做一个可以画一条线的控件),当然第一个事情是打开VS(如果你有安装的话),新建一个项目(这个应该不难):

第二步:在新建的这个项目里面,右单击”LineControlsTest”这个项目,在出现的菜单里面找到“添加”,然后选择“用户控件”。添加一个用户自定义控件,我发现我还是不会讲,用图片来说明吧(有图有真相)

第三步:做完上面这几个步骤之后,你们应该可以看到这个界面:

在这个界面下按下“F7”这个按键(好吧,我开始讨厌自己这么啰嗦了),进入代码编辑界面。如下图:

把控件的继承类从原来的“UserControl”改为“Control”,这样做的目的是不要VS自动帮我们做的界面,这个界面我们要自己做。但是这样做会出现错误,按一下F5运行项目时会报错,如下:

解决办法是把“ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;”这句代码删除掉就可以了,因为这句代码是针对“UserControl”类的,我们现在从Control类继承,不需要这句代码。(还有一种做法不会报错,就是新建一个类,而不是新建一个用户控件,然后让这个类继承System.Windows.Forms.Control类,但是这种做法要在Using里面增加几个引用,有兴趣的童鞋可以试试,效果是一样的)

第四步:开始写代码了,这个是最重要的,也是本次这个项目的唯一需要我们动脑的一个环节。好吧,下面剩下的事情变得简单了,只需要把下面的代码Copy到类里面就完成了。建议你们亲自动手在VS里面打入这些代码,会有新发现哦。

protected override void OnPaint(PaintEventArgs e)

{

Pen pen = new Pen(SystemColors.ControlText);//定义一个画笔

this.Height = 18;//设置本控件的高度

pen.Width = 1;//设置画笔的宽度

e.Graphics.DrawLine(pen, 0, this.Height - pen.Width, this.Width - 1, this.Height - pen.Width); //在控件的底部画一条线

Brush br =new SolidBrush(SystemColors.MenuHighlight); //定义一个刷子

SizeF sizeF = e.Graphics.MeasureString(Text, this.Font); //根据控件设置的字体和控件的文字(Text)属性,获取控件文字在本控件中的大小

e.Graphics.DrawString(Text, this.Font, br, (this.Width-sizeF.Width)/2,1);//根据上面这行代码获取的文件大小,在控件的中间写上控件的文字

br.Dispose();//笔刷用完了就要清楚掉,避免占用内存

base.OnPaint(e);//这句不能少,这个是调用基础类(Control)的OnPaint代码

}

第五步:解决方案里面右单击项目名称,在出现的菜单里面点击“生成”。

第六步:双击解决方案里面的Form1,在出现的Form1窗体界面上面,可以看到我们设计的控件出现在工具栏里面了,拖动我们自己的控件(PxyLine),到窗体上面,可以看到我们做得控件实现了我们开始设计的功能。

太简单了,但不是所有的项目都这么简单的。

三、还需要些解释什么吗

我想我已经讲得很清楚了,以我这样的文字功底,这个已经是我能说的最清楚的事情了,更何况我的代码里面每一句都有注释(这个在平常是不可能的)。如果一定还要讲的,就是这个override和OnPaint,不过也许你们可以找一下帮助文档。微软官方是这样解释override的:要扩展或修改继承的方法、属性、索引器或事件的抽象实现或虚实现,必须使用 override 修饰符。至于OnPaint微软讲得更简单:引发 Paint 事件。当然,通过这个项目,也许你会有所体会。

四、OK了吗

如果只是满足基本功能,这样是OK了,但是如果是我公司的人交付给我这样的代码,我是远不能满意的(我不算是苛刻的老板,但是这样的代码真的太烂了,居然是我写的:-()。

比如:文字为什么是居中显示的,如果我需要靠左显示呢?能不能做一个属性,我设置一下就可以改变显示方式呢?

比如:控件高度怎么写死在里面呀,如果我需要修改控件高度,是不是一定要到源代码里面去修改并且重新编译呀?这也太次了吧

比如:如果我要求画的线粗一些呢?

比如:文件的颜色和线条的颜色呢?

还有,再比如……,你们也想象一下 :)

好吧再加点料,针对上面说的几个比如,我再做一个补充,其他几个交给你们去实现。我希望你们实现完了也和我一样,把代码分享出来让大家也乐一乐(也许我可以对你们的代码再提一下修改意见)。

第一步:为了把控件的线条粗细做成可以调整,我们定义一个私有变量penwidth,并且默认值为1,代码如下:

private int penwidth = 1;

第二步:封装:选中penwidth(鼠标放置在penwidth这几个字母里面),右单击出现如下菜单(最简单的方法是在此时按下Ctrl+R,再按下E):

VS会自动生成如下代码:

public int Penwidth

{

get { return penwidth; }

set { penwidth = value; }

}

再在上做一些注释(这个是我比较骄傲的一个好习惯,不知道你们有没有),成了这样的

/// <summary>

/// 设置画笔宽度

/// </summary>

public int Penwidth

{

get { return penwidth; }

set { penwidth = value; }

}

对了,还要加上这个[Browsable(true), Category("自定义"), Description("设置控件画笔宽度")],成了这样的:

/// <summary>

/// 设置画笔宽度

/// </summary>

[Browsable(true), Category("自定义"), Description("设置控件画笔宽度")]

public int Penwidth

{

get { return penwidth; }

set { penwidth = value; }

}

好吧,我已经看到有同学举手了。

“[Browsable(true), Category("自定义"), Description("设置控件画笔宽度")]”是什么,看一下这个:

上面这段代码添加之后,我们点击Form1上面的pxyLine控件,在该控件的属性窗体里面就会出现一个“自定义”的目录,里面就是我们刚才定义的控件属性“penWidth”,在这里,用户可以自由设置控件的Penwidth属性。其他的详细解释找百度。

第三步,修改Onpaint代码。

把原来的这句代码:pen.Width = 1;改成:pen.Width = Penwidth;

好了,这回是真正的OK了,“完整”代码贴在下面。其它几个“比如”就靠你们了。

五、最终代码

public PxyLine()

{

InitializeComponent();

}

private int penwidth = 1;

/// <summary>

/// 设置画笔宽度

/// </summary>

[Browsable(true), Category("自定义"), Description("设置控件画笔宽度")]

public int Penwidth

{

get { return penwidth; }

set { penwidth = value; }

}

protected override void OnPaint(PaintEventArgs e)

{

Pen pen = new Pen(SystemColors.ControlText);//定义一个画笔

this.Height = 18;//设置本控件的高度

//pen.Width = 1;//设置画笔的宽度

pen.Width = Penwidth;//使用控件的属性,这样使用者可以通过修改属性来控制这个控件的行为,而不是修改源代码后再编译

e.Graphics.DrawLine(pen, 0, this.Height - pen.Width, this.Width - 1, this.Height - pen.Width); //在控件的底部画一条线

Brush br =new SolidBrush(SystemColors.MenuHighlight); //定义一个刷子

SizeF sizeF = e.Graphics.MeasureString(Text, this.Font); //根据控件设置的字体和控件的文字(Text)属性,获取控件文字在本控件中的大小

e.Graphics.DrawString(Text, this.Font, br, (this.Width-sizeF.Width)/2,1);//根据上面这行代码获取的文件大小,在控件的中间写上控件的文字

br.Dispose();//笔刷用完了就要清除掉,避免占用内存

base.OnPaint(e);//这句不能少,这个是调用基础类(Control)的OnPaint代码

}

时间: 2024-10-07 18:26:32

Vs自定义控件设计第一例(直线控件的设计)的相关文章

Qt编写自定义控件23-广告轮播控件

一.前言 广告轮播这个控件做的比较早,是很早以前定制一个电信客户端时候用到的,该客户端需要在首页展示轮播预先设定好的图片,图片的路径可以自由设定,然后轮播的间隔速度可以自由控制,同时该控件还需要提供两种指示器的风格,一种是迷你型的样式,一种是数字型的样式. 本控件很早就做好了,由于当时的QPainter功力不足,还不是很熟悉QPainter,采用的是效率比较低的直接用现有控件堆积而成,比如指示器采用的QLabel,用样式表来控制对应的形状,指示器所在的底部放一个widget,采用左右布局,然后右

Qt编写自定义控件24-图片轮播控件

一.前言 上一篇文章写的广告轮播控件,采用的传统widget堆积设置样式表做的,这次必须要用到更高级的QPainter来绘制了,这个才是最高效的办法,本控件参考雨田哥的轮播控件,经过大规模的改造而成,相比于原来的广告轮播控件,本控件可以说完爆他,按在地上使劲摩擦.除了可以设置图片路径集合以外,还可以设置对应的提示信息,这个在众多的web轮播图片效果中最常见,比如新闻的标题等,可以更直观的显示当前图片,而且单击图片还可以支持跳转,指示器的位置也能设置左边+中间+右边,指示器的样式更加增加到椭圆条状

iOS开发——UI高级OC篇&amp;自定义控件之调整按钮中子控件(图片和文字)的位置

自定义控件之调整按钮中子控件(图片和文字)的位置 其实还有一种是在storyBoard中实现的,只需要设置对应空间的左右间距: 这里实现前面两种自定义的方式 一:imageRectForContentRect/titleRectForContentRect 自定义一个按钮控件在系统自带的位置设置方法中实现对应子控件位置调整 1 /** 2 3 * 设置内部图标的frame 4 5 */ 6 7 - (CGRect)imageRectForContentRect:(CGRect)contentRe

我的第一个开源控件-DragGridView

我的第一个开源控件出炉了,希望各个小伙伴给个star,支持下.项目地址 1. 前言 由于项目需要,要做一个类似腾讯视频,频道管理,拖拽排序的效果.这个控件是在原地址 之上改造出来的.先看下效果图. 1.0版本的效果图 由于我电脑是ubuntu,没法弄gif,等星期一到了公司上gif吧,不过,github上有apk,可以弄下来看看, 2. 实现思路 2.1 如何响应长按事件 我们虽然可以给view设置监听器,但是我们需要频繁的调用GridVIew的一些方法,显然,那样做是不合适的.于是,我们在on

WPF自定义控件与样式(10)-进度控件ProcessBar自定义样

一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: ProcessBar自定义标准样式: ProcessBar自定义环形进度样式: 二.ProcessBar标准样式 效果图: ProcessBar的样式非常简单: <!--ProgressBar Style--> <Style TargetType="ProgressBar" x

ASP.NET - 自定义控件处理页面事件(控件与页面数据交互)的方法

//用委托的方法实现 //控件代码 public delegate void DelegateFunction( string sPageTitle ); private DelegateFunction delegateChangePageTitle = null; public DelegateFunction ChangePT { get { return delegateChangePageTitle; }set { delegateChangePageTitle = value; }

WPF自定义控件第一 - 进度条控件

本文主要针对WPF新手,高手可以直接忽略,更希望高手们能给出一些更好的实现思路. 前期一个小任务需要实现一个类似含步骤进度条的控件.虽然对于XAML的了解还不是足够深入,还是摸索着做了一个.这篇文章介绍下实现这个控件的步骤,最后会放出代码.还请高手们给出更好的思路.同时也希望这里的思路能给同道中人一些帮助.话不多说,开始正题. 实现中的一些代码采用了网上现有的方案,代码中通过注释标记了来源,再次对代码作者一并表示感谢. 首先放一张最终效果图. 节点可以被点击 控件会根据绑定的集合数据生成一系列节

WinRT自定义控件第一 - 转盘按钮控件

之前的文章中,介绍了用WPF做一个转盘按钮控件,后来需要把这个控件移植到WinRT时,遇到了很大的问题,主要原因在于WPF和WinRT还是有很大不同的.这篇文章介绍了这个移植过程,由于2次实现的控件功能完全一样,文章主要关注点放在WPF与WinRT的不同上. 定义控件模板的XAML文件 在WinRT上的实现和WPF中实现一个很大的不同是,这个实现的TemplatedControl没有从ItemsControl继承,而是由Control继承手动添加了一些对集合属性的支持.不从ItemsContro

Android自定义控件之轮播图控件

背景 最近要做一个轮播图的效果,网上看了几篇文章,基本上都能找到实现,效果还挺不错,但是在写的时候感觉每次都要单独去重新在Activity里写一堆代码.于是自己封装了一下.本篇轮播图实现原理原文出处:循环广告位组件的实现,这里只是做了下封装成一个控件,不必每次重复写代码了. 效果图 实现分析 轮播图的功能就是实现左右滑动的广告.图片信息展示,那我们就用ViewPager来实现,由于考虑到用户体验,我们还需要在下面加一个指示器来标示滑动到了第几张轮播图.指示器我们可以用一个线性布局来根据要展示的轮