该控件是继承于 Control 基类开发的。主要添加做标题栏,标题栏包括图标和文本,目前边框不可以调整,如果你有需要动态调整边框,你可以继续完善这个控件。
该控件的标题和边框是属于非工作区绘制的。
非工作区的绘制主要是靠拦截 Window 消息完成如下
1 protected override void WndProc(ref Message m) 2 { 3 switch (m.Msg) 4 { 5 case WM_NCCALCSIZE: 6 { 7 if (m.WParam != IntPtr.Zero) 8 { 9 NCCALCSIZE_PARAMS ncsize = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS)); 10 ncsize.ncOldClientRectangle.Top = ncsize.ncNewRectangle.Top += this.titleHeight; 11 ncsize.ncOldClientRectangle.Left = ncsize.ncNewRectangle.Left += this.border; 12 ncsize.ncOldClientRectangle.Right = ncsize.ncNewRectangle.Right -= this.border; 13 ncsize.ncOldClientRectangle.Bottom = ncsize.ncNewRectangle.Bottom -= this.border; 14 Marshal.StructureToPtr(ncsize, m.LParam, false); 15 } 16 else 17 { 18 RECT ncsize = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT)); 19 ncsize.Top += this.titleHeight; 20 ncsize.Left += this.border; 21 ncsize.Right -= this.border; 22 ncsize.Bottom -= this.border; 23 Marshal.StructureToPtr(ncsize, m.LParam, false); 24 } 25 26 this.Send_WM_NCPAINT_Message(); 27 return; 28 } 29 case WM_NCPAINT: 30 case WM_NCACTIVATE: 31 { 32 this.NCInvalidate(); 33 return; 34 } 35 } 36 base.WndProc(ref m); 37 }
再定义重绘非工作区 如下
1 /// <summary> 2 /// 绘制非工作区域 3 /// </summary> 4 protected virtual void OnNCPaint(PaintEventArgs e) 5 { 6 Graphics g = e.Graphics; 7 8 #region 边框 9 if (this.border > 0) 10 { 11 Pen border_pen = new Pen(this.BorderColor, this.border); 12 g.DrawLine(border_pen, new PointF(g.VisibleClipBounds.X, g.VisibleClipBounds.Bottom - this.border / 2), new PointF(g.VisibleClipBounds.Right, g.VisibleClipBounds.Bottom - this.border / 2)); 13 g.DrawLine(border_pen, new PointF(g.VisibleClipBounds.X + this.border / 2, g.VisibleClipBounds.Y + this.titleHeight), new PointF(g.VisibleClipBounds.X + this.border / 2, g.VisibleClipBounds.Bottom)); 14 g.DrawLine(border_pen, new PointF(g.VisibleClipBounds.Right - this.border / 2, g.VisibleClipBounds.Y+this.titleHeight), new PointF(g.VisibleClipBounds.Right - this.border / 2, g.VisibleClipBounds.Bottom)); 15 border_pen.Dispose(); 16 } 17 #endregion 18 19 #region 标题 20 SolidBrush title_back_sb = new SolidBrush(this.TitleBackColor); 21 RectangleF title_rect = new RectangleF(g.VisibleClipBounds.X, g.VisibleClipBounds.Y, g.VisibleClipBounds.Width, this.titleHeight); 22 g.FillRectangle(title_back_sb, title_rect); 23 title_back_sb.Dispose(); 24 25 #region 标题图标 26 if (this.TitleImage != null) 27 { 28 int image_w = this.TitleImage.Width; 29 int image_h = this.TitleImage.Height; 30 g.DrawImage(this.TitleImage, new RectangleF(g.VisibleClipBounds.X + this.border, g.VisibleClipBounds.Y + (this.titleHeight - image_h) / 2, image_w, image_h)); 31 } 32 #endregion 33 34 #region 标题文本 35 if (!String.IsNullOrWhiteSpace(Title)) 36 { 37 SolidBrush title_text_sb = new SolidBrush(this.TitleTextColor); 38 SizeF text_size = g.MeasureString(this.Title, this.TitleFont); 39 RectangleF text_rect = RectangleF.Empty; 40 if (this.TitleAlign == TitleAligns.Left) 41 { 42 int image_w = this.TitleImage == null ? 0 : this.TitleImage.Width; 43 text_rect = new RectangleF(g.VisibleClipBounds.X + this.border + image_w + 5, g.VisibleClipBounds.Y + (this.titleHeight - text_size.Height) / 2f, text_size.Width, text_size.Height); 44 } 45 else if (this.TitleAlign == TitleAligns.Center) 46 { 47 text_rect = new RectangleF(g.VisibleClipBounds.X + (g.VisibleClipBounds.Width - text_size.Width) / 2f, g.VisibleClipBounds.Y + (this.titleHeight - text_size.Height) / 2f, text_size.Width, text_size.Height); 48 } 49 else 50 { 51 text_rect = new RectangleF(g.VisibleClipBounds.Right - text_size.Width - this.border, g.VisibleClipBounds.Y + (this.titleHeight - text_size.Height) / 2f, text_size.Width, text_size.Height); 52 } 53 g.DrawString(this.Title, this.TitleFont, title_text_sb, text_rect); 54 title_text_sb.Dispose(); 55 } 56 #endregion 57 58 #endregion 59 60 } 61 62 63 /// <summary> 64 /// 重新绘制非工作区 65 /// </summary> 66 private void NCInvalidate() 67 { 68 IntPtr hDC = GetWindowDC(this.Handle); 69 Graphics g = Graphics.FromHdc(hDC); 70 this.OnNCPaint(new PaintEventArgs(g, new Rectangle(0, 0, this.Width, this.Height))); 71 g.Dispose(); 72 ReleaseDC(this.Handle, hDC); 73 } 74 75 /// <summary> 76 /// 发送非工作区绘制信息 77 /// </summary> 78 private void Send_WM_NCPAINT_Message() 79 { 80 SendMessage(this.Handle, WM_NCPAINT, (IntPtr)1, (IntPtr)0); 81 }
新增属性如下