跟我学做c#皮肤美化(六)

跟我学做c#皮肤美化(六)

                      --MainForm窗体的制作3

前续文章导航

最终源码下载


在上一篇中,我们虽然已经做出界面大概的样子出来了。不过还是存在着一些问题,包括运行缓慢和闪烁等一些问题。那么下面就让我们一起来解决吧。

先来说说闪烁和缓慢的问题

我认为最主要的还是由于我们设置了transparent所造成的。网上的一些解释是这样的,当窗体显示时我们设置的透明部分在显示的时候会先呈现出黑色然后再在上面显示图片。这样一来控件一多我们很容易就看见了。不管解释的对不对,反正我们知道设置窗体的transparent肯定是对窗体的显示有一些负面影响的(接下来的窗体避免设置transparent也确实证明了这一点)。既然是这个transparent“搞的鬼”,那能不能不用它来实现窗体的透明呢?答案是我还没找到。但是不代表这个问题解决不了。

我们不妨先来回忆一下我们为什么要使用这个transparent。还记得下面这张图吧?

 

我们运用transparent就是为了解决四个角上透明度的问题。现在我们不想使用transparent怎么办呢?其实简单的换个思路就行了。我们为什么非要那边是透明的啊,它不透明就让它不透明呗,我们只要在显示的时候“切掉”它不就行了。也就是说我们自己先要在原有的窗口内画出一个圆矩形出来然后四个直角就自然切掉不要了。那怎么画怎么切?看下面的系统API,

 

 

 

 

第一个是用来画的,而第二个当然就是用来切的啦。MSDN上面已经给我们解释的很清楚了。CreateRoundRectRgn前面四个参数分别是左上角和右下角的坐标,我们在画的时候只需要将其起点设置为(1,1)终点设置为(this.width-1,this.height-1)就能得到一个外边距相当于1的矩形啦。如图:

图中的蓝色部分就是我们需要省略的部分。

 

最后两个参数分别是椭圆形的宽高(其实就是我们切的圆角的弧度啦)。这个函数执行成功了就会返回切好的区域的句柄,然后我们只要在SetWindowRgn中拿到这个handle就可以把我们需要的圆矩形部分切下来啦。

可是好像又有一个问题那!到底该什么时候切呢?铅笔,刀都准备好了,但总不能让他傻傻站那儿不知道什么时候动手吧!时机很重要。我们应该让他在窗体大小变化的时候就行动一次,这样才能保证每次窗体大小变化(比如说最大化)后还能保证是圆角矩形。好啦,原理讲好了,现在该真正动手干活咯。

首先第一步就是切掉原来窗体的transparent,这个就不用我多说了吧!会设置还不会取消嘛!接着就重写一个OnResize函数就可以啦。两句话搞定,

 

       protected overridevoid OnResize(EventArgse)
       {
            base.OnResize(e);
            intRgn = Win32.CreateRoundRectRgn(1, 1, this.Width - 1, this.Height- 1, 7, 7);
            Win32.SetWindowRgn(this.Handle, Rgn, true);
       }

 

 

好了,来运行一下看看效果吧!

 

现在我们再来最大化,最小化还原看看效果确实比上次好多了。基本看不到左上角还有闪烁的情况了,而且响应也蛮快的。不过大家也从上图看出来了,就是最大化的时候周围有空隙的啊。其实也不难想到这些空隙就是我们切掉不要的那一部分窗体。要想最大化的时候窗体完全覆盖只要在最大化的时候稍微增加一下窗体的宽和高就是了。于是我们在上一期的代码中再对最大化事件做以下修改。

 

       private voidbtmax_Click(object sender, EventArgs e)
       {
            this.btmax.Top-= 30;
            this.btres.Top= 0;
 
            //最大化之前记录窗口信息便于缩小
            orginHeight = this.Height;
            orginWidth = this.Width;
            X = this.Location.X;
            Y = this.Location.Y;
 
            this.Top= 1;
            this.Left= 1;
            BorderWidth = Screen.PrimaryScreen.WorkingArea.Width +4;
            BorderHeight = Screen.PrimaryScreen.WorkingArea.Height +4;
            st = stat.Max;
  }

 

 

其中这个窗体的宽和高我试了一下,加4正好差不多能覆盖原来的空隙了。大家可以试一下。

OK,闪烁终于算是解决了。接下来实现窗体大小的拖动功能。

这个问题还是由于我们的窗体样式为None导致的(看来这个None还真是搞出了不少麻烦呢)。不过不管怎样,咱还是想办法解决吧。前面的窗口移动我们是通过API来完成的,没有疑问的大小的调整我们也借助系统API发送消息来完成。Win32.SendMessage(Handle,274, 61440 + x, 0);其中的x代表了不同的数字,当数字不同的时候产生的拖动大小的方向也不同。具体的数字代表的方向大家可以看我的代码。

现在最主要的问题就是实现鼠标到达窗体边缘时可以拖动。这里我运用了MouseMove这个事件。当鼠标到达指定区域时我们通过判断鼠标左键是否按下来实现改变大小消息的发送与否。我举一个稍微复杂一点的事件说一下吧。拿右上角来说吧。右上角运用ptbtr_MouseMove这个事件来判断是否更改大小。看图:

 

我将右上角的区域分为了四个区域。当鼠标分别落在1,2,4区域并按下鼠标的时候我们才相应的赋予x值从而改变窗体大小。那么如何判断鼠标经过的区域呢?我们可以直接用MouseEventArgs e参数中的x,y属性。该属性表明了鼠标在相应的panel或者picture下的相对位置。还好是相对位置,不然我们又要麻烦了,呵呵。

看代码:首先我们用if (!sizeAble)判断是否设置了可更改大小。当可以改变大小时,我们再逐一判断鼠标左键按下时鼠标的位置,并相应作出更改。代码中我那个点是采用3个像素的位置作为分界线的(就是1和4的分界区),这个位置如果大家觉得不合适可以自己更改。只要按照上面的思路去一个一个的设置窗体最后肯定会获得你想要的效果的。

在这里顺便打一下小广告^ ^,这个窗体皮肤的效果已经被我用在了我编写的一个小软件“上网计时小助手”上了,如果想看看皮肤的运用效果不妨去看看那个软件哦!嘿嘿....软件地址:http://www.cnblogs.com/qianlifeng/archive/2010/05/03/1726801.html

好了,窗体部分经过3个部分的讲解终于算是结束了

相信大家对控件的编写也有了一定的“感觉”了吧。这个窗体其实说起来还有一些地方不够完善的,比如说窗体的起始位置没有地方设置,再比如说当窗体上的控件太多的时候加载显示窗体还是有一定程度上的不好的显示现象的等等。这些缺点还只是我暂时发现的,肯定还有其他一些不好的地方就等待着细心而认真的你发现并去尝试着解决它了。

posted @ 2010-05-16 21:42  qianlifeng  阅读(16728)  评论(38编辑  收藏  举报