Обработка сообщений Windows Hook. Обработать сообщение от другой программы
Имеется программа, рассылающая сообщения на c++.
В WPF принимаю следующим образом:
public static void RegisterWindowMessage(this Window window, string lpString, Action<string> action)
{
_action = action;
_msg = RegisterWindowMessage(lpString);
var source = HwndSource.FromHwnd(new WindowInteropHelper(window).Handle);
source?.AddHook(WndProc);
}
И обработка Hook:
private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == _msg)
{
_action(lParam.ToString());
}
return IntPtr.Zero;
}
Возникла задача перенести проект на MAUI. Соответственно решил сделать тоже самое через WinApi:
[DllImport("user32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr SetWindowsHookEx(int hookType, HookProc lpfn, IntPtr hMod, IntPtr dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern uint RegisterWindowMessage(string lpString);
[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentThreadId();
public static void RegisterWindowMessage(string lpString, Action<string> action)
{
_action = action;
_msg = RegisterWindowMessage(lpString.ToString()); //49824
HoockProc = new HookProc(HookCallback);
ProcessModule module = Process.GetCurrentProcess().MainModule;
IntPtr hModule = GetModuleHandle(module.ModuleName);
IntPtr hwnd = ((MauiWinUIWindow)App.Current.Windows[0].Handler.PlatformView).WindowHandle;
MainThread.BeginInvokeOnMainThread(() =>
{
var WH_MSGFILTER = SetHook(HookTypes.WH_MSGFILTER, HoockProc);
var WH_MSGFILTERErrorCode = Marshal.GetLastWin32Error();
var WH_CALLWNDPROC = SetHook(HookTypes.WH_CALLWNDPROC, HoockProc);
var WH_CALLWNDPROCErrorCode = Marshal.GetLastWin32Error();
var WH_CALLWNDPROCRET = SetHook(HookTypes.WH_CALLWNDPROCRET, HoockProc);
var WH_CALLWNDPROCRETErrorCode = Marshal.GetLastWin32Error();
var WH_KEYBOARD = SetHook(HookTypes.WH_KEYBOARD, HoockProc);
var WH_KEYBOARDErrorCode = Marshal.GetLastWin32Error();
var WH_KEYBOARD_LL = SetHook(HookTypes.WH_KEYBOARD_LL, HoockProc, false);
var WH_KEYBOARD_LLErrorCode = Marshal.GetLastWin32Error();
var WH_MOUSE = SetHook(HookTypes.WH_MOUSE, HoockProc);
var WH_MOUSE_ErrorCode = Marshal.GetLastWin32Error();
var WH_MOUSE_LL = SetHook(HookTypes.WH_MOUSE_LL, HoockProc, false);
var WH_MOUSE_LLErrorCode = Marshal.GetLastWin32Error();
var WH_JOURNALRECORD = SetHook(HookTypes.WH_JOURNALRECORD, HoockProc, false);//
var WH_JOURNALRECORDErrorCode = Marshal.GetLastWin32Error();
var WH_JOURNALPLAYBACK = SetHook(HookTypes.WH_JOURNALPLAYBACK, HoockProc, false);//
var WH_JOURNALPLAYBACKErrorCode = Marshal.GetLastWin32Error();
var WH_FOREGROUNDIDLE = SetHook(HookTypes.WH_FOREGROUNDIDLE, HoockProc);
var WH_FOREGROUNDIDLEKErrorCode = Marshal.GetLastWin32Error();
var WH_SYSMSGFILTER = SetHook(HookTypes.WH_SYSMSGFILTER, HoockProc, false, false);//
var WH_SYSMSGFILTERErrorCode = Marshal.GetLastWin32Error();
var WH_GETMESSAGE = SetHook(HookTypes.WH_GETMESSAGE, HoockProc);
var WH_GETMESSAGEErrorCode = Marshal.GetLastWin32Error();
var WH_CBT = SetHook(HookTypes.WH_CBT, HoockProc);
var WH_CBTErrorCode = Marshal.GetLastWin32Error();
var WH_HARDWARE = SetHook(HookTypes.WH_HARDWARE, HoockProc);
var WH_HARDWAREErrorCode = Marshal.GetLastWin32Error();
var WH_DEBUG = SetHook(HookTypes.WH_DEBUG, HoockProc);
var WH_DEBUGErrorCode = Marshal.GetLastWin32Error();
var WH_SHELL = SetHook(HookTypes.WH_SHELL, HoockProc);
var WH_SHELLErrorCode = Marshal.GetLastWin32Error();
});
//_hookId = SetWindowsHookEx((int)HookTypes.WH_GETMESSAGE, HoockProc, nint.Zero, GetCurrentThreadId());
}
#endregion
private static IntPtr SetHook(HookTypes typeOfHook, HookProc callBack, bool onThread = true, bool onDescriptor = false)
{
IntPtr hwnd = ((MauiWinUIWindow)App.Current.Windows[0].Handler.PlatformView).WindowHandle;
var descriptor = onDescriptor ? hwnd : IntPtr.Zero;
var thread = onThread ? GetCurrentThreadId() : nint.Zero;
return SetWindowsHookEx((int)typeOfHook, callBack, descriptor, thread);
//IntPtr hInstance = LoadLibrary("User32");
using (Process currentProcess = Process.GetCurrentProcess())
using (ProcessModule currentModule = currentProcess.MainModule)
{
if (onThread)
return SetWindowsHookEx((int)typeOfHook, callBack, IntPtr.Zero, GetCurrentThreadId());
else
return SetWindowsHookEx((int)typeOfHook, callBack, 0, 0);
//return SetWindowsHookEx((int)typeOfHook, callBack, GetModuleHandle(currentModule.ModuleName), 0);
}
}
private static IntPtr HookCallback(IntPtr hwnd, uint message, IntPtr wParam, IntPtr lParam)
{
// Ваш обработчик сообщений
Debug.WriteLine($"{hwnd} - {message} - {lParam} - {wParam}");
//_action?.Invoke(message);
return IntPtr.Zero;
}
Вывод в debug:
Обрабатывает сообщения мыши, клавиатуры, работу с окном, но не видит этих сообщений.
Как можно изменить код, чтобы прилетели сообщения?
Источник: Stack Overflow на русском