C# Windows窗体组合框将在选中某个项目之前窃取焦点

C# Windows窗体组合框将在选中某个项目之前窃取焦点,c#,winforms,combobox,focus,user-experience,C#,Winforms,Combobox,Focus,User Experience,我在使用标准Windows窗体组合框时遇到了一个特殊问题。 基本上,如果我单击组合框,然后再次单击它,或者单击escape退出下拉列表,则焦点被窃取。下面的动画显示了如何执行此操作: 当焦点被盗时,WM_SETFOCUS消息不会被接收,这有一些有趣的后果: Alt+F4命令不会关闭激活的窗口 单击TabControl上的选项卡不会切换页面 无法使用Tab或Shift+Tab切换聚焦控件 可以想象,这会使应用程序处于一种不可接受的状态,因为用户可能不知道为什么,或者更重要的是,不知道如何解决

我在使用标准Windows窗体组合框时遇到了一个特殊问题。 基本上,如果我单击
组合框
,然后再次单击它,或者单击escape退出下拉列表,则焦点被窃取。下面的动画显示了如何执行此操作:

当焦点被盗时,
WM_SETFOCUS
消息不会被接收,这有一些有趣的后果:

  • Alt+F4命令不会关闭激活的窗口
  • 单击
    TabControl
    上的选项卡不会切换页面
  • 无法使用Tab或Shift+Tab切换聚焦控件
可以想象,这会使应用程序处于一种不可接受的状态,因为用户可能不知道为什么,或者更重要的是,不知道如何解决这个焦点问题,并且由于没有响应而认为存在错误

经过一些测试,我发现可以通过从有问题的
组合框
中选择一个项目来恢复焦点

当下拉列表退出而未选择项目时,如何防止组合框窃取焦点?
我从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_ACTIVATE
消息,而不会再次检索焦点。

您可能希望在此处查看此主题:


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

为什么不在下拉菜单关闭后立即关注表单?这似乎是个好主意,但在
DropDownClosed
事件上调用
This.focus()。Spy++仍然显示在按下tab/shift+tab时,
WM_SETFOCUS
未被发送。你确定我的想法行不通吗?为什么不创建一个txtbox,隐藏它,并在下拉关闭时将焦点设置为它?我知道这不是最好的练习,但值得一试,对吧?对于踢腿,我甚至在关闭下拉列表后1秒将其包装在计时器中触发,以确保它不会被覆盖。仍然没有运气,但正如OP所指出的,选择一个项目仍然会修复焦点锁定;)唉,但愿我能复制/粘贴代码,而不是让我的眼睛被动画gif攻击。我的水晶球说你需要注意WM_激活,这是ToolStrip的一个已知问题。完美!就是这样!
<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