如何在 32 位平台上调用 GetWindowLongPtr 和 SetWindowLongPtr?

发布于 2024-09-11 06:06:36 字数 1899 浏览 8 评论 0原文

我想 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤独难免 2024-09-18 06:06:36

我建议您按照 Windows 窗体内部的方式处理此问题:

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);

I'd recommend you deal with this the way Windows Forms does it internally:

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);
森林很绿却致人迷途 2024-09-18 06:06:36
  1. 打开头文件(在 MSDN 页面上,该文件列为 Winuser.h)。 Win32 标头通常位于 C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include
  2. 搜索 SetWindowLongPtr/GetWindowLongPtr 的所有实例>。
  3. 注意,当_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 对本机代码的行为相同。

  1. Open the header file (on the MSDN page, this is listed as Winuser.h). Win32 headers are usually found at C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include
  2. Search for all instances of SetWindowLongPtr/GetWindowLongPtr.
  3. Note that when _WIN64 is defined, they are functions; when it's not, they are #define'd 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.

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 using SetWindowLongPtr/GetWindowLongPtr will use the actual functions, but any 32-bit code using them will use SetWindowLong/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). Using IntPtr.Size in managed code emulates the same behavior as _WIN64 does for native code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文