Create control with drop-down similar to ComboBox

B

Bob Dankert

Hello,

I have created a control where I am trying to mimic the behavior of the
drop-down component of a ComboBox. Currently, when I display the drop-down
portion I am changing the size of the control (specifically, the height) and
custom painting what I need to paint in the lower drop-down area through the
OnPaint event.

My problem using this method is that by changing the height I am unable to
view the drop-down if my control is near the bottom of Panel/GroupBox (or if
I embed it in a ToolStrip, it causes the ToolStrip to get very large). How
can I make it so that the drop-down portion of my control does not require
me to change the size of the control, making it so the drop-down "floats"
over everything as it does with a ComboBox?

Thanks for any help offered,

Bob Dankert
 
L

Linda Liu [MSFT]

Hi Bob,

Thank you for posting.
I have two questions on your issue.
1. Since your custom control imitates the behavior of the drop-down
component of a ComboBox, why don't you use the ComboBox directly?

2. What are you going to paint in the lower drop-down area of your custom
control?

To make the drop-down portion "float", I think you may have a try replacing
the lower drop-down area of your custom control with a winform whose
FormBorderStyle property is set to None. When you want to display the
drop-down portion, you may show the form in a location you would like.

I am looking forward to your reply. Thanks.


Sincerely,
Linda Liu
Microsoft Online Community Support

====================================================
When responding to posts,please "Reply to Group" via
your newsreader so that others may learn and benefit
from your issue.
====================================================
 
B

Bob Powell [MVP]

Hi Linda,
This solution is a poor one because the form would take the focus and
inactivate the main window form. The functionality of the dropdown would be
difficult to manage too.

The correct way to do this is to derive a class from NativeWindow and create
a popup window, similar to a tooltip window, that can be shown using the
SW_SHOWNOACTIVATE setting and the ShowWindow function via interop. A class
created in this way would mimic the behaviour of the base Win32 controls and
it would be easier to create the desired internal functionality such as item
selection and so-on.

As proof of it's nastiness I created a quick and dirty combo-box in the code
below my signature. It's horrible in every way.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

--------------------------------------------------------------------------
public class FauxCombo : System.Windows.Forms.UserControl

{

private System.Windows.Forms.TextBox textBox1;

private System.Windows.Forms.Button button1;

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

public FauxCombo()

{

// This call is required by the Windows.Forms Form Designer.

InitializeComponent();

// TODO: Add any initialization after the InitializeComponent call

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Component Designer generated code

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

this.textBox1 = new System.Windows.Forms.TextBox();

this.button1 = new System.Windows.Forms.Button();

this.SuspendLayout();

//

// textBox1

//

this.textBox1.Location = new System.Drawing.Point(0, 0);

this.textBox1.Name = "textBox1";

this.textBox1.TabIndex = 0;

this.textBox1.Text = "textBox1";

//

// button1

//

this.button1.Location = new System.Drawing.Point(104, 0);

this.button1.Name = "button1";

this.button1.Size = new System.Drawing.Size(23, 23);

this.button1.TabIndex = 1;

this.button1.Text = "V";

this.button1.Click += new System.EventHandler(this.button1_Click);

//

// FauxCombo

//

this.Controls.Add(this.button1);

this.Controls.Add(this.textBox1);

this.Name = "FauxCombo";

this.Size = new System.Drawing.Size(128, 24);

this.ResumeLayout(false);

}

#endregion

Form dropdown;

private void button1_Click(object sender, System.EventArgs e)

{

if(dropdown==null)

{

dropdown=new Form();

dropdown.FormBorderStyle=FormBorderStyle.None;

dropdown.BackColor=Color.White;

dropdown.ShowInTaskbar=false;

dropdown.StartPosition=FormStartPosition.Manual;

dropdown.Location=this.PointToScreen(new Point(0,23));

dropdown.Size=new Size(80,200);

dropdown.MouseDown+=new MouseEventHandler(dropdown_MouseDown);

dropdown.Closed+=new EventHandler(dropdown_Closed);

dropdown.Show();

dropdown.Capture=true;

}

else

{

dropdown.Hide();

dropdown.MouseDown-=new MouseEventHandler(dropdown_MouseDown);

dropdown.Closed-=new EventHandler(dropdown_Closed);

dropdown.Dispose();

dropdown=null;

}

}

private void dropdown_MouseDown(object sender, MouseEventArgs e)

{

Form f=(Form)sender;

if(!f.ClientRectangle.Contains(new Point(e.X,e.Y)))

f.Close();

}

private void dropdown_Closed(object sender, EventArgs e)

{

dropdown.MouseDown-=new MouseEventHandler(dropdown_MouseDown);

dropdown.Closed-=new EventHandler(dropdown_Closed);

dropdown.Dispose();

dropdown=null;

}

}
 
B

Bob Dankert

Thanks for the response Bob and Linda,

Linda, unfortunately I can not use the combobox to do as I want as I need to
change what is drawn in the combobox dropdown based on the position of the
mouse and numerous other things (buttons, etc) and need to have events such
as mouseover, mousedown, and click - all of which are not registered by the
combobox in the dropdown portion. I agree with Bob that using a form to
display the drop-down portion is very clumsy and not a very good solution at
all (unless someone can provide me an example of a "good" implementation,
but I do not think this is possible).

Does anyone by any chance have an example of using the NativeWindow
implementation that Bob Powell described?

Thanks,

Bob Dankert
 
B

Bob Powell [MVP]

It's an article that needs doing for WFT&T but it's fairly involved and not
something I can bash out in a few minutes.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
 
B

Bob Dankert

Thanks for the update Bob - I think I have found a way to get around my
problem (more or less I am changing the control size on dropdown, making
sure it is in front of everything else, and making sure the control is in a
parent large enough to hold the entire dropdown). Certainly not the most
versatile solution, but it will work for now. I would definately be
interested to read an article on this if you ever get the chance to write
one. I'll keep an eye on your site.

Thanks again,

Bob Dankert
 
B

Bob Dankert

Thanks a lot Mick, this looks like it demonstrates the exact functionality I
am looking for.

Bob Dankert

"Mick Doherty"
 
M

Mick Doherty

Bob Dankert said:
Thanks a lot Mick, this looks like it demonstrates the exact functionality
I am looking for.

Bob Dankert

You're welcome.

I hadn't tried it out before posting the link, but since Steve's been around
a while, I assumed it would work without problem.

I have now taken a quick look at the example and can see that it needs a
little tweaking. The popupform is being closed instead of hidden, and this
causes problems with 'cannot access a disposed object'. However, simply
changing Close() to Hide() causes the popupwindow to steal the focus, which
is an undesirable effect, and so you will have a little work to do.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top