简体   繁体   English

如何在32位平台上pinvoke到GetWindowLongPtr和SetWindowLongPtr?

[英]How do I pinvoke to GetWindowLongPtr and SetWindowLongPtr on 32-bit platforms?

I want to P/Invoke to GetWindowLongPtr and SetWindowLongPtr , and I'm seeing conflicting information about them. 我想P / Invoke到GetWindowLongPtrSetWindowLongPtr ,我看到有关它们的相互矛盾的信息。

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. 有些消息称,在32位平台上,GetWindowLongPtr只是一个调用GetWindowLong的预处理器宏,而GetWindowLongPtr不作为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". SetWindowLongPtrpinvoke.net条目有一个静态方法,它检查IntPtr.Size,然后调用SetWindowLong或SetWindowLongPtr,注释说“遗留操作系统不支持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". StackOverflow答案是 “On 32bit系统GetWindowLongPtr只是一个指向GetWindowLong的C宏”。

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. 因此,这些来源似乎表明* Ptr入口点根本不存在于32位Windows 7附带的user32.dll版本中。

But I see no indication of this in the MSDN documentation. 但我在MSDN文档中没有看到这一点。 According to MSDN, SetWindowLongPtr supersedes SetWindowLong, plain and simple. 根据MSDN, SetWindowLongPtr取代了SetWindowLong,简单明了。 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). 根据SetWindowLongPtr页面的要求部分,看起来SetWindowLongPtr自Windows 2000(客户端和服务器版本)以来一直在user32.dll中。 Again, no mention of the entry points being missing in 32-bit OSes. 同样,没有提到32位操作系统中缺少的入口点。

I suspect that the truth is somewhere in between: that when you tell the C++ compiler to target older OSes (ie, 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. 怀疑事实介于两者之间:当你告诉C ++编译器定位较旧的操作系统(即编译将在Win9x和NT4上运行的东西)时,头文件将SetWindowLongPtr声明为调用SetWindowLong的宏,但是入口点可能确实存在于Windows 2000及更高版本中,如果您告诉编译器定位这些平台,您将直接获取它(而不是宏)。 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. 目标平台也可能扮演一个角色 - 如果您为x86平台编译应用程序,那么就不应该在64位操作系统上调用SetWindowLongPtr。 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. MSDN似乎暗示SetWindowLongPtr始终是正确的。

Can anyone tell me whether it's safe to simply P/Invoke to SetWindowLongPtr and be done with it? 任何人都可以告诉我,简单的P / Invoke到SetWindowLongPtr是否安全并完成它? (Assume Windows 2000 and later.) Would P/Invoking to SetWindowLongPtr give me the correct entry point: (假设Windows 2000及更高版本。)P /调用SetWindowLongPtr会给我正确的入口点:

  • if I run an app targeting the x86 platform on a 32-bit OS? 如果我在32位操作系统上运行针对x86平台的应用程序?
  • if I run an app targeting the x86 platform on a 64-bit OS? 如果我在64位操作系统上运行针对x86平台的应用程序?
  • if I run an app targeting the x64 platform on a 64-bit OS? 如果我在64位操作系统上运行针对x64平台的应用程序?

I'd recommend you deal with this the way Windows Forms does it internally: 我建议你按照Windows Forms内部的方式处理这个问题:

public static IntPtr GetWindowLong(HandleRef hWnd, int nIndex)
{
    if (IntPtr.Size == 4)
    {
        return GetWindowLong32(hWnd, nIndex);
    }
    return GetWindowLongPtr64(hWnd, nIndex);
}


[DllImport("user32.dll", EntryPoint="GetWindowLong", CharSet=CharSet.Auto)]
private static extern IntPtr GetWindowLong32(HandleRef hWnd, int nIndex);

[DllImport("user32.dll", EntryPoint="GetWindowLongPtr", CharSet=CharSet.Auto)]
private static extern IntPtr GetWindowLongPtr64(HandleRef hWnd, int nIndex);
  1. Open the header file (on the MSDN page, this is listed as Winuser.h). 打开头文件(在MSDN页面上,这列为Winuser.h)。 Win32 headers are usually found at C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0A\\Include Win32标头通常位于C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0A\\Include
  2. Search for all instances of SetWindowLongPtr / GetWindowLongPtr . 搜索SetWindowLongPtr / GetWindowLongPtr所有实例。
  3. Note that when _WIN64 is defined, they are functions; 注意,当定义_WIN64时,它们是函数; when it's not, they are #define 'd to SetWindowLong / GetWindowLong . 如果不是,那么他们就是# #define to SetWindowLong / 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. 这意味着32位操作系统可能没有SetWindowLongPtr / GetWindowLongPtr作为实际函数,因此看起来pinvoke.net上的注释是正确的。

Update (more clarification on _WIN64): 更新(关于_WIN64的更多说明):

_WIN64 is defined by the C/C++ compiler when compiling 64-bit code (that will only run on a 64-bit OS). _WIN64由C / C ++编译器在编译64位代码时定义(仅在64位操作系统上运行)。 So this means that any 64-bit code using SetWindowLongPtr / GetWindowLongPtr will use the actual functions, but any 32-bit code using them will use SetWindowLong / GetWindowLong instead. 所以这意味着使用SetWindowLongPtr / GetWindowLongPtr任何64位代码都将使用实际函数,但使用它们的任何32位代码都将使用SetWindowLong / GetWindowLong This includes 32-bit code running on a 64-bit OS. 这包括在64位操作系统上运行的32位代码。

To emulate the same behavior in C#, I recommend checking IntPtr.Size as done by pinvoke.net; 要在C#中模拟相同的行为,我建议检查IntPtr.SizeIntPtr.Size所做; that tells you whether you're running 32-bit or 64-bit code. 它告诉您是否正在运行32位或64位代码。 (Keeping in mind that 32-bit code may run on a 64-bit OS). (请记住,32位代码可能在64位操作系统上运行)。 Using IntPtr.Size in managed code emulates the same behavior as _WIN64 does for native code. 在托管代码中使用IntPtr.Size可以模拟与_WIN64对本机代码相同的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何判断我的应用程序是作为32位还是64位应用程序运行? - How do I tell if my application is running as a 32-bit or 64-bit application? 如何在C#中将16位“short”转换为32位整数? - How do I cast a 16 bit 'short' into a 32-bit integer in C#? 如何为32位和64位安全地从GetTokenInformation()调用结构的可变长度数组? C# - How to pinvoke a variable-length array of structs from GetTokenInformation() safely for 32-bit and 64-bit? C# 我如何从x64打开OLEDB Prompt for 32-bit - How do I open OLEDB Prompt for 32-bit from x64 如何将4字节字符串编码为单个32位整数? - How do I encode a 4-byte string as a single 32-bit integer? 使用 NAudio 如何将非隔行 32 位浮点格式保存到文件 - Using NAudio how do I save Non-interlaced 32-bit float format to file 如何做 RegAsm 使其覆盖 32 位和 64 位? - How to do RegAsm so that it cover 32-bit and 64-bit? 如何在C#Express中选择32位或64位构建? - How can I choose between 32-bit or 64-bit build in C# Express? 如何检查给定地址是 32 位还是 64 位? - How can I check if a given address is 32-bit or 64-bit? 使用WMI,如何确定远程进程是32位还是64位? - Using WMI, how can I determine whether a remote process is 32-bit or 64-bit?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM