views:

222

answers:

3

Hello. I'm trying to implement code-completion popup window in my project. The window is derived from Form. It contains two controls: custom list derived from UserControl (it shows completion possibilities with icons) and a VScrollBar.

When the popup appears, it doesn't steal focus from the editor (form's ShowWithoutActivation is overriden to return true) and the editor sends certain keystrokes to the popup so the user can interact with it using keyboard. So far it works like a charm.

The problem is, I want to allow the user to use mouse as well. But, when the user clicks into the popup window, its form activates and steals focus from the editor. I can react to this by giving the focus back to the editor, I have even set up a Timer to do this regularly, but apart from being a poor solution, the title bar of the editor always flickers when this happens (when the popup is clicked).

Is there any way to interact with the popup form (using mouse) that doesn't make the form activate?

The ShowWithoutActivation's documentation reads: "If your non-activated window needs to use UI controls, you should consider using the ToolStrip controls, such as ToolStripDropDown. These controls are windowless, and will not cause a window to activate when they are selected." This seems exactly like the thing I need, but I want to use a custom control and a scroll bar.

The same problem would be with a tooltip that shows these two arrows to switch method overloads (known from VS) - the whole form would use no controls at all (only render the text and the arrows), but when clicked, it should not activate. The problem could be summarized up to "How to create a form that would never activate, but allow the user to interact with certail controls inside?".

Thanks.

A: 

Just override the onFocus event...

public partial class myListBox:ListBox
{
    protected override void OnGotFocus(EventArgs e)
    {
    }
}
choudeshell
Thanks, but this doesn't work, I have tried it before. If I call "_editor.Focus()" as a reaction to GotFocus or Activated events, I cannot click the popup form anymore - it does not respond. And the flicker is still there. It works, however, if I call "_editor.Focus()" as a reaction to MouseDown events, but the editor's title bar still flickers when this happens.
Xerxes
A: 

The issue is that you're using a Form for this rather than building some custom control that doesn't run in its' own UI thread like a Form does. The flashing and highlighting is handled by windows whenever a Form activates/focuses. The only thing I cay think of is to make your Form borderless and create/draw/handle your own title bar that doesn't flash when focused.

Tom Frey
A: 

OK, I may have found a solution. The key seems to be WM_MOUSEACTIVATE message, which the popup form must intercept and respond with MA_NOACTIVATE. But there's a catch - the control derived from UserControl still grabs focus when clicked (the scrollbar luckily doesn't anymore). The problem seems to be in the UserControl.OnMouseDown method, which internally puts focus on the control. There are some ways to fix this:

  • derive the control from Control instead of UserControl
  • override the OnMouseDown method and not call base.OnMouseDown there
  • make the control's CanFocus property return false, but this seems not possible, because that means to make the control either not visible or not enabled, which is both undesirable

The last case when the popup form steals focus seems to be when its resizing (using mouse) ends. But it is safe here to call Owner.Activate() as a result to Activated event...

Xerxes