使用 DefWindowProc 或不使用 DefWindowProc

To use DefWindowProc or not to use DefWindowProc

本文关键字:DefWindowProc 使用      更新时间:2023-10-16

我目前正在编写自己的迷你可视化框架,以将纯WinAPI包装在类中。

目前,分析消息的过程如下所示:

  • 静态Application::Run有一个消息循环;它获取新消息并将其调度给专有的 WndProc。

  • 我创建的所有窗口都是从同一个类创建的(就 WinAPI 而言),因此调用了相同的WndProc。实际上,这是一种静态FormAPI::WndProc方法。这个检查,消息引用哪个窗口并调用其WndProc

  • 调用Form::WndProc分析消息的方法。假设,这是一个WM_MOUSEMOVE。它调用ProcessMouseMove,然后调用DefWindowProc。记住这一点是 [1]。

  • 私有Form::ProcessMouseMove从消息中获取实际数据(例如x,y,shift状态),将其转换为可用数据并调用受保护的Form::OnMouseMove

  • 最后,受保护OnMouseMove检查是否设置了事件处理程序(即std::function<void(Form *, int, int, ShiftState)>),如果是,则调用处理程序。否则,它什么也不做。

我担心的是打电话给DefWindowProc.看起来,它只是"为我做默认行为",但有时它实际上做了一些关键的事情。例如,通过不调用DefWindowProc来禁用WM_LBTNDOWN将导致无法通过单击 [X] 按钮关闭窗口。

另一方面,有时我不想打电话给DefWindowProc.例如,如果WM_CLOSE来了,我可能会决定不关闭应用程序。 在这种情况下,DefWindowProc调用DestroyWindow

我的问题是:我应该打电话给DefWindowProc吗?如果是这样,总是还是只有偶尔?

在决定如何处理消息时,您有三个选择:

  • 不调用 DefWindowProc()。 当您想要完全自定义消息的处理方式并且不需要默认实现时,适用。 WM_COMMAND和WM_PAINT是典型的例子。

  • 执行一些自定义操作,然后调用 DefWindowProc()。 当您喜欢或需要默认实现时适用。 WM_CLOSE就是一个典型的例子。

  • 首先调用 DefWindowProc(),然后在适当的情况下更改结果。 一个典型的例子是WM_NCHITTEST

选择适当的选项没有黄金法则,它在很大程度上取决于特定的消息和窗口的特定默认处理。 请注意,如果要对窗口进行子类化,这可能不是记录的默认处理。 然而,弄错通常很容易诊断。

看来,我只是通过提问就回答了我的问题。我举了两个案例:

  • WM_LBTNDOWN何时必须调用DefWindowProc - 否则窗口将无法正常工作;
  • WM_CLOSE ,当 - 取决于事件处理程序 - 不得调用DefWindowProc - 否则它会破坏框架的逻辑。

答案是:这取决于信息的种类。我必须仔细阅读DefWindowProc在每种情况下的工作方式,并采取适当的行动。