使用 DefWindowProc 或不使用 DefWindowProc
To use DefWindowProc or not to use DefWindowProc
我目前正在编写自己的迷你可视化框架,以将纯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在每种情况下的工作方式,并采取适当的行动。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- C++:TypeDef使用元组
- 使用std::multimap迭代器创建std::list
- 从不同线程使用int64的不同字节安全吗
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么在全局范围内使用"extern int a"似乎不行?
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用Google Mock来模拟gettimeofday()
- 如何使用默认参数等选择模板专业化
- 为什么使用 "this" 指针调用派生成员函数?
- 使用新行和不使用新行读取文件
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 如何确定我已使用非编码文件到达 EOF?
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 使用CMake创建QML插件
- 使用strcpy将char数组的元素复制到另一个数组
- 在c++中使用nlohmann从类到json的转换
- 使用指针从C++中的数组中获取最大值
- 使用 DefWindowProc 或不使用 DefWindowProc