Click here to Skip to main content
Email Password   helpLost your password?

Sample application using a custom popup control:

Custom pop-up control

Another application using a custom tooltip...

Custom tooltip

... and a more complex popup that can be resized:

Resizable pop-up

Tracking popup opening below the specified part of a control:

simplepopup.gif

Cascade of popup controls:

Cascade of pop-up controls

Introduction

Popup windows are everywhere. Each tooltip is a popup window; each combobox has its popup list; many advertisements are also shown in popup windows.

How To Create a Popup Control in .NET?

At first, we might choose the Form class as a base class for our popup control. Unfortunately, it is a bad choice because when we show our popup form, the parent form loses its focus. A popup window should not cause that. Luckily, there is a class that does not cause loss of focus. We can use it as a base class for our popup control. It is the ToolStripDropDown class.

How To Use the ToolStripDropDown Class?

This would be the simplest way, without deriving from that class:

ToolStripDropDown popup = new ToolStripDropDown();
popup.Margin = Padding.Empty;
popup.Padding = Padding.Empty;
ToolStripControlHost host = new ToolStripControlHost(content);
host.Margin = Padding.Empty;
host.Padding = Padding.Empty;
popup.Items.Add(host);
popup.Show(parentForm, location);

In this case, content is a control we want to show in a popup window. Of course, we have to remember to later dispose the popup window and its contents.

Popup Class

I wrote a Popup class that derives from ToolStripDropDown and simplifies the creating and managing of popup windows. The class calculates by itself where it should "pop" on the screen. It also disposes itself immediately after disposing the content control. To show a popup with a button, for example, we could write:

new Popup(new Button()).Show(someControl);

Here, someControl would be a control below which we want to show our popup.

Popup Resizing

To enable resizing for your popup, you must set the Resizable property to true and add the following code into your content control class:

protected override void WndProc(ref Message m)
{
    if ((Parent as Popup).ProcessResizing(ref m)) return;
    base.WndProc(ref m);
}

You also have to set the ResizeRedraw property of the content control to true.

Important!

To specify the minimum and maximum size of the content control, please use the following properties:

ComboBox Class

The System.Windows.Forms.ComboBox class behaves in a strange way when it is on a popup control. It closes the popup control when the user clicks on a part of the combobox's dropdown that sticks out of a popup. So, I have created a PopupControl.ComboBox class that behaves properly.

PopupComboBox Class

This is a base class for comboboxes that can have a custom dropdown attached.

Animation Support

Animation is enabled by default. To change it, set AnimationDuration, HidingAnimation and ShowingAnimation properties.

Popup Members

Properties

Constructor

Methods

TODO

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
Questionuse as intellisense?
MSeirer
13:34 8 Mar '10  
heya lukasz,

thx for this nice control! Smile

i am thinking about using this as a basis for a intellisense-like control
i want to type in a TextBox and on the TextChanged event i want to show the
popup and let it filter its ListBox.

i expected the property "FocusOnOpen" to help me achieve this. but the focus
after the popup is shown is not in the owner-form. a

((TextBox)sender).Focus();

doesnt help.

do you have an idea how to solve this?

best regards
GeneralRightToLeft forms problem
AbdelRahman Doghish
1:01 2 Feb '10  
Dear,

When I try to add a form that is has the property (RightToLeft = RightToLeft.Yes); the popup throws the following exception (Error creating window handle.).
Note that the problem is solved when I changed the value of this property only and make it (RightToLeft = RightToLeft.No)

Code:

frmDetail.RightToLeft = RightToLeft.Yes;
Popup popupScreen;
popupScreen = new Popup(frmDetail);

//The last line throws the exception

Is there any solution for this problem because I want to add a RightToLeft form to the popup?
Thank you very much in advance for your cooperation.

Best Regards,
AbdelRahman Doghish
GeneralTransparency
dbalboa
6:44 3 Dec '09  
Its a great resource! But i have 1 question. There is any posibility to accept a transparent user control and make the popup transparent?

