这篇介绍窗体的制作

做了许多的用户控件,现在让我们换换口味,开始窗体的制作吧!这个窗体的制作可以说是整个美化中比较重要的一部分,因为她显示的是整个美化的窗体。而且内容也比较多,所以我会分几篇把她讲完,而且窗体制作的时候会和前面控件将的时候不一样,我不会在第一篇把最后的代码就放出来,而是希望做成跟着我一起一个版本一版本的完成不断的修改不断的发现问题并去完善。这也是我做这个时候的一个思路:先做一个大致的框架,然后在其基础上增加功能或者发现问题,最后完成功能和解决问题。不知道大家感觉这样是不是更好一点呢?

好了,不多说了,先看最终的效果图:

怎么样?是不是有点心动了?下面就正式开始吧!首先在以前的项目 QLFUI 上新建一个窗体(不是用户控件咯)并重新命名为 MainForm。如图:

接着来设置几个属性,如下:

FormBorderStyle:None
Size:300,300

接下来就是用 picturebox 和 panel 来布局了。这一部分可能比较繁琐。首先总体介绍一下大概的布局。见图:

因为我们做的窗体是圆角的,所以窗体的四个角上(红色)我们会放上四个 picturebox。标题栏和状态栏(蓝色)会是两个 panel。二个边框线(绿色)是两个 picturebox。最后的主体部分(棕色)是一个 panel。说完了大体的布局,下面就来动手做啦。一个一个来:

左上角

Name:ptbtl
Location:0,0
Size:10,31

上方的标题栏

Modifiers:Protected;
Name:panelt
Location:10,0
Size:280,31

右上角

Name:ptbtr
Location:290,0
Size:10,31

左侧的边框线

Name:ptbml
Location:0,31
Size:2,232

主窗体部分

Modifiers:Protected;
BackgroundImageLayout:Stretch
Name:panelm
Location:2,31
Size:296,232

右侧的边框线

Name:ptbmr
Location:298,31
Size:2,232

左下角

Name:ptbbl
Location:0,263
Size:10,37

下方的状态栏

Modifiers:Protected;
Name:panelb
Location:10,263
Size:280,37

右下角

Name:ptbbr
Location:290,263
Size:10,37

最后还有右上方的三个按钮可不要忘记了,注意按钮都是在 panelt 里面设置的而且这三个按钮都是我们前面做的按钮哦,终于派上用场啦!

最小化按钮

Caption:0
Name:btmin
Location:180,0
Size:31,22

最大化按钮

Caption:0
Name:btmax
Location:211,0
Size:31,22

关闭按钮

Caption:0
Name:btclose
Location:243,0
Size:37,22

还原按钮

Caption:0
Name:btres
Location:211,-30
Size:31,22

最后再加上一个 label 作为窗体的标题

Name:lbtitle
Location:6,9
Size:35,12
BackColor:Transparent

呼,终于结束了!不知道大家有没有晕乎乎的感觉,反正我是有点儿了,呵呵。最后的布局图应该是这个样子滴:

老规矩,界面的事情弄完了,现在开始编码了。上代码:

2014-11-02 更新:因为附件找不到了,所以代码也看不了了,抱歉

变量部分:

变量我在代码里都注明了其作用。这里只会说说为什么要这些变量。首先 needMaxbt 和 needMinbt 是指示该窗体是否需要最大化或最小化按钮的,毕竟窗体有很多种吧,比如说一个消息框就没必要用最大化按钮吧,所以我们这边也就设置的灵活一点,下面会将这两个变量封装成属性以便在设计模式下方便的选择。接下来的四个变量

orginWidth;
orginHeight;
X;
Y;

都是用来记录窗体的信息的,分别是窗体的宽,高,x 坐标值,y 坐标值。为什么要设置一些变量呢?说起来也比较郁闷,这些都是为了窗口的最大化和还原准备的。可能有人会问了最大化不就一句话嘛 this.WindowState= FormWindowState.Maximized;何必还要这些个变量呢。关键郁闷就郁闷在这里啦,假如直接用这一句话最后窗体虽然也能最大化可就是右上角的一小段边框线莫名其妙的没有了,如图:

搞了半天也不明白。最后不得已才想出个自己手动最大化的方法来,讲到具体的地方再和大家说吧。 接下来我又定义了一个枚举 stat,用来表示窗体的三种状态,正常,最大化,最小化。下面的那个 st 就是枚举的一个变量,默认的是 normal 也就是窗体正常显示啦。

