如何创建 Windows GUI 控件 ID?

Posted

技术标签:

【中文标题】如何创建 Windows GUI 控件 ID?【英文标题】:How are Windows GUI control ids created? 【发布时间】:2011-11-17 07:16:25 【问题描述】:

在 Windows 中,对于每个控件(例如每个对话框、窗口、文本框和复选框等)都会给出一个控件 ID。

这个控件 ID 是如何创建的? Windows 中的两个应用程序可以具有相同的控件 ID 吗?有没有办法手动设置 Windows 控件 ID?

【问题讨论】:

这是真的吗?我认为控件可以选择是否使用 ID。一个窗口句柄就足以识别一个控件。 不是。它通常只为从对话框模板创建的对话框设置。稍后可以使用 SetWindowLongPtr、GWLP_ID 进行更改。 控件ID有多种类型。自动化 ID 是您要设置的。您是否为您的应用程序使用 WinForms、WPF 或 Win32?对于每个框架,“是否有任何方法可以手动设置 Windows 控件 ID”的答案会有所不同。并且自动化 ID 不必是全局唯一的 - 它们只需要在给定范围内唯一才能有用,因为您只需要沿着树的唯一路径来识别特定控件。有关 .Net GUI 应用程序,请参阅此内容:msdn.microsoft.com/en-us/library/aa349646.aspx @Hans:根据 MSDN,SetWindowLongPtr(GWLP_ID) 仅对子窗口有效。顶层窗口、对话框或其他,根本没有控件 ID;窗口数据的那个槽(从历史上看,不确定 impl 是否仍然如此)用于 HMENU。 (从对话框模板创建的子窗口可以有一个控件 ID,但 AFAIK 它不是由对话框代码设置的;它完全取决于拥有的代码来使用 SetWindowLongPtr 设置它。) 【参考方案1】:

控件 ID 是传递给CreateWindow 函数的参数之一。如果控件是从对话框模板创建的,则对话框管理器会从对话框模板中获取控件 ID。两个控件具有相同的 ID 是很常见的。例如,大多数 Cancel 按钮将具有控件 ID IDCANCEL

【讨论】:

我看不到 CreateWindow 的哪个参数是控件 ID。 msdn.microsoft.com/en-us/library/windows/desktop/… 啊,找到了。您使用 hMenu。在此页面上找到它:msdn.microsoft.com/en-us/library/windows/desktop/… 在备注部分。 同一个窗口中的两个控件具有相同的ID是相当不常见的。例如,GetDlgItem function 取决于此。【参考方案2】:

除了雷蒙德写的:

窗口创建子窗口(也称为控件)并赋予它们相同的 ControlId 是完全合法的。唯一的问题是您将无法通过其 id 唯一地检索控件(使用 GetDlgItem())。如果您对在运行时操作控件(例如静态标签)不感兴趣,则不必关心给它一个唯一的控件 ID。只需给它 0xFFFF)。

对于不同的应用程序或父窗口中的不同控件/子窗口(例如按钮的 IDCANCEL 或 IDOK),相同的控件 ID 肯定是合法的(并且通常)。 GetDlgItem() 检索一个给定父窗口的控件。

【讨论】:

【参考方案3】:

除了其他答案中的信息:

在每个控件的窗口中,例如(对于每个对话框、窗口、文本框和复选框等),将给出一个控件 ID

这实际上并不完全正确:***窗口 - 例如应用程序窗口和对话框,实际上根本没有控件 ID。只有子窗口可以有控件 ID。

(顶层窗口使用 CreateWindow 的那个参数来指示窗口的 HMENU - 所以只有顶层窗口可以有菜单栏。)

真正由应用开发者决定如何分配和使用 ID。通常它们与 GetDlgItem() 一起使用,它查找具有给定 ID 和父 HWND 的 HWND,因此在这种情况下,ID 只需要在该父级中是唯一的。如果开发人员不需要在运行时查找控件,它可以给它任何 ID,传统上在那里使用 -1。

有些框架根本不使用控件 ID,只是在创建 HWND 时对其进行跟踪。

【讨论】:

使用 WinSpy++ 我查看了 calc.exe 的***窗口,它有一个控件 ID。我知道它是***窗口,因为它的父窗口 ID 是“00000000”。 这个值很可能实际上是窗口的菜单句柄;窗口具有菜单处理程序或控件 ID,具体取决于它们是***窗口还是子窗口。 Microsoft 的 Spy++ 工具在其窗口属性对话框版本中使用同一行来显示此值,默认情况下使用标签“控件 ID”,如果窗口是***窗口并且值为非空。可能 WinSpy++ 在这里对标签的使用没有那么勤奋。 感谢您的回复。但是,我可以将所述控制 ID 传递给 GetDlgItem() 并获得有意义的 hwnd 作为回报。我在想,如果GetDlgItem() 将数据项视为有效的控件 ID,那么它一定是一个。 您将什么 HWND 作为 hwnd 参数传递给 GetDlgItem?您可能不想使用 GetDlgItem 来查找***窗口;它的设计目的是在父对话框中按 ID 查找子窗口, 已经自己分配了所有 ID,因此您知道会得到什么。大多数*** HWND 都会将此值设为 null 或 HMENU 值,这实际上是随机的。您真正想在这里做什么?可能有更好的方法来做到这一点,而不是 [mis] using GetDlgItem :) 我开发了一个驱动 calc.exe 的小应用程序。当我使用 WinSpy++ 查看 calc.exe 时,我能为每个按钮找到的唯一唯一 ID 是它的 Control ID;例如,按钮“1”是 0x83,“+”是 0x5D。然后,我枚举了 calc.exe 的所有子窗口(其中 136 个)并搜索了这些控件 ID 并找到了它们的 hwnd 值。我使用 hwnd 进行 SendMessage 调用。有用。我知道控制 ID 可能不是唯一的或可能为空,但在 calc.exe 的情况下,它们可以完成这项工作。除了 GetDlgItem 之外,我找不到任何其他方法来检索给定控件 ID 的 hwnd。再次感谢您。【参考方案4】:

除了其他答案:

虽然控件的 ID 可以相同,但最好使其唯一。控件使用其 id 和 hwnd 向其父窗口报告事件。在父级的消息循环中,我们一般使用id来标识控件,这种情况下,如果想要不同的事件处理,就为每个控件使用不同的id。

【讨论】:

以上是关于如何创建 Windows GUI 控件 ID?的主要内容,如果未能解决你的问题,请参考以下文章

显示当前电池电量的 gui 控件 windows mobile C#

.NET GUI 中是不是仍在使用本机 Windows 控件?

MFC GUI自定义控件:如何绘制光标更新以响应鼠标移动?

Windows 7 GUI 参考

qt如何让控件在单独线程运行

如何创建 Windows GUI 应用程序来播放视频