Mfc 对话框失效时如何调试/跟踪?

Mfc 对话框失效时如何调试/跟踪?,mfc,view,invalidation,Mfc,View,Invalidation,我的MFC应用程序有一个CView和两个浮动非模态对话框。我目前正在试图弄清楚为什么视图的失效/重新绘制也会导致对话框被重新绘制。即使对话框与视图不重叠,也会发生这种情况 有人知道如何调试/跟踪请求重画特定对话框的人吗?拦截对话框上的WM_PAINT消息似乎为时已晚 提前感谢您的帮助 致以最良好的祝愿 费边看看这个: 您可能会覆盖OnPaint并找出消息的来源 编辑: 当Windows或应用程序请求重新绘制应用程序窗口的一部分时,框架调用此成员函数。 因此,要么是操作系统请求您重新绘制,要么是

我的MFC应用程序有一个CView和两个浮动非模态对话框。我目前正在试图弄清楚为什么视图的失效/重新绘制也会导致对话框被重新绘制。即使对话框与视图不重叠,也会发生这种情况

有人知道如何调试/跟踪请求重画特定对话框的人吗?拦截对话框上的WM_PAINT消息似乎为时已晚

提前感谢您的帮助

致以最良好的祝愿

费边看看这个:

您可能会覆盖OnPaint并找出消息的来源

编辑:

当Windows或应用程序请求重新绘制应用程序窗口的一部分时,框架调用此成员函数。

因此,要么是操作系统请求您重新绘制,要么是从应用程序内部完成

也可以看看这个论坛帖子上的第一个答案:

我会像调试MFC中我不太理解的任何东西一样,尝试通过在一个全新的项目中重现行为来隔离问题

所以,创建一个全新的MFC应用程序,在其中添加一个无模式对话框,在CView上调用Invalidate,看看它是否仍然存在

如果它仍然发生,那么它必须是你的主机发送油漆信息。因此,您可以尝试在大型机的预翻译消息中捕获这一点


如果它没有发生,那么您在应用程序中所做的事情就是导致它的原因。如果是这样的话,您可以尝试通过消除应用程序中的复杂性来了解您所做的工作,直到找到导致它不再发生的原因。

对话框也会收到WM_PAINT消息的原因是,正如Karim所建议的,它们是CView的子窗口

最可能发生的情况是,在导致视图重新绘制的无效之后,一条
WM_-PAINT
消息被发送到此窗口,并且此窗口的标准OnPaint()处理程序(CWnd成员)将
WM_-PAINT
消息发送到其子窗口(对话框)

WM_PAINT消息本身由windows发送,以响应对
UpdateWindow()
重画窗口()
的调用,请参阅

WM_PAINT消息由以下内容生成: 不应通过以下方式发送系统和 申请书

最接近消息处理机制背后的场景是重写从CWnd派生的CView类的WindowProc。这是接收WM_PAINT和任何其他消息的回调

干杯
霍尔格

我想你的非模态对话框是WS_弹出窗口,对吗?(即,它们是浮动窗口,可以出现在屏幕上的任何位置,而不仅仅是在应用程序窗口内。)

如果它们是浮动窗口,那么从技术上讲,它们不是框架窗口的子窗口,但是文档倾向于在真正应该使用所有者的地方使用术语parent,所以这很容易混淆。子窗口不能出现在其父窗口的客户端区域之外,拥有的窗口可以。每当其父窗口无效时,子窗口将无效。但拥有的窗口不会

只有带有WS_子样式标志的窗口才能是子窗口,否则它们是自有窗口

如果这些是自有窗口,它们将不会从主应用程序窗口继承无效,因此您需要在代码中查找调用::InvalidateBu立()的位置,其中第一个参数为NULL句柄。通常这是因为一个未初始化的变量

当您调用
::invalidate(NULL,…)
时,这会告诉Windows使所有窗口无效。(它实际上告诉Windows使桌面窗口无效,桌面窗口是所有窗口的父窗口)。使用MFC,所有窗口的基类都有一个用于调用windows api的方法,该方法使用当前对象的窗口句柄进行调用。作为一阶近似值,我认为您可以假设窗口句柄将正确初始化。您应该从在自己的代码中查找调用开始

一旦你得到了OnPaint,要知道失效请求来自哪里就太晚了。因此,为了找到这个bug,您必须检查代码或截取
invalidate()
并在第一个参数中查找NULL

在一般情况下,这是一个困难的问题,因为有几种方法可以使窗口的全部或部分无效,并且头文件中有大量代码可以通过创建自动执行某些操作的函数变体来“帮助”您

您可以尝试在
invalidate
(位于user32.dll中)的顶部设置断点,并将第一个参数设为null作为条件。但根据调试器的设置方式,可能不允许您执行此操作

您还可以尝试强制编译所有代码,以便通过您控制的函数重定向对Invalidate的调用

// in some header file that gets included early by all of your code
#define InvalidateRect my_InvalidateRect

// in one of your .cpp files.
BOOL WINAPI my_InvalidateRect(HWND hwnd, CONST RECT *prc, BOOL bErase)
{
  #undef InvalidateRect
  assert(hwnd != NULL);
  InvalidateRect(hwnd, prc, bErase);
  #define InvalidateRect my_InvalidateRect
};
如果找不到,则对
InvalidateRgn
重画窗口执行相同的操作


这些种类的虫子很难找到。我不羡慕你。在我自己的代码中,我永久禁止直接调用InvalidateBu立,它们必须始终通过包装函数,这样我就可以在调试构建中始终检查空窗口句柄。但是,再说一遍,我不使用MFC,所以执行这种策略更容易。

非模态对话框是CMainFrame还是CView的孩子?好问题。他们是我的孩子。我认为你无法确定最初是谁发送了请求。无效生成一条存储在windows消息队列中的消息,并组合多个此类无效,直到队列中没有其他消息,然后应用程序收到WM_绘制。所以