问题描述
|
我正在编写一种应用程序,该应用程序需要获取系统输入语言,而应用程序窗口未聚焦。
搜索Google之后,我发现执行此操作的方法是挂起
WM_INPUTLANGCHANGE
消息。
但是我找不到钩子的语法示例。
我找到了以下代码,并尝试使其适应我的需要,但失败了:
编辑:
我已将WM_KEYUP替换为WM_INPUTLANGCHANGE,但是它不起作用。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace KeyHook
{
class LenHook
{
private const int WM_INPUTLANGCHANGE = 0x0051;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
[DllImport(\"user32.dll\",CharSet = CharSet.Auto,SetLastError = true)]
private static extern IntPtr SetwindowsHookEx(int idHook,LowLevelKeyboardProc lpfn,IntPtr hMod,uint dwThreadId);
[DllImport(\"user32.dll\",SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport(\"user32.dll\",SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk,int nCode,IntPtr wParam,IntPtr lParam);
[DllImport(\"kernel32.dll\",SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
private delegate IntPtr LowLevelKeyboardProc(int nCode,IntPtr lParam);
public LenHook()
{
_hookID = SetHook(_proc);
UnhookWindowsHookEx(_hookID);
System.Windows.Forms.Application.Run();
}
//Install hook
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (var curProcess = Process.GetCurrentProcess())
{
using (var curModule = curProcess.MainModule)
{
return SetwindowsHookEx(WM_INPUTLANGCHANGE,proc,GetModuleHandle(curModule.ModuleName),0);
}
}
}
//Do it when key press
private static IntPtr HookCallback(int nCode,IntPtr lParam)
{
MessageBox.Show(wParam.ToString());
return CallNextHookEx(_hookID,nCode,wParam,lParam);
}
}
}
解决方法
我的一个项目中的这段代码对我有用,似乎我们可能使用了相同的示例:
private static IntPtr _hookId = IntPtr.Zero;
private readonly External.LowLevelKeyboardProc _proc;
public FrmMain()
{
_proc = HookCallback;
_hookId = SetHook(_proc);
InitializeComponent();
}
private static IntPtr SetHook(External.LowLevelKeyboardProc proc)
{
using(var curProcess = Process.GetCurrentProcess())
{
using(var curModule = curProcess.MainModule)
{
return External.SetWindowsHookEx(External.WH_KEYBOARD_LL,proc,External.GetModuleHandle(curModule.ModuleName),0);
}
}
}
private IntPtr HookCallback(int nCode,IntPtr wParam,IntPtr lParam)
{
// You can change this to WM_KEYDOWN
if (nCode >= 0 && wParam == (IntPtr)External.WM_KEYUP)
{
// Code you want to run when a button is pressed.
}
return External.CallNextHookEx(_hookId,nCode,wParam,lParam);
}
另外,这是我的External
课。
public static class External
{
public delegate IntPtr LowLevelKeyboardProc(int nCode,IntPtr lParam);
public const int WH_KEYBOARD_LL = 13;
public const int WM_KEYDOWN = 0x0100;
public const int WM_KEYUP = 0x0101;
public const uint WM_GETTEXT = 0x0D;
public const uint WM_GETTEXTLENGTH = 0x0E;
public const uint EM_GETSEL = 0xB0;
[DllImport(\"user32.dll\",CharSet = CharSet.Auto,SetLastError = true)]
public static extern IntPtr GetForegroundWindow();
[DllImport(\"user32.dll\",SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd,out uint lpdwProcessId);
[DllImport(\"kernel32.dll\",SetLastError = true)]
public static extern uint GetCurrentThreadId();
[DllImport(\"user32.dll\",SetLastError = true)]
public static extern bool AttachThreadInput(uint idAttach,uint idAttachTo,bool fAttach);
[DllImport(\"user32.dll\",SetLastError = true)]
public static extern IntPtr GetFocus();
[DllImport(\"user32.dll\",SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd,uint Msg,int wParam,StringBuilder lParam);
[DllImport(\"user32.dll\",out int wParam,out int lParam);
[DllImport(\"user32.dll\",SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook,LowLevelKeyboardProc lpfn,IntPtr hMod,uint dwThreadId);
[DllImport(\"user32.dll\",SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport(\"user32.dll\",SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk,int nCode,IntPtr lParam);
[DllImport(\"kernel32.dll\",SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport(\"user32.dll\",SetLastError = true)]
public static extern bool GetCaretPos(out Point lPoint);
[DllImport(\"user32.dll\",SetLastError = true)]
public static extern int GetClassName(IntPtr hWnd,StringBuilder lpClassName,int nMaxCount);
}
我已经读到,如果您尝试从控制台应用程序执行这些挂钩,尽管您对Application.Run()
的调用应该可以解决此问题,但是您会遇到问题。