This is how i see the image if i set the transparency: http://img267.imageshack.us/i/24902031.png/[^]

This is how i see the image withouth the transparency property set to true (the problem is that that shadow should be semi-transparent, but the backcolor is set to white): http://img442.imageshack.us/i/55940912.png/[^]
QuestionMono compatibility, again
Gerhard Olsson
14:49 19 Jul '09  
I try to use Simple popup with Mono.
More info here:
CheckBox ComboBox Extending the ComboBox Class and Its Items[^]

The version used in CheckBoxComboBox does not use the P/Invoke AnimateWindow
However, the code still not works in Mono.
Same traceback appears when testing Mono with PopupTest.exe

Any hints what can be done to get the code work with Mono?

G:\Users\go\dev\SimplePopup>mono --debug MoreComplexPopup.exe

Unhandled Exception: System.NullReferenceException: Object reference not set to
an instance of an object
at PopupControl.Popup.OnSizeChanged (System.EventArgs e) [0x00000]
at System.Windows.Forms.Control.UpdateBounds (Int32 x, Int32 y, Int32 width, I
nt32 height, Int32 clientWidth, Int32 clientHeight) [0x000f2] in C:\cygwin\tmp\m
onobuild\build\BUILD\mono-2.4\mcs\class\Managed.Windows.Forms\System.Windows.For
ms\Control.cs:5191
at System.Windows.Forms.Control.UpdateBounds (Int32 x, Int32 y, Int32 width, I
nt32 height) [0x00023] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.4\mcs\class
\Managed.Windows.Forms\System.Windows.Forms\Control.cs:5152
at System.Windows.Forms.Control.SetBoundsCoreInternal (Int32 x, Int32 y, Int32
width, Int32 height, BoundsSpecified specified) [0x0012c] in C:\cygwin\tmp\mono
build\build\BUILD\mono-2.4\mcs\class\Managed.Windows.Forms\System.Windows.Forms\
Control.cs:5021
at System.Windows.Forms.Control.SetBoundsCore (Int32 x, Int32 y, Int32 width,
Int32 height, BoundsSpecified specified) [0x00000] in C:\cygwin\tmp\monobuild\bu
ild\BUILD\mono-2.4\mcs\class\Managed.Windows.Forms\System.Windows.Forms\Control.
cs:4967
at System.Windows.Forms.ToolStrip.SetBoundsCore (Int32 x, Int32 y, Int32 width
, Int32 height, BoundsSpecified specified) [0x00000] in C:\cygwin\tmp\monobuild\
build\BUILD\mono-2.4\mcs\class\Managed.Windows.Forms\System.Windows.Forms\ToolSt
rip.cs:1161
at System.Windows.Forms.ToolStripDropDown.SetBoundsCore (Int32 x, Int32 y, Int
32 width, Int32 height, BoundsSpecified specified) [0x00000] in C:\cygwin\tmp\mo
nobuild\build\BUILD\mono-2.4\mcs\class\Managed.Windows.Forms\System.Windows.Form
s\ToolStripDropDown.cs:688
at System.Windows.Forms.Control.SetBoundsInternal (Int32 x, Int32 y, Int32 wid
th, Int32 height, BoundsSpecified specified) [0x000a8] in C:\cygwin\tmp\monobuil
d\build\BUILD\mono-2.4\mcs\class\Managed.Windows.Forms\System.Windows.Forms\Cont
rol.cs:4422
at System.Windows.Forms.Control.SetBounds (Int32 x, Int32 y, Int32 width, Int3
2 height, BoundsSpecified specified) [0x00044] in C:\cygwin\tmp\monobuild\build\
BUILD\mono-2.4\mcs\class\Managed.Windows.Forms\System.Windows.Forms\Control.cs:4
407
at System.Windows.Forms.Control.set_Size (Size value) [0x00000] in C:\cygwin\t
mp\monobuild\build\BUILD\mono-2.4\mcs\class\Managed.Windows.Forms\System.Windows
.Forms\Control.cs:3277
at System.Windows.Forms.ToolStripDropDown.OnLayout (System.Windows.Forms.Layou
tEventArgs e) [0x0016d] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.4\mcs\clas
s\Managed.Windows.Forms\System.Windows.Forms\ToolStripDropDown.cs:614
at System.Windows.Forms.Control.PerformLayout (System.Windows.Forms.Control af
fectedControl, System.String affectedProperty) [0x00066] in C:\cygwin\tmp\monobu
ild\build\BUILD\mono-2.4\mcs\class\Managed.Windows.Forms\System.Windows.Forms\Co
ntrol.cs:4084
at System.Windows.Forms.Control.PerformLayout () [0x00000] in C:\cygwin\tmp\mo
nobuild\build\BUILD\mono-2.4\mcs\class\Managed.Windows.Forms\System.Windows.Form
s\Control.cs:4061
at System.Windows.Forms.Control.ResumeLayout (Boolean performLayout) [0x0007c]
in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.4\mcs\class\Managed.Windows.Forms
\System.Windows.Forms\Control.cs:4274
at System.Windows.Forms.Control.ResumeLayout () [0x00000] in C:\cygwin\tmp\mon
obuild\build\BUILD\mono-2.4\mcs\class\Managed.Windows.Forms\System.Windows.Forms
\Control.cs:4255
at System.Windows.Forms.ToolStrip..ctor (System.Windows.Forms.ToolStripItem[]
items) [0x00128] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.4\mcs\class\Manag
ed.Windows.Forms\System.Windows.Forms\ToolStrip.cs:122
at System.Windows.Forms.ToolStrip..ctor () [0x00000] in C:\cygwin\tmp\monobuil
d\build\BUILD\mono-2.4\mcs\build\common\Consts.cs:1
at System.Windows.Forms.ToolStripDropDown..ctor () [0x00000] in C:\cygwin\tmp\
monobuild\build\BUILD\mono-2.4\mcs\build\common\Consts.cs:1
at PopupControl.Popup..ctor (System.Windows.Forms.Control content) [0x00000]
at (wrapper remoting-invoke-with-check) PopupControl.Popup:.ctor (System.Windo
ws.Forms.Control)
at MoreComplexPopup.MainForm..ctor () [0x00000]
at (wrapper remoting-invoke-with-check) MoreComplexPopup.MainForm:.ctor ()
at MoreComplexPopup.MainForm.Main () [0x00000]

