Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Minimize a borderless form by Win + M windows shortcut

Tags:

c#

.net

winforms

The standard Win + M keyboard shortcut minimizes open windows, but it does not minimize a borderless form.

I'm thinking of capturing key events of Win + M in KeyDown event but no luck, since it does not capture both but only captures the first key.

I can't programmatically minimize it using a keyboard shortcut

Any idea on how to minimize my for form by keyboard shortcut? or can I capture Win + M to trigger minimize function?

I'm using borderless form. To reproduce the problem, create a Form and set its BorderStyle to None and run the application. When you press Win + M, all the windows minimize, but my borderless form stays normal.

like image 439
myelxx Avatar asked Jan 26 '21 14:01

myelxx


1 Answers

As a totally different option you can register a low level keyboard hook using SetWindowsHookEx and check if you received the Win + M, then minimize the window and let the key goes through other windows.

Add the following piece of code to your Form and then Win + M will work as expected:

private const int WH_KEYBOARD_LL = 13;
[StructLayout(LayoutKind.Sequential)]
private struct KBDLLHOOKSTRUCT
{
    public Keys vkCode;
    public int scanCode;
    public int flags;
    public int time;
    public IntPtr dwExtraInfo;
}
private delegate IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(
    int idHook, HookProc lpfn, IntPtr hmod, uint dwThreadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(
    IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern short GetKeyState(int keyCode);
private const int KEY_PRESSED = 0x8000;
private static bool IsKeyDown(Keys key)
{
    return Convert.ToBoolean(GetKeyState((int)key) & KEY_PRESSED);
}

private IntPtr ptrHook;
private HookProc hookProc;
private IntPtr CaptureKeys(int code, IntPtr wParam, IntPtr lParam)
{
    if (code >= 0)
    {
        KBDLLHOOKSTRUCT objKeyInfo = 
            (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(
                lParam, typeof(KBDLLHOOKSTRUCT));
        if (objKeyInfo.vkCode == (Keys.M) &&
            (IsKeyDown(Keys.LWin) || IsKeyDown(Keys.RWin)))
        {
            this.WindowState = FormWindowState.Minimized;
            return (IntPtr)0;
        }
    }
    return CallNextHookEx(ptrHook, code, wParam, lParam);
}
bool HasAltModifier(int flags)
{
    return (flags & 0x20) == 0x20;
}
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    var module = Process.GetCurrentProcess().MainModule;
    hookProc = new HookProc(CaptureKeys);
    ptrHook = SetWindowsHookEx(
        WH_KEYBOARD_LL, hookProc, GetModuleHandle(module.ModuleName), 0);
}
like image 189
Reza Aghaei Avatar answered Nov 02 '22 12:11

Reza Aghaei