在某些项目中需要保证程序置顶,并屏蔽系统按键,防止在程序运行时有弹窗出现,比如win、alt+tab。这可以通过windows的键盘钩子实现,代码如下。
在编辑模式时会偶发crash,原因未知,发布后正常使用。
注意的是,SetWindowsHookEx 第三个参数有多种获取方式,可看下代码开头的参考链接。
using UnityEngine;
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
/// <summary>
/// http://geekswithblogs.net/aghausman/archive/2009/04/26/disable-special-keys-in-win-app-c.aspx
/// https://gist.github.com/Lunchbox4K/291f9c8a2501170221d11d29d1355ee1
/// https://csharp.hotexamples.com/zh/examples/-/KBDLLHOOKSTRUCT/-/php-kbdllhookstruct-class-examples.html
/// https://gist.github.com/Stasonix/3181083
/// https://blog.walterlv.com/post/add-global-windows-hook-in-dotnet.html
/// https://stackoverflow.com/questions/14260522/why-use-loadlibrary-instead-of-just-getting-baseaddress-of-your-program
/// https://answers.unity.com/questions/1398007/how-do-i-disable-the-system-shortcut-key-after-the-1.html
/// </summary>
///
public class KeyboardHook : MonoBehaviour
{
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref KeyboardHookData lParam);
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr GetModuleHandle(string name);
// <see cref="https://msdn.microsoft.com/en-us/library/windows/desktop/ms644967(v=vs.85).aspx"/>
struct KeyboardHookData
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
delegate int keyboardHookProc(int code, int wParam, ref KeyboardHookData lParam);
// <see cref="https://msdn.microsoft.com/en-us/library/windows/desktop/ms644959%28v=vs.85%29.aspx#wh_keyboard_llhook"/>
static readonly int WH_KEYBOARD_LL = 13;
static readonly int WM_KEYDOWN = 0x100;
static readonly int WM_KEYUP = 0x101;
static readonly int WM_SYSKEYDOWN = 0x104;
static readonly int WM_SYSKEYUP = 0x105;
static IntPtr hhook = IntPtr.Zero;
static void Hook()
{
//注释的三种方式都可以
var hModule = LoadLibrary("User32");
//var hModule = GetModuleHandle(null);
//var hModule = Process.GetCurrentProcess().MainModule.BaseAddress;
//var hModule = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
//Call library hook function
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, new keyboardHookProc(HookProc), hModule, 0);
}
static void Unhook()
{
UnhookWindowsHookEx(hhook);
}
// <see cref="https://msdn.microsoft.com/en-us/library/windows/desktop/ms644984%28v=vs.85%29.aspx"/>
static int HookProc(int code, int wParam, ref KeyboardHookData lParam)
{
if (code >= 0)
{
if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP || wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
{
UnityEngine.Debug.Log("lParam.vkCode = " + lParam.vkCode + " / lParam.flags = " + lParam.flags);
bool Suppress = false;
if (((lParam.flags == 32) && (lParam.vkCode == 0x09)) || // Alt+Tab
((lParam.flags == 32) && (lParam.vkCode == 0x1B)) || // Alt+Esc
((lParam.flags == 0) && (lParam.vkCode == 0x1B)) || // Ctrl+Esc
((lParam.flags == 1) && (lParam.vkCode == 0x5B)) || // Left Windows Key
((lParam.flags == 1) && (lParam.vkCode == 0x5C)) || // Right Windows Key
((lParam.flags == 32) && (lParam.vkCode == 0x73)) || // Alt+F4
((lParam.flags == 32) && (lParam.vkCode == 0x20))) //Alt+Space
Suppress = true;
if (Suppress)
{
return 1;
}
}
}
return CallNextHookEx(hhook, code, wParam, ref lParam);
}
void Start()
{
Hook();
}
void OnDestroy()
{
Unhook();
}
}
技术文章,学习了。暑期快乐,感谢博主的分享,支持了。
2021-07-31 17:22 回复能帮到你就Ok
2021-08-16 17:40 回复过来学习一下!
2021-09-06 17:24 回复