Winform窗口大小调整、拖动页面、侧面菜单栏折叠/展开

发布时间 2023-11-05 15:01:39作者: 赵书记

控件库用的是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,则直接返回,不进行窗口尺寸的计算,从而实现去除窗口工具栏的效果。