为啥消息处理程序在调试模式下不起作用?
Posted
技术标签:
【中文标题】为啥消息处理程序在调试模式下不起作用?【英文标题】:Why a message handler doesn't work in debugging mode?为什么消息处理程序在调试模式下不起作用? 【发布时间】:2016-05-04 01:38:03 【问题描述】:我在 Windows 10 中使用柏林。
以下消息处理程序在构建的应用程序中运行良好,但在调试模式下不可用。
如何调试消息处理程序?
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure onReceive(var message: TMessage); message WM_COPYDATA;
end;
procedure TForm1.onReceive(var message: TMessage);
begin
Memo1.Lines.Add('a');
end;
发送方代码如下,struct的值无意义。
procedure TForm1.FormClick(Sender: TObject);
var
_Handle: Cardinal;
_CopyDataStruct: TCopyDataStruct;
begin
_Handle := FindWindow(nil, 'test form');
_CopyDataStruct.dwData := 0;
_CopyDataStruct.cbData := Sizeof(_Handle);
_CopyDataStruct.lpData := @_handle;
SendMessage(_Handle, WM_COPYDATA, Handle, integer(@_CopyDataStruct));
end;
【问题讨论】:
在Memo1.Lines.Add('a')
上设置断点,然后运行。然后运行您的另一个应用程序,将 WM_COPYDATA 消息发送到您的第一个应用程序。
我的猜测是消息永远不会到达,发送方的目标是设计器中的窗口。
你的调试器运行提升了?
@JOSeongGng:UIPI 阻止低完整性进程将窗口消息发送到高完整性(即提升)进程的窗口,除非高完整性进程调用自身的ChangeMessageFilter/Ex()
以允许通过 UIPI 过滤器发送特定窗口消息的低完整性进程。
停止运行提升的调试器。它会让你感到痛苦。
【参考方案1】:
如果您的 TForm1
类在 IDE 的表单设计器中打开,并且它的 Caption
在对象检查器中是 test form
,那么 FindWindow()
可能会发现 HWND
在运行时而不是正在运行的应用程序中的HWND
(您可以使用GetWindowThreadProcessId()
来验证)。这意味着您会将您的消息发送到错误的HWND
。这是在调试器中运行时使用FindWindow()
通过标题搜索TForm
时的常见问题。在 IDE 中关闭 TForm1
源文件,然后 FindWindow()
将无法再找到 HWND
,它会在您正在运行的应用程序中找到 HWND
。
顺便说一句,您的_Handle
变量需要声明为HWND
或THandle
而不是Cardinal
,并且SendMessage()
的最后一个参数需要类型转换为LPARAM
而不是@ 987654341@.
【讨论】:
查看 cmets 似乎提问者的问题是 ide 被提升了运行 这不会影响应用程序发送消息的能力,只会接收它们..我仍然认为问题与应用程序尝试有关发送到设计器窗口。如果 IDE 正在提升运行,并且FindWindow()
正在寻找设计器窗口,则 UIPI 将适用,尽管这并不重要,因为无论如何设计器都是错误的目标。使 IDE 不提升运行只会删除 UIPI,这仅在被调试的应用程序是接收方而不是发送方时才重要。我怀疑 zorder 只是不同,导致FindWindow()
找到不同的窗口。
接收失败可以说明问题。 Asker 评论说,运行非提升的 IDE 解决了这个问题。问题中的代码显示发送和接收。
如果 IDE 运行提升,任何从它运行的应用程序也将提升。提升的应用可以“看到”所有其他提升的应用,并且在许多情况下“看到”非提升的应用。以上是关于为啥消息处理程序在调试模式下不起作用?的主要内容,如果未能解决你的问题,请参考以下文章