我想P / Invoke到GetWindowLongPtr和SetWindowLongPtr,我看到有关它们的相互矛盾的信息。
有些消息称,在32位平台上,GetWindowLongPtr只是一个调用GetWindowLong的预处理器宏,GetWindowLongPtr不作为user32.dll中的入口点存在。例如:
因此,这些来源似乎表明* 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会给我正确的入口点:
答案 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)
C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include
SetWindowLongPtr
/ GetWindowLongPtr
。_WIN64
时,它们是函数;如果不是,则#define
为SetWindowLong
/ GetWindowLong
。这意味着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
对本机代码相同的行为。