为什么对话框会删除其内容而不刷新?

2024-01-12

我遇到了一个非常奇怪的问题,窗口似乎正在擦除其内容,并且在擦除后没有重新绘制它。该对话框源自CDHtmlDialog,我认为这是问题的一部分。发生某种非确定性代码执行,导致某些代码在某些情况下先于其他代码执行,而在其他情况下则相反。

涉及的消息处理程序有:

BEGIN_MESSAGE_MAP(CCalcDrillDownDlg, CDHtmlDialog)
    ON_WM_PAINT()
END_MESSAGE_MAP()

BEGIN_EVENTSINK_MAP(CCalcDrillDownDlg, CDHtmlDialog)
     ON_EVENT(CCalcDrillDownDlg, AFX_IDC_BROWSER, 250 /* BeforeNavigate2 */, _OnBeforeNavigate2b, VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL)
END_EVENTSINK_MAP()

The OnInitDialog()函数如下:

BOOL CCalcDrillDownDlg::OnInitDialog()
{
    SetHostFlags(DOCHOSTUIFLAG_FLAT_SCROLLBAR);

    CDHtmlDialog::OnInitDialog(); // << will eventually call _OnBeforeNavigate2b()

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);         // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon

    LoadFromResource(IDR_CALC_DRILLDOWN); // << will eventually call _OnBeforeNavigate2b()
    CString title = getStr2Ptr(22574);
    SetWindowText(title);
    ShowWindow(SW_SHOW);

    return TRUE;  // return TRUE  unless you set the focus to a control
}

这是OnPaint()功能:

void CCalcDrillDownDlg::OnPaint() 
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDHtmlDialog::OnPaint();
    }
}

我还没有把内容_OnBeforeNavigate2b()功能,因为它似乎与重绘系统没有任何关系。

因此,有时会发生的情况是,对话框内容会在调用之前以某种方式绘制CCalcDrillDownDlg::OnPaint()。如果发生这种情况,则调用CDHtmlDialog::OnPaint()将从窗口上擦除内容。

其他时候,在调用之前内容不会绘制在窗口上CCalcDrillDownDlg::OnPaint()。如果发生这种情况,则调用CDHtmlDialog::OnPaint()可能仍然会擦除尚未绘制的窗口上的内容,然后在调用后的某个时间CCalcDrillDownDlg::OnPaint(),它会被重绘。

当系统正确重绘窗口时,Spy++ 不会捕获任何消息,因此我删除了此问题生成的消息。

有谁知道重绘是如何完成的以及为什么订单有时会被禁止?

Edit