G:\Users\go\dev\SimplePopup>
AnswerRe: Mono compatibility, again
Lukasz Swiatkowski
17:49 19 Jul '09  
It looks like Mono’s Windows Forms still doesn’t work exactly like .NET’s Windows Forms.

Anyway… in the Popup.cs file, in method OnSizeChanged add "if (content != null)" checking… this fixes the NullReferenceException.
But the popups still don’t look very good because of bug in Mono, look here: http://go-mono.com/forums/#nabble-td22184714[^]

Łukasz

~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

AnswerQuick fix
Lukasz Swiatkowski
20:33 19 Jul '09  
You may add this code as well to the Popup class, it fixes almost all bugs related to Mono.
protected override void OnLayout(LayoutEventArgs e)
{
Size suggestedSize = GetPreferredSize(Size.Empty);
if (AutoSize && suggestedSize != Size)
{
Size = suggestedSize;
}
SetDisplayedItems();
OnLayoutCompleted(EventArgs.Empty);
Invalidate();
}
Łukasz

~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralRe: Quick fix
Gerhard Olsson
9:40 20 Jul '09  
Thanks, great!
Any problem having this fix in .NET too or should the following be used?

public static bool IsRunningOnMono()
{
return Type.GetType("Mono.Runtime") != null;
}
protected override void OnLayout(LayoutEventArgs e)
{
if (IsRunningOnMono())
{
Size suggestedSize = GetPreferredSize(Size.Empty);
if (AutoSize && suggestedSize != Size)
{
Size = suggestedSize;
}
SetDisplayedItems();
OnLayoutCompleted(EventArgs.Empty);
Invalidate();
}
else
{
base.OnLayout(e);
}
}

