delphi - 了解消息处理过程的堆栈跟踪

标签 delphi delphi-2007

我在主窗体上放置了一个 TApplicationEvents 组件并添加了以下事件代码:

procedure TAniWinMainForm.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
begin
    if (ActiveMDIChild is TFormStartDialog) and
       (Msg.Message = WM_KEYDOWN) and (Msg.WParam = VK_F4) then
        Handled := True;
end;

部署应用程序后,我通过以下 EurekaLog 错误报告报告了用户的 EInvalidOp 错误:

Modul Name   : KERNELBASE.dll
Typ          : EInvalidOp


|77A4E60A|ntdll.dll   |           |               |NtCallbackReturn                        |         |
|74515EAA|win32u.dll  |           |               |NtUserGetPointerInfoList                |         |
|754595F9|user32.dll  |           |               |GetPointerTouchInfo                     |         |
|778E3923|msvcrt.dll  |           |               |sqrt                                    |         |
|778E388D|msvcrt.dll  |           |               |sqrt                                    |         |
|778E387B|msvcrt.dll  |           |               |_CIsqrt                                 |         |
|778E3870|msvcrt.dll  |           |               |_CIsqrt                                 |         |
|75460AC0|user32.dll  |           |               |SendMessageW                            |         |
|77A235DB|ntdll.dll   |           |               |RtlDeactivateActivationContextUnsafeFast|         |
|75470090|user32.dll  |           |               |CallWindowProcA                         |         |
|00CA5549|Program.exe |MAIN.pas   |TMainForm      |ApplicationEvents1Message               |700[1]   |
|7547BC0B|user32.dll  |           |               |DispatchMessageA                        |         |
|7547BC00|user32.dll  |           |               |DispatchMessageA                        |         |
|00D1376A|Program.exe |Program.dpr|               |                                        |1145[477]|
|772962C2|KERNEL32.DLL|           |               |BaseThreadInitThunk                     |         |

我猜这个错误与我的代码无关,但我不明白可能发生了什么。 谁能解释一下什么可能导致这个堆栈跟踪? 我不应该看到哪个函数正在调用 CallWindowProcA 吗?

最佳答案

我的猜测是对 CallWindowProcA 的调用是由 ActiveMDIChild 进行的。这是一个属性,其 getter 如下所示:

function TCustomForm.GetActiveMDIChild: TForm;
begin
  Result := nil;
  if (FormStyle = fsMDIForm) and (FClientHandle <> 0) then
    Result := TForm(FindControl(SendMessage(FClientHandle, WM_MDIGETACTIVE, 0,
      0)));
end;

您希望在调用堆栈中的 ApplicationEvents1Message 正上方看到 SendMessage,但我怀疑 EurekaLog 堆栈跟踪代码不够好,无法在在 Win32 API 函数内。现在,对 SendMessage 的调用将调用客户端窗口的窗口过程,因此对 CallWindowProcA 的调用非常有意义。

至于实际问题,这听起来很像 Win32 代码期望浮点异常被屏蔽的问题。我建议您在引用 ActiveMDIChild 之前屏蔽异常。

我还强烈建议您更改 if 语句中条件的顺序。程序处理的每条排队消息都会调用此事件。您确实不想读取其中每个的 ActiveMDIChild 属性。像这样编写 if 语句:

if (Msg.Message = WM_KEYDOWN) and
   (Msg.WParam = VK_F4) and
   (ActiveMDIChild is TFormStartDialog) then

因此您可以像这样重写事件处理程序:

procedure TAniWinMainForm.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
var
  Save8087CW: Word;
begin
  if (Msg.Message = WM_KEYDOWN) and (Msg.WParam = VK_F4) then
  begin
    Save8087CW := Get8087CW;
    Set8087CW($027F); // this is the default Windows control word, with floating point exceptions masked
    if ActiveMDIChild is TFormStartDialog then
      Handled := True;
    Set8087CW(Save8087CW);
  end;
end;

关于delphi - 了解消息处理过程的堆栈跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44155569/

相关文章:

delphi - 使用delphi 2007对base64进行编码和解码base64

json - 如何用Delphi解析Json

Delphi接口(interface)实现

delphi - 为什么大多数 Delphi 示例使用 FillChar() 来初始化记录?

delphi - TApplicationEvents 作为动态组件或静态组件用于跟踪在 Delphi 中调用的例程

java - 如何使用 JNA 调用返回字符串的 Delphi 函数?

delphi - 在登录之前,如何在运行时确定 Crystal XI 报表的连接方法?

delphi - Delphi的TCanvas中有错误吗?

与 Delphi 7 相比,Delphi 2010 的 Canvas 透明度有何不同?

delphi - 如何区分用D2007编译和构建?