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

时间:2010-07-27 12:45:04

标签: c# .net pinvoke setwindowlong getwindowlong

我想P / Invoke到GetWindowLongPtrSetWindowLongPtr,我看到有关它们的相互矛盾的信息。

有些消息称,在32位平台上,GetWindowLongPtr只是一个调用GetWindowLong的预处理器宏,GetWindowLongPtr不作为user32.dll中的入口点存在。例如:

  • pinvoke.net entry for SetWindowLongPtr有一个静态方法,它检查IntPtr.Size,然后调用SetWindowLong或SetWindowLongPtr,并发表评论说“遗留操作系统不支持SetWindowLongPtr”。没有解释“遗留操作系统”的含义。
  • answer on StackOverflow状态“在32位系统上GetWindowLongPtr只是一个指向GetWindowLong的C宏”。

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

但我在MSDN文档中没有看到这一点。根据MSDN,SetWindowLongPtr取代了SetWindowLong,简单明了。根据{{​​3}}的要求部分,看起来SetWindowLongPtr自Windows 2000(客户端和服务器版本)以来一直在user32.dll中。同样,没有提到32位操作系统中缺少入口点。

怀疑真相介于两者之间:当你告诉C ++编译器定位旧操作系统时(即编译将在Win9x和NT4上运行的东西),那么头文件将SetWindowLongPtr声明为调用SetWindowLong的宏,但是入口点可能确实存在于Windows 2000及更高版本中,如果您告诉编译器定位这些平台,您将直接获取它(而不是宏)。但这只是猜测;我真的没有资源或技术可以深入挖掘并验证它。

目标平台也可能扮演一个角色 - 如果您为x86平台编译应用程序,那么就不应该在64位操作系统上调用SetWindowLongPtr。再一次,我知道这个问题,但我不知道如何找到答案。 MSDN似乎暗示SetWindowLongPtr始终是正确的。

有人可以告诉我,只需P / Invoke到SetWindowLongPtr是否安全并完成它? (假设Windows 2000及更高版本。)P /调用SetWindowLongPtr会给我正确的入口点:

  • 如果我在32位操作系统上运行针对x86平台的应用程序?
  • 如果我在64位操作系统上运行针对x86平台的应用程序?
  • 如果我在64位操作系统上运行针对x64平台的应用程序?

2 个答案:

答案 0 :(得分:17)

我建议你按照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 :(得分:4)

  1. 打开头文件(在MSDN页面上,这被列为Winuser.h)。 Win32标头通常位于C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include
  2. 搜索SetWindowLongPtr / GetWindowLongPtr
  3. 的所有实例
  4. 请注意,定义_WIN64时,它们是函数;如果不是,则#defineSetWindowLong / GetWindowLong
  5. 这意味着32位操作系统可能没有SetWindowLongPtr / GetWindowLongPtr作为实际功能,所以看起来pinvoke.net上的评论是正确的。

    更新(有关_WIN64的更多说明):

    编译64位代码时,C / C ++编译器定义了

    _WIN64(只能在64位操作系统上运行)。这意味着使用SetWindowLongPtr / GetWindowLongPtr的任何64位代码都将使用实际函数,但使用它们的任何32位代码都将使用SetWindowLong / GetWindowLong代替。这包括在64位操作系统上运行的32位代码。

    要在C#中模拟相同的行为,我建议像pinvoke.net一样检查IntPtr.Size;它告诉您是否正在运行32位或64位代码。 (请记住,32位代码可能在64位操作系统上运行)。在托管代码中使用IntPtr.Size模拟与_WIN64对本机代码相同的行为。