谁是GWLP_USERDATA单元的所有者?

众所周知, GWLP_USERDATA可用于将指针大小数据与指定的窗口关联起来。 但谁有权这样做呢? 显然,如果两个代码独立地做到这一点 – 一个是覆盖另一个的数据 – 所以只能有一个所有者。 但是必须清楚确定一个通用规则 – 谁是GWLP_USERDATA单元的所有者? 它属于谁?

可以是两个内部一致的协议:

  1. 创build该窗口的代码是所有者。 属于窗户的创造者
  2. 实现窗口类的代码。 属于窗口类实现者

这两个解决scheme必须使用什么?

1.从MSDN :

GWLP_USERDATA

设置与窗口关联的用户数据。 此数据旨在供创build该窗口的应用程序使用 。 它的值最初是零。

如何理解This data is intended for use by the application that created the window

所以调用CreateWindowExCreateDialogParamDialogBoxParam等的代码只有这个代码可以使用GWLP_USERDATA 。 由此也可以看出,窗口类的实现者不能使用GWLP_USERDATA 。 所以GWLP_USERDATA用于将类的实例绑定到指定的窗口的示例数量巨大不正确。 pipe理应用程序状态 – 官方MSDN示例,其中GWLP_USERDATA用于将数据结构绑定到窗口不正确?

SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);

在这个规则下是错误的。

有什么可以说赞成这个版本? 我检查不同的Windows版本(从XP到WIN10) – 我怎么能看到所有的Windows内置窗口类( WC_*和其他)使用

SetWindowLongPtr(hwnd, 0, (LONG_PTR)pThis);

用于将类的实例绑定到指定的窗口。 始终使用索引0,而不是GWLP_USERDATA

很多人可以说 – 那又怎样? 即使现在这是真的,未来的Windows版本呢? 但是如果想想,从GWLP_USERDATA索引0(真正的私有实现者索引)什么意义上迁移? 改变现有的SetWindowLongPtr(hwnd, 0, (LONG_PTR)pThis); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis); 什么奖项? 或者额外的开始使用GWLP_USERDATA与索引0呢? 这已经绝对没有意义了 – 一个指针对于绑定窗口到数据结构是足够的,所有额外的指针必须是(在Windows代码将是),在这个结构已经。 所以我个人可以认为这没有改变


也可以在 这里 注意 SetWindowLongPtr GetWindowLongPtr 的文档中的错误

要设置的值为零的偏移量。 有效值的范围为零至额外窗口内存的字节数,减去整数的大小

真正减去一个指针的大小,这个指针在x64的8个字节上,当一个整数的大小总是4。


2.看一个有信誉的博客 – 在GWLP_USERDATA奖金窗口字节 :

请注意,此值…属于窗口类,不属于创build窗口的代码…只有窗口类实现者可以读取或写入值。

也有接下来的两位作者的评论:

有趣。 我正在检查。 但是,即使它属于窗口的创build者,也有足够的窗口类实现使用它,为了安全起见,您仍然应该远离它。

我问周围,指导是“不清楚”,虽然略微倾向于“它属于调用CreateWindow的人”。 为了安全起见,你应该避免它,除非你能build立明确的所有权

再次寻找pipe理应用程序状态的 MSDN示例 – 窗口类实现者使用GWLP_USERDATA

寻找ATL atlhost.hAtlAxWindowProc使用了GWLP_USERDATA

 //case WM_CREATE: ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD_PTR)pAxWindow); 

再次使用类实现者GWLP_USERDATA

但是根据这个协议,我们不能使用带有CreateDialogParamDialogBoxParam GWLP_USERDATA ,因为这里我们不是实现者( DialogProc函数是DefDlgProc调用的应用程序定义的callback函数 – 用于对话的真实类实现代码 – 所以只有DefDlgProc可以潜在地使用GWLP_USERDATA单元)


所以创build窗口窗口类实现者的应用程序是所有者?


如果认为 – 创build窗口的变体应用程序更合乎逻辑。 窗口类实现者有两种select:可以将cbWndExtra设置为sizeof(PVOID)并使用索引0或使用GWLP_USERDATA索引。 当创build窗口的应用程序 – 没有select – 只有GWLP_USERDATA索引或使用像SetPropSetWindowSubclass等另一种(不太有效和更复杂)的方式,如果窗口类实现者使用索引0绑定自己的数据窗口和离开为创build该窗口的代码提供免费的GWLP_USERDATA 。 又如何CreateDialogParamDialogBoxParam – 最原始的方式这里使用数据结构绑定到对话框使用GWLP_USERDATA索引,但在这里,我们的窗口创build者,而不是对话框类的实现者! 那么可以使用GWLP_USERDATA吗?

在所有情况下,需要考虑到现有的自定义窗口类实现使用GWLP_USERDATA

我的假设:

  • 如果我们为非Windows核心内置类调用CreateWindowEx – 我们不能在这里使用GWLP_USERDATA
  • 如果我们调用CreateDialogParamDialogBoxParam – 我假设我们可以在这里使用GWLP_USERDATA
  • 如果我们调用CreateWindowEx for windows内置类(WC_ * named),我们也可以使用GWLP_USERDATA
  • 如果我们窗口类实现者 – 最好的select – 将cbWndExtra设置为sizeof(PVOID)并使用索引0