关于c#:如何在32位平台上使用GetWindowLongPtr和SetWindowLongPtr?

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

我想P /调用GetWindowLongPtr和SetWindowLongPtr,并且看到有关它们的冲突信息。

一些消息来源说,在32位平台上,GetWindowLongPtr只是一个调用GetWindowLong的预处理器宏,而GetWindowLongPtr在user32.dll中并不存在。例如:

  • SetWindowLongPtr的pinvoke.net条目具有一个静态方法,该方法将检查IntPtr.Size,然后调用SetWindowLong或SetWindowLongPtr,并带有注释,指出"旧版OS不支持SetWindowLongPtr"。没有关于"旧版OS"的含义的解释。
  • 关于StackOverflow的回答指出"在32位系统上,GetWindowLongPtr只是一个指向GetWindowLong的C宏"。

因此这些来源似乎表明,例如32位Windows 7附带的user32.dll版本中根本没有* Ptr入口点。

但是我在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 /调用SetWindowLongPtr给我正确的入口点:

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

我建议您以Windows窗体内部执行此操作的方式进行处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);


  • 打开头文件(在MSDN页面上,该文件列为Winuser.h)。 Win32标头通常位于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位OS上运行)时定义。因此,这意味着使用SetWindowLongPtr / GetWindowLongPtr的任何64位代码都将使用实际功能,但是使用它们的任何32位代码将使用SetWindowLong / GetWindowLong代替。这包括在64位OS上运行的32位代码。

    要在C#中模拟相同的行为,我建议像pinvoke.net一样检查IntPtr.Size。告诉您运行的是32位还是64位代码。 (请记住,32位代码可以在64位OS上运行)。在托管代码中使用IntPtr.Size可以模拟与_WIN64对于本机代码相同的行为。