应用程序卡在全屏?

要重现我的问题,请执行以下操作:

  1. 在C#中创建一个新的Windows窗体应用程序。
  2. 在Form1的“属性”窗口中,将FormBorderStyle设置为None
  3. 启动程序并按Windows + Up
  4. 现在你陷入全屏。

在默认的FormBorderStyle设置中, MaximizeBox属性为false将禁用Windows + Up全屏快捷方式。

如果FormBorderStyle设置为None Microsoft决定禁用除向上箭头之外的所有Windows +箭头键快捷键,然后禁用禁用MaximizeBox属性。

这是一个小故障吗? 禁用此快捷方式的任何简单方法都是在所有其他FormBorderStyles上禁用的同一方式

检查此解决方案 – 它通过API调用删除Maximize / Minimize / Titlebar / Border。

 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, // ie 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(); } } 

这按预期工作。 通过设置WindowState最大化/最小化也可以。

人们可以从源头分析框架的作用以及它的“错误”(或不完全正确)。

编辑:我添加了样式值的调试输出。 请在Form1构造函数中尝试以下命令序列:

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

您将看到,设置FormBorderStyle.None启用WS_MAXIMIZEBOX样式。 这不能被另一个MaximizeBox = false “纠正”。 似乎有必要调用API函数。

Windows通过调用SetWindowPos()来改变窗口的位置和大小。 可以通过侦听WM_WINDOWPOSCHANGING消息并覆盖设置来通知窗口。 你可以做很多事情,比如通过根据自己的喜好resize和位置来保持操作的意义。 你可以通过打开NOSIZE和NOMOVE标志来完全阻止它。

将此代码粘贴到您的表单中:

  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); } 

如果您想自己更改窗口,只需将AllowWindowChange字段暂时设置为true即可。

捕获WM_GETMINMAXINFO消息,该消息允许您指定表单的最大大小和位置。 从技术上讲,您的表单仍然会将状态更改为最大化,但它会显示相同,因为我们指定最大化的大小/位置与表单的正常状态相同:

 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); } } 

覆盖ProcessCmdKey (Form中的受保护方法)显式允许我们应用自定义钩子并可以在您的场景中使用。 这基本上允许我们覆盖内置的击键处理。

注意 :下面的示例演示了如何处理不同击键或其组合的想法。 现在,您可能需要微调以下代码以与您的方案一起工作。 例如:当用户按下LWin+Up箭头时,理想情况下更改FormBorderStyleForm Size

 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); } } 

更新了如何在您的案例LwinRWin禁用Windows键

 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()); } }