Windows 7 not firing WM_SETFOCUS when switching nodes within a tree control
My application has a tree of type CTreeCtrl. One of the nodes of the tree is CComboBox control created as a child of this tree structure.
c_combo->Create( WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_HASSTRINGS | CBS_DROPDOWNLIST, myrect, m_pTree, IDD_OBTC_COMBO );
In essence, the ComboBox gets created when clicked on the tree node and we destroy it in the ::OnComboKillFocus() method (which basically handles the ON_CBN_KILLFOCUS message).
Windows does not fire the开发者_如何学Python WM_SETFOCUS message when navigating from one node of the tree to the other UNLESS when one of the node is a control like in our case we have the combobox. So when I select an option from the ComboBox dropdown list and then left click on a different node of the tree, a WM_SETFOCUS is fired. This is the behavior in Windows XP.
However, apparently in Windows 7, after selecting an option from the ComboBox drop down list, sigle clicking on a different node does not fire a WM_SETFOCUS message. So, the focus remains with the ComboBox though the new node is highlighted! And scrolling the mouse wheel or using the arrow keys would still result in the options of the ComboBox being changed.
Is this a known problem or an expected behavior of Windows 7 (different than Windows Xp)?
Is there a way I can get Windows 7 to fire the WM_SETFOCUS message when I switch from one node (like a ComboBox) to a different node?
To add more detail -
We handle TVN_SELCHANGED message for the tree control and handle the ON_CBN_KILLFOCUS message for the Combo box control so that we can do some logic in ::OnComboKillFocus() method and then destroy the Combo box and revert the node to a simple tree item. The ::OnSelChanged() gets hit but not the ::OnComboKillfocus()
In essence, Win 7 notifies a change in selection of the node but does not notify a change of focus (from a Combo box node to another node of the tree). I also used Spy++ and confirmed that Win 7 does not fire the WM_SETFOCUS upon selecting (single clicking) a different tree node with the initial focus on a Combo box (which is another node of the same tree). Win XP fires the message.
Also, the following work arounds help Win 7 to trigger the WM_SETFOCUS
Doing a SetFocus() on the tree (CTreeCtrl) control within the ::OnSelChanged()
Handling the ON_CBN_CLOSEUP message of the Combo box
Or handling the ON_CBN_SELENDOK message of the Combo box
New findings -
My application is built with the directive to 'Enable Visual Styles'. Apparently, the XP style ComCtl32.dll does not cause this problem but the ComCtl32.dll on Windows Vista and Windows 7 do cause the above problem.
Not enabling the visual styles and running the application on a Windows 7 does not cause the above problem.
This is expected behavior. Or better: you're using an undocumented behavior. WM_SETFOCUS is sent if a control gets/loses the focus. The tree control is one single control - it might be built using different other controls, but that's not fixed - and as you can see in Win7 that has changed: the tree control is now one single control and the tree items are drawn directly, not built from different other controls.
use the TVN_BEGINLABELEDIT notification instead. Or if you want something similar as WM_SETFOCUS, use the TVN_ITEMCHANGED notification and check for a change in the selection state.
精彩评论