Winform窗口大小调整、拖动页面、侧面菜单栏折叠/展开
控件库用的是FontAwesome.Sharp
侧面菜单栏折叠/展开,效果如下图:
侧面菜单栏折叠/展开
菜单缩放按钮代码如下:
private void btnMenu_Click(object sender, EventArgs e) { CollapseMenu(); }
CollapseMenu()方法代码如下:
private void CollapseMenu() { if (this.panelMenu.Width > 200) { panelMenu.Width = 100; iconPictureBox1.Visible = false; btnMenu.Dock = DockStyle.Top; this.panel1.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 = 260; iconPictureBox1.Visible = true; btnMenu.Dock = DockStyle.None; this.panel1.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.Margin = new Padding(10, 0, 0, 0); } } }
这段C#代码实现了一个CollapseMenu()方法,用于控制侧边栏菜单的折叠和展开。
首先判断当前侧边栏的宽度是否大于200,如果是,则将宽度设置为100,隐藏图标,将菜单按钮的Dock属性设置为Top,设置面板的内边距为上边10像素,下左右为0,并遍历所有的菜单按钮,将它们的文本设置为空,图像对齐方式设置为居中,内边距设置为0。
如果当前侧边栏的宽度小于等于200,就将宽度设置为260,显示图标,将菜单按钮的Dock属性设置为None,设置面板的内边距为上下左右都为0,并遍历所有的菜单按钮,将它们的文本设置为按钮的Tag属性值前面加两个空格,图像对齐方式设置为左对齐,文本对齐方式设置为右对齐,按钮文本和图像的相对位置设置为文本在图像左侧,内边距设置为上0像素,左边距为10像素,下右边距为0。
拖动页面
这里用的是pannel控件的MouseDown事件,当鼠标在panel控件范围内被按下,就可以拖动窗体,固定代码如下:
以下代码都为固定代码
[DllImport("user32.DLL", EntryPoint = "ReleaseCapture")] private extern static void ReleaseCapture(); [DllImport("user32.DLL", EntryPoint = "SendMessage")] private extern static 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); }
窗口拉伸/去除窗口工具栏
固定代码如下:
protected override void WndProc(ref Message m) { #region 随意拉伸窗口 const int WM_NCCALCSIZE = 0x0083;//Standar Title Bar - Snap Window const int WM_SYSCOMMAND = 0x0112; const int SC_MINIMIZE = 0xF020; //Minimize form (Before) const int SC_RESTORE = 0xF120; //Restore form (Before) const int WM_NCHITTEST = 0x0084;//Win32, Mouse Input Notification: Determine what part of the window corresponds to a point, allows to resize the form. const int resizeAreaSize = 10; // Resize/WM_NCHITTEST values const int HTCLIENT = 1; //Represents the client area of the window const int HTLEFT = 10; //Left border of a window, allows resize horizontally to the left const int HTRIGHT = 11; //Right border of a window, allows resize horizontally to the right const int HTTOP = 12; //Upper-horizontal border of a window, allows resize vertically up const int HTTOPLEFT = 13;//Upper-left corner of a window border, allows resize diagonally to the left const int HTTOPRIGHT = 14;//Upper-right corner of a window border, allows resize diagonally to the right const int HTBOTTOM = 15; //Lower-horizontal border of a window, allows resize vertically down const int HTBOTTOMLEFT = 16;//Lower-left corner of a window border, allows resize diagonally to the left const int HTBOTTOMRIGHT = 17;//Lower-right corner of a window border, allows resize diagonally to the right ///<Doc> More Information: https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-nchittest </Doc> if (m.Msg == WM_NCHITTEST) { //If the windows m is WM_NCHITTEST base.WndProc(ref m); if (this.WindowState == FormWindowState.Normal)//Resize the form if it is in normal state { if ((int)m.Result == HTCLIENT)//If the result of the m (mouse pointer) is in the client area of the window { Point screenPoint = new Point(m.LParam.ToInt32()); //Gets screen point coordinates(X and Y coordinate of the pointer) Point clientPoint = this.PointToClient(screenPoint); //Computes the location of the screen point into client coordinates if (clientPoint.Y <= resizeAreaSize)//If the pointer is at the top of the form (within the resize area- X coordinate) { if (clientPoint.X <= resizeAreaSize) //If the pointer is at the coordinate X=0 or less than the resizing area(X=10) in m.Result = (IntPtr)HTTOPLEFT; //Resize diagonally to the left else if (clientPoint.X < (this.Size.Width - resizeAreaSize))//If the pointer is at the coordinate X=11 or less than the width of the form(X=Form.Width-resizeArea) m.Result = (IntPtr)HTTOP; //Resize vertically up else //Resize diagonally to the right m.Result = (IntPtr)HTTOPRIGHT; } else if (clientPoint.Y <= (this.Size.Height - resizeAreaSize)) //If the pointer is inside the form at the Y coordinate(discounting the resize area size) { if (clientPoint.X <= resizeAreaSize)//Resize horizontally to the left m.Result = (IntPtr)HTLEFT; else if (clientPoint.X > (this.Width - resizeAreaSize))//Resize horizontally to the right m.Result = (IntPtr)HTRIGHT; } else { if (clientPoint.X <= resizeAreaSize)//Resize diagonally to the left m.Result = (IntPtr)HTBOTTOMLEFT; else if (clientPoint.X < (this.Size.Width - resizeAreaSize)) //Resize vertically down m.Result = (IntPtr)HTBOTTOM; else //Resize diagonally to the right m.Result = (IntPtr)HTBOTTOMRIGHT; } } } return; } if (m.Msg == WM_SYSCOMMAND) { /// <see cref="https://docs.microsoft.com/en-us/windows/win32/menurc/wm-syscommand"/> /// Quote: /// In WM_SYSCOMMAND messages, the four low - order bits of the wParam parameter /// are used internally by the system.To obtain the correct result when testing /// the value of wParam, an application must combine the value 0xFFF0 with the /// wParam value by using the bitwise AND operator. int wParam = (m.WParam.ToInt32() & 0xFFF0); if (wParam == SC_MINIMIZE) //Before formSize = this.ClientSize; if (wParam == SC_RESTORE)// Restored form(Before) this.Size = formSize; } #endregion #region 去除窗口工具栏 //去除窗口工具栏 //const int WM_NCCALCSIZE = 0x0083; if (m.Msg == WM_NCCALCSIZE && m.WParam.ToInt32() == 1) { return; } base.WndProc(ref m); #endregion }
1. 随意拉伸窗口
在窗口的客户区域,即窗口内部,用户可以通过鼠标拖动窗口边缘进行拉伸大小。该功能通过处理 WM_NCHITTEST 消息实现。当用户移动鼠标到窗口边缘时,窗口会检测鼠标的位置,并返回一个对应的值,该值表示鼠标所在位置对应的窗口边缘位置。根据该值,就可以实现窗口边缘的拉伸。
2. 去除窗口工具栏
在窗口的非客户区域,即窗口边框和标题栏,系统默认会显示窗口工具栏,包括关闭、最小化和最大化按钮。该功能通过处理 WM_NCCALCSIZE 消息实现。在该消息中,参数 wparam 的值为 1,表示窗口尺寸需要计算。在处理该消息时,如果 wparam 的值为 1,则直接返回,不进行窗口尺寸的计算,从而实现去除窗口工具栏的效果。