翻译《The Old New Thing》 - What’s the point of DeferWindowPos?

What's the point of DeferWindowPos? - The Old New Thing (microsoft.com)icon-default.png?t=N7T8https://devblogs.microsoft.com/oldnewthing/20050706-26/?p=35023

Raymond Chen 在 2005年7月6日


DeferWindowPos 的作用是什么?

简要

        文章讨论了 DeferWindowPos 函数的用途,即一次性移动多个子窗口,以减少窗口移动时发生的重绘数量。

正文

  DeferWindowPos 函数的目的是一次性移动多个子窗口。这在一定程度上减少了窗口移动时发生的重绘数量。

        拿几个月前的 DC 刷子示例,进行以下修改:

HWND g_hwndChildren[2];
BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpcs) {const static COLORREF s_rgclr[2] = { RGB(255,0,0), RGB(0,255,0) };for (int i = 0; i < 2; i++) {g_hwndChildren[i] = CreateWindow(TEXT("static"), NULL,WS_VISIBLE | WS_CHILD, 0, 0, 0, 0,hwnd, (HMENU)IntToPtr(s_rgclr[i]), g_hinst, 0);if (!g_hwndChildren[i]) return FALSE;}return TRUE;
}

        注意我使用控件 ID 来保存所需的颜色。在选择背景颜色时,我们会检索它。

HBRUSH OnCtlColor(HWND hwnd, HDC hdc, HWND hwndChild, int type) {Sleep(500);SetDCBrushColor(hdc, (COLORREF)GetDlgCtrlID(hwndChild));return GetStockBrush(DC_BRUSH);
}
HANDLE_MSG(hwnd, WM_CTLCOLORSTATIC, OnCtlColor);

         我加了一个半秒的睡眠,这样更容易观察绘制过程。

