0

我的应用程序有一个 CTreeCtrl 类型的树。树的节点之一是 CComboBox 控件,该控件创建为该树结构的子项。

c_combo->创建(WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_HASSTRINGS | CBS_DROPDOWNLIST,myrect,m_pTree,IDD_OBTC_COMBO);

本质上,当单击树节点时会创建 ComboBox,然后我们在 ::OnComboKillFocus() 方法(它基本上处理 ON_CBN_KILLFOCUS 消息)中将其销毁。

当从树的一个节点导航到另一个节点时,Windows 不会触发 WM_SETFOCUS 消息,除非其中一个节点是控件,就像在我们的例子中我们有组合框一样。因此,当我从 ComboBox 下拉列表中选择一个选项,然后左键单击树的不同节点时,会触发 WM_SETFOCUS。这是 Windows XP 中的行为。

但是,显然在 Windows 7 中,从 ComboBox 下拉列表中选择一个选项后,单击不同的节点不会触发 WM_SETFOCUS 消息。因此,尽管突出显示了新节点,但焦点仍然在 ComboBox 上!滚动鼠标滚轮或使用箭头键仍然会导致 ComboBox 的选项被更改。

这是 Windows 7(不同于 Windows Xp)的已知问题还是预期行为?

当我从一个节点(如 ComboBox)切换到另一个节点时,有没有办法让 Windows 7 触发 WM_SETFOCUS 消息?

要添加更多细节 -

我们为树控件处理 TVN_SELCHANGED 消息并为组合框控件处理 ON_CBN_KILLFOCUS 消息,以便我们可以在 ::OnComboKillFocus() 方法中执行一些逻辑,然后销毁组合框并将节点恢复为简单的树项。::OnSelChanged() 被击中,但 ::OnComboKillfocus() 未被击中

本质上,Win 7 通知节点选择的变化,但不通知焦点的变化(从组合框节点到树的另一个节点)。我还使用了 Spy++ 并确认 Win 7 在选择(单击)不同的树节点时不会触发 WM_SETFOCUS,初始焦点在组合框(这是同一树的另一个节点)上。Win XP 会触发该消息。

此外,以下解决方法有助于 Win 7 触发 WM_SETFOCUS

  1. 在 ::OnSelChanged() 中的树 (CTreeCtrl) 控件上执行 SetFocus()

  2. 处理 Combo box 的 ON_CBN_CLOSEUP 消息

  3. 或者处理Combo box的ON_CBN_SELENDOK消息

新发现——

我的应用程序是使用“启用视觉样式”指令构建的。显然,XP 风格的 ComCtl32.dll 不会导致此问题,但 Windows Vista 和 Windows 7 上的 ComCtl32.dll 会导致上述问题。

不启用视觉样式并在 Windows 7 上运行应用程序不会导致上述问题。

4

1 回答 1

1

这是预期的行为。或者更好:您正在使用未记录的行为。如果控件获得/失去焦点,则发送 WM_SETFOCUS 。树控件是一个单独的控件 - 它可能是使用不同的其他控件构建的,但这不是固定的 - 正如您在 Win7 中看到的那样,它已经发生了变化:树控件现在是一个单独的控件,树项目是直接绘制的,而不是由不同的其他控件构建。

请改用TVN_BEGINLABELEDIT通知。或者,如果您想要类似于 WM_SETFOCUS 的东西,请使用TVN_ITEMCHANGED通知并检查选择状态的变化。

于 2010-07-26T14:49:04.520 回答