当前位置: 首页 > news >正文

翻译《The Old New Thing》- What a drag: Dragging a virtual file (HGLOBAL edition)

What a drag: Dragging a virtual file (HGLOBAL edition) - The Old New Thing (microsoft.com)icon-default.png?t=N7T8https://devblogs.microsoft.com/oldnewthing/20080318-00/?p=23083

Raymond Chen 2008年03月18日


拖拽虚拟文件(HGLOBAL 版本)

        现在我们已经对简单的数据对象有所了解,让我们来做点稍微复杂但极其有用的事情:拖拽一个虚拟文件。实现这一功能的方法有很多,但我将从最简单的方法开始,即虚拟文件以内存块的形式表示。

        记住,这个系列的副标题是“这是你能做的最少”。你可以(甚至应该)做很多可选的事情,但我将从绝对最小化的部分开始。

        对我们一直在研究的拖拽/放置程序进行以下更改。首先,更改数据类型的枚举:

enum {DATA_FILEGROUPDESCRIPTOR,DATA_FILECONTENTS,DATA_NUM,DATA_INVALID = -1,
};

        拖拽虚拟文件的核心剪贴板格式是 FILEGROUPDESCRIPTOR,它描述了正在拖拽的文件数量以及它们的各种信息。对于文件组描述符中的每个文件,你必须提供相关的文件内容,由 CFSTR_FILECONTENTS 剪贴板格式表示。

CTinyDataObject::CTinyDataObject() : m_cRef(1)
{SetFORMATETC(&m_rgfe[DATA_FILEGROUPDESCRIPTOR],RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR));SetFORMATETC(&m_rgfe[DATA_FILECONTENTS],RegisterClipboardFormat(CFSTR_FILECONTENTS),TYMED_HGLOBAL, /* lindex */ 0);
}

        初始化文件组描述符条目和之前看到的差不多。注意,结构体称为 FILEGROUPDESCRIPTOR,但剪贴板格式是 CFSTR_FILEDESCRIPTOR 而不是“group”。这可能最初是一个印刷错误,但现在我们只能接受它。

        文件内容条目有一个转折:lindex 是零,而不是 -1。文件内容剪贴板格式使用 lindex 作为从零开始的索引,选择调用者所谈论的是哪个虚拟文件。由于我们只有一个虚拟文件,它的索引是零。

        和以前一样,所有真正的工作都在数据对象的核心,即 IDataObject::GetData 方法中。

HRESULT CTinyDataObject::GetData(FORMATETC *pfe, STGMEDIUM *pmed)
{ZeroMemory(pmed, sizeof(*pmed));switch (GetDataIndex(pfe)) {case DATA_FILEGROUPDESCRIPTOR:{FILEGROUPDESCRIPTOR fgd;ZeroMemory(&fgd, sizeof(fgd));fgd.cItems = 1;StringCchCopy(fgd.fgd[0].cFileName,ARRAYSIZE(fgd.fgd[0].cFileName),TEXT("Dummy"));pmed->tymed = TYMED_HGLOBAL;return CreateHGlobalFromBlob(&fgd, sizeof(fgd),GMEM_MOVEABLE, &pmed->hGlobal);}case DATA_FILECONTENTS:pmed->tymed = TYMED_HGLOBAL;return CreateHGlobalFromBlob("Dummy", 5,GMEM_MOVEABLE, &pmed->hGlobal);}return DV_E_FORMATETC;
}

        当调用者请求文件组描述符时,我们填写一个 FILEGROUPDESCRIPTOR 结构体,在填写之前清零我们不关心的字节,以避免信息泄露漏洞。正如我指出的,我们从做绝对最小的必要事情开始,这在虚拟文件传输的情况下仅仅包括指定有多少虚拟文件以及它们的名称。

