Windows窗体ComboBox窃取焦点直到选中一个项目

时间:2018-03-28 19:38:15

标签: c# winforms combobox focus user-experience

使用标准Windows窗体ComboBox时遇到了一个特殊问题。 基本上,如果我单击ComboBox,然后再次单击它或点击“退出”退出下拉列表,焦点就会被盗。下面的动画显示了这是如何完成的:

ComboBox Stealing Focus

当焦点被盗时,未收到WM_SETFOCUS条消息,这会产生一些有趣的后果:

  • Alt + F4 命令不会关闭激活的窗口。
  • 点击TabControl上的标签页不会切换页面。
  • 无法使用 Tab Shift + Tab 切换聚焦控件。

可以想象,这会使应用程序处于不可接受的状态,因为用户可能不知道为什么,或者更重要的是,如何解决这个聚焦问题,并且由于没有响应而被认为存在错误。

经过一些测试后,我发现可以通过从违规ComboBox中选择一个项目来恢复焦点。

如果退出下拉列表而不选择项目,可以采取哪些措施来防止组合框窃取焦点?

我从Spy ++收集了一些日志,展示了第三个子弹(切换焦点)。 可以看出,按Tab键但Spy ++不监视WM_SETFOCUS

<000434> 0025574E R WM_NCCALCSIZE fuValidRect:0000 lpncsp:007CE9CC
<000435> 0025574E S WM_NCCALCSIZE fCalcValidRects:True lpncsp:007CE9CC
<000436> 0025574E R WM_NCCALCSIZE fuValidRect:0000 lpncsp:007CE9CC
<000437> 0025574A P WM_LBUTTONUP fwKeys:0000 xPos:237 yPos:26
<000438> 0025574E P WM_LBUTTONDOWN fwKeys:MK_LBUTTON xPos:236 yPos:-7
<000439> 0025574A P WM_LBUTTONUP fwKeys:0000 xPos:237 yPos:26
<000440> 0025574A P WM_KEYDOWN nVirtKey:VK_TAB cRepeat:1 ScanCode:0F fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<000441> 0025574A P WM_KEYUP nVirtKey:VK_TAB cRepeat:1 ScanCode:0F fExtended:0 fAltDown:0 fRepeat:1 fUp:1
<000442> 0025574A P WM_KEYDOWN nVirtKey:VK_TAB cRepeat:1 ScanCode:0F fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<000443> 0025574A P WM_KEYUP nVirtKey:VK_TAB cRepeat:1 ScanCode:0F fExtended:0 fAltDown:0 fRepeat:1 fUp:1
<000444> 0025574A P WM_KEYDOWN nVirtKey:VK_TAB cRepeat:1 ScanCode:0F fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<000445> 0025574A P WM_KEYUP nVirtKey:VK_TAB cRepeat:1 ScanCode:0F fExtended:0 fAltDown:0 fRepeat:1 fUp:1
<000446> 0025574A P WM_KEYDOWN nVirtKey:VK_TAB cRepeat:1 ScanCode:0F fExtended:0 fAltDown:0 fRepeat:0 fUp:0

但是,在我们选择下拉列表中的项目后,焦点可以更改,Spy ++会捕获WM_SETFOCUS个消息。

<000742> 002555E0 S WM_NCCALCSIZE fCalcValidRects:True lpncsp:007CCFA4
<000743> 002555E0 R WM_NCCALCSIZE fuValidRect:0000 lpncsp:007CCFA4
<000744> 002555E0 S WM_NCCALCSIZE fCalcValidRects:True lpncsp:007CCC94
<000745> 002555E0 R WM_NCCALCSIZE fuValidRect:0000 lpncsp:007CCC94
<000746> 0025574E R WM_KEYDOWN
<000747> 0025574A P WM_KEYUP nVirtKey:VK_DOWN cRepeat:1 ScanCode:50 fExtended:1 fAltDown:0 fRepeat:1 fUp:1
<000748> 0025574A P WM_KEYDOWN nVirtKey:VK_TAB cRepeat:1 ScanCode:0F fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<000749> 0025574A S WM_KILLFOCUS hwndGetFocus:00265748
<000750> 0025574A R WM_KILLFOCUS
<000751> 00265748 S WM_SETFOCUS hwndLoseFocus:0025574A
<000752> 00265748 R WM_SETFOCUS
<000753> 00265748 P WM_KEYUP nVirtKey:VK_TAB cRepeat:1 ScanCode:0F fExtended:0 fAltDown:0 fRepeat:1 fUp:1
<000754> 00265748 P WM_KEYDOWN nVirtKey:VK_TAB cRepeat:1 ScanCode:0F fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<000755> 00265748 S WM_KILLFOCUS hwndGetFocus:00255770
<000756> 00265748 R WM_KILLFOCUS

我最初认为窃取焦点的行为是ComboBox为下拉显示创建新窗口的副作用,而没有正确地重新激活父窗口。但是,单击任务栏中的应用程序图标将导致WM_ACTIVATE消息显示在Spy ++中,而不会再次检索焦点。

1 个答案:

答案 0 :(得分:1)

您可以在此处查看此主题:

Cannot tab out of databound Winforms dropdown list

数据绑定可能会在幕后的数据验证中引发异常。