调整大小时在窗口中绘图留下未绘制的边框

2024-05-16

我遇到的问题看似微不足道,但我找不到解决的方法。这里是。我有一个窗口,里面有一些图形。

为了简单起见,我们假设它是一个实心绿色矩形,填充了窗口的整个客户区域。我希望每次窗口改变大小时都重新绘制这个矩形并填充整个窗口。我最初做的就是这样的。我已经发布WM_PAINT消息来自WM_SIZE处理程序。

它有效,但如果我快速移动鼠标,我会在绿色矩形周围看到一些未绘制的(白色)区域(实际上只有一侧或两侧,靠近鼠标所在的位置)。我对这个问题的理解是,处理用户输入(鼠标)的系统线程比我的 WM_PAINT 消息处理程序运行得更快。这意味着当我开始绘制更新的矩形(其大小取自 WM_SIZE)时,鼠标实际上移动了一点,并且系统绘制了一个新的窗口框架,该窗口框架与我尝试用绿色填充的窗口框架不同。这会在边框旁边创建未填充的区域,这些区域在调整大小时会移动。

当我停止调整大小时,绿色最终会填充整个窗口,但在调整大小期间,边界附近会发生一些闪烁,这很烦人。为了解决这个问题,我尝试了以下方法。

bool finishedPainting;
RECT windowRect;

case WM_PAINT :
    // .....  painting here

  finishedPainting = TRUE;
  break;

case WM_SIZE :
    // .... some actions

    // posting WM_PAINT
  InvalidateRect(hWnd, NULL, FALSE);
  PostMessage(hWnd, WM_PAINT, 0, 0);
  break;

case WM_SIZING :
    // this supposedly should prevent the system from passing
    // new window size to WM_SIZE
  if (!finishedPainting) memcpy((void*)lParam, &windowRect, sizeof(windowRect));
  else {
      // remember current window size for later use
    memcpy(&windowRect, (void*)lParam, sizeof(windowRect));
    finishedPainting = FALSE;
  }
  return TRUE;

这不起作用。作为一个细微的变化,我也尝试过这个。

bool  finishedPainting;
POINT cursorPos;

case WM_PAINT :
    // .....  painting here

  finishedPainting = TRUE;
  break;

case WM_SIZE :
  if (!finishedPainting) SetCursorPos(cursorPos.x, cursorPos.y);
  else {
    finishedPainting = FALSE;
    GetCursorPos(&cursorPos);

      // .... some actions

    InvalidateRect(hWnd, NULL, FALSE);
    PostMessage(hWnd, WM_PAINT, 0, 0);
  }
  break;

这也是行不通的。据我了解,问题的解决方案在于以某种方式减慢鼠标速度,以便仅在绘画完成后鼠标才移动到屏幕上的下一个位置(用鼠标拖动窗口的角落或一侧)。

有什么想法如何实现这一目标?或者也许我看待问题的方式有根本性的错误,解决方案在其他地方?

// ================================================== ====

Update

我做了一些实验,这是我发现的

1) 调整大小时,消息顺序为WM_SIZING - WM_NCPAINT - WM_SIZE - WM_PAINT。这对我来说看起来有点奇怪。我希望 WM_SIZE 跟随 WM_SIZING 而不会被 WM_NCPAINT 中断

2)在每个消息处理程序中,我在调整大小期间检查窗口的宽度(为简单起见,我仅更改宽度)。令人惊讶的是,WM_SIZE 中测量的宽度与 WM_SIZING 中测量的宽度不同,但与 WM_NCPAINT 和 WM_PAINT 中测量的宽度相同。这本身并不是一个问题,只是一个奇怪的事实。

3)我得出的结论是,窗口边框附近发生闪烁的主要原因有两个。第一个是 WM_NCPAINT 出现在 WM_PAINT 之前。想象一下您正在拉伸窗户。新框架将首先出现(WM_NCPAINT 首先出现),然后 WM_PAINT 填充客户区。当新帧已经出现在屏幕上但它是空的时,人眼会捕捉到这一短暂的时间。即使您指定不希望在重新绘制之前删除窗口背景,新添加的区域仍然是空的,您可以立即看到它。当您抓住右侧窗口边缘并将其快速向右移动时,可以最好地证明闪烁的原因。闪烁效果的另一个原因不太明显,当您抓住左窗口边缘并将其向左移动时,最容易看到。在此移动过程中,您将看到沿右边缘的未填充区域。据我了解,效果就是由此造成的。当用户调整大小时,Windows 会执行以下操作:A)发送 WM_NCPAINT 来绘制新框架,B)将旧客户区的内容复制到新的窗口左上角(在我们的例子中,它移动到左侧), C) 它发送WM_PAINT来填充新的客户区。然而,在 B 阶段,由于某种原因,Windows 会沿着右边缘生成那些未填充的区域,尽管看起来不应该,因为旧内容应该保留在原来的位置,直到在 WM_PAINT 期间重新绘制。