当调用者请求文件零(我们唯一拥有的)的内容时,我们生成一个包含“Dummy”这个词的五字节内存块。

        运行这个程序,并将不可见的对象拖出客户端区域并将其放置到桌面上。哇,你的虚拟文件已经被复制到桌面上,并变成了一个真实的文件。(你甚至可以将它拖放到Outlook邮件撰写窗口中,它将作为附件出现!)

        这里还有一些问题,但我们已经至少完成了拖拽由内存块表示的虚拟文件的绝对最小必要事项。让我们看看其中一些可选特性,其中一些对您和最终用户都有重大影响。

        首先,您可能已经注意到创建的 Dummy 文件在末尾可能有一些垃圾字节。我说“可能”,因为这些垃圾字节的存在取决于堆管理器的感受。如果您只提供 HGLOBAL,则内存块大小的唯一指示是 GlobalSize 函数的输出。但 GlobalSize 函数返回的大小不需要等于传递给 GlobalAlloc 的大小;唯一的保证是它至少和请求的大小一样大。它可能更大,这是由于内部堆管理,例如将所有分配舍入到最近的16字节的倍数。如果进行了这样的舍入,那么创建的 Dummy 文件将包含那些额外的垃圾字节。

        为了避免这个问题,在 FILEGROUPDESCRIPTOR 中设置 FD_FILESIZE 标志,并在 nFileSizeLownFileSizeHigh 成员中指定确切的文件大小:

        在 FILEGROUPDESCRIPTOR 中指定文件大小也有利于最终用户,因为它为文件复制进度条提供了它应该接收多少字节的信息。没有它,进度条不知道那个虚拟文件中有多少字节。它最终在请求文件内容时找到,但它是从每个文件复制时逐个学习的。进度对话框没有机会预先收集这些信息,以提供有意义的进度反馈。

        另一个可选细节,您可能希望利用的是,在 FILEGROUPDESCRIPTOR 中指定文件属性和修改时间。例如,您可能希望在复制时使文件隐藏,或者您可能希望自定义最后修改时间。

        我们来做一些事情。我们将在文件组描述符中指定文件大小以避免垃圾并改善进度反馈,并将最后修改时间设置为特定日期。

case DATA_FILEGROUPDESCRIPTOR:
{FILEGROUPDESCRIPTOR fgd;ZeroMemory(&fgd, sizeof(fgd));fgd.cItems = 1;fgd.fgd[0].dwFlags = FD_FILESIZE | FD_WRITESTIME;fgd.fgd[0].nFileSizeLow = 5;fgd.fgd[0].ftLastWriteTime.dwLowDateTime = 0x256d4000;fgd.fgd[0].ftLastWriteTime.dwHighDateTime = 0x01bf53eb;StringCchCopy(fgd.fgd[0].cFileName,ARRAYSIZE(fgd.fgd[0].cFileName),TEXT("Dummy"));pmed->tymed = TYMED_HGLOBAL;return CreateHGlobalFromBlob(&fgd, sizeof(fgd),GMEM_MOVEABLE, &pmed->hGlobal);
}

        现在,当您放置文件时,它在末尾将没有任何垃圾字节,时间戳将是2000年1月1日午夜UTC。(由于文件太小,您不会注意到进度条有任何改进。)

        尽管我们没有做很多,但这对许多人来说可能已经足够了,尤其是那些只想允许用户从他们的程序中拖拽一个对象并将其放入资源管理器窗口以创建相应文件的人,只要 HGLOBAL 是文件内容的方便格式。这对于小文件是合适的,但随着文件变大,您必须一次性生成整个文件的事实可能变得昂贵。下次我们将看看一个替代方案。

相关文章:

翻译《The Old New Thing》- What a drag: Dragging a virtual file (HGLOBAL edition)

What a drag: Dragging a virtual file (HGLOBAL edition) - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20080318-00/?p23083 Raymond Chen 2008年03月18日 拖拽虚拟文件(HGLOBAL 版本) 现在我们已经对简单的数据…...

SA316系列音频传输模块-传输距离升级音质不打折

SA316是思为无线研发的一款远距离音频传输模块,音频采样率为48K,传输距离可达200M。为了满足更多用户需求,思为无线在SA316基础上进一步增加传输距离推出SA316F30。相比SA316性能,同样其采用48K采样,-96dBm灵敏度&…...

【机器学习】智能选择的艺术:决策树在机器学习中的深度剖析

在机器学习的分类和回归问题中,决策树是一种广泛使用的算法。决策树模型因其直观性、易于理解和实现,以及处理分类和数值特征的能力而备受欢迎。本文将解释决策树算法的概念、原理、应用、优化方法以及未来的发展方向。 🚀时空传送门 &#x…...

电脑缺少运行库,无法启动程序

在我们使用一些软件的时候,由于电脑缺少一些运行库,导致无法启动应用软件,此时需要我们安装缺少的运行库。 比如当电脑提示: Cannot load library Qt5Xlsx.dll 我们就需要下载C得运行库,以满足软件运行需要。 下载链…...

【计算机软考_初级篇】每日十题2

各位老师大家好,软考对于日常的知识储备和企业中的考试,或者说在校大学生来说,那用处是非常大的!!那么下面我们进入正题,软考呢是分两种语言,java和C,对于其他语言目前还没&#xff…...

HR人才测评,如何做营销人员岗位素质测评?

营销人员是企业中的重要角色,他们直接负责企业产品或服务的销售和推广,是企业中最直接影响销售业绩的人才之一。因此,营销人员的基本素质测评非常重要,能够有效评估营销人员的能力和潜力,为企业招聘和培养优秀的营销人…...

LabVIEW调用第三方硬件DLL常见问题及开发流程