I have not been able to fix my intended usage yet: CheckBoxComboBox uses an older version of Simple Popup, the test application itself is not working with Mono the plugin that uses CheckBoxComboBox has other issues too. Upgraded Simple Popup works slightly better.

/Gerhard
GeneralRe: Quick fix
Lukasz Swiatkowski
1:26 22 Jul '09  
Checking for Mono would be good Smile
private static bool? _isRunningOnMono;
public static bool IsRunningOnMono()
{
if (!_isRunningOnMono.HasValue)
_isRunningOnMono = Type.GetType("Mono.Runtime") != null;
return _isRunningOnMono.Value;
}


~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralGreat !!!
iccb1013
17:02 15 Jul '09  
I LOVE YOU SO MUCH!
GeneralRe: Great !!!
Lukasz Swiatkowski
10:20 17 Jul '09  
Hehe, thanks ;>

~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralToolStripDropDown Not Showing
winheart
22:47 28 Jun '09  
Hi,

I had a GroupBox which contain so many text boxes and labels alligned like a data entry form. i added one button and add this code in the button click.

            ToolStripDropDown tspopUp = new ToolStripDropDown();
tspopUp.Margin = Padding.Empty;
tspopUp.Padding = Padding.Empty;
ToolStripControlHost host = new ToolStripControlHost(CategoryPanel);
host.Margin = Padding.Empty;
host.Padding = Padding.Empty;
tspopUp.Items.Add(host);
tspopUp.Show(GroupBox1,txtcategory.Location);

in a plain form if we add this, it will work nicely but if lot of control inside a form it will not popup. it's very bad.

How people told this code as excellent, i don't know.

Raj
GeneralRe: ToolStripDropDown Not Showing
Lukasz Swiatkowski
8:24 29 Jun '09  
Hi,

Well, you wrote to little I could help you. I've testes a form with 4 groupboxes, each of them contained 40 labels, 40 textboxes and 40 buttons, and all worked fine. Which version of .NET do you use? Have you installed latest service pack for the .NET you’re using?

Anyway… some time ago I’ve read an article which said that there is a bug in Windows Forms which occurs when there are very many controls on a Form. Maybe you had that “pleasure” to notice that bug. I don’t know.

Regards,
Łukasz

~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralRe: ToolStripDropDown Not Showing
winheart
2:38 26 Oct '09  
hai,

i am using the latest version to .net frame work. in my form i have lot of text boxes and label. i am added panel and trying to host that control in the toolstip host control. but it was not poping -up. After that i made it in a user control, then it start showing.

After this i implement this same user control in a DataGridView for populating data on clicking on the button in each row according to the key value in each row. But it disappointed me very much.Only once the data will get populate. next time onwards data is populating to the grid. but it's showing the frist populated data.

Can u check this dynamic databinding to a toolstripdropdown while clicking on each row of datagridview.


Raj
GeneralUse as a ToolTip
Bob Carboni
8:16 18 Jun '09  
This is a very nice control, and was easy to setup and start using. I have a couple of questions about using this control as a tooltip, and I wonder if you have already done a similar project.

1. I was considering using this as a tooltip for a TreeView. I want to show a tooltip when hovering over each node. However, since a TreeNode is not a Control, and does not have a MouseLeave event, I tried to display the popup when the mouse is moved over the tree itself. This works to display the popup, but after the popup is visible the MouseMove event of the TreeView is no longer called. This makes it difficult to determine when to hide or redisplay the popup. Do you have any suggestions how to use this as a tooltip over a tree?

2. As a tooltip, it would be nice to have delay properties for display and redisplay like the ToolTip class. Have you given any thought to this?
GeneralRe: Use as a ToolTip
Lukasz Swiatkowski
10:50 24 Jun '09  
Thank you, I am glad you like it.

