【问题标题】:What's an alternative to GWL_USERDATA for storing an object pointer?用于存储对象指针的 GWL_USERDATA 的替代方法是什么?
【发布时间】:2010-09-06 14:08:51
【问题描述】:

在我从事的 Windows 应用程序中,我们有一个直接位于 Win32 之上的自定义框架(不要问)。当我们创建一个窗口时,我们通常的做法是通过SetWindowLong(hwnd, GWL_USERDATA, this)this 放入窗口的用户数据区,这样我们就可以有一个类似MFC 的回调或紧密集成的WndProc,这取决于。问题是这在 64 位 Windows 上不起作用,因为 LONG 只有 32 位宽。在 32 位和 64 位系统上都有什么更好的解决方案来解决这个问题?

【问题讨论】:

    标签: windows winapi 32bit-64bit


    【解决方案1】:

    SetWindowLongPtr 在这些情况下被创建来替换 SetWindowLong。它的 LONG_PTR 参数允许您存储 32 位或 64 位编译的指针。

    LONG_PTR SetWindowLongPtr(      
        HWND hWnd,
        int nIndex,
        LONG_PTR dwNewLong
    );
    

    记住常量也发生了变化,所以现在的用法如下:

    SetWindowLongPtr(hWnd, GWLP_USERDATA, this);
    

    另外别忘了现在要检索指针,你必须使用GetWindowLongPtr

    LONG_PTR GetWindowLongPtr(      
        HWND hWnd,
        int nIndex
    );
    

    并且用法看起来像(同样,更改了常量):

    LONG_PTR lpUserData = GetWindowLongPtr(hWnd, GWLP_USERDATA);
    MyObject* pMyObject = (MyObject*)lpUserData;
    

    【讨论】:

    • 对。并且 LONG_PTR 可用于将数据作为整数或 size_t(与操作系统指针一样大)存储到 Window(在许多情况下非常实用)以存储像 int 之类的值(通过强制转换),如果不想分配一个内存(和空闲)指向,一个 int 就足够了。它与 32 位的 SetWindowLong 大致相同,但是(过去)您需要将 long 转换为指向分配数据的指针。而且 64 位系统中的指针可能比 long 长,所以这个更改是一种改进,因为我们可以将它转换为我们喜欢的任何值。
    【解决方案2】:

    另一种选择是 SetProp/RemoveProp(当您对已经使用 GWLP_USERDATA 的窗口进行子类化时)

    另一个不错的选择是 WNDPROC 的 ATL 样式 thunking,有关详细信息,请参阅

    【讨论】:

    • thunking 的问题(至少根据文章)在于它依赖于处理器,因为它依赖于低级程序集 - 文章仅针对 x86; OP的问题是关于不同的架构。当处理器中立的技术可用时,几乎没有理由选择特定于处理器的技术:Get/SetWindowLongPtr 适用于 32 位和 64 位编译。
    • @BrendanMcK IIRC windows 链接控件使用 GWLP_USERDATA 因此,如果您将其子类化,则需要将数据存储在其他地方。是的,thunking 是特定于 CPU 的,请参阅 masm32.com/board/index.php?topic=4572.0 了解 x64 版本(在 08 IIRC 中找不到任何示例)
    • (啊,这是由于最近的编辑而在 RSS 字段中以某种方式显示为“新”的旧答案中的另一个……)是的,我同意答案的第一部分; Get/SetProp 是子类化时要走的路。当有一个有效的 API 时,仍然没有理由使用汇编程序。 (也许几年后代码也需要更改以添加 ARM 版本!)
    • @BrendanMcK ARM 将成为仅限 WinRT 的 AFAIK。使用 thunking 的原因是性能; mov+jmp 比什么都快...
    • ...我会质疑 perf 在许多情况下是否真的合理;任何认为性能可能是一个问题的人都需要在求助于汇编程序之前先进行测量。我敢肯定 thunk 有合法用途,但 IMO 似乎只在极少数情况下是合理的;所以在推荐它们而不是更具可读性、健壮性和可维护性的 API 时会非常谨慎。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-22
    • 2012-09-02
    • 2014-02-03
    • 2023-04-05
    • 2023-04-05
    • 1970-01-01
    相关资源
    最近更新 更多