C++ 从ole32.dll获取光标(4个奇怪字节)

C++ 从ole32.dll获取光标(4个奇怪字节),c++,winapi,C++,Winapi,你好 我正试图将此光标从“ole32.dll”加载到我的程序中 起初我不知道这个游标的名称(索引),所以我使用了,并将它提取到一个文件中。指数为“4”。该文件包含以下内容: 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, // ICONDIR header 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, // ICONDIREN

你好

我正试图将此光标从“ole32.dll”加载到我的程序中

起初我不知道这个游标的名称(索引),所以我使用了,并将它提取到一个文件中。指数为“4”。该文件包含以下内容:

0x00, 0x00, 0x02, 0x00, 0x01, 0x00, // ICONDIR header

0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01,
0x00, 0x00, 0x16, 0x00, 0x00, 0x00, // ICONDIRENTRY header

0x28 ... // image data of the cursor itself (the size of this block is 304 bytes)
然后我写了一个简单的代码(在C#上,但这并不重要):

但是我发现
SizeofResource
函数返回的是308,而不是304。然后我得到了字节数组:

0x00, 0x00, 0x00, 0x00, // 4 missed bytes
0x28 ... // data, 304 bytes
所以我的问题是:这4个字节意味着什么?它是某个不存在的结构的长度吗

第二个问题:在一般情况下,如何获得光标资源的正确标题(特别是热点的x-/y坐标和光标图像的宽度/高度)

谢谢大家!

“最初我不知道这个游标的名称(索引),所以我使用了资源黑客并将其提取到一个文件中。”

这是你第一次出错的地方。您不应该只是从Windows DLL中提取资源并期望使用它们。如果它们是供公众使用的,那么将有一个记录在案的机制来使用它们。如果没有,那么你不应该使用它们。它们是私有的,为操作系统保留。偷它们几乎肯定是不合法的;咨询律师

在这种情况下,当您使用OLE库实现拖放时,光标将自动显示。处理
IDropSource::GiveFeedback
时,返回值
DRAGDROP\u S\u USEDEFAULTCURSORS
以…使用默认光标

然后我写了一个简单的代码

这就是你真正出错的地方。撇开合法性不谈,如果您想将与Windows捆绑在一起的游标提取到一个文件中,并将它们作为嵌入资源包含在应用程序中,那么您完全可以自由地这样做。但您当然不应该尝试在Windows DLL内部使用未记录的项目。这不仅在法律上是可疑的,而且在技术上是无效的,因为当Windows更新时,您的代码可能会停止工作。您也会遇到像这样的各种棘手问题,可能与填充有关,或者只是没有充分记录实现细节。这真的不值得进一步调查;这是其中一种情况,在这种情况下,当做起来很痛苦时,你应该停止做

如果你执意要伤害自己,那么至少要用简单的方法,打电话(或
LoadImage
获取更多控制权)。这些助手函数为您处理所有事情,包括为系统的当前DPI设置加载适当大小的光标,以及映射热点的坐标。在处理标准资源类型时,很少有令人信服的理由手动查找和加载它们

// error-checking omitted, because we are hardcore
HMODULE hmodOle = LoadLibraryEx(TEXT("ole32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE);
HCURSOR hCursor = LoadCursor(hmodOle, MAKEINTRESOURCE(2));
FreeLibrary(hmodOle);

还要注意,在我选中的地方(在WindowsServer2003和Windows7上),问题中显示的光标实际上是2,而不是4。光标#4是带有快捷方式覆盖的光标。当然,随时可能有变化。我提到过你应该提取资源并将该文件嵌入到你自己的可执行文件中,而不是依赖Windows DLL中的私有资源吗?

这是光标的热点。两个16位值(0,0)使左上角的箭头尖端成为活动像素。非常不清楚您为什么不简单地使用LoadCursor()或LoadImage(),这是将资源转换为HCURSOR的简单方法。@Hans Passant,对不起,我之前没有注意到您的消息。。。非常感谢!:)@汉斯·帕桑,也许你可以把这个答案贴到主线上,这样我就可以投票了?要是我一点儿也不知道你为什么要这么做就好了。Cody正在与您合作,他应该让您走上正确的轨道。我尝试使用
LoadCursor
LoadImage
,但当流程执行到行
Marshal.Copy(指针、数组、0、大小)AccessViolationException(在这种情况下,返回的句柄不是null,并且
封送处理.GetLastWin32Error()
返回
0
)。但是无论如何,也许你可以建议手动枚举.dll文件中的游标资源,黑客使用的资源方式?我根本不明白你为什么要做
Marshal.Copy
。这些函数返回光标的句柄(
HCURSOR
)。您的P/Invoke声明应该将其表示为
IntPtr
。将该
IntPtr
传递给任何需要
HCURSOR
的对象。永远不需要复制任何位@injectorWPF只提供一个构造函数-
新游标(流)
。我试图使用
非托管的MemoryStream
,但无论如何,我不得不将光标的图像与其标题结合起来。@我觉得我一次只能从您那里获得一点信息。问题中没有提到
Marshal.Copy
,问题中也没有提到WPF。这从来不是一个好的开始;堆栈溢出不是论坛,讨论不应该发生在评论中。无论如何,不,
System.Windows.Input.Cursor
只有一个接受游标句柄的内部构造函数,句柄属性也是内部的。它不是为Win32互操作而设计的。基于流的构造函数设计用于从文件(ANI或CUR)加载游标。它不适用于内存中游标对象的句柄。这是一个不透明的GDI句柄;该类需要专门支持它。您可能需要跳过大量的限制,例如将光标渲染为位图,将位图保存到光标文件,然后使用提供的构造函数将其加载到
光标
类中,或者只需P/调用所需的SDK函数来操纵光标。这就是我要做的。或者,嗯……将光标作为资源添加到WPF项目中,并以框架本机支持的正常方式加载它。
// error-checking omitted, because we are hardcore
HMODULE hmodOle = LoadLibraryEx(TEXT("ole32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE);
HCURSOR hCursor = LoadCursor(hmodOle, MAKEINTRESOURCE(2));
FreeLibrary(hmodOle);