以下是该内容的内容IDR_CALC_DRILLDOWN资源:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Calculation Drilldown</title>
    <style type="text/css">
        body { overflow-y: auto; font-family: arial, Helvetica, sans-serif; font-size: 90%; }

        a:link { color: black; }
        a:visited { color: black; }
        table { border-collapse: collapse; }

        tr.runcache td { background-color: #B5B5B5; color: black; }
        tr.runcache td a:link { color: black; }
        tr.runcache td a:visited { color: black; }

        tr.tracker td { background-color: white; color: black; }
        tr.tracker td a:link { color: black; }
        tr.tracker td a:visited { color: black; }

        td.numericvalue { text-align: right; }

        tr.paramTitle td { background-color: #4A4A4A; color: white; }

        tr.resultTitle td { background-color: #4A4A4A; color: white; }
        tr.resultTitle td a:link { color: white; }
        tr.resultTitle td a:visited { color: white; }

        tr.param td { background-color: white; color: black; }
        tr.param td a:link { color: black; }
        tr.param td a:visited { color: black; }

        span.selection { background-color: #EBEBEB; }
    </style>
</head>
<body>
    <div id="calculation"></div>
    <div id="details" style="padding-left: 0.1in; display: none;"></div>
</body>
</html>

Edit #2

进一步的调查似乎表明 CDHtmlDialog 类(或其基类)将绘制窗口,无论我是否CCalcDrillDownDlg::OnPaint() calls CDHtmlDialog::OnPaint()或者不是,这很奇怪而且不直观。 :(

另外,这似乎可能与线程相关,因为这似乎取决于渲染窗口所需的时间。如果需要很短的时间,则显示良好。如果需要半秒或更长时间,就会搞砸。

目前,我正在使用一种解决方法,其中我有m_bRepaint类中的标志最初设置为true。致电后CCalcDrillDownDlg::OnPaint()它不是标志性的,我检查标志并强制调整大小。这不是最佳选择,因为它会导致初始闪烁,但至少可以确保绘制窗口的内容。

    if (!m_bRepaint)
    {
        CDHtmlDialog::OnPaint();
    }
    else
    {
        CRect winRect;
        GetWindowRect(&winRect);
        SetWindowPos(NULL, 0, 0, winRect.Width() - 1, winRect.Height(), SWP_NOMOVE | SWP_NOZORDER);
        SetWindowPos(NULL, 0, 0, winRect.Width()    , winRect.Height(), SWP_NOMOVE | SWP_NOZORDER);
        m_bRepaint = false;
    }

Using Invalidate()不起作用。我必须将其大小调整为当前大小以外的大小,然后再将其大小调整回来。

This CDHtmlDialogclass 是一个可以使用的 PITA,如果有选择的话我不建议任何人使用它。


好吧,看来这是由于 Windows 消息队列不是确定性的,所以看起来底层COM控制在其 DC 上绘画之前WM_PAINT信息。

为了解决这个问题,我通过等待来等待窗口自动显示WM_WINDOWPOSCHANGED消息,发布另一条应用程序消息,然后调用Invalidate() and UpdateWindow(),从而强制重新绘制窗口。

该技术被描述为here https://blogs.msdn.microsoft.com/oldnewthing/20060925-02/?p=29603在 Raymond Chen 的博客“The Old New Thing”上。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么对话框会删除其内容而不刷新? 的相关文章

  • 使用 BitmapEncoder 生成时如何使 GIF 循环重复

    我能够使用 BitmapEncoder C WinRT 创建动画 gif 但是 我一直无法弄清楚如何让GIF循环回来并从头开始 没有尝试太多 因为我不确定要尝试什么 搜索了更多要在 GIF 上设置的属性 但找不到任何相关内容 好吧 终于能弄
  • 哪个版本的 Miniconda 具有适用于 Windows 64 位的 Python 3.6?

    我正在开发一个需要这些深度学习库的项目 keras 和 tensorflow 不幸的是 这些不适用于 Python 3 7 有人可以告诉我一个带有 Python 3 6 的 Miniconda 版本 适用于 Windows 64 位 吗 我
  • 开发者可以在 Windows 应用程序中使用 iCloud 吗?

    开发人员可以使用 Apple 的 iCloud API 在 Mac OS X 和 iOS 上的不同版本的应用程序之间同步应用程序数据 如果开发人员拥有 Windows 版本的应用程序 该版本是否也可以使用 iCloud 将应用程序数据与 M
  • 如何通过命令行将Flash .fla编译为.swf? [复制]

    这个问题在这里已经有答案了 如何在基于 Windows 的操作系统上通过命令行将 Flash fla 文件编译为 swf 需要安装的命令行工具就可以了 谁能建议我该怎么做 以直接的方式 谢谢 您可以使用JSFL为 Flash IDE 编写脚
  • 批处理脚本 FOR 循环仅设置输出的第一个字母 wsl --list -q

    我正在编写一个批处理脚本 将文件从 Windows 目录复制到 WSL 发行版 其中一部分是选择将文件复制到哪个发行版 如果我使用命令wsl list q如果给我以下输出 Ubuntu 22 04 Ubuntu 18 04 我正在尝试使用此
  • 在 Windows 7 上的 Sourcetree 中比较 Word docx 文件

    我一直在尝试获取在 Windows 7 上的 Sourcetree 中工作的 Word docx 文件的文本差异 我已按照此处的说明进行操作将 Microsoft Word 与 git 结合使用 http blog martinfenner
  • 无法加载 JNI 共享库 (JDK)

    当我尝试打开时Eclipse http www eclipse org 弹出对话框指出 无法加载 JNI 共享库 C JDK bin client jvm dll 此后 Eclipse 强制关闭 我想提出以下几点 我检查了这条路径上是否存在
  • conio.h 不包含 textcolor()?

    我一直在考虑在我用 C 编写的 DOS 程序中使用颜色 有人告诉我conio h有textcolor 函数 但是当我在代码中使用它时 编译器 链接器会向我抛出错误 说我对该函数有未定义的引用 Does conio h真的有这个功能还是有人告
  • 如何使用 Win32 API 与 com 端口 (RS232) 通信

    我正在尝试使用 win32 API 与 com 端口对话 我找到了这个http www robbayer com files serial win pdf http www robbayer com files serial win pdf
  • 为什么#pragma optimize("", off)

    我正在审查一个 C MFC 项目 在某些文件的开头有这样一行 pragma optimize off 我知道这会关闭所有以下功能的优化 但这样做的动机通常是什么 我专门使用它来在一组特定代码中获得更好的调试信息 并在优化的情况下编译应用程序
  • 在高 dpi Windows 平台上自动重新缩放应用程序?

    我正在编写一个需要在高 dpi Windows 192dpi 而不是 96dpi 上运行的 Qt 应用程序 不幸的是 Qt 框架尚不支持高 dpi 至少在 Windows 上 因此我的应用程序及其所有元素看起来只有应有尺寸的一半 有没有办法
  • Visual C++ 找不到“Windows 类型”,如 PVOID、DWORD、ULONG 等

    Windows 似乎无法找到任何这些类型 我完全不知道该怎么办 我在 MSDN 上找到的东西似乎表明它们是默认包含的 但它们在 Native 程序或 CLR 程序中不起作用 我收到的具体错误是
  • Windows 8 Metro 应用程序(网格应用程序)过渡时出现黑色闪烁

    我正在基于网格应用程序模板构建 Windows 8 Metro 应用程序 一切都很顺利 直到我尝试更改应用程序的主题和背景 我将图像背景应用于所有 3 个 XAML 页面的网格 另外 我在应用程序包清单中将主题更改为 Light 但它没有执
  • 如何捕获未发送到 stdout 的命令行文本?

    我在项目中使用 LAME 命令行 mp3 编码器 我希望能够看到某人正在使用什么版本 如果我只执行 LAME exe 而不带参数 我会得到 例如 C LAME gt LAME exe LAME 32 bits version 3 98 2
  • 什么是 SO_SNDBUF 和 SO_RCVBUF

    你能解释一下到底是什么吗SO SNDBUF and SO RCVBUF选项 好的 出于某种原因 操作系统缓冲传出 传入数据 但我想澄清这个主题 他们的角色 通 常 是什么 它们是每个套接字的缓冲区吗 传输层的缓冲区 例如 TCP 缓冲区 和
  • 如何将十六进制字符串转换为无符号长整型?

    我有以下十六进制值 CString str str T FFF000 如何将其转换为unsigned long 您可以使用strtol作用于常规 C 字符串的函数 它使用指定的基数将字符串转换为 long long l strtol str
  • MFC 中位图背景绘制的线程类型

    我有一个 MFC 文档 视图 C 图形应用程序 它将所有绘图都绘制到离屏位图 然后将其复制到 OnDraw 方法中提供的 CDC 指针 在过去的几天里 我一直在寻找将绘图组件放置在单独的工作线程中 这样它就不会停止 GUI 当我执行此操作时
  • 用于基于 MFC 的 GUI 应用程序的免费自动化测试工具

    我是 Windows 开发和测试平台的新手 我正在开发一个基于 MFC 的 GUI 应用程序 并正在寻找有助于 UI 自动化测试的工具 我搜索时出现了一大堆工具 但大多数似乎都不支持MFC 我考虑的选项是 A 编码 UI UI 自动化 看起
  • 如何一步步遍历目录树?

    我发现了很多关于遍历目录树的示例 但我需要一些不同的东西 我需要一个带有某种方法的类 每次调用都会从目录返回一个文件 并逐渐遍历目录树 请问我该怎么做 我正在使用函数 FindFirstFile FindNextFile 和 FindClo
  • 如何为 Windows toast 注册协议?

    如何注册 Windows toast 协议 样本中来自https blogs msdn microsoft com tiles and toasts 2015 07 02 adaptive and interactive toast not

随机推荐