1. Did you set FocusOnOpen property to false so the popup does not steal the focus? See the grid-example, I believe you want to achieve something similar.

2. Yes, time permitting I shall create a base class for tooltip.

Łukasz

~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralRe: Use as a ToolTip
Bob Carboni
14:47 24 Jun '09  
After some testing, I was able to successfully create a custom tooltip over a treeview by using a Timer with the mouse events. The code looks something like this:

Class Variables
        Popup toolTip;
CustomToolTip customToolTip;
Timer toolTipTimer = new Timer();
TreeNode toolTipNode = null;

Initialize Code
            toolTip = new Popup(customToolTip = new CustomToolTip());
toolTip.AutoClose = false;
toolTip.FocusOnOpen = false;
toolTip.DropShadowEnabled = true;
toolTip.ShowingAnimation = toolTip.HidingAnimation = PopupAnimations.Blend;
toolTip.AutoSize = true;
toolTip.Resizable = true;

toolTipTimer.Interval = 1500;
toolTipTimer.Tick += new EventHandler(toolTipTimer_Tick);

// Do not show the built in tooltips for the tree nodes
tv.ShowNodeToolTips = false;


Events
        int nStartX = 0;    // Starting X position of the custom tooltip
int nStartY = 0; // Starting Y position of the custom tooltip
int nLastX = 0; // Last known mouse X position
int nLastY = 0; // Last known mouse Y position
void toolTipTimer_Tick(object sender, EventArgs e)
{
if (toolTipNode != null)
{
toolTipTimer.Stop();
customToolTip.TipText = toolTipNode.Text.Trim();
toolTip.Show(this, nLastX + 10, nLastY + 50);
}
}

private void tv_MouseMove(object sender, MouseEventArgs e)
{
TreeNode node = tv.GetNodeAt(e.X, e.Y);

if (node == null)
{
toolTipTimer.Stop();
if (toolTip.Visible)
{
toolTip.Close();
}
}
else {
if (!toolTipTimer.Enabled)
{
toolTipNode = node;
toolTipTimer.Start();
nStartX = nLastX;
nStartY = nLastY;
}
else if ((e.X < nStartX-5) || (e.X > nStartX+5) || (e.Y < nStartY-3) || (e.Y > nStartY+3))
{
toolTipTimer.Stop();
if (toolTip.Visible)
toolTip.Close();
}
}

nLastX = e.X;
nLastY = e.Y;

}

private void tv_MouseLeave(object sender, System.EventArgs e)
{
toolTipTimer.Stop();
toolTip.Close();
}




This works nice to keep the tooltip displayed until the mouse is moved again. I might try a second timer to close the tooltip after a delay.
GeneralRe: Use as a ToolTip
Lukasz Swiatkowski
8:07 29 Jun '09  
I’ve created a code which uses NodeMouseHover event instead of MouseMove. You may take a look at it:
public partial class Form1 : Form
{
public Form1()
{
Control.CheckForIllegalCrossThreadCalls = true;
InitializeComponent();
_popup = new Popup(_popupPanel = new Panel()
{
AutoSize = true,
AutoSizeMode = AutoSizeMode.GrowAndShrink,
BackColor = SystemColors.WindowFrame,
Padding = new Padding(0),
})
{
AutoSize = true,
FocusOnOpen = false,
};
_popupLabel = new Label()
{
AutoSize = true,
BackColor = SystemColors.Info,
BorderStyle = BorderStyle.FixedSingle,
Dock = DockStyle.Fill,
ForeColor = SystemColors.InfoText,
TextAlign = ContentAlignment.MiddleCenter,
};
_popupPanel.Controls.Add(_popupLabel);
_popup.Opened += (s, e) =>
{
object o = new object();
System.Threading.Timer timer = null;
Action close = () =>
{
if (_popupLabel.RectangleToScreen(_popupLabel.ClientRectangle).Contains(Cursor.Position)) return;
if (timer != null)
{
lock (o)
{
if (timer != null)
{
timer.Dispose();
timer = null;
_popup.Close();
}
}
}
};
_popupLabel.MouseLeave += (s2, e2) => close();
timer = new System.Threading.Timer((_) => Invoke(close), null, 2500, -1);
};
}

Popup _popup;
Panel _popupPanel;
Label _popupLabel;

private void treeView1_NodeMouseHover(object sender, TreeNodeMouseHoverEventArgs e)
{
_popupLabel.Text = e.Node.ToolTipText;
_popup.Size = _popupLabel.Size;
_popup.Show(treeView1.RectangleToScreen(e.Node.Bounds).Location);
// or
//_popup.Show(treeView1, e.Node.Bounds);
}
}
It’s only a draft, but finally I’ll create a base class for tooltips using this code.

