zoukankan      html  css  js  c++  java
  • Winfrom中From控件的重绘

    重绘目的

    • 1. 满足非默认主题下的标题栏样式
    • 2. 在保留停靠功能的同时进行重绘。

    代码如下:

      1 public partial class FormEx: Form
      2     {
      3         public FormEx()
      4         {
      5             InitializeComponent();
      6             TitleBar.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(TitleBar, true, null);
      7             Icon = Properties.Resources.shark;
      8             CloseButtonImage = Properties.Resources.close;
      9             MaximumButtonImage = Properties.Resources.window_max;
     10             MaximumNormalButtonImage = Properties.Resources.window;
     11             MinimumButtonImage = Properties.Resources.window_min;
     12             CaptionBackgroundColor = Color.FromArgb(230, 230, 230);
     13             CaptionHeight = 30;
     14             BackColor = Color.White;
     15             ControlBackColor = Color.Transparent;
     16             this.TransparencyKey = boderColor;
     17             ControlActivedColor = DrawHelper.GetNearColor(Color.White, 0, -35, -24, -30);
     18 
     19             TitleBar.SendToBack();
     20 
     21             base.SetStyle(
     22              ControlStyles.UserPaint |
     23              ControlStyles.AllPaintingInWmPaint |
     24              ControlStyles.OptimizedDoubleBuffer |
     25              ControlStyles.ResizeRedraw |
     26              ControlStyles.SupportsTransparentBackColor|
     27              ControlStyles.DoubleBuffer, true);
     28             base.AutoScaleMode = AutoScaleMode.None;
     29         }
     30 
     31         #region 公开变量
     32         [Category("标题栏"), Description("关闭按钮图片")]
     33         public Image CloseButtonImage { get; set; }
     34 
     35         [Category("标题栏"), Description("最大化按钮图片")]
     36         public Image MaximumButtonImage { get; set; }
     37 
     38         [Category("标题栏"), Description("最大化默认按钮图片")]
     39         public Image MaximumNormalButtonImage { get; set; }
     40 
     41         [Category("标题栏"), Description("最小化按钮图片")]
     42         public Image MinimumButtonImage { get; set; }
     43 
     44         [Category("标题栏"), Description("标题栏按钮鼠标悬浮背景色"), DefaultValue(typeof(Color), "#000000")]
     45         public Color ControlActivedColor { get; set; }
     46 
     47         [Category("标题栏"), Description("标题栏按钮默认状态背景色"), DefaultValue(typeof(Color))]
     48         public Color ControlBackColor { get; set; }
     49 
     50         private int captionHeight;
     51         [Category("标题栏"), Description("标题栏高度"), DefaultValue(typeof(int), "30")]
     52         public int CaptionHeight { get { return captionHeight; } set { captionHeight = value; TitleBar.Height = value; } }
     53 
     54         [Category("标题栏"), Description("标题位置")]
     55         public ContentAlignment TitleAlign { set; get; } = ContentAlignment.MiddleLeft;
     56 
     57         private Color captionBackgroundColor;
     58         [Category("标题栏"), Description("标题栏背景颜色"), DefaultValue(typeof(Color), "White")]
     59         public Color CaptionBackgroundColor
     60         {
     61             get { return captionBackgroundColor; }
     62             set
     63             {
     64                 captionBackgroundColor = value;
     65                 TitleBar.BackColor = captionBackgroundColor;
     66             }
     67         }
     68         #endregion
     69 
     70         #region 私有变量
     71 
     72         private MouseState _mouseState = MouseState.Out; 
     73         private Rectangle closeRect = Rectangle.Empty;      //关闭按钮范围
     74         private Rectangle maxRect = Rectangle.Empty;        //最大化按钮范围
     75         private Rectangle minRect = Rectangle.Empty;        //最小化按钮范围
     76         private Rectangle captionRect;                      //标题范围
     77 
     78         private int btnH = 24;              //按钮大小
     79         private int boderWidth = 8;         //边框宽度
     80         private Color boderColor = Color.FromArgb(254, 254, 253);
     81         #endregion
     82 
     83         #region 重绘事件
     84         private void TitleBar_Paint(object sender, PaintEventArgs e)
     85         {
     86             captionRect = new Rectangle(0, 0, TitleBar.Width, TitleBar.Height);
     87             DrawTitle(e.Graphics);
     88             DrawControlButton(e.Graphics);
     89         }
     90 
     91         protected override void OnPaint(PaintEventArgs e)
     92         {
     93             base.OnPaint(e);
     94             DrawBound(e.Graphics);
     95         }
     96 
     97         /// <summary>
     98         /// 绘制边框
     99         /// </summary>
    100         private void DrawBound(Graphics g)
    101         {
    102             Pen pen = new Pen(boderColor, boderWidth * 2);
    103             Rectangle rectangle = new Rectangle(0, 0, Width, Height);
    104             g.DrawRectangle(pen, rectangle);
    105             pen = new Pen(Color.Black, 1);
    106             rectangle = new Rectangle(boderWidth - 1, boderWidth - 1, Width - boderWidth * 2 + 1, Height - boderWidth * 2 + 1);
    107             g.DrawRectangle(pen, rectangle);
    108             Padding = new Padding(boderWidth);
    109         }
    110 
    111         /// <summary>
    112         /// 绘制控制按钮
    113         /// </summary>
    114         private void DrawControlButton(Graphics g)
    115         {
    116             int x = ClientSize.Width - btnH - 15 - boderWidth;
    117             if (CloseButtonImage != null)
    118             {
    119                 DrawButtonImage(ref closeRect, ref x, _mouseState == MouseState.CloseHover, g, CloseButtonImage);
    120             }
    121             if (MaximizeBox)
    122             {
    123                 if (WindowState == FormWindowState.Maximized && MaximumNormalButtonImage != null)
    124                     DrawButtonImage(ref maxRect, ref x, _mouseState == MouseState.MaxHover, g, MaximumNormalButtonImage);
    125                 else if (MaximizeBox && WindowState != FormWindowState.Maximized && MaximumButtonImage != null)
    126                     DrawButtonImage(ref maxRect, ref x, _mouseState == MouseState.MaxHover, g, MaximumButtonImage);
    127             }
    128             if (MinimizeBox && MinimumButtonImage != null)
    129             {
    130                 DrawButtonImage(ref minRect, ref x, _mouseState == MouseState.MinHover, g, MinimumButtonImage);
    131             }
    132         }
    133 
    134         private void DrawButtonImage(ref Rectangle rect, ref int x, bool isHover, Graphics g, Image image)
    135         {
    136             //rect = new Rectangle(x, (captionHeight - btnH) / 2, btnH, btnH);
    137             rect = new Rectangle(x, 0, btnH, btnH);
    138             Brush brush = new SolidBrush(isHover ? ControlActivedColor : ControlBackColor);
    139             g.FillRectangle(brush, rect);
    140             g.DrawImage(image, rect);
    141             if (image == CloseButtonImage)
    142                 rect = new Rectangle(x, 0, btnH + boderWidth, btnH);
    143             x -= btnH;
    144         }
    145 
    146         /// <summary>
    147         /// 绘制标题
    148         /// </summary>
    149         private void DrawTitle(Graphics g)
    150         {
    151             int x = 6;
    152             if (ShowIcon && Icon != null)
    153             {
    154                 g.SmoothingMode = SmoothingMode.AntiAlias;
    155                 ImageAttributes image = new ImageAttributes();
    156                 image.SetWrapMode(WrapMode.TileFlipXY);
    157                 using (Bitmap bitmap = Icon.ToBitmap())
    158                 {
    159                     Rectangle rec = new Rectangle(x, (captionHeight - btnH) / 2, CaptionHeight - 6, CaptionHeight - 6);
    160                     g.DrawImage(bitmap, rec, 0, 0, bitmap.Width, bitmap.Height, GraphicsUnit.Pixel, image);
    161                 }
    162                 x += 35;
    163             }
    164             if (!string.IsNullOrEmpty(Text))
    165             {
    166                 int fontHeight = Size.Ceiling(g.MeasureString("Text", TitleBar.Font)).Height;
    167                 int fontWidth = Size.Ceiling(g.MeasureString(Text, TitleBar.Font)).Width;
    168                 Brush brush = new SolidBrush(ForeColor);
    169                 if (TitleAlign == ContentAlignment.MiddleLeft)
    170                     g.DrawString(Text, TitleBar.Font, brush, x, (CaptionHeight - fontHeight) / 2);
    171                 else if (TitleAlign == ContentAlignment.TopCenter)
    172                     g.DrawString(Text, TitleBar.Font, brush, (Width - fontWidth)/2, boderWidth);
    173 
    174 
    175             }
    176         }
    177         #endregion
    178 
    179         #region 其他事件
    180         private void TitleBar_MouseClick(object sender, MouseEventArgs e)
    181         {
    182             if (e.Clicks != 1 || e.Button != MouseButtons.Left)
    183                 return;
    184             switch (_mouseState)
    185             {
    186                 case MouseState.CloseHover:
    187                     Close();
    188                     break;
    189                 case MouseState.MaxHover:
    190                     WindowState = WindowState == FormWindowState.Maximized ? FormWindowState.Normal : FormWindowState.Maximized;
    191                     return;
    192                 case MouseState.MinHover:
    193                     WindowState = FormWindowState.Minimized;
    194                     return;
    195             }
    196             _mouseState = MouseState.Normal;
    197         }
    198 
    199         private void TitleBar_MouseDown(object sender, MouseEventArgs e)
    200         {
    201             if (_mouseState != MouseState.CaptionHover)
    202                 return;
    203 
    204             if (e.Clicks == 1)
    205             {
    206                 Win32API.ReleaseCapture();
    207                 Win32API.SendMessage(Handle, Win32API.WM_SYSCOMMAND, Win32API.SC_MOVE + Win32API.HTCAPTION, 0);
    208             }
    209             else if (e.Clicks == 2 && e.Button == MouseButtons.Left)
    210             {
    211                 WindowState = WindowState == FormWindowState.Maximized ? FormWindowState.Normal : FormWindowState.Maximized;
    212             }
    213         }
    214 
    215         private void TitleBar_MouseMove(object sender, MouseEventArgs e)
    216         {
    217             Point p = new Point(e.X, e.Y);
    218             if (closeRect != Rectangle.Empty && closeRect.Contains(p))
    219                 _mouseState = MouseState.CloseHover;
    220             else if (minRect != Rectangle.Empty && minRect.Contains(p))
    221                 _mouseState = MouseState.MinHover;
    222             else if (maxRect != Rectangle.Empty && maxRect.Contains(p))
    223                 _mouseState = MouseState.MaxHover;
    224             else if (captionRect != Rectangle.Empty && captionRect.Contains(p))
    225                 _mouseState = MouseState.CaptionHover;
    226             else
    227                 _mouseState = MouseState.Normal;
    228             
    229             Invalidate(captionRect, true);
    230         }
    231 
    232         private void TitleBar_MouseLeave(object sender, EventArgs e)
    233         {
    234             _mouseState = MouseState.Out;
    235             Invalidate(captionRect, true);
    236         }
    237 
    238         private void FormEx_SizeChanged(object sender, EventArgs e)
    239         {
    240             Invalidate(captionRect, true);
    241         }
    242         #endregion
    243 
    244         #region 调整窗口大小
    245 
    246         protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
    247         {
    248             if (width == Width + 16)
    249                 return;
    250             base.SetBoundsCore(x, y, width, height, specified);
    251         }
    252 
    253         protected override void WndProc(ref Message m)
    254         {
    255             if (_mouseState == MouseState.CloseHover || _mouseState == MouseState.MinHover)
    256             {
    257                 base.WndProc(ref m);
    258                 return;
    259             }
    260             switch (m.Msg)
    261             {
    262                 case 0x0084:
    263                     base.WndProc(ref m);
    264                     Point vPoint = new Point((int)m.LParam & 0xFFFF,
    265                         (int)m.LParam >> 16 & 0xFFFF);
    266                     vPoint = PointToClient(vPoint);
    267                     if (vPoint.X <= 10)
    268                         if (vPoint.Y <= 10)
    269                             m.Result = (IntPtr)Win32API.Guying_HTTOPLEFT;
    270                         else if (vPoint.Y >= ClientSize.Height - 10)
    271                             m.Result = (IntPtr)Win32API.Guying_HTBOTTOMLEFT;
    272                         else m.Result = (IntPtr)Win32API.Guying_HTLEFT;
    273                     else if (vPoint.X >= ClientSize.Width - 10)
    274                         if (vPoint.Y <= 10)
    275                             m.Result = (IntPtr)Win32API.Guying_HTTOPRIGHT;
    276                         else if (vPoint.Y >= ClientSize.Height - 10)
    277                             m.Result = (IntPtr)Win32API.Guying_HTBOTTOMRIGHT;
    278                         else m.Result = (IntPtr)Win32API.Guying_HTRIGHT;
    279                     else if (vPoint.Y <= 10)
    280                         m.Result = (IntPtr)Win32API.Guying_HTTOP;
    281                     else if (vPoint.Y >= ClientSize.Height - 10)
    282                         m.Result = (IntPtr)Win32API.Guying_HTBOTTOM;
    283                     break;
    284                 case 0x0201:                    //鼠标左键按下的消息   
    285                     m.Msg = 0x00A1;             //更改消息为非客户区按下鼠标   
    286                     m.LParam = IntPtr.Zero;     //默认值   
    287                     m.WParam = new IntPtr(2);   //鼠标放在标题栏内   
    288                     base.WndProc(ref m);
    289                     break;
    290                 case 0x0083:
    291                     if (m.WParam != IntPtr.Zero)
    292                     {
    293                         NCCALCSIZE_PARAMS rcsize = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
    294                         Marshal.StructureToPtr(rcsize, m.LParam, false);
    295                     }
    296                     m.Result = new IntPtr(1);
    297                     break;
    298                 default:
    299                     base.WndProc(ref m);
    300                     break;
    301             }
    302         }
    303         #endregion
    304     }
    305 
    306     public enum MouseState
    307     {
    308         Normal,
    309         MaxHover,
    310         MinHover,
    311         CloseHover,
    312         CaptionHover,
    313         Out,
    314     }

    因为主要目的是为了保留窗体是停靠功能,所以不能使用无边框然后直接重绘标题栏。拦截了window绘制有效区域标题栏的消息,仍然存在很多不完善的地方,如拦截边框消息后没有重新绘制原边框位置的图形,导致了原区域的透明等等。

  • 相关阅读:
    css最简单的在背景图片上显示模糊背景色的方法
    css添加网格背景
    获取bing必应图片
    JavaScript超过一定高度导航添加类名
    6行css就可以解决的瀑布流布局的方法
    css实现背景图横向滚动
    JavaScript根据一个元素的显示隐藏控制另一个元素的显示和隐藏
    JavaScript判断地址栏链接与导航栏链接是否一致并给导航添加class
    JavaScript实现选中文字自动复制
    Day 74 算法基础(二)
  • 原文地址:https://www.cnblogs.com/yincq/p/11582607.html
Copyright © 2011-2022 走看看