好吧,问题仍然是 - 如何在调整大小期间消除这些伪影。据我现在所知,使用标准技术和函数是不可能的,因为它们是由 Windows 在调整大小期间执行的步骤顺序引起的。交换 WM_NCPAINT 和 WM_PAINT 可能会有所帮助,但这似乎超出了我们的控制范围(除非有一种我不知道的简单方法可以做到这一点)。


您不应该自己发布或发送 WM_PAINT 消息。相反,使用 ::InvalidateRect 使窗口的某些部分无效,并让 Windows 决定何时发送 WM_PAINT 消息。

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

调整大小时在窗口中绘图留下未绘制的边框 的相关文章

  • 部署 MVC4 项目时出错:找不到文件或程序集

    过去 我只需使用 Visual Studio 2012 发布到 AWS 菜单项即可部署我的 MVC4 网站 到 AWS Elastic Beanstalk 现在 程序可以在本地编译并运行 但无法部署 从消息来看 它似乎正在寻找不在当前部署的
  • ROWNUM 的 OracleType 是什么

    我试图参数化所有现有的 sql 但以下代码给了我一个问题 command CommandText String Format SELECT FROM 0 WHERE ROWNUM lt maxRecords command CommandT
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • 在 Xamarin Android 中将图像从 URL 异步加载到 ImageView 中

    我有一个包含多个项目的 ListView 列表中的每个项目都应该有一个与之关联的图像 我创建了一个数组适配器来保存每个列表项并具有我希望加载的图像的 url 我正在尝试使用 Web 请求异步加载图像 并设置图像并在加载后在视图中更新它 但视
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 写入和读取文本文件 - C# Windows 通用平台应用程序 Windows 10

    有用 但在显示任何内容之前 您必须在文本框中输入内容 我想那是因为我使用了 TextChanged 事件处理程序 如果我希望它在没有用户交互的情况下显示文本文件的内容 我应该使用哪个事件处理程序 因此 我想在按下按钮时将一些数据写入 C W
  • c# Asp.NET MVC 使用FileStreamResult下载excel文件

    我需要构建一个方法 它将接收模型 从中构建excel 构建和接收部分完成没有问题 然后使用内存流导出 让用户下载它 不将其保存在服务器上 我是 ASP NET 和 MVC 的新手 所以我找到了指南并将其构建为教程项目 public File
  • HttpClient 像浏览器一样请求

    当我通过 HttpClient 类调用网站 www livescore com 时 我总是收到错误 500 可能服务器阻止了来自 HttpClient 的请求 1 还有其他方法可以从网页获取html吗 2 如何设置标题来获取html内容 当
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • Windows 窗体不会在调试模式下显示

    我最近升级到 VS 2012 我有一组在 VS 2010 中编码的 UI 测试 我试图在 VS 2012 中启动它们 我有一个 Windows 窗体 在开始时显示使用 AssemblyInitialize 属性运行测试 我使用此表单允许用户
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • 作为字符串的动态属性名称

    使用 DocumentDB 创建新文档时 我想设置属性名称动态地 目前我设置SomeProperty 像这样 await client CreateDocumentAsync dbs db colls x new SomeProperty
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 如何使用 ReactiveList 以便在添加新项目时更新 UI

    我正在创建一个带有列表的 Xamarin Forms 应用程序 itemSource 是一个reactiveList 但是 向列表添加新项目不会更新 UI 这样做的正确方法是什么 列表定义 listView new ListView var
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐

  • 如何从 os x 终端启动屏幕保护程序(并锁定屏幕)?

    有没有办法从 bash 脚本启动屏幕保护程序 并锁定屏幕 你试过这个吗 System Library Frameworks ScreenSaver framework Resources ScreenSaverEngine app Cont
  • 缓存一致性是否始终可以防止读取过时的值?失效队列允许吗?

    在 MESI 协议中 仅当将缓存行保持在独占 修改状态时才写入缓存行 要获取独占状态 您可以向持有同一高速缓存行的所有核心发送无效请求 但是是否存在一种微架构 其中某些内核会在实际使缓存线无效之前做出确认响应 如果确实如此 那不是违反了缓存
  • 如何让 Win32 使用 Windows XP 样式字体

    我正在使用纯 C 和 WinAPI 编写 Win32 应用程序 不允许使用 MFC 或 C 为了让控件使用适当的样式进行绘制 我使用了清单 如相应的 MSDN 文章中所述 一切都很好 当我更改系统样式时 我的应用程序也会更改样式 但使用的字
  • 有没有办法在 jqgrid treeGrid url 请求中传回附加数据?

    i am 使用 jqgrid 树视图 http www trirand com jqgridwiki doku php id wiki 3atreegrid我正在传回 json 响应 效果很好 我想将一些有关请求的附加信息传递回 GUI 并
  • Flutter如何在BottomNavigationBar中添加边距或填充

    我正在尝试制作底部导航栏 但在屏幕上左右填充 现在 我用容器包裹 BottomNavigationBar 并在其中添加填充 问题是 BottomNavigationBar 默认背景仍然包裹所有图层 所以我们可以删除那里的背景颜色吗 Goal
  • 如何让Symfony2直接加载CSS、JS文件而不是通过PHP?

    老问题 请参阅下面的更新版本 我的开发环境不是最快的 每个 PHP 请求大约需要 500 毫秒 它开始成为 Symfony2 资源文件的问题 因为每个资源文件都是通过 Symfony 的内部控制器请求的 http localhost myp
  • Mandrill 验证错误

    很高兴能在 StackOverflow 上提出我的第一个问题 多年来我一直依靠它自学了很多东西 我的问题是这样的 尝试通过 Mandrill 的 API 发送邮件时出现以下错误 status error code 1 name Valida
  • 如何在url请求中发送数组

    我的要求如下 我想给出演员姓名 开始日期 结束日期并获取他在该时期出演的所有电影 因此 我的服务请求是这样的 http localhost 8080 MovieDB GetJson name Actor startDate 20120101
  • WCF 服务中的“即发即忘”

    我在 Azure 上有很多 WCF REST 服务 在某些 WCF 服务中 我向外部服务调用 Http 请求 例如发送电子邮件 短信 对非关键第三方服务的 http 请求 我不希望这阻碍我对客户电话的响应 需要一些关于在这种情况下使用的模式
  • 如何作为应用程序发布到页面?

    所以 我有一个应用程序 Facebook 应用程序实体 并且我有一个页面 我想使用应用程序通过java代码 通过restfb或任何其他建议 发布到页面 看起来我错过了页面授予应用程序发布权限的阶段 不知道该怎么做 谢谢你们 乌里 您只能 作
  • 从 Firebase Crashlytics 控制台导出数据?

    我正在试用 Firebase Crashlytics 日志数据的控制台显示很混乱 见下图 有没有办法导出完整的崩溃报告 我在 Firebase 控制台中看不到 我从未使用过原始的 Crashlytics 但我看到它有一个导出工具 Fireb
  • 将 firebase auth 与 google app engine 云端点集成

    有人可以指定 使用一些示例代码 如何验证谷歌云端点中的 firebase 令牌吗 最近提出的问题根本没有澄清 如何将 Firebase 身份验证与 Google 应用引擎端点集成 https stackoverflow com questi
  • 使用 Apache POI Excel 写入特定单元格位置

    如果我有一个未排序的参数 x y z 列表 是否有一种简单的方法将它们写入使用 POI 创建的 Excel 文档中的特定单元格 就好像前两个参数是 X 和Y 坐标 例如 我有如下行 10 4 100 是否可以在第 10 行第 4 列的单元格
  • 从 Spring MVC XML 文件转移到 javaconfig。我真的对我的数据库 XML 文件感到困惑

    我从 Spring MVC XML 文件转移到 javaconfig 我真的对我的数据库 XML 文件感到困惑 我不知道如何让 Hibernate4 工作以及我的 JBoss JNDI 数据源工作 有人可以告诉我如何使 javaconfig
  • 文本的彩虹色

    rainbowtext background image webkit gradient linear left top right top color stop 0 f22 color stop 0 15 f2f color stop 0
  • 无法使用cordova-plugin-file-transfer上传base64图像

    我正在尝试使用 cordova plugin file transfer 将 Base64 格式的图像上传到我的服务器 但到目前为止它还无法正常工作 我的代码是这样的 photoBase64 photoBase64 replace data
  • 在 Swift 中以编程方式为 iOS 制作带有名字首字母的图像,例如 Gmail

    我需要在 UITableView 中显示与其姓名相对应的每个用户的个人资料图片 在下载图像之前 我需要显示一张带有他名字的第一个字母的图像 就像在 GMail 应用程序中一样 如何在 Swift for iOS 中以编程方式执行此操作 不需
  • for 循环中的绘图没有可见点

    我正在努力解决我想使用 for 循环制作的情节 我知道当我在循环之后添加它时它会起作用 只是一个简单的图 但我想用另一种方式尝试一下 fib ones 1 10 for k 3 10 hold on fib k fib k 1 fib k
  • WebRTC 不适用于 Windows

    每当我尝试为 Windows 构建 WebRTC 时 运行 gclient runhooks 时都会收到此错误 running C path to depot tools python276 bin python exe src build
  • 调整大小时在窗口中绘图留下未绘制的边框

    我遇到的问题看似微不足道 但我找不到解决的方法 这里是 我有一个窗口 里面有一些图形 为了简单起见 我们假设它是一个实心绿色矩形 填充了窗口的整个客户区域 我希望每次窗口改变大小时都重新绘制这个矩形并填充整个窗口 我最初做的就是这样的 我已