如何在 32 位平台上调用 GetWindowLongPtr 和 SetWindowLongPtr?
我想 P/Invoke 到 GetWindowLongPtr 和 < a href="http://msdn.microsoft.com/en-us/library/ms644898(VS.85).aspx" rel="noreferrer">SetWindowLongPtr,并且我看到有关它们的冲突信息。
有消息称,在 32 位平台上,GetWindowLongPtr 只是一个调用 GetWindowLong 的预处理器宏,并且 GetWindowLongPtr 并不作为 user32.dll 中的入口点存在。例如:
- SetWindowLongPtr 的 pinvoke.net 条目 有一个静态方法,该方法检查 IntPtr.Size,然后调用 SetWindowLong 或 SetWindowLongPtr,并附有注释“旧版操作系统不支持 SetWindowLongPtr”。没有解释“遗留操作系统”的含义。
- StackOverflow 上的答案指出“在 32 位系统上 GetWindowLongPtr 只是一个 C指向 GetWindowLong 的宏”。
因此,这些来源似乎表明 *Ptr 入口点根本不存在于 32 位 Windows 7 附带的 user32.dll 版本中。
但我在 MSDN 文档中没有看到任何迹象。根据 MSDN,SetWindowLongPtr 取代了 SetWindowLong,简单且简单的。并根据 SetWindowLongPtr 页面 的要求部分,看来 SetWindowLongPtr 自 Windows 2000(客户端和服务器版本)以来一直存在于 user32.dll 中。再次强调,没有提到 32 位操作系统中缺少入口点。
我怀疑事实介于两者之间:当您告诉 C++ 编译器以较旧的操作系统为目标(即编译将在 Win9x 和 NT4 上运行的东西)时,头文件将 SetWindowLongPtr 声明为一个调用 SetWindowLong 的宏,但入口点可能确实存在于 Windows 2000 及更高版本中,如果您告诉编译器以这些平台为目标,您将直接获得它(而不是宏)。但这只是一个猜测;我真的没有资源或专业知识来挖掘和验证它。
目标平台也可能发挥了作用 - 如果您为 x86 平台编译应用程序,那么您不应该在 64 位操作系统上调用 SetWindowLongPtr。再说一遍,我知道的足以思考这个问题,但我不知道如何找到答案。 MSDN 似乎表明 SetWindowLongPtr 总是正确的。
谁能告诉我简单地 P/Invoke SetWindowLongPtr 并完成它是否安全? (假设 Windows 2000 及更高版本。)P/Invoking SetWindowLongPtr 会给我正确的入口点吗:
- 如果我在 32 位操作系统上运行针对 x86 平台的应用程序?
- 如果我在 64 位操作系统上运行针对 x86 平台的应用程序?
- 如果我在 64 位操作系统上运行针对 x64 平台的应用程序?
I want to P/Invoke to GetWindowLongPtr and SetWindowLongPtr, and I'm seeing conflicting information about them.
Some sources say that, on 32-bit platforms, GetWindowLongPtr is just a preprocessor macro that calls GetWindowLong, and GetWindowLongPtr doesn't exist as an entry point in user32.dll. For example:
- The pinvoke.net entry for SetWindowLongPtr has a static method that checks IntPtr.Size and then calls either SetWindowLong or SetWindowLongPtr, with a comment saying that "legacy OSes do not support SetWindowLongPtr". There's no explanation of what is meant by "legacy OSes".
- An answer on StackOverflow states "On 32bit systems GetWindowLongPtr is just a C macro that points to GetWindowLong".
So these sources seem to indicate that the *Ptr entry points simply aren't there in the version of user32.dll that ships with, say, 32-bit Windows 7.
But I see no indication of this in the MSDN documentation. According to MSDN, SetWindowLongPtr supersedes SetWindowLong, plain and simple. And according to the requirements section of the SetWindowLongPtr page, it appears that SetWindowLongPtr has been in user32.dll since Windows 2000 (both client and server editions). Again, no mention of the entry points being missing in 32-bit OSes.
I suspect that the truth is somewhere in between: that when you tell the C++ compiler to target older OSes (i.e., to compile something that will run on Win9x and NT4), then the header files declare SetWindowLongPtr as a macro that calls SetWindowLong, but the entry point probably does exist in Windows 2000 and later and you'll get it directly (instead of the macro) if you tell the compiler to target those platforms. But that's just a guess; I don't really have the resources or the knowhow to dig in and verify it.
It's also possible that the target platform plays a role -- that if you compile your app for the x86 platform, then you shouldn't call SetWindowLongPtr on a 64-bit OS. Again, I know enough to think of the question, but I don't know how to find the answer. MSDN seems to suggest that SetWindowLongPtr is always correct.
Can anyone tell me whether it's safe to simply P/Invoke to SetWindowLongPtr and be done with it? (Assume Windows 2000 and later.) Would P/Invoking to SetWindowLongPtr give me the correct entry point:
- if I run an app targeting the x86 platform on a 32-bit OS?
- if I run an app targeting the x86 platform on a 64-bit OS?
- if I run an app targeting the x64 platform on a 64-bit OS?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我建议您按照 Windows 窗体内部的方式处理此问题:
I'd recommend you deal with this the way Windows Forms does it internally:
C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include
SetWindowLongPtr
/GetWindowLongPtr
的所有实例>。_WIN64
被定义时,它们是函数;如果不是,则将它们#define
设置为SetWindowLong
/GetWindowLong
。这意味着 32 位操作系统可能没有
SetWindowLongPtr
/GetWindowLongPtr
作为实际函数,因此 pinvoke.net 上的评论似乎是正确的。更新(对 _WIN64 进行更多说明):
_WIN64
是由 C/C++ 编译器在编译 64 位代码(只能在 64 位操作系统上运行)时定义的。因此,这意味着使用SetWindowLongPtr
/GetWindowLongPtr
的任何 64 位代码都将使用实际函数,但使用它们的任何 32 位代码都将使用SetWindowLong
>/GetWindowLong
相反。这包括在 64 位操作系统上运行的 32 位代码。要在 C# 中模拟相同的行为,我建议检查
IntPtr.Size
,如 pinvoke.net 所做的那样;它告诉您正在运行 32 位还是 64 位代码。 (请记住,32 位代码可以在 64 位操作系统上运行)。在托管代码中使用IntPtr.Size
模拟的行为与_WIN64
对本机代码的行为相同。C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include
SetWindowLongPtr
/GetWindowLongPtr
._WIN64
is defined, they are functions; when it's not, they are#define
'd toSetWindowLong
/GetWindowLong
.This implies that 32-bit OSes may not have
SetWindowLongPtr
/GetWindowLongPtr
as an actual function, so it would appear that the comment on pinvoke.net is correct.Update (more clarification on _WIN64):
_WIN64
is defined by the C/C++ compiler when compiling 64-bit code (that will only run on a 64-bit OS). So this means that any 64-bit code usingSetWindowLongPtr
/GetWindowLongPtr
will use the actual functions, but any 32-bit code using them will useSetWindowLong
/GetWindowLong
instead. This includes 32-bit code running on a 64-bit OS.To emulate the same behavior in C#, I recommend checking
IntPtr.Size
as done by pinvoke.net; that tells you whether you're running 32-bit or 64-bit code. (Keeping in mind that 32-bit code may run on a 64-bit OS). UsingIntPtr.Size
in managed code emulates the same behavior as_WIN64
does for native code.