Freigeben über


Writing custom popup controls

Orangy asks:

Hello, thanks for nice articles. Could you please write one about creating combobox-style controls using WinForms? I mean control with a popup element, which is hidden when user clicks (or tabs, alt-tabs, win-button, hit global shortcut which activates something)somewhere outside it, like combo drop-down, popup menu and such. I've spent a lot of time trying to mimic this behavior including various WinAPI calls, hooks, modal loops, etc, but can't get it work just right.

Orangy - I feel your pain. If you're thinking about doing this in 1.1, it's going to be a major pain. The closest sample I've got for you is Raymond Chen's FakeMenu sample, which you would have to port over to managed code.  

But the news gets better in Windows Forms 2.0, you can just host *any* control within a ToolStripDropDown using ToolStripControlHost. I've talked a bit about a ComboBox which shows a TreeView using this method. You can ALSO handle the Closing event for the DropDown and check the ToolStripDropDown close reason, or permanently keep the DropDown open by setting AutoClose = false.

Here's the snippit which adds a TreeView to a ToolStripDropDown. The dropDown is later shown at the right time in the full sample via dropDown.Show(...).

ToolStripControlHost treeViewHost;
ToolStripDropDown dropDown;

public MyTreeViewCombo() {

TreeView treeView = new TreeView();
treeView.BorderStyle = BorderStyle.None;
treeViewHost = new ToolStripControlHost(treeView);

// create drop down and add it

dropDown = new ToolStripDropDown();
dropDown.Items.Add(treeViewHost);

}

Comments

  • Anonymous
    September 18, 2005
    Thanks for the fast response! Unfortunately, I can't switch to 2.0 yet, so I'm stuck with p/invoke. FakeMenu example works, but it involves modal loop, which is (http://weblogs.asp.net/oldnewthing/archive/2005/02/18/376080.aspx) not good without disabling parent window.
    Things are getting much worse, when you have child controls, which are inside popup window.
    When I asked about combo-like controls, I thought you can explain "what happens there and how does combobox work".
    May it is more suitable for Raymond's blog :)
  • Anonymous
    September 19, 2005
    Ok, well here's all the grit I was hoping you wouldnt have to delve into:

    Yes the modal loop kindof stinks. The only alternative I have is a message hook.
    The main reason he's pushing a modal loop there is to change who the keyboard message goes to. You can achieve this through a WH_GETMESSAGE window hook instead. If you want to eat a message altogether, you can just swap it out to be WM_NULL.

    Because your window wont take window activation, you'll want to look for places where someone has clicked outside your window in addition to changes in activation. The best place is WM_NCLBUTTONDOWN and WM_LBUTTONDOWN. You can use the IsChild or GetAncestor with GA_ROOT to determine if the m.Hwnd is not a child of your window.

    If you happen to see a keyboard message - change the m.Hwnd to be your control. This is how the combobox gets "focus" to it's listbox - it fakes it by re-routing keystrokes to it.

    Finally, you may want to consider playing around with the WM_MOUSEACTIVATE message. You do not want your child window to take focus AT ALL or else the main window will turn light blue. You can say MA_NOACTIVATE, which will prevent the mouse click from setting focus to your window.

    Writing a windows hook in managed code
    http://support.microsoft.com/default.aspx?scid=kb;EN-US;318804

    About window hooks
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/abouthooks.asp

    More than you want to know about mouse input
    http://blogs.msdn.com/jfoscoding/archive/2005/07/28/444647.aspx

    More than you want to know about keyboard input
    http://blogs.msdn.com/jfoscoding/archive/2005/01/24/359334.aspx

  • Anonymous
    September 19, 2005
    Thanks a lot. I've got some new information :) Actually, I did hooks in managed code, I decompiled all WinForms with Reflector and traced it all down, so I new most of the stuff when I was reading your articles about kbrd and mouse input. I even wrote my own AlternativeForms from scratch (including VS designer and visual styles support), though not finished it. But I still had the feeling that I missed something. It seems to be "fake focus" by rerouting kbrd messages. I will check with this and get back to you with information and/or code. Could be nice sample for others.
  • Anonymous
    October 24, 2006
    I heard more than few times question on how to build combobox like dropdown custom control where clicking