按名称捕获 Windows 条已注册的消息
Capture Windows registered messages by name
在 Windows tablets 上有两个屏幕键盘应用程序(我知道),c:\program files\common files\microsoft shared\ink\tabtip.exe
和 C:\Windows\System32\OSK.exe.
我想捕获这些应用程序在启动、放置在我的应用程序顶部以及关闭时发送到我的应用程序的消息。
然后我可以检查 IsIconic 作为保险,尽可能地知道键盘处于什么状态,以便我可以相应地调整我的应用程序显示。
使用 spy++ 我为 TabTip 捕获了以下消息:
<000050> 00130426 P message:0xC298 [Registered:"ImmersiveFocusNotification"] wParam:FFFFFFFC lParam:00000000
<000051> 00130426 P message:0xC297 [Registered:"TipCloseMenus"] wParam:00000000 lParam:00000000
<000052> 00130426 P message:0xC061 [Registered:"TabletInputPanelOpening"] wParam:00000000 lParam:00000000
我认为有一个 Windows API 调用允许我在 OS 上注册以在我的应用程序的 window 过程中接收这些消息,或者使用消息处理程序 proc 获取通知,但我似乎找不到它。
尽管这些消息出现在我应用程序的 spy++ 消息队列中,但我似乎无法在我的 WindowProc 中识别它们,并且 Delphi 不允许我为这些消息指定消息处理过程id 在 49xxx 范围内。
有谁知道用名字注册这些消息的方法吗?我认为可以通过
这样的字符串来实现
TabletInputPanelOpening
或
TipCloseMenus
以便当 OS 处理该名称的消息时,我的应用程序可以接收/处理它?
谢谢。
更新: 使用 Application.OnMessage 处理程序,如果我忽略消息发送到的句柄,我可以接收消息。我假设这意味着这是一条广播消息(?)。
我仍然需要知道如何注册以接收以下消息:
1) Sent by PostMessage or SendMessage
2) Established with the system by using RegisterWindowMessage
3) Have a named constant that identifies the message, such as 'TipCloseMenus' or 'TaskbarCreated'
更新#2:
我发现了一个旧示例,该示例显示 RegisterWindowMessage 和 GetClipboardFormatName 似乎使用相同的内部 table 来存储已注册的 window 消息和剪贴板格式。使用 TMsg.message 作为参数调用 GetClipboardFormatName 以查找 messageid 的标签。因此,显然在某种程度上,这些消息存储在同一个内部 table 中。下面是一些示例代码来说明:
function GetRegisteredWindowMessageLabel(var Msg: TMsg): UnicodeString;
var
ay: array[0..99] of Char;
i: Integer;
begin
Result := '';
if (Msg.message <= $FFFF) and (Msg.message >= $C000) then
begin
i := GetClipboardFormatName(Msg.message,ay,Pred(SizeOf(ay)));
if i > 0 then
Result := StrPas(ay);
end;
end;
谢谢。
您不能为已注册消息编写编译时消息处理程序,因为它们不使用静态消息 ID。您必须在运行时调用 RegisterWindowMessage()
然后使用注册的 ID 过滤收到的消息,例如:
var
msgImmersiveFocusNotification: UINT = 0;
msgTipCloseMenus: UINT = 0;
msgTabletInputPanelOpening: UINT = 0;
msgTaskbarCreated: UINT = 0;
procedure TMainForm:FormCreate(Sender: TObject);
begin
msgImmersiveFocusNotification := RegisterWindowMessage('ImmersiveFocusNotification');
msgTipCloseMenus := RegisterWindowMessage('TipCloseMenus');
msgTabletInputPanelOpening := RegisterWindowMessage('TabletInputPanelOpening');
msgTaskbarCreated := RegisterWindowMessage('TaskbarCreated');
end;
procedure TMainForm.WndProc(var Message: TMessage);
begin
inherited;
if (msgImmersiveFocusNotification <> 0) and (Message.Msg = msgImmersiveFocusNotification) then
begin
//...
end
else if (msgTipCloseMenus <> 0) and (Message.Msg = msgTipCloseMenus) then
begin
//...
end
else if (msgTabletInputPanelOpening <> 0) and (Message.Msg = msgTabletInputPanelOpening) then
begin
//...
end
else if (msgTaskbarCreated <> 0) and (Message.Msg = msgTaskbarCreated) then
begin
//...
end;
end;
在 Windows tablets 上有两个屏幕键盘应用程序(我知道),c:\program files\common files\microsoft shared\ink\tabtip.exe 和 C:\Windows\System32\OSK.exe.
我想捕获这些应用程序在启动、放置在我的应用程序顶部以及关闭时发送到我的应用程序的消息。
然后我可以检查 IsIconic 作为保险,尽可能地知道键盘处于什么状态,以便我可以相应地调整我的应用程序显示。
使用 spy++ 我为 TabTip 捕获了以下消息:
<000050> 00130426 P message:0xC298 [Registered:"ImmersiveFocusNotification"] wParam:FFFFFFFC lParam:00000000
<000051> 00130426 P message:0xC297 [Registered:"TipCloseMenus"] wParam:00000000 lParam:00000000
<000052> 00130426 P message:0xC061 [Registered:"TabletInputPanelOpening"] wParam:00000000 lParam:00000000
我认为有一个 Windows API 调用允许我在 OS 上注册以在我的应用程序的 window 过程中接收这些消息,或者使用消息处理程序 proc 获取通知,但我似乎找不到它。
尽管这些消息出现在我应用程序的 spy++ 消息队列中,但我似乎无法在我的 WindowProc 中识别它们,并且 Delphi 不允许我为这些消息指定消息处理过程id 在 49xxx 范围内。
有谁知道用名字注册这些消息的方法吗?我认为可以通过
这样的字符串来实现TabletInputPanelOpening
或
TipCloseMenus
以便当 OS 处理该名称的消息时,我的应用程序可以接收/处理它?
谢谢。
更新: 使用 Application.OnMessage 处理程序,如果我忽略消息发送到的句柄,我可以接收消息。我假设这意味着这是一条广播消息(?)。
我仍然需要知道如何注册以接收以下消息:
1) Sent by PostMessage or SendMessage
2) Established with the system by using RegisterWindowMessage
3) Have a named constant that identifies the message, such as 'TipCloseMenus' or 'TaskbarCreated'
更新#2: 我发现了一个旧示例,该示例显示 RegisterWindowMessage 和 GetClipboardFormatName 似乎使用相同的内部 table 来存储已注册的 window 消息和剪贴板格式。使用 TMsg.message 作为参数调用 GetClipboardFormatName 以查找 messageid 的标签。因此,显然在某种程度上,这些消息存储在同一个内部 table 中。下面是一些示例代码来说明:
function GetRegisteredWindowMessageLabel(var Msg: TMsg): UnicodeString;
var
ay: array[0..99] of Char;
i: Integer;
begin
Result := '';
if (Msg.message <= $FFFF) and (Msg.message >= $C000) then
begin
i := GetClipboardFormatName(Msg.message,ay,Pred(SizeOf(ay)));
if i > 0 then
Result := StrPas(ay);
end;
end;
谢谢。
您不能为已注册消息编写编译时消息处理程序,因为它们不使用静态消息 ID。您必须在运行时调用 RegisterWindowMessage()
然后使用注册的 ID 过滤收到的消息,例如:
var
msgImmersiveFocusNotification: UINT = 0;
msgTipCloseMenus: UINT = 0;
msgTabletInputPanelOpening: UINT = 0;
msgTaskbarCreated: UINT = 0;
procedure TMainForm:FormCreate(Sender: TObject);
begin
msgImmersiveFocusNotification := RegisterWindowMessage('ImmersiveFocusNotification');
msgTipCloseMenus := RegisterWindowMessage('TipCloseMenus');
msgTabletInputPanelOpening := RegisterWindowMessage('TabletInputPanelOpening');
msgTaskbarCreated := RegisterWindowMessage('TaskbarCreated');
end;
procedure TMainForm.WndProc(var Message: TMessage);
begin
inherited;
if (msgImmersiveFocusNotification <> 0) and (Message.Msg = msgImmersiveFocusNotification) then
begin
//...
end
else if (msgTipCloseMenus <> 0) and (Message.Msg = msgTipCloseMenus) then
begin
//...
end
else if (msgTabletInputPanelOpening <> 0) and (Message.Msg = msgTabletInputPanelOpening) then
begin
//...
end
else if (msgTaskbarCreated <> 0) and (Message.Msg = msgTaskbarCreated) then
begin
//...
end;
end;