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

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(使用前将#替换为@)

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

  • 在 Windows 上不使用 OpenSSL 从 pfx 文件或证书存储中提取私钥

    正如标题所示 我想在不使用 OpenSSL 或任何其他第三方工具的情况下导出我的私钥 如果我需要一个 cer文件或 pfx我可以通过 MMC 或 PowerShell 轻松导出这些文件pkiclient但我找不到获取私钥的方法 https
  • 调用 printf 系统子例程在汇编代码中输出整数错误[重复]

    这个问题在这里已经有答案了 来回 在windows7控制台窗口中运行gcc s2 asm 然后生成一个exe文件 运行a exe 然后崩溃 为什么 s2 asm 代码由以下源代码生成 int m m 1 iprint m s2 asm请参考
  • 在哪里可以获得 PHP 5.3+ 的 runkit DLL 扩展?

    这是一个简单的问题 我在哪里可以获得 PHP 5 3 版本的 runkit 扩展 它的手册 http php net manual en book runkit php http php net manual en book runkit
  • Windows 目录永远不会包含临时文件的非 ASCII 字符?

    在 Windows 上使用 MinGW 7 3 0 由于 Windows 限制 Hunspell 无法从包含非 ASCII 字符的位置加载字典文件 我已经尝试了所有方法 1 现在我将文件复制到没有 ASCII 字符的路径 然后再将其交给 H
  • 在哪里可以找到 Windows 7 UX 指南中推荐的图标/动画?

    Windows 7 UX 指南有很好的插图和图标示例 但我在 SDK 中确实找不到它们 他们藏在某个地方 还是找不到 如果您谈论的是常见的 UI 图标 那么您应该以编程方式获取它们 例如 您可以使用 var errIcon HICON be
  • 如何向未知用户目录读取/写入文件?

    我正在尝试从用户目录 C Users USERNAME Test Source 读取和写入文件 但我未能成功找到任何有关如何自动检测用户名的资源 其中的 USERNAME上面的例子 或者无论如何 我可以让它读取和写入目录 而不需要知道用户名
  • 所见即所得与 Unicode

    我在 Delphi 中编写了一个 Windows 程序 该程序使用 GetCharWidth 和 Em Square 将文本非常精确地放置并换行到屏幕和打印机 这对于 ANSI 文本效果很好 您只需要检索和计算 255 个字符的宽度 但当您
  • 获取自动热键中的可用屏幕区域

    我正在尝试编写一些简单的 AutoHotkey 脚本来移动窗口 但在获取正确的屏幕尺寸值时遇到问题 我试图获取屏幕上可用区域的大小 通常是全屏分辨率减去任务栏 也许还有任何其他停靠窗口 如 Vista 中的侧边栏 我发现的获取屏幕宽度的方法
  • 如何迭代所有注册表项?

    我正在尝试迭代所有注册表项以查找 包含 并删除 jre1 5 0 14 值 有办法做到吗 下面的代码只是在特定键下找到jre1 5 0 14 我确实想迭代所有的键 顺便说一句 if 子句获取是否等于 jre1 5 0 14 但如果它包含 j
  • Windows 上使用 g++ 的 Makefile,链接库

    我已经厌倦了 MSVC 6 以及每个人总是告诉我它是一个蹩脚的编译器等等 所以现在我决定尝试使用 vim 加 g 和 makefile 这是我的问题 我有以下 makefile This is supposed to be a commen
  • 相对文件路径的区别:Qt Creator的调试模式和发布模式

    QFile file test txt if file open QIODevice ReadOnly qDebug lt lt You got me 我在用 Qt 4 8 6 与 MSVC 2010 Qt 创建者 3 1 1 Window
  • 如何处理来自单独线程的窗口消息?

    我希望启动一个单独的线程来处理窗口消息 通过阻塞 GetMessage 循环 但之后仍然在初始线程中创建窗口 在单独的线程中 一旦启动 我就会调用PeekMessage使用 PM NOREMOVE 确保消息队列存在 有必要吗 然后 Atta
  • npm package.json bin 无法在 Windows 上运行

    我正在尝试通过 package json 启动我的 cli 工具bin财产 我有以下内容 name mycli bin bin mycli 当我在包路径中打开 cmd 并输入 mycli 时 它表示该命令无法识别 我应该运行 npm 命令吗
  • 使用Windows 7计算器进行对数计算[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我想使用Windows计算器在科学模式中为了求解一个非常基本的对数方程 但不幸的是 我无法做到这一点 问题是这样的 log 5 125 非常感谢您的帮
  • 为什么同一个curl命令在windows和linux下输出不同的东西?

    为什么同样的curl o file https www link com 命令输出不同的东西 例如 如果我运行命令curl o source txt https www youtube com playlist list PLIx6Fwnp
  • 如何使用命令行压缩指定文件夹

    你们能告诉我如何将指定的文件压缩到同一个 Zip 文件中吗 让我告诉我我的文件夹是如何填充的 任务调度程序有我的数据库的备份 并每天将它们保存到文件中 它每天创建 4 个数据库备份 这意味着每天会多出 4 个文件 因此 我需要将新创建的备份
  • 从 vbscript 获取 bat 中的错误级别

    我试图确定用户是否在 UAC 提示中单击 否 如果是 则不设置空端口 我将此脚本称为批处理文件 如果用户单击 否 我想退出该脚本 VB 脚本 选项显式 Main Sub Main Dim oShell objWMIService servS
  • 具有多处理功能的 Python 代码无法在 Windows 上运行

    以下简单的绝对初学者代码在 Ubuntu 14 04 Python 2 7 6 和 Cygwin Python 2 7 8 上运行 100 但在 Windows 64 位 Python 2 7 8 上挂起 我使用另一个片段观察到了同样的情况
  • 使用 Java 检索 Window 进程的 CPU 使用率

    我正在寻找一个 Java 解决方案来查找 Windows 中正在运行的进程的 CPU 使用情况 查了一下网上 关于Java解决方案的信息似乎很少 请记住 我并不是要查找 JVM 的 CPU 使用情况 而是要查找当时在 Windows 中运行
  • 为什么标签存在却提示“系统找不到指定的批次标签”?

    在 Windows XP 中运行批处理文件时 我发现随机出现的错误消息 系统找不到指定name of label的批次标签 标签当然存在 导致此错误的原因是什么 实际上 要实现这一点 你需要两个条件 批处理文件不得使用 CRLF 行结尾 您

随机推荐