Полагаю, вы ссылаетесь на этот раздел в документации :
Эта роль в качестве сигнала для остановки записи в журнале означает, что комбинация клавиш CTRL + BREAK сама по себе не можетбыть записанным.Поскольку комбинация клавиш CTRL + C не играет такой роли, как сигнал журналирования, ее можно записать.Есть две другие комбинации клавиш, которые не могут быть записаны: CTRL + ESC и CTRL + ALT + DEL.Эти две комбинации клавиш приводят к тому, что система прекращает все действия по ведению журнала (запись или воспроизведение), удаляет все перехватчики ведения журнала и отправляет сообщение WM_CANCELJOURNAL
в приложение ведения журнала.
Проблема заключается в том, что WM_CANCELJOURNAL
сообщение - это , а не , отправленное функции обратного вызова, установленной вами с SetWindowsHookEx
.Но в отличие от других сообщений WM_*
, оно также не предназначено для обработки оконной процедурой (WndProc
в WinForms), поскольку оно отправляется в очередь сообщений потока и не связано ни с какимиконкретное окно.
Скорее всего, документация рекомендует обрабатывать его в основном цикле приложения или с помощью WH_GETMESSAGE
hook :
Это сообщение делаетне вернуть значение.Он предназначен для обработки из основного цикла приложения или подключаемой процедуры GetMessage, а не из оконной процедуры.
[.,,]
Сообщение WM_CANCELJOURNAL
имеет дескриптор окна NULL
, поэтому его нельзя отправить в оконную процедуру.У приложения есть два способа увидеть сообщение WM_CANCELJOURNAL
: если приложение выполняется в своем главном цикле, оно должно перехватить сообщение между вызовом GetMessage
или PeekMessage
и вызовом DispatchMessage
.Если приложение не выполняется в своем основном цикле, оно должно установить подключаемую процедуру GetMsgProc
(посредством вызова SetWindowsHookEx
, указывающего тип подключения WH_GETMESSAGE
), который отслеживает сообщение.
В управляемом коде WinForms вы, очевидно, не имеете доступа к главному циклу приложения или не можете его контролировать.Я не уверен, если добавление фильтра сообщений в ваше приложение позволит вам обработать это сообщение или нет: я не пробовал его.Если это произойдет, это, вероятно, тот маршрут, который вы хотите выбрать, учитывая альтернативный вариант: установить второй хук, WH_GETMESSAGE
, а затем в этой процедуре хука прослушать сообщение WM_CANCELJOURNAL
.
Обновление:
В функции обратного вызова GetMessageProc
параметр code
просто указывает, должна ли процедура подключенияобработать сообщениеПрактически все время это будет 0, что эквивалентно символической константе HC_ACTION
.Если параметр code
меньше 0, подключаемая процедура должна просто вызвать функцию CallNextHookEx
без какой-либо дальнейшей обработки.По сути, это то же самое, что вы сделали для функции обратного вызова JournalRecordProc
.
Сообщение окна будет найдено в MSG
структуре , указатель на которую передаетсяфункция обратного вызова в качестве параметра lParam
.Но это вещи Win32.Не связывайтесь с необработанными указателями в .NET, пусть маршалер P / Invoke обрабатывает все эти грязные вещи для вас.Собственная структура MSG
эквивалентна управляемой System.Windows.Forms.Message
структуре (то же самое, что используется методом WndProc
), поэтому, если вы объявите свою функцию обратного вызова GetMessageProc
следующим образом, все будетнамного проще:
public delegate int GetMessageProc(int code, IntPtr wParam, ref Message lParam);
Затем сообщение Windows будет найдено как Msg
член структуры Message
.Это значение, которое вы хотите сравнить с WM_CANCELJOURNAL
:
public static int GetMessageProc(int code, IntPtr wParam, ref Message lParam)
{
if (code >= 0)
{
if (lParam.Msg == WM_CANCELJOURNAL)
{
// do something
}
}
return CallNextHookEx(messageHook, code, wParam, ref lParam);
}
Обратите внимание, что для того, чтобы вышеуказанный вызов CallNextHookEx
работал, вам также нужно будет предоставить перегруженное определение CallNextHookEx
функция, которая соответствует сигнатуре вашей GetMessageProc
функции обратного вызова:
[DllImport("user32.dll")]
public static extern int CallNextHookEx(IntPtr hHook, int nCode,
IntPtr wParam, ref Message lParam);