Winform中實現無邊框窗體只需要設定一個屬性FormBorderStyle = FormBorderStyle.None;即可,或者在設計器中直接設定。無邊框表單的結果是丟失了標題欄和控制框(最小化、最大值和關閉按鈕)。如果沒有標題欄,則無法拖動和移動視窗。如果沒有邊框,則無法拖動 Windows 邊緣來調整其大小。移動表單非常簡單,但邊緣拖動調整大小有點棘手。
下面透過監聽滑鼠事件和調整游標形狀,實現了一個使用者可以透過拖拽窗體邊緣來調整窗體大小的功能。同時,它還確保了當滑鼠離開窗體時,游標形狀會恢復為預設的箭頭形狀。
先上效果圖
具體來說,它允許使用者透過拖動滑鼠來改變窗體的大小。以下是程式碼的工作原理概述:
1.初始化:
在建構函式 Form1() 中,為 Form1 例項註冊了兩個事件處理器:MouseMove 用於處理滑鼠移動時的行為,MouseLeave 用於處理滑鼠離開窗體時的行為。
2.滑鼠移動處理 (Main_MouseMove):
如果滑鼠接近右下角,則顯示雙向對角線箭頭。
如果滑鼠接近右側,則顯示水平箭頭。
如果滑鼠接近底部,則顯示垂直箭頭。
Cursors.SizeNWSE: 允許同時改變窗體的寬度和高度。
Cursors.SizeWE: 只允許改變窗體的寬度。
Cursors.SizeNS: 只允許改變窗體的高度。
當滑鼠在窗體內移動時,會觸發 MouseMove 事件。
如果滑鼠左鍵被按下,並且游標形狀是某種尺寸調整箭頭(Cursors.SizeNWSE, Cursors.SizeWE, 或 Cursors.SizeNS),則根據當前游標型別調整窗體的寬度和/或高度。
根據滑鼠位置與窗體邊緣的距離(5畫素內),動態地改變游標形狀以提示使用者可以進行何種型別的尺寸調整:
如果滑鼠不在這些區域,則恢復預設的箭頭游標。
3.滑鼠離開窗體處理 (Main_Leave):
當滑鼠指標離開窗體範圍時,將游標恢復到預設的箭頭狀態。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApp7 { public partial class Form1 : Form { private int borderSize = 2; [DllImport("user32.DLL", EntryPoint = "ReleaseCapture")] private extern static void ReleaseCapture(); [DllImport("user32.DLL", EntryPoint = "SendMessage")] private static extern void SendMessage(System.IntPtr hWnd, int wMsg, int wParam, int lParam); private void panelTitleBar_MouseDown(object sender, MouseEventArgs e) //panel的MouseDown事件 { ReleaseCapture(); SendMessage(this.Handle, 0x112, 0xf012, 0); } public Form1() { InitializeComponent(); this.Padding = new Padding(borderSize); this.BackColor = Color.FromArgb(245, 245, 255); //98, 102, 244);// this.ControlBox = false; this.Text = string.Empty; this.FormBorderStyle = FormBorderStyle.None; //this.WindowState = FormWindowState.Maximized; this.MaximizedBounds = Screen.FromHandle(this.Handle).WorkingArea; MouseMove += Main_MouseMove; MouseLeave += Main_Leave; // 有控制元件在邊緣時,處理一下更好一些 } private void Form1_Load(object sender, EventArgs e) { this.panelMenu.Width = 180; } #region 退出按鈕 private void appExit(object sender, EventArgs e) { //退出按鈕 Application.Exit(); } #endregion #region 最大化按鈕 private void butMax_Click(object sender, EventArgs e) { //最大化按鈕 if (this.WindowState == FormWindowState.Normal) { this.WindowState = FormWindowState.Maximized; } else { this.WindowState = FormWindowState.Normal; } } #endregion #region 最小化按鈕 private void butMin_Click(object sender, EventArgs e) { //最小化按鈕 this.WindowState = FormWindowState.Minimized; } #endregion #region 側面選單欄摺疊與展開 //private void CollapseMenu() //{ // if (this.panel1.Width > 50) // { // this.panel1.Width = 50; // this.pictureBox1.Visible = false; // //this.button7.Dock = DockStyle.Fill; // foreach (Button control in panel1.Controls.OfType<Button>()) // { // control.Text = ""; // control.ImageAlign = ContentAlignment.MiddleCenter; // control.Padding = new Padding(0); // } // } // else // { // this.panel1.Width = 180; // this.pictureBox1.Visible = true; // //this.button7.Dock = DockStyle.Right; // foreach (Button control in panel1.Controls.OfType<Button>()) // { // control.Text = control.Tag.ToString(); // control.ImageAlign = ContentAlignment.MiddleLeft; // control.Padding = new Padding(45, 0, 0, 0); // } // } //} private void CollapseMenu() { //這段C#程式碼實現了一個CollapseMenu()方法,用於控制側邊欄選單的摺疊和展開 //首先判斷當前側邊欄的寬度是否大於200,如果是,則將寬度設定為100,隱藏圖示, //將選單按鈕的Dock屬性設定為Top, //設定皮膚的內邊距為上邊10畫素,下左右為0, //並遍歷所有的選單按鈕,將它們的文字設定為空, //影像對齊方式設定為居中,內邊距設定為0。 //如果當前側邊欄的寬度小於等於200, //就將寬度設定為260,顯示圖示,將選單按鈕的Dock屬性設定為None, //設定皮膚的內邊距為上下左右都為0, //並遍歷所有的選單按鈕,將它們的文字設定為按鈕的Tag屬性值前面加兩個空格, //影像對齊方式設定為左對齊,文字對齊方式設定為右對齊, //按鈕文字和影像的相對位置設定為文字在影像左側, //內邊距設定為上0畫素,左邊距為10畫素,下右邊距為0。 if (this.panelMenu.Width > 100) { panelMenu.Width = 50; iconPictureBox1.Visible = false; //btnMenu.Dock = DockStyle.Top; //this.panelMenu.Padding = new Padding(0, 10, 0, 0); foreach (var mybutton in this.panelMenu.Controls.OfType<Button>()) //篩選出panelMenu內所有屬於Button型別的子控制元件 { mybutton.Text = ""; mybutton.ImageAlign = ContentAlignment.MiddleCenter; //將其影像對齊方式設定為居中對齊 mybutton.Padding = new Padding(0); //內邊距設為0 } } else { panelMenu.Width = 180; iconPictureBox1.Visible = true; //btnMenu.Dock = DockStyle.None; //this.panelMenu.Padding = new Padding(0, 0, 0, 0); foreach (var mybutton in this.panelMenu.Controls.OfType<Button>()) //篩選出panelMenu內所有屬於Button型別的子控制元件 { mybutton.Text =mybutton.Tag.ToString(); //將控制元件的Tag賦值給Text " " + mybutton.ImageAlign = ContentAlignment.MiddleLeft; mybutton.TextAlign = ContentAlignment.MiddleRight; mybutton.TextImageRelation = TextImageRelation.ImageBeforeText; //Text和Image位置關係 mybutton.Padding = new Padding(30, 0, 0, 0); } } } //側面選單欄摺疊與展開 private void btnMenu_Click(object sender, EventArgs e) { CollapseMenu(); } #endregion #region 保持整體佈局不變 private void AdjustForm() { switch (this.WindowState) { case FormWindowState.Normal: if (this.Padding.Top != borderSize) this.Padding = new Padding(borderSize); break; case FormWindowState.Minimized: this.Padding = new Padding(8, 8, 8, 8); break; case FormWindowState.Maximized: break; default: break; } } private void Form1_Resize(object sender, EventArgs e) { AdjustForm(); } #endregion #region 控制無邊框拉伸 private void Main_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left)//左鍵按下移動,拖拽調整大小 { // MousePosition的參考點是螢幕的左上角,表示滑鼠當前相對於螢幕左上角的座標。this.Left和this.Top的參考點也是螢幕 if (Cursor == Cursors.SizeNWSE) // 傾斜拖拽 { // 改變窗體寬和高的程式碼,其寬高為滑鼠螢幕位置減去窗體的Left,Top距離 this.Width = MousePosition.X - this.Left; this.Height = MousePosition.Y - this.Top; } else if (Cursor == Cursors.SizeWE) // 水平拖拽 { Width = MousePosition.X - this.Left; } else if (Cursor == Cursors.SizeNS) // 垂直拖拽 { Height = MousePosition.Y - this.Top; } } //滑鼠移動過程中,座標時刻在改變 //當滑鼠移動時橫座標距離窗體右邊緣5畫素以內且縱座標距離下邊緣也在5畫素以內時,要將游標變為傾斜的箭頭形狀 if (e.Location.X >= this.Width - 5 && e.Location.Y > this.Height - 5) { this.Cursor = Cursors.SizeNWSE; // 右下角 雙向對角線游標 } //當滑鼠移動時橫座標距離窗體右邊緣5畫素以內時,要將游標變為雙向水平箭頭形狀 else if (e.Location.X >= this.Width - 5) { this.Cursor = Cursors.SizeWE; // 雙向水平游標 } //當滑鼠移動時縱座標距離窗體下邊緣5畫素以內時,要將游標變為垂直水平箭頭形狀 else if (e.Location.Y >= this.Height - 5) { this.Cursor = Cursors.SizeNS; // 雙向垂直游標 } //否則,以外的窗體區域,滑鼠星座均為單向箭頭(預設) else this.Cursor = Cursors.Arrow; } private void Main_Leave(object sender, EventArgs e) { Cursor = Cursors.Arrow;// 移出窗體變為正常 } #endregion } }
透過這種方式,當使用者將滑鼠懸停在窗體邊緣並拖動時,窗體會相應地改變其大小,提供了直觀的使用者體驗。這段程式碼沒有涉及到實際的拖動整個窗體的位置,僅關注於改變窗體的尺寸。如果需要實現窗體位置的拖動,還需要額外的邏輯來處理標題欄或其他指定區域的拖動行為。