OLE拖放接收器处理非标准格式及流读取异常问题咨询
OLE拖放接收器常见问题解答
1. 如何获取私有剪贴板格式的详细信息
你提到的49165、49763并非TYMED编码(TYMED是指数据存储介质类型,比如TYMED_ISTREAM对应的数值是4),而是私有剪贴板格式ID,这类格式通常是Office等应用注册的自定义格式。获取详细信息可通过以下方式:
- 调用
GetClipboardFormatNameW函数:传入格式ID,获取该格式的名称字符串。多数Office私有格式会返回有辨识度的名称,比如Word拖放文本对应的格式可能关联富文本相关名称,Outlook邮件对应的格式会包含邮件对象相关标识。 - 结合FORMATETC结构辅助判断:查看枚举得到的
FORMATETC对象的dwAspect(显示维度,比如DVASPECT_CONTENT表示内容数据)、ptd(目标设备)字段,可辅助推断数据的用途和类型。
2. IStream读取返回S_OK但ActuallyRead为0的原因及解决方法
这种情况不代表流为空,最常见的原因是:
- 流的当前读取指针已经指向了流的末尾。OLE数据源返回IStream时,并未保证指针处于起始位置。解决方法是在调用
Read前,先重置指针到流开头:// 重置流指针到起始位置 LARGE_INTEGER liZero = {0}; Stream->Seek(liZero, STREAM_SEEK_SET, nullptr); - 少数情况下可能是延迟加载机制导致:部分OLE数据源采用延迟加载,首次
Read仅触发数据准备但未返回实际内容,可尝试再次调用Read;另外要确认调用IDataObject::GetData时,FORMATETC的参数是否正确(比如dwAspect需设为DVASPECT_CONTENT,tymed明确指定TYMED_ISTREAM)。
修正后的读取代码示例
// Stream is IStream* -- initialized, not NULL LARGE_INTEGER liZero = {0}; // 先将流指针移到起始位置 HRESULT res_seek = Stream->Seek(liZero, STREAM_SEEK_SET, nullptr); if (FAILED(res_seek)) { // 处理定位失败逻辑 return; } const int BufferSize = 100000; char* BufferPtr = (char*)malloc(BufferSize); if (BufferPtr == nullptr) return; ULONG ActuallyRead = 0; HRESULT res_read = Stream->Read(BufferPtr, BufferSize, &ActuallyRead);
内容的提问来源于stack exchange,提问作者LUN
相关产品推荐
相关产品推荐

