繼上次C#制作高仿360安全衛士窗體<一>發布之后響應還不錯,我的博客放肆雷特也來了不少的新朋友,在這里先謝謝大家的支持!我自己也反復看了一下覺得對不起大家,寫的非常亂而且很少文字介紹。在這里先說明一下,我是一個純粹想搞技術的,文筆較差。我也想鍛煉自己所以才會慢慢的將自己的所學分享出來。一來可以鍛煉自己的文筆,二來可以分享知識留給像我一樣喜歡這些東西的朋友。所以以后如果缺少介紹和說明,請大家多多補充指正,相互提高。下面進入主題。 上一篇主要講的如何繪制一個按鈕,那么今天講解如何繪制窗體。之前也說過,先制作按鈕的作用是可以將按鈕用到窗體上面那些系統按鈕如最大化、最小化、關閉、還原等。首先我們對按鈕的不同狀態的圖片進行提取,在上一篇提出來皮膚文件之后,將按鈕的文件sys_button_max.png,sys_button_min.png,sys_button_close.png,sys_button_max.png,sys_button_restore.png這幾個圖片文件進行提取。在這里說明,可以直接使用,也可以自己進行加工。以下是我加工過的(如果需要可以直接右鍵另存為):




一、嵌入資源 圖片素材准備好之后在解決方案中Images目錄里面建立一個FormImages文件夾,將圖片素材拷貝進去,並設置圖片屬性中生成操作選擇為“嵌入的資源”。 二、創建窗體 資源嵌入之后再在ControlEx目錄中建立一個FormEx文件夾,在該文件夾下創建一個名為BaseForm的窗體。該窗體需要修改的選項很少,大部分可以使用代碼來解決。窗體創建完畢后,將創建好的ButtonEx拖進窗體,這里需要拖放5個。為了使內容更好看,還拖一個Panel進來。擺放的位置可以隨意,后期通過代碼控制,但是為了便於開發我擺放為如下:

三、編碼
控件擺放完了之后就可以開始編碼了,窗體編碼主要難度在於消息的處理還有一個比較麻煩一點的是窗體中不同狀態下按鈕的位置處理,我直接上代碼不懂的留言詢問我再詳細解答:
1、變量申明
1 #region 聲明 2 private int Rgn; 3 private Graphics g; 4 private bool _IsResize = true;//是否允許改變窗口大小 5 private FormSystemBtn _FormSystemBtnSet = FormSystemBtn.SystemAll; 6 private Bitmap btn_closeImg = ImageObject.GetResBitmap("FANGSI.UI.Images.FormImages.btn_close.png"); 7 private Bitmap btn_maxImg = ImageObject.GetResBitmap("FANGSI.UI.Images.FormImages.btn_max.png"); 8 private Bitmap btn_miniImg = ImageObject.GetResBitmap("FANGSI.UI.Images.FormImages.btn_mini.png"); 9 private Bitmap btn_restoreImg = ImageObject.GetResBitmap("FANGSI.UI.Images.FormImages.btn_restore.png"); 10 private Bitmap _BackImg = ImageObject.GetResBitmap("FANGSI.UI.Images.FormImages.background_mainwnd.jpg"); 11 private Size oldSize;//記錄當前窗口大小 12 private bool _MaximizeBox = true;//是否啟用最大化按鈕 13 private int _TopHeight = 100;//窗體頭部高度 14 //枚舉系統按鈕狀態 15 public enum FormSystemBtn 16 { 17 SystemAll = 0, 18 SystemNo = 1, 19 btn_close = 2, 20 btn_miniAndbtn_close = 3, 21 btn_maxAndbtn_close = 4 22 } 23 #endregion
2、構建方法,主要將窗體消息的處理以及按鈕位置等信息進行設置
1 #region 方法 2 protected void SystemBtnSet() 3 { 4 int btnTop = 0; 5 int btnRight = 6; 6 int panelMargin = 2; 7 if (WindowState == FormWindowState.Maximized && FormBorderStyle != System.Windows.Forms.FormBorderStyle.None) 8 { 9 btnTop = 10; 10 btnRight = 16; 11 panelMargin = 10; 12 } 13 this.ContentPanel.Location = new Point(panelMargin, _TopHeight); 14 this.ContentPanel.Size = new Size(ClientRectangle.Width - (panelMargin * 2), ClientRectangle.Height - _TopHeight - panelMargin); 15 16 switch ((int)_FormSystemBtnSet) 17 { 18 case 0: 19 btn_close.BackImg = btn_closeImg; 20 btn_close.Location = new Point(this.Width - 32, btnTop); 21 btn_mini.BackImg = btn_miniImg; 22 btn_mini.Location = new Point(this.Width - 86, btnTop); 23 btn_max.BackImg = btn_maxImg; 24 btn_restore.BackImg = btn_restoreImg; 25 if (WindowState == FormWindowState.Normal) 26 { 27 btn_max.Location = new Point(this.Width - 59, btnTop); 28 btn_restore.Location = new Point(this.Width - 59, -22); 29 } 30 else 31 { 32 btn_max.Location = new Point(this.Width - 59, -22); 33 btn_restore.Location = new Point(this.Width - 59, btnTop); 34 } 35 break; 36 case 1: 37 btn_close.BackImg = btn_closeImg; 38 btn_close.Location = new Point(this.Width - 32, -22); 39 btn_max.BackImg = btn_maxImg; 40 btn_max.Location = new Point(this.Width - 59, -22); 41 btn_mini.BackImg = btn_miniImg; 42 btn_mini.Location = new Point(this.Width - 86, -22); 43 btn_restore.BackImg = btn_restoreImg; 44 btn_restore.Location = new Point(this.Width - 59, -22); 45 break; 46 case 2: 47 btn_close.BackImg = btn_closeImg; 48 btn_close.Location = new Point(this.Width - 32, btnTop); 49 btn_max.BackImg = btn_maxImg; 50 btn_max.Location = new Point(this.Width - 59, -22); 51 btn_mini.BackImg = btn_miniImg; 52 btn_mini.Location = new Point(this.Width - 86, -22); 53 btn_restore.BackImg = btn_restoreImg; 54 btn_restore.Location = new Point(this.Width - 59, -22); 55 break; 56 case 3: 57 btn_close.BackImg = btn_closeImg; 58 btn_close.Location = new Point(this.Width - 32, btnTop); 59 btn_max.BackImg = btn_maxImg; 60 btn_max.Location = new Point(this.Width - 59, -22); 61 btn_mini.BackImg = btn_miniImg; 62 btn_mini.Location = new Point(this.Width - 59, 0); 63 btn_restore.BackImg = btn_restoreImg; 64 btn_restore.Location = new Point(this.Width - 59, -22); 65 break; 66 case 4: 67 btn_close.BackImg = btn_closeImg; 68 btn_close.Location = new Point(this.Width - 32, btnTop); 69 btn_mini.BackImg = btn_miniImg; 70 btn_mini.Location = new Point(this.Width - 86, -22); 71 btn_max.BackImg = btn_maxImg; 72 btn_restore.BackImg = btn_restoreImg; 73 if (WindowState == FormWindowState.Normal) 74 { 75 btn_max.Location = new Point(this.Width - 59, btnTop); 76 btn_restore.Location = new Point(this.Width - 59, -22); 77 } 78 else 79 { 80 btn_max.Location = new Point(this.Width - 59, -22); 81 btn_restore.Location = new Point(this.Width - 59, btnTop); 82 } 83 break; 84 } 85 } 86 87 private void WM_NCHITTEST(ref Message m) 88 { 89 int wparam = m.LParam.ToInt32(); 90 Point point = new Point(Win32.LOWORD(wparam), Win32.HIWORD(wparam)); 91 point = PointToClient(point); 92 if (_IsResize) 93 { 94 if (point.X <= 8) 95 { 96 if (point.Y <= 8) m.Result = (IntPtr)Win32.HTTOPLEFT; else if (point.Y > Height - 8) 97 m.Result = (IntPtr)Win32.HTBOTTOMLEFT; 98 else 99 m.Result = (IntPtr)Win32.HTLEFT; 100 } 101 else if (point.X >= Width - 8) 102 { 103 if (point.Y <= 8) m.Result = (IntPtr)Win32.HTTOPRIGHT; else if (point.Y >= Height - 8) 104 m.Result = (IntPtr)Win32.HTBOTTOMRIGHT; 105 else 106 m.Result = (IntPtr)Win32.HTRIGHT; 107 } 108 else if (point.Y <= 8) { m.Result = (IntPtr)Win32.HTTOP; } else if (point.Y >= Height - 8) 109 m.Result = (IntPtr)Win32.HTBOTTOM; 110 else 111 m.Result = (IntPtr)Win32.HTCAPTION; 112 } 113 else 114 { m.Result = (IntPtr)Win32.HTCAPTION; } 115 } 116 117 private void btn_close_Click(object sender, EventArgs e) 118 { 119 this.Close(); 120 } 121 122 private void btn_mini_Click(object sender, EventArgs e) 123 { 124 Win32.PostMessage(base.Handle, Win32.WM_SYSCOMMAND, Win32.SC_MINIMIZE, 0); 125 } 126 127 private void btn_max_Click(object sender, EventArgs e) 128 { 129 Win32.PostMessage(base.Handle, Win32.WM_SYSCOMMAND, Win32.SC_MAXIMIZE, 0); 130 } 131 132 private void btn_restore_Click(object sender, EventArgs e) 133 { 134 Win32.PostMessage(base.Handle, Win32.WM_SYSCOMMAND, Win32.SC_RESTORE, 0); 135 } 136 137 private void btn_close_MouseEnter(object sender, EventArgs e) 138 { 139 toolTip1.SetToolTip(btn_close, "關閉"); 140 } 141 142 private void btn_max_MouseEnter(object sender, EventArgs e) 143 { 144 toolTip1.SetToolTip(btn_max, "最大化"); 145 } 146 147 private void btn_mini_MouseEnter(object sender, EventArgs e) 148 { 149 toolTip1.SetToolTip(btn_mini, "最小化"); 150 } 151 152 private void btn_restore_MouseEnter(object sender, EventArgs e) 153 { 154 toolTip1.SetToolTip(btn_restore, "還原"); 155 } 156 #endregion
3、屬性定義以及方法重寫,將擴展屬性和窗體重繪等方法結合上一篇的基礎類庫進行處理
1 #region 重寫方法 2 protected override void OnInvalidated(InvalidateEventArgs e) 3 { 4 base.OnInvalidated(e); 5 } 6 7 //重繪窗口 8 protected override void OnPaint(PaintEventArgs e) 9 { 10 try 11 { 12 g = e.Graphics; 13 g.SmoothingMode = SmoothingMode.HighQuality; //高質量 14 g.PixelOffsetMode = PixelOffsetMode.HighQuality; //高像素偏移質量 15 ImageDrawRect.DrawRect(g, ClientRectangle, base.BackColor, _TopHeight);//繪制白色內容區域 16 Brush brush = new SolidBrush(Color.White);//定義畫筆 17 PointF point = new PointF(10, 10);//定義標題顯示坐標 18 Font TitleFont = new System.Drawing.Font("微軟雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 19 g.DrawString(base.Text, TitleFont, brush, point.X, point.Y); 20 21 } 22 catch 23 { } 24 } 25 26 //重載WndProc方法 27 protected override void WndProc(ref Message m) 28 { 29 try 30 { 31 switch (m.Msg) 32 { 33 //用戶選擇最大化按鈕,最小化按鈕,復原按鈕或關閉按鈕時,窗口將會接收該消息 34 case Win32.WM_SYSCOMMAND: 35 #region 36 if ((m.WParam != (IntPtr)Win32.SC_MAXIMIZE) && (m.WParam.ToInt32() != 0xf032)) 37 { 38 if ((m.WParam == (IntPtr)Win32.SC_RESTORE) || (m.WParam.ToInt32() == 0xf122)) 39 { 40 base.Size = this.oldSize; 41 } 42 else if ((m.WParam == (IntPtr)Win32.SC_MINIMIZE) || (m.WParam.ToInt32() == 0xf022)) 43 { 44 if (this.oldSize.Width == 0) 45 { 46 this.oldSize = base.Size; 47 } 48 } 49 break; 50 } 51 this.oldSize = base.Size; 52 53 #endregion 54 break; 55 //在需要計算窗口客戶區的大小和位置時發送。通過處理這個消息,應用程序可以在窗口大小或位置改變時控制客戶區的內容 56 case Win32.WM_NCCALCSIZE: 57 //窗體客戶區以外的重繪消息,一般是由系統負責處理 58 case Win32.WM_NCPAINT: 59 return; 60 //鼠標移動,按下或釋放都會執行該消息 61 case Win32.WM_NCHITTEST: 62 WM_NCHITTEST(ref m); 63 return; 64 //畫窗體被激活或者沒有被激活時的樣子 65 case Win32.WM_NCACTIVATE: 66 #region 67 if (m.WParam == (IntPtr)Win32.WM_FALSE) 68 { 69 m.Result = (IntPtr)Win32.WM_TRUE; 70 } 71 #endregion 72 return; 73 default: 74 base.WndProc(ref m); 75 return; 76 } 77 base.WndProc(ref m); 78 } 79 catch { } 80 } 81 82 private void BaseForm_Resize(object sender, EventArgs e) 83 { 84 SystemBtnSet(); 85 } 86 87 protected override void OnResizeEnd(EventArgs e) 88 { 89 base.OnResizeEnd(e); 90 this.oldSize = base.Size; 91 } 92 93 /// 94 /// 重寫標題屬性 95 /// 96 public override string Text 97 { 98 set 99 { 100 if (value != base.Text) 101 { 102 base.Text = value; 103 this.Invalidate(); 104 } 105 } 106 get 107 { 108 return base.Text; 109 } 110 } 111 #endregion
3、窗體屬性的定義
1 #region 屬性 2 3 [DefaultValue(true)] 4 [CategoryAttribute("放肆雷特皮膚擴展屬性"), Description("是否允許改變窗口大小")] 5 public bool IsResize 6 { 7 get { return this._IsResize; } 8 set { _IsResize = value; } 9 } 10 11 [DefaultValue(true)] 12 [CategoryAttribute("放肆雷特皮膚擴展屬性"), Description("是否在右上角顯示最大化按鈕")] 13 public new bool MaximizeBox 14 { 15 get 16 { 17 return base.MaximizeBox; 18 } 19 set 20 { 21 base.MaximizeBox = value; this.btn_max.Enabled = value; 22 } 23 } 24 25 [CategoryAttribute("放肆雷特皮膚擴展屬性"), Description("系統按鈕設置")] 26 public FormSystemBtn FormSystemBtnSet 27 { 28 get 29 { 30 return _FormSystemBtnSet; 31 } 32 set 33 { 34 _FormSystemBtnSet = value; 35 this.Invalidate(); 36 37 } 38 } 39 40 [CategoryAttribute("放肆雷特皮膚擴展屬性"), Description("獲取或設置窗體圖標")] 41 public new Icon Icon 42 { 43 get 44 { 45 return base.Icon; 46 } 47 set 48 { 49 if (value != base.Icon) 50 { 51 base.Icon = value; 52 this.Invalidate(); 53 } 54 55 } 56 } 57 58 [CategoryAttribute("放肆雷特皮膚擴展屬性"), Description("獲取或設置窗體頭部高度"), DefaultValue(100)] 59 public new int TopHeight 60 { 61 get 62 { 63 return _TopHeight; 64 } 65 set 66 { 67 _TopHeight = value; 68 this.Invalidate(); 69 70 } 71 } 72 #endregion
4、窗體構造函數中窗體樣式以及動作進行初始化設置
1 #region 構造函數 2 public BaseForm() 3 { 4 InitializeComponent(); 5 this.SetStyle(ControlStyles.UserPaint, true);//自繪 6 this.SetStyle(ControlStyles.DoubleBuffer, true);// 雙緩沖 7 this.SetStyle(ControlStyles.ResizeRedraw, true);//調整大小時重繪 8 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景. 9 this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);// 雙緩沖 10 this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); //透明效果 11 if (this.BackgroundImage == null) 12 { 13 this.BackgroundImage = _BackImg; 14 } 15 SystemBtnSet(); 16 } 17 #endregion
使用的時候只需要在窗體中繼承這個窗體就可以使用窗體的風格了!下面是效果圖:

進行到這里窗體和按鈕結合的窗體就已經出來了,中間的背景圖片是從360安全衛士提取出來的資源中拿到的。如果還有不懂的歡迎進行留言提問。下一篇就開始將文本框的制作敬請期待喔。。
本文來自 放肆雷特 | 胖子的技術博客
