我的应用程序有一个 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
在 ::OnSelChanged() 中的树 (CTreeCtrl) 控件上执行 SetFocus()
处理 Combo box 的 ON_CBN_CLOSEUP 消息
或者处理Combo box的ON_CBN_SELENDOK消息
新发现——
我的应用程序是使用“启用视觉样式”指令构建的。显然,XP 风格的 ComCtl32.dll 不会导致此问题,但 Windows Vista 和 Windows 7 上的 ComCtl32.dll 会导致上述问题。
不启用视觉样式并在 Windows 7 上运行应用程序不会导致上述问题。