在LabVIEW中调用第三方硬件DLL时,除了技术问题,还涉及开发流程、资料获取及与厂家的沟通协调。常见问题包括函数接口不兼容、数据类型转换错误、内存管理问题、线程安全性等。解决这些问题需确保函数声明准确、数据类型匹配、正确的内存管理及线程保护。…...

datax实现MySQL数据库迁移shell自动化脚本

datax实现MySQL数据库迁移 (1)生成python脚本 # codingutf-8 import json import getopt import os import sys import MySQLdb#MySQL相关配置,需根据实际情况作出修改 mysql_host "xxxx" mysql_port "3306" mysql_u…...

PostgreSQL的学习心得和知识总结(一百四十四)|深入理解PostgreSQL数据库之sendTuples的实现原理及功能修改

目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《PostgreSQL数据库内核分析》 2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》 3、PostgreSQL数据库仓库…...

C++数据结构之:链List

摘要: it人员无论是使用哪种高级语言开发东东,想要更高效有层次的开发程序的话都躲不开三件套:数据结构,算法和设计模式。数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合&am…...

10.Redis之set类型

谈到一个术语,这个术语很可能有多种含义~~ 1.Set 1) 集合. 2)设置 (和 get 相对应) 集合就是把一些有关联的数据放到一起~~ 1.集合中的元素是无序的! 【此处说的无序和 前面list这里的有序 是对应的, 有序: 顺序很重要. 变换一下顺序, 就是不同的 list 了 无序: 顺序不…...

SpringBoot + mongodb 删除集合中的数据

MongoTemplate是Spring Data MongoDB提供的一个工具类,用于与MongoDB进行交互。它提供了许多方法来执行数据库操作,包括删除数据。 本文将介绍如何使用Java MongoTemplate删除集合内的数据,并提供相应的代码示例。 1. 引入MongoTemplate 首…...

【日常记录】【JS】前端预览图片的两种方式,Base64预览和blob预览

文章目录 1、前言1、FileReader3、window.URL.createObjectURL4、参考链接 1、前言 一般来说,都是 后端返回给前端图片的url,前端直接把这个值插入到 img 的src 里面即可还有一种情况是前端需要预览一下图片,比如:上传头像按钮&a…...

每日刷题——杭电2156.分数矩阵和杭电2024.C语言合法标识符

杭电2156.分数矩阵 原题链接:Problem - 2156 题目描述 Problem Description:我们定义如下矩阵: 1/1 1/2 1/3 1/2 1/1 1/2 1/3 1/2 1/1 矩阵对角线上的元素始终是1/1,对角线两边分数的分母逐个递增。请求出这个矩阵的总和。 Input&#xf…...

爬虫学习--18.反爬斗争 selenium(3)

操作多窗口与页面切换 有时候窗口中有很多子tab页面。这时候肯定是需要进行切换的。selenium提供了一个叫做switch_to.window来进行切换,具体切换到哪个页面,可以从driver.window_handles中找到。 from selenium import webdriver from selenium.webdri…...

如何评价GPT-4o?

GPT-4o是OpenAI为聊天机器人ChatGPT发布的一款新语言模型,其名称中的“o”代表Omni,即全能的意思,凸显了其多功能的特性。这款模型在多个方面都有着显著的优势和进步。 首先,GPT-4o具有极强的多模态能力,它能够接受文本…...

算能BM1684+FPGA+AI+Camera推理边缘计算盒

搭载算丰智算芯片BM1684,是面向AI推理的边缘计算盒。高效适配市场上所有AI算法,实现视频结构化、人脸识别、行为分析、状态监测等应用,为智慧城市、智慧交通、智慧能源、智慧金融、智慧电信、智慧工业等领域进行AI赋能。 产品规格 处理器芯片…...

不同厂商SOC芯片在视频记录仪领域的应用

不同SoC公司芯片在不同产品上的应用信息: 大唐半导体 芯片型号: LC1860C (主控) LC1160 (PMU)产品应用: 红米2A (399元)大疆晓Spark技术规格: 28nm工艺,4个ARM Cortex-A7处理器,1.5GHz主频,2核MaliT628 GPU,1300万像…...

【Python入门学习笔记】Python3超详细的入门学习笔记,非常详细(适合小白入门学习)

Python3基础 想要获取pdf或markdown格式的笔记文件点击以下链接获取 Python入门学习笔记点击我获取 1,Python3 基础语法 1-1 编码 默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串。 当然你也可以为源码文件指…...

通用代码生成器应用场景三,遗留项目反向工程

通用代码生成器应用场景三,遗留项目反向工程 如果您有一个遗留项目,要重新开发,或者源代码遗失,或者需要重新开发,但是希望复用原来的数据,并加快开发。 如果您的项目是通用代码生成器生成的,…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

JavaSec-RCE

简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性&#xff0c…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

深度学习习题2

1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...

蓝桥杯 冶炼金属

原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...