变量讲完了接下来讲属性。

  1. 第一个属性 Size。这个属性有点特别,因为它里面有一个 new 关键字,为什么呢?因为 Size 这个属性在设计器里面原来就有了所以我们加上这个 new 就相当于重写这个属性啦。这个属性里面我只写了一个 get 方法。我写这个属性的目的就是要将设计器下原来的 size 属性隐藏(看见了上面的那个[Browsable(false)]吗?就是用它来隐藏的),这样别人如果要设置窗体的大小就得修改我们下面提到的 BorderWidth 和 BorderHeight 了。那为什么要隐藏原来的实现呢,这是因为当我们设置窗体大小的时候窗体上相应的 picturebox 和 panel 也需要相应的改变,这里面就需要设置很多的东西。所以我们另外设置属性来完成这些工作。

  2. 第二个属性 BorderWidth。毫无疑问,这个就是用来设置窗体的宽度的啦。[CategoryAttribute(“QLFSkinDll”), Description(“设置窗体宽度”)]我就不讲了,前面已经提到过了。里面的 get 也很简单就是返回当前窗口的宽度。重点讲解 set。首先我们用 if 语句限制了用户设置的值不能小于 180 像素,因为当小于 180 个像素的时候,界面上的最小化按钮就有将标题都“挤”没了。所以最小 180 啦。接下来如果用户设置的值和设置前的不一样,那么就开始一下一连串的设置了。我们用 newwidth 把用户设置的这个值记录下来,下面要用到。然后紧接着就改变窗体的大小。 如果仅仅这样就结束了你会发现 panel,picturebox 那些控件的位置都没有动,这不是我们想要的。接下来就是设置这些控件的位置啦。一开始我做的时候也被这些设置搞乱了,最后我用的相对位置才搞清楚的。什么叫相对位置,打比方说无论你窗体的大小怎么变化,关闭按钮总是在距窗体右侧 57 个像素的位置。按照这个一句来做我们也会发现其他的控件都是一样的。于是一个一个的设置,找相对距离。当然我现在已经找好了,大家就不必再麻烦一个一个找一遍来了。至此,BorderWidth 属性讲完。

  3. 第三个属性 BorderHeight。经过上面 BorderWidth 属性的讲解,我想 height 属性就不要我再讲解了,都是一样的道理。

  4. 第四个属性 FormTitle。看意思就应该看出来了吧,这个是用来设置窗体的标题的。这个在前面讲到的 button,checkbox 等控件里也有差不多的属性,这里也不就不罗嗦了。

  5. 第五个属性 NeedMax。这个属性是用来指定窗体是否需要最大化按钮的。怎么指定呢?看代码。如果用户设置的是 false 也就是不需要,那我们就会将 btmax 按钮向上移动 50 个像素(this.btmax.Top = -50;)同时 btmin 按钮顶替最大化按钮的位置(this.btmin.Left = this.Width - 89;),怎么样?是不是很简单就实现了按钮的隐藏呢?

  6. 第六个属性 NeedMin。用法参见上面的第五个属性。

接下来讲构造函数。

前四句就不要我讲了吧,前面也遇到过就是开启双缓冲和系统默认的是初始化控件。剩下的 N 多的语句都是用来加载图片的,其实也没啥好说的要说的点前面控件制作的时候也已经介绍过了,呵呵。。。说一下最后一句的意思吧。因为我们的窗体默认是没有状态栏什么的,所以也就决定了当窗体最小化后右击任务栏上的窗体没有菜单弹出来。如果要实现这个功能就需要借助系统 API 来完成了。不过在 c#里面是不可以直接调用 API 的,需要实现声明一下。在这里就偷懒一下直接将别人封装好的 API 类(win32.cs)。一句话完成这个功能: Win32.SetWindowLong(this.Handle, -16, Win32.WS_SYSMENU+ Win32.WS_MINIMIZEBOX);好了,来运行看看吧:

发现问题:

大体的模样是出现了。不过也许大家看图看不清楚,图中被我画圈的其实都不是透明的,而是灰色的。我们在下一篇文章的讲解中将解决或实现以下几个问题:

  1. 消除图中不透明的地方
  2. 实现标题栏的拖动
  3. 实现窗体的最大化,最小化,关闭功能。

敬请期待。。。