Application stuck in full screen?

前端 未结 4 1825
醉酒成梦
醉酒成梦 2020-12-08 17:01

To reproduce my problem please do the following:

  1. Create a new Windows Form Application in C#.
  2. In the Properties window of Form1 set FormBorderSt
相关标签:
4条回答
  • 2020-12-08 17:35

    Check this solution - it removes Maximize/Minimize/Titlebar/Border by API calls.

    public partial class Form1 : Form
    {
        // import necessary API functions to get and set Windows styles for P/Invoke
        [DllImport("user32.dll")]
        internal extern static int SetWindowLong(IntPtr hwnd, int index, int value);
    
        [DllImport("user32.dll")]
        internal extern static int GetWindowLong(IntPtr hwnd, int index);
    
        // define constants like they are named in SDK in order to make source more readable
        const int GWL_STYLE = -16;
        const int GWL_EXSTYLE = -20;
        const int WS_MINIMIZEBOX = 0x00020000;
        const int WS_MAXIMIZEBOX = 0x00010000;
        const int WS_CAPTION = 0x00C00000;
        const int WS_THICKFRAME = 0x00040000;
        const int WS_EX_DLGMODALFRAME = 0x00000001;
        const int WS_EX_CLIENTEDGE = 0x00000200;
        const int WS_EX_STATICEDGE = 0x00020000;
    
        // this replaces MinimizeBox=false and MaximizeBox=false
        void HideMinimizeAndMaximizeButtons()
        {
            // read current style
            int style = GetWindowLong(Handle, GWL_STYLE);
            Debug.WriteLine("0x{0:X}", style);
            // update style - remove flags for MinimizeBox and MaximizeBox
            style = style & ~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX;
            Debug.WriteLine("0x{0:X}", style);
            SetWindowLong(Handle, GWL_STYLE, style);
        }
    
        // part of removing the whole border
        void HideTitleBar()
        {
            // read current style
            int style = GetWindowLong(Handle, GWL_STYLE);
            Debug.WriteLine("0x{0:X}", style);
            // update style - remove flag for caption
            style = style & ~WS_CAPTION;
            Debug.WriteLine("0x{0:X}", style);
            SetWindowLong(Handle, GWL_STYLE, style);
        }
    
        // hide the border
        void HideBorder()
        {
            // read current style
            int style = GetWindowLong(Handle, GWL_STYLE);
            Debug.WriteLine("0x{0:X}", style);
            // update style - remove flag for border (could use WS_SIZEBOX which is the very same flag (see MSDN)
            style = style & ~WS_THICKFRAME;
            Debug.WriteLine("0x{0:X}", style);
            SetWindowLong(Handle, GWL_STYLE, style);
    
            // read current extended style
            style = GetWindowLong(Handle, GWL_EXSTYLE);
            Debug.WriteLine("0x{0:X}", style);
            // update style by removing some additional border styles -
            // may not be necessary, when current border style is not something exotic,
            // i.e. as long as it "normal"
            style = style & ~WS_EX_DLGMODALFRAME & ~WS_EX_CLIENTEDGE & ~WS_EX_STATICEDGE;
            Debug.WriteLine("0x{0:X}", style);
            SetWindowLong(Handle, GWL_EXSTYLE, style);
        }
    
        public Form1()
        {
            InitializeComponent();
    
            // hide those unwanted properties - you can try to leave out one or another to see what it does
            HideMinimizeAndMaximizeButtons();
            HideTitleBar();
            HideBorder();
        }
    }
    

    This works as intended. Maximizing/minimizing by setting WindowState works as well.

    One could analyze in sources what the framework does and what it does "wrong" (or not quite correct).

    Edit: I added debug output of the style values. Please try this sequence of commands in Form1 constructor:

    MaximizeBox = false;
    FormBorderStyle = FormBorderStyle.Sizable;
    HideMinimizeAndMaximizeButtons();
    FormBorderStyle = FormBorderStyle.None;
    MaximizeBox = true;
    MaximizeBox = false;
    HideMinimizeAndMaximizeButtons();
    FormBorderStyle = FormBorderStyle.None;
    HideMinimizeAndMaximizeButtons();
    

    You'll see, that setting FormBorderStyle.None enables the WS_MAXIMIZEBOX style. This cannot be "corrected" by another MaximizeBox = false. It seems it's necessary to call API functions.

    0 讨论(0)
  • 2020-12-08 17:45

    Overriding the ProcessCmdKey (protected method in Form) explicitly allow us to apply custom hook and can be used in your scenario. This essentially allow us to override built-in keystroke handling.

    Note: Following example demonstrate the idea of how to handle different keystroke or combination of it. Now, you probably need to fine tune the following code to work inline with your scenario. Eg: Ideally changing the FormBorderStyle or Form Size when user press the LWin+Up arrow.

    public partial class Form1 : Form
     {
    
      protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
    
         if (keyData == (Keys.LWin | Keys.Up))//Left windows key + up arrow
           {
    
               FormBorderStyle = FormBorderStyle.FixedDialog;
               return true;
            }
    
        if (keyData == Keys.Escape) //Form will call its close method when we click Escape.
            Close();
    
            return base.ProcessCmdKey(ref msg, keyData);
       }
    }
    

    Updated on How to disable windows Key in your case Lwin or RWin

    public partial class Form1 : Form
        {
    
    
            // Structure contain information about low-level keyboard input event
            [StructLayout(LayoutKind.Sequential)]
            private struct KBDLLHOOKSTRUCT
            {
                public Keys key;
                public int scanCode;
                public int flags;
                public int time;
                public IntPtr extra;
            }
    
            //System level functions to be used for hook and unhook keyboard input
            private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr SetWindowsHookEx(int id, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId);
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool UnhookWindowsHookEx(IntPtr hook);
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr CallNextHookEx(IntPtr hook, int nCode, IntPtr wp, IntPtr lp);
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr GetModuleHandle(string name);
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            private static extern short GetAsyncKeyState(Keys key);
    
    
            //Declaring Global objects
            private IntPtr ptrHook;
            private LowLevelKeyboardProc objKeyboardProcess;
    
            public Form1()
            {
                ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule;
                objKeyboardProcess = new LowLevelKeyboardProc(captureKey);
                ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0);
    
    
                InitializeComponent();
            }
    
            private IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp)
            {
                if (nCode >= 0)
                {
                    KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));
    
                    if (objKeyInfo.key == Keys.RWin || objKeyInfo.key == Keys.LWin) // Disabling Windows keys
                    {
                        return (IntPtr)1;
                    }
                }
                return CallNextHookEx(ptrHook, nCode, wp, lp);
            }
    
    
    
            private void Form1_KeyPress(object sender, KeyPressEventArgs e)
            {
                MessageBox.Show(e.KeyChar.ToString());
            }
    
    
        }
    
    0 讨论(0)
  • 2020-12-08 17:55

    Trap the WM_GETMINMAXINFO message which will allow you to specify the maximized size and location of your form. Technically your form will still change state to Maximized, but it will appear the same since we specify the maximized size/position to be the same as the normal state of the form:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    
        public struct POINTAPI
        {
            public Int32 X;
            public Int32 Y;
        }
    
        public struct MINMAXINFO
        {
            public POINTAPI ptReserved;
            public POINTAPI ptMaxSize;
            public POINTAPI ptMaxPosition;
            public POINTAPI ptMinTrackSize;
            public POINTAPI ptMaxTrackSize;
        }
    
        public const Int32 WM_GETMINMAXINFO = 0x24;
    
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_GETMINMAXINFO:
                    MINMAXINFO mmi = (MINMAXINFO)System.Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, typeof(MINMAXINFO));
                    mmi.ptMaxSize.X = this.Width;
                    mmi.ptMaxSize.Y = this.Height;
                    mmi.ptMaxPosition.X = this.Location.X;
                    mmi.ptMaxPosition.Y = this.Location.Y;
                    System.Runtime.InteropServices.Marshal.StructureToPtr(mmi, m.LParam, true);
                    break;
            }
            base.WndProc(ref m);
        }
    
    }
    
    0 讨论(0)
  • 2020-12-08 17:58

    Windows does this by calling SetWindowPos() to change the position and size of the window. A window can be notified about this by listening for the WM_WINDOWPOSCHANGING message and override the settings. Lots of things you can do, like still giving the operation a meaning by adjusting the size and position to your liking. You completely prevent it by turning on the NOSIZE and NOMOVE flags.

    Paste this code into your form:

        private bool AllowWindowChange;
    
        private struct WINDOWPOS {
            public IntPtr hwnd, hwndInsertAfter;
            public int x, y, cx, cy;
            public int flags;
        }
    
        protected override void WndProc(ref Message m) {
            // Trap WM_WINDOWPOSCHANGING
            if (m.Msg == 0x46 && !AllowWindowChange) {
                var wpos = (WINDOWPOS)System.Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, typeof(WINDOWPOS));
                wpos.flags |= 0x03; // Turn on SWP_NOSIZE | SWP_NOMOVE
                System.Runtime.InteropServices.Marshal.StructureToPtr(wpos, m.LParam, false);
            }
            base.WndProc(ref m);
        }
    

    When you want to change the window yourself, simply set the AllowWindowChange field temporarily to true.

    0 讨论(0)
提交回复
热议问题