【问题标题】:Win form vanishes on maximizing获胜形式在最大化时消失
【发布时间】:2018-04-19 06:18:18
【问题描述】:

我正在为使用 Windows 窗体的应用程序开发 UI。在咨询了this questionthis one 之后,我制作了一个可调整大小的无边框表单。

我有一台多屏电脑。当我在主屏幕上最大化时,表单通常会最大化。如果我将表单完全移动到第二个屏幕,然后使用最大化,表单就会消失。经过调查,我发现即使第二个屏幕的属性“this.MaximizedBounds”是正确确定的,即当我使用该语句时 {X=-1440,Y=0,Width=1440,Height=900}

this.WindowState = FormWindowState.Maximized; 

表格在 {X=-2880,Y=0,Width=1440,Height=900} 处绘制,好像由于某种原因绘制方向颠倒了?鉴于此,我知道我可以以编程方式确定绘制表单,但我想知道我是否缺少设置一些附加属性以确保绘制方向正确?

以编程方式最大化表单的问题在于,表单的状态仍然是 FormWindowState.Normal,我无法将其更改为 FormWindowState.Maximized 而不会导致 from 在错误的位置重绘

使表单无边框的代码

    protected override void WndProc(ref Message m)
    {
        const int RESIZE_HANDLE_SIZE = 10;

        switch (m.Msg)
        {
            case 0x0084/*NCHITTEST*/ :
                base.WndProc(ref m);

                if ((int)m.Result == 0x01/*HTCLIENT*/)
                {
                    Point screenPoint = new Point(m.LParam.ToInt32());
                    Point clientPoint = this.PointToClient(screenPoint);
                    if (clientPoint.Y <= RESIZE_HANDLE_SIZE)
                    {
                        if (clientPoint.X <= RESIZE_HANDLE_SIZE)
                            m.Result = (IntPtr)13/*HTTOPLEFT*/ ;
                        else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE))
                            m.Result = (IntPtr)12/*HTTOP*/ ;
                        else
                            m.Result = (IntPtr)14/*HTTOPRIGHT*/ ;
                    }
                    else if (clientPoint.Y <= (Size.Height - RESIZE_HANDLE_SIZE))
                    {
                        if (clientPoint.X <= RESIZE_HANDLE_SIZE)
                            m.Result = (IntPtr)10/*HTLEFT*/ ;
                        else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE))
                            m.Result = (IntPtr)2/*HTCAPTION*/ ;
                        else
                            m.Result = (IntPtr)11/*HTRIGHT*/ ;
                    }
                    else
                    {
                        if (clientPoint.X <= RESIZE_HANDLE_SIZE)
                            m.Result = (IntPtr)16/*HTBOTTOMLEFT*/ ;
                        else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE))
                            m.Result = (IntPtr)15/*HTBOTTOM*/ ;
                        else
                            m.Result = (IntPtr)17/*HTBOTTOMRIGHT*/ ;
                    }
                }
                return;
        }
        base.WndProc(ref m);
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.Style |= 0x20000; // <--- use 0x20000
            cp.ClassStyle |= 0x08; 
            return cp;
        }
    }

退出、最大化/恢复、最小化的代码

    private void button1_Click(object sender, EventArgs e)
    {
        Application.Exit();
    }
    private void button2_Click(object sender, EventArgs e)
    {
        if(this.WindowState==FormWindowState.Normal)
        {
            this.button2.Image = ((System.Drawing.Image)(Properties.Resources.Restore_Down));
            this.MaximizedBounds = Screen.FromHandle(this.Handle).WorkingArea;
            this.WindowState = FormWindowState.Maximized;

        }
        else if(this.WindowState == FormWindowState.Maximized)
        {
            this.WindowState = FormWindowState.Normal;
            this.button2.Image = ((System.Drawing.Image)(Properties.Resources.Maximize));
        }
    }
    private void button3_Click(object sender, EventArgs e)
    {
        this.WindowState = FormWindowState.Minimized;
    }

【问题讨论】:

    标签: c# winforms maximize-window


    【解决方案1】:

    我的假设是您正在创建一个无边框表单,然后创建自己的工具栏。在没有WndProc 的情况下可以实现这种最大化、最小化和恢复。只需要三个按钮和它们的单击事件处理程序,就像这样(它也可以在多个监视器上工作):

        private void ClickMinimizeButton(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Minimized;
        }
    
        private void ClickRestoreButton(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Normal;
    
        }
    
        private void ClickMaximizeButton(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Maximized;
    
        }
    

    要移动表单,您需要使用WndProc。专门处理WM_NCLBUTTONDOWN windows 消息。这应该在MouseDown 事件处理程序中完成。

            if (e.Button == MouseButtons.Left)
            {
                ReleaseCapture();
                SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
            }
    

    ReleaseCaptureSendMessage 都是 user32.dll 的一部分。

    要调整大小,您将再次需要使用 WndProc。但是,由于您有 2 台显示器,因此您需要自己获取屏幕坐标。下列的 接受的回复来自this 问题。它可能会帮助您获得正确的坐标。

    static class ControlExtensions
    {
        ///<summary>
        /// Returns the position of the point in screen coordinates of that control instead
        /// of the main-screen coordinates
        ///</summary>
        public static Point PointToCurrentScreen(this Control self, Point location)
        {
            var screenBounds = Screen.FromControl(self).Bounds;
            var globalCoordinates = self.PointToScreen(location);
            return new Point(globalCoordinates.X - screenBounds.X, globalCoordinates.Y - screenBounds.Y);
        }
    }
    

    【讨论】:

    • 我确实做到了这一点。我有自己的工具栏和按钮用于最大化等。我面临的问题特别是当我在第二个屏幕上最大化时,表单会在不可见的坐标处绘制。简单地说WindowState = FormWindowState.Maximized; 这在除主监视器之外的任何监视器上都无法正常工作。虽然this.MaximizedBounds = Screen.FromHandle(this.Handle).WorkingArea; 给了我我需要的正确的最大化界限。但它只是没有最大化到提供的坐标
    • 屏幕坐标码是我需要的。如果微软在屏幕而不是全局坐标中提到“MaximizedBounds”,那将会很有帮助
    【解决方案2】:

    为什么要使用 WndProc 使其无边界?
    Windows 窗体具有“FormBorderStyle”属性,

           this.FormBorderStyle = FormBorderStyle.None;
    

    应该让它无边界,也许这种更默认的方法也解决了窗口位置问题

    【讨论】:

    • 我也这样做了。 WndProc 代码是为了使无边界表单可调整大小和可移动
    猜你喜欢
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-18
    • 2015-01-18
    • 1970-01-01
    相关资源
    最近更新 更多