c++ - MFC GUI 自定义控件 : how to draw cursor updates in response to mouse moves?

标签 c++ windows user-interface mfc

我有一个从 CButton 子类化的自定义 Windows 控件(不知道为什么选择它——这是 17 年前的代码;没有类似的按钮功能)。

DrawItem( LPDRAWITEMSTRUCT pdis ) 方法由 CButton::OnChildNotify 调用以响应 WM_DRAWITEM。它使用 DC CDC::FromHandle( pdis->hDC ) 渲染它的场景。

鼠标事件方法 OnMouseMove() 计算新的光标位置并调用 RedrawWindow( NULL, NULL, RDW_INVALIDATE )。跟随鼠标的光标适时出现在新的鼠标位置。它工作正常,但速度很慢。事实上,只有以前的和新的光标单元需要重绘(如果那样的话),但随着整个场景多次渲染,图形更新开始滞后。

我想在我的 OnMouseMove() 方法中,可以只绘制有问题的单元格,而不是重新绘制整个场景。它已经具有单元格的确切 X 和 Y 坐标以及指向其数据的指针。我认为 CPaintDC(this) 会提供一个允许这样做的 DC,但它不会绘制。 (也不崩溃,难得的开心。)

我模糊的记忆是,执行此操作的“最佳”方法是仅使两个单元格的区域无效,并且 DrawItem() 方法最终会被告知这些区域已无效,而不是完全重新绘制它可以只从坐标计算出它们是哪些单元格(顺便说一句,这不是一个简单的操作)并重新绘制它们,这不仅可以简化这个光标问题,而且还可以确保只绘制几个单元格是部分 -模糊控制部分显示。但是时间压力不允许,用例似乎也不需要对此进行优化。

所以问题是:OnMouseMove() 是否有一些很好的方法来立即重新呈现单个控件,如果有,用什么DC? (例如,我可以缓存通过 FromHandle() 在 DrawItem() 中收到的 DC 吗?

现在我唯一的想法是让一个对象成员指向要重绘的单个单元格,用这个 RDW_UPDATENOW 标志调用 RedrawWindow(),并让 DrawItem(),如果该标志被设置,就这样做一项。这将导致 DrawItem() 获得一个 DC,该 DC 可能会像往常一样工作。不过,这似乎是一个真正的技巧,有没有更好的方法?

最佳答案

在 Windows 应用程序中,通常执行所有渲染以响应 WM_PAINT (或 WM_NCPAINT )消息。需要触发重绘的代码通过调用 InvalidateRect 将窗口的部分或全部客户区标记为脏(和 friend )。该系统针对这种方法进行了优化,将多个请求合并到一个更新区域中,并随后在没有更重要的工作要做(如处理输入)时发出 WM_PAINT 消息。

这工作可靠,并且通常比将渲染分布在多个地方更容易实现。然而,偏离这一点并在代码中的任何位置执行渲染是完全合法的。虽然 WM_PAINT 消息仍然可以随时到达,但最好让带外渲染产生与 WM_PAINT 处理程序相同的视觉结果,以防止视觉伪影.

所有渲染都经过一个称为 device context 的抽象(直流电)。在 MFC 应用程序中处理 WM_PAINT 消息时,可以通过构造 CPaintDC 来获得合适的 DC实例。在其他任何地方渲染时,您不能使用 CPaintDC,但需要使用 CClientDC相反(或 CWindowDC ,也渲染非客户区)。通常,渲染代码不需要知道它正在渲染到哪种类型的 DC,并且通常可以在不更改的情况下重复使用。

关于c++ - MFC GUI 自定义控件 : how to draw cursor updates in response to mouse moves?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55883399/

相关文章:

c++ - eclipse同步的C/C++项目同步失败

c++ - 如何序列化 boost::accumulators::accumulator_set<>?

java - 有什么方法可以让我的 JavaFX 代码更加清晰吗?

windows - MongoDB:服务器有启动警告

c++ - 在 C++ 中的 Windows 上使用 SendInput 发送同步键盘事件

GDB 前端 DDD 的 Windows 版本

jQuery UI 模式对话框不阻塞

c++ - 从 C++ 读取垃圾文件

c++ - Visual Studio 链接器无法写入 [十六进制数]

c++ - Windows 受限用户安装