博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c#控件编写 (3)重绘From的非工作区
阅读量:6537 次
发布时间:2019-06-24

本文共 6555 字,大约阅读时间需要 21 分钟。

     重绘窗体的工作区的时候我们可以用到OnPaint来实现。而非工作区的绘制有几种思路

    1.直接实现WM_NCCALCSIZE消息绘制

    2.把窗体修改成None状态并拦截WM_NCCALCSIZE修改非工作区的大小实现

    3.把窗体修改成None直接做一个模拟的状态 

     这三种方法都会有一些弱点,这些弱点也许是我没有找到对应的解决方法 。

   1.在实现后需要修改 base.ControlBox = false,要不然在鼠标经过的时候会出现如下图的效果

其实我们是要的下面的这种效果

   但是这样做的后果是无法使用任务栏的菜单 ,如果有谁知道这个怎么解决的话留个言,在此谢过了 

 

  2.第二种实现的话在最大化最小化的时候,不知道是什么原因会产生窗体自动缩小在WM_NCCALCSIZE定义的标题栏的大小,这个也有一个折中的解决方法,就是重写SetBoundsCore然后注释掉里面的内容,但是在这样的话在Visual Studio里面就无法改变窗体的大小了。  如果这个也有解决方法的话,在此谢过了。

protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)        {            //base.SetBoundsCore(x, y, width, height, specified);        }

3.第三种当然是最好实现的了 ,但是模拟的状态无法直接替换到以前已经写好的窗体,直接否掉了 。

 

第一种和第二种其实是有点类似的,主要的地方还是在绘制上面  。

 

重绘非工作区,这个地方的重点在 DarwRegion函数里的

using (Bitmap img = new Bitmap(this.Bounds.Width, this.Bounds.Height))

{ Graphics g = Graphics.FromImage(img);

……

gs.DrawImage(img, Point.Empty);

}

这里利用双缓存先在图片上绘制了然后在画在窗体上

 

绘制函数 ///         /// 重绘非工作区         ///         private void NCPaint()        {            IntPtr wdc = Common.GetWindowDC(this.Handle);// Graphics.FromHwnd(this.Handle);            Graphics g = Graphics.FromHdc(wdc);            try            {                DarwRegion(g);            }            catch            { }            Common.ReleaseDC(this.Handle, wdc);        }        private void DarwRegion(Graphics gs)        {            if (this.FormBorderStyle == FormBorderStyle.None)                return;            using (Bitmap img = new Bitmap(this.Bounds.Width, this.Bounds.Height))            {                Graphics g = Graphics.FromImage(img);                if (mouseMove == MouseMose.None)                {                    GraphicsPath drawRect = RectX(new Rectangle(0, 0, this.Bounds.Width, this.Bounds.Height), Arc);                    //绘制渐变色                     Rectangle rect = new Rectangle(0, 0, this.Bounds.Width, this.Bounds.Height);                    LinearGradientBrush brush = new LinearGradientBrush(rect, this._colorA, this._colorB, 90);                    drawRect.AddRectangle(new Rectangle(BorderWidth, HeadHeight, this.ClientSize.Width, this.ClientSize.Height));                    g.FillPath(brush, drawRect);                    //绘制图标Icon                    if (ShowIcon)                        g.DrawIcon(this.Icon, new Rectangle(BorderWidth + 5, (HeadHeight - 16) / 2, 16, 16));                    //绘制标题                     StringFormat sf = new StringFormat();                    sf.LineAlignment = StringAlignment.Center;                    //求标题栏的区域                    ToolTitle = new Rectangle(BorderWidth + 23, 0, this.Bounds.Width, HeadHeight);                    g.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), ToolTitle, sf);                    //绘制最大最小关闭按钮                      //g.DrawImage(butClose, ButClose);                    //g.DrawImage(butMax, ButMax);                    //g.DrawImage(butMin, ButMin);                    DrawButton(g);                    //绘制边框                      g.SmoothingMode = SmoothingMode.HighQuality; //高质量                    drawRect = RectX(new Rectangle(1, 1, this.Bounds.Width - 4, this.Bounds.Height - 4), Arc - 1);                    g.DrawPath(new Pen(Color.FromArgb(100, Color.White), 1), drawRect);//绘制内边框                    drawRect = RectX(new Rectangle(0, 0, this.Bounds.Width - 2, this.Bounds.Height - 2), Arc - 1);                    g.DrawPath(new Pen(SolidColor, 1), drawRect);//绘制外边框                 }                else                {                    int i = this.Bounds.Width - 3, h = 1;                    foreach (ToolButton a in ListButton)                    {                        if (!a.Start)                            continue;                        i = i - a.Size.Width;                        Rectangle rect = new Rectangle(new Point(i, h), a.Size);                        if (a == _newbutton)                        {                            g.FillRectangle(new SolidBrush(ColorA), rect);                            g.DrawImage(a.Move, rect);                        }                        else                            if (a == _oldbutton)                            {                                g.FillRectangle(new SolidBrush(ColorA), rect);                                g.DrawImage(a.Default, rect);                            }                    }                }                gs.DrawImage(img, Point.Empty);                            }                  }

 
三个按钮的绘制,可以参考我前一篇重写TabControl标签的方法  。

最后是几个需要重绘的消息 

非客户区刷新 ///         /// 非客户区刷新         ///         private void NCUpdate()        {            Common.SendMessage(this.Handle, (int)Msg.WM_NCPAINT, 0, 0);        }

非客户区刷新 switch (m.Msg)            {                case (int)Msg.WM_NCCALCSIZE:                    BorderWidth = (this.Bounds.Width - this.ClientSize.Width) / 2;                    HeadHeight = this.Bounds.Height - this.ClientSize.Height - BorderWidth;                    mouseMove = MouseMose.None;                    // NCPaint();                    base.WndProc(ref m);                    break;                case (int)Msg.WM_NCACTIVATE:                    base.WndProc(ref m);                    mouseMove = MouseMose.None;                    NCUpdate();                    break;                case (int)Msg.WM_NCPAINT:                    NCPaint();                    break;                case (int)Msg.WM_NCLBUTTONDOWN:                    if (GetMouseButton() == null)                    {                        base.WndProc(ref m);                        // Console.WriteLine(1);                    }                    break;                case (int)Msg.WM_NCLBUTTONUP:                    ToolButton but = GetMouseButton();                    if (but != null)                    {                        but.OnClick();                    }                    base.WndProc(ref m);                    break;                case (int)Msg.WM_NCMOUSEMOVE:                    NewButton = GetMouseButton();                    base.WndProc(ref m);                    break;                case (int)Msg.WM_ERASEBKGND:                    base.WndProc(ref m);                    NCPaint();                    mouseMove = MouseMose.None;                    NCUpdate();                                      break;                                default:                    base.WndProc(ref m);                    break;            }
在这里鼠标点击关闭按钮是会出现WM_NCLBUTTONDOWN无法接收到消息,研究了很久发现了一个可以收到的方法,在WM_NCLBUTTONUP事件中判断是否是在最大最小关闭按钮按下的,如果是就不执行
base.WndProc(
ref m)这句。

        基本上窗体绘制的原理就这么些东西了,如果哪位同学对上面的方法有更好的建议的话,欢迎讨论 。

转载地址:http://hcbdo.baihongyu.com/

你可能感兴趣的文章
Go kit 概览
查看>>
[Gradle] Gradle 构建工具的未来
查看>>
【转】Selenium专题—JQuery选择器
查看>>
m2-第5周作业
查看>>
也谈WordPress获取文章首张图片
查看>>
通过view实现rest api接口
查看>>
Windows下安装Memcached for PHP
查看>>
Mybatis一对多查询得不到多方结果
查看>>
Python和C|C++的混编(二):利用Cython进行混编
查看>>
css笔记(二)——几种经常使用的模式
查看>>
Windows Phone开发——触控操作之GestureListener
查看>>
inactive transaction branch
查看>>
python之路异常
查看>>
可移动点控件
查看>>
hdu 1040 As Easy As A+B
查看>>
【SpringCloud构建微服务系列】使用Spring Cloud Config统一管理服务配置
查看>>
异步代理池2--正确实现并发
查看>>
CF - 1111D Destroy the Colony DP
查看>>
RSA 分段加解密【解决“不正确的长度”的异常】
查看>>
Python installation
查看>>