To reproduce this bug you need to create custom ToolStripItem
, using ToolStripControlHost
.
In my case, I made ToolStripDateTimePicker
control (as seen on many good tutorials). The control however behaves slightly different than a regular DateTimePicker
.
Regular one produces default Windows bell sound when ESC
is pressed while it's active. The ToolStrip
hosted control reacts for ESC
pressed in a more sensible manner. The control becomes inactive, no beep.
Here's the bug part: when focusing another control with a click - regular DateTimePicker
triggers Leave
event. As expected. ToolStrip
hosted control DOES NOT trigger any event!
Yes, I've tried KeyDown
event - it's not sent when ESC
key is pressed, but sent when any other key is pressed.
I believe it's a bug in .NET itself.
The consequence of this is broken focus behavior of the form containing the ToolStrip
control. The form cannot be focused again after entering ToolStrip
hosted control.
But it's a workaround for this: you can focus an other form (or even maybe another control), and then the target form - it works for me.
However I would like to have it done automatically - the moment user exits the hosted control. The problem is I don't have an event for this. Any ideas?
What's weird, Leave
event is eventually triggered when the hosted control is disposed - it's clearly a bug, because the event is totally useless there.
Here: sample application illustrating the problem
I've replaced it with sample workaround, to see the problem comment out OnGotFocus()
and OnLostFocus()
overrides.
It worked nice (and could not reproduce the bug) until I've changed FlowLayoutPanel
TabIndex
to 0, so the DateTimePicker
is not active when the application starts.
Here's what I learned:
The problem was not exactly with
ToolStripControlHost
class, but with theDateTimePicker
control itself, and to be more specific - with it's interaction withFlowLayoutPanel
s and possibly other similar controls. And I'm not sure if it's a bug or expected behavior, but seems more like a bug.Here's how it works: If there is another control which can be obviously activated (like
TextBox
), leaving theDatePickerControl
means activating the other control. But if the other control is empty container, or container with no controls which can be activated -Leave
event is not triggered despite theDateTimePicker
control is not active anymore.Why would you want to have a container with no active controls active itself? I use
FlowLayoutPanel
to produce a read-only, non-editable report. It is not editable, but I want it scrollable, and I don't wantDateTimePicker
control to steal focus fromFlowLayoutPanel
- so in this caseFlowLayoutPanel
is an active control.Of course it doesn't work this way. There are more workarounds needed for such behavior to be achieved, like receiving mouse events from containing form, but correct
Focus
/Leave
behavior forToolStripDatePickerControl
is a good start.So without further ado, my perfect
ToolsStripDateTimePicker
control, with focus glitch fixed:DesignerToolStripControlHost
class:ToolStripDateTimePicker
class:Workarounds explained:
OnGotFocus()
andOnLostFocus()
event handlers are overridden to trigger my new controlEnter
andLeave
events. Note that they are triggered almost correctly.Enter
andLeave
events. We don't want those, so I check the time between events, if it's smaller than 10ms I just ignore later event.DesignerToolStripControlHost
is used to fix broken designer behavior. If you usedToolStripControlHost
directly, you would get an exception trying to show the control's designer view, because designer tries to instantiate this class with no argument, and this class does not have a constructor with no argument. So my new class does.ToolStripDateTimePicker
break which you can tell by seeing DTP disappeared, just close designer view and open it again. It will work fine until you compile or debug your application again.Glitch fix was tested with 1ms time window and worked fine. So I chose 10ms to ensure it works on slower or more loaded machines, but it's still short enough to capture any event from user interaction.