Łukasz

~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralMatters about using with MonthCalendar
zmfeng(China)
22:10 8 Jun '09  
I'm using this nice popup to pop a MonthCalendar inside a MaskedTextBox so that the user can enter or pick dates easily, the code is simple,but the popup's size is not enough to show the whole calendar(the proper should be (322,185) but it's now (178,155)).
Can somebody help me?
Generalcommercial distribution question
Silent Winter
4:15 5 May '09  
I have read the license agreement, and I am still wondering about some things.

As a contributor, the agreement states that all recipients of the software would be able to re-sell the software. Is this a misinterpretation? I would not be able to use this if all software that has this popup must be able to be reproduced and redistributed by buyers.

I do not fully understand the copyright requirements for software distributed without code.

Thank you for your help.
GeneralRe: commercial distribution question
Lukasz Swiatkowski
8:29 5 May '09  
Paragraph 4 (commercial distribution) states that you may include the Popup in a commercial product (application), but as a creator of the popup I disallow embedding and/or re-selling this control in libraries/packages/component packs/etc.
So re-selling the Popup maybe is not prohibited by the CPL license, but by myself.

You can use of course the binaries in your software (or compile-in provided source code).

Regards,
Łukasz

~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralRe: commercial distribution question
Silent Winter
11:12 5 May '09  
Thank you for your quick response.

I was not looking to sell your popup as a featured item, but simply to use it in a distributed application. I had already made a popup control, and I was looking to add resizing capabilities when I found your control.

For use, it sounds like I will have to keep your control in its separate project, and derive off of it elsewhere for the specific functionality I need to add.

As far as copyrights, there was nothing in the license about including your copyright in the distributed application. This is what I will continue to assume unless informed otherwise.

Again, thank you for your response, and your work in making an excellent control.
GeneralRe: commercial distribution question
Lukasz Swiatkowski
11:49 5 May '09  
You have to link your project to my dll file or use my original projects; if you include my code in your project or make changes to the code, you have to release the code under CPL license as well. So you're right, you should derive from it in another project to add specific functionality. You don't have to include copyright in the distributed application; besides, it's in the PopupControl.dll file's properties.

Here there is some "human-readable" information about CPL license: http://en.wikipedia.org/wiki/Common_Public_License[^]

I'm glad you like my control.

Regards,
Łukasz

~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralMono compatibility
KaSA1
6:55 31 Mar '09  
Hello!

Nice control, thanks!
But, i develop app that must be crossplatform via Mono (2.4)
Mono Migration Analyzer (http://mono-project.com/MoMA[^]) says that only ONE ussue is present - invoke call of AnimateWindow.
It is very pity for me.

How do you think, is it possible to rewrite that function functionality on pure .NET code?

Thanks!
GeneralRe: Mono compatibility
Lukasz Swiatkowski
7:06 31 Mar '09  
Well, I think it is possible, but it wouldn't be very easy, because it would require to 'mess' with custom regions. I've tried it once but finally I've replaced it with AnimateWindow API.

Regards,
Łukasz

~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralSwietna robota Lukasz :)
PL01
1:01 12 Mar '09  
I find it very useful Smile

/PL01


Last Updated 16 Jan 2009 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010