void OnSize(HWND hwnd, UINT state, int cx, int cy) {int cxHalf = cx/2;SetWindowPos(g_hwndChildren[0],NULL, 0, 0, cxHalf, cy,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);SetWindowPos(g_hwndChildren[1],NULL, cxHalf, 0, cx-cxHalf, cy,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
}

        我们将两个子窗口并排放置在客户区域。首先,我们使用 SetWindowPos 函数来定位窗口。

编译并运行这个程序,一旦它启动,点击最大化按钮。仔细观察绿色矩形的哪些部分被重绘。

        现在让我们将定位代码更改为使用 DeferWindowPos 函数。延迟窗口定位函数的使用模式如下:

HDWP hdwp = BeginDeferWindowPos(n);
if (hdwp) hdwp = DeferWindowPos(hdwp, …); // 1
if (hdwp) hdwp = DeferWindowPos(hdwp, …); // 2
if (hdwp) hdwp = DeferWindowPos(hdwp, …); // 3
…
if (hdwp) hdwp = DeferWindowPos(hdwp, …); // n
if (hdwp) EndDeferWindowPos(hdwp);

        这里有一些关键点:

  • 你传递给 BeginDeferWindowPos 函数的值是你打算移动的窗口数量。即使这个值错了也没关系,但正确的值会减少内部重新分配的数量。

  • DeferWindowPos 返回的值存储回 hdwp,因为返回值不一定与最初传递的值相同。如果延迟预订需要执行重新分配,DeferWindowPos 函数返回指向新的延迟信息的句柄;旧的延迟信息不再有效。更重要的是,如果延迟失败,旧的延迟信息将被销毁。这与 realloc 函数不同,如果重新分配失败,原始对象保持不变。模式 p = realloc(p, …) 会导致一个内存泄漏,但模式 hdwp = DeferWindowPos(hdwp, …) 不会。

        第二点很重要,但许多人都弄错了。

        现在你可能对这个函数感到害怕,让我们将重新定位代码更改为利用延迟窗口定位。它真的没有那么难。(将这些更改保存到一个新文件中,不过。我们将想要并排运行旧版本和新版本。)

void OnSize(HWND hwnd, UINT state, int cx, int cy) {HDWP hdwp = BeginDeferWindowPos(2);int cxHalf = cx/2;if (hdwp) hdwp = DeferWindowPos(hdwp, g_hwndChildren[0],NULL, 0, 0, cxHalf, cy,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);if (hdwp) hdwp = DeferWindowPos(hdwp, g_hwndChildren[1],NULL, cxHalf, 0, cx-cxHalf, cy,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);if (hdwp) EndDeferWindowPos(hdwp);
}

        编译并运行这个程序,再次启动后,最大化窗口并观察哪些区域重新绘制。你会发现新版本与旧版本相比,重绘的区域略有减少。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/670422.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【.sh】Shell 脚本文件的基础内容

目录 &#x1f30a;1. 基础知识 &#x1f30a;2. 简单示例 &#x1f30d;2.1 示例一 输出"Hello, World!" &#x1f30d;2.2 示例二 输入输出创建 &#x1f30a;1. 基础知识 .sh文件是什么&#xff1f; .sh文件即 Shell 脚本文件&#xff0c;通常用来执行一系列…

zTasker v1.88.1一键定时自动化任务

软件介绍 zTasker是一款完全免费支持定时、热键或条件触发的方式执行多种自动化任务的小工具&#xff0c;支持win7-11。其支持超过100种任务类型&#xff0c;50种定时/条件执行方法&#xff0c;而且任务列表可以随意编辑、排列、移动、更改类型&#xff0c;支持任务执行日志&a…

【强训笔记】day9

NO.1 思路&#xff1a;利用两个string&#xff0c;一个输入数据&#xff0c;一个做逗号处理&#xff0c;如果该字符的位数减去下标减去1等于3的倍数的话&#xff0c;该位置就插入逗号。 代码实现&#xff1a; #include<iostream> #include<string> using names…

多目标转化依赖DBMTL与AIT区别

DBMTL&#xff1a;通过前序目标输出作为后序目标输入刻画概率转移关系&#xff0c;概率关系的刻画是通过MLP来刻画的&#xff1b;目标之间如果存在内在联系&#xff0c;稀疏目标能利用非稀疏目标中的信息&#xff0c;得到特殊收益&#xff1b; DBMTL与ESMM区别&#xff1a;直接…

《第一行代码》第二版学习笔记(9)——服务

文章目录 一、线程二、解决异步消息处理机制1、消息组成2、AsyncTask 三、Service1、启动和停止服务2、活动和服务通信3、服务的生命周期4、创建前台服务5、使用IntentService 四、服务的最佳实践 一、线程 android不允许在子线程中更新IU操作 二、解决异步消息处理机制 1、…

【Three.js基础学习】14.Galaxy Generator

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 课程知识点 1. 实现星际编辑器 2. 创建粒子 1000&#xff0c; 在随机位置 3. 创建材质 PointsMaterial 4. Points() 接收 5. 放到gui 中调试 但是会发现调整size 等 属…

【机器学习-15】决策树(Decision Tree,DT)算法介绍:原理与案例实现

前言 决策树算法是机器学习领域中的一种重要分类方法&#xff0c;它通过树状结构来进行决策分析。决策树凭借其直观易懂、易于解释的特点&#xff0c;在分类问题中得到了广泛的应用。本文将介绍决策树的基本原理&#xff0c;包括熵和信息熵的相关概念&#xff0c;以及几种经典的…

linux(ubuntu18.04.2) Qt编译 MySQL(8.0以上版本)链接库 Qt版本 5.12.12及以上 包含Mysql动态库缺失问题

整理这篇文档的意义在于&#xff1a;自己走了很多弯路&#xff0c;淋过雨所以想为别人撑伞&#xff0c;也方便回顾&#xff0c;仅供参考 一、搭建开发环境&#xff1a; 虚拟机&#xff08;ubuntu-20.04.6-desktop-amd64&#xff09;&#xff1a;Mysql数据库 8.0.36Workbench …

透明屏幕的亮度如何?在强光环境下是否仍然清晰可见?

透明屏幕的亮度是一个重要的指标&#xff0c;决定了屏幕在明亮环境中的可视程度。在透明屏幕领域&#xff0c;高亮度的屏幕可以确保在强光环境下仍然能够清晰显示内容。 OLED透明屏通常具有较高的亮度&#xff0c;可以达到500尼特以上&#xff0c;这使得它们在明亮的环境中仍然…

中间件研发之Springboot自定义starter

Spring Boot Starter是一种简化Spring Boot应用开发的机制&#xff0c;它可以通过引入一些预定义的依赖和配置&#xff0c;让我们快速地集成某些功能模块&#xff0c;而无需繁琐地编写代码和配置文件。Spring Boot官方提供了很多常用的Starter&#xff0c;例如spring-boot-star…

图:广度优先遍历(BFS)和深度优先遍历(DFS)

1.工具类&#xff1a;队列和字典 export class DictionNary {// 字典的封装constructor() {this.items {}}set(key, value) {// 添加键this.items[key] value}has(key){// 判断键是否存在return this.items.hasOwnProperty(key)}get(key){// 获取键的valuereturn this.has(k…

H3C ripng实验(ipv6)

H3C ripng实验&#xff08;ipv6&#xff09; 实验需求 按照图示为路由器配置IPv6地址 所有路由器运行ripng&#xff0c;进行ipv6网段的互通 查询路由表后&#xff0c;​进行全网段的ping测试&#xff0c;实验目的RTD可以ping通RTA 实验解法 按照图示为路由器配置IPv6地址 …