Advanced: Bug with Owner Drawn Context Menus and ComboBoxes

A

Andrew Baker

I posted this a while back, but thought I would give this another go:

Have a look at the code below. It's a really simple example where I
have added two controls to a form, a textbox and a combo box. Both add
owner drawn context menus to the controls, but the the custom drawn
context menu item does not draw on the combobox.

I have tried EVERYTHING (deriving from MenuItem and even tried calling
TrackPopupMenuEx directly), but it just won't work! My theory is that
it isn't working because of bug in the way that comboboxes custom drawn
their list items. I am guessing that the combobox isn't delegating the
draw event down to the menuitem, but there must be a work around eh?!


thanks
andrew


using System;
using System.Drawing;
using System.Diagnostics;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;


namespace ComboContextBug
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private ComboTest comboBox1;
private TextBoxTest textBox1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Containe­r components = null;


public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();


//
// TODO: Add any constructor code after 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 Windows Form 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.comboBox1 = new ComboContextBug.ComboTest();
this.textBox1 = new ComboContextBug.TextBoxTest();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// comboBox1
//
this.comboBox1.Location = new System.Drawing.Point(180, 32);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(121, 21);
this.comboBox1.TabIndex = 0;
this.comboBox1.Text = "comboBox1";
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(180, 98);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(121, 20);
this.textBox1.TabIndex = 1;
this.textBox1.Text = "textBox1";
//
// label1
//
this.label1.Location = new System.Drawing.Point(8, 20);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(168, 52);
this.label1.TabIndex = 2;
this.label1.Text = "Right click this combo and you will see that
the OwnerDrawn item does NOT appear!" +
"";
//
// label2
//
this.label2.Location = new System.Drawing.Point(8, 86);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(168, 52);
this.label2.TabIndex = 3;
this.label2.Text = "Right click this textbox and you will see that
the OwnerDrawn item DOES appear!";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(336, 157);
this.Controls.Add(this.label2)­;
this.Controls.Add(this.label1)­;
this.Controls.Add(this.textBox­1);
this.Controls.Add(this.comboBo­x1);
this.Name = "Form1";
this.Text = "Combo Context Menu Bug";
this.ResumeLayout(false);


}
#endregion


/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
}


public class ComboTest: ComboBox
{
public ComboTest()
{
base.ContextMenu = new ContextMenu();


MenuItem mnuOwnerDraw = new MenuItem();
mnuOwnerDraw.Text = "This text WILL NOT appear on a ComboBox!";
mnuOwnerDraw.OwnerDraw = true;
mnuOwnerDraw.DrawItem +=new
DrawItemEventHandler(mnuOwnerD­raw_DrawItem);
mnuOwnerDraw.MeasureItem +=new
MeasureItemEventHandler(mnuOwn­erDraw_MeasureItem);
base.ContextMenu.MenuItems.Add­(0, mnuOwnerDraw);


MenuItem mnuNormalDraw = new MenuItem();
mnuNormalDraw.Text = "This text WILL appear!";
mnuNormalDraw.OwnerDraw = false;
base.ContextMenu.MenuItems.Add­(0, mnuNormalDraw);
}


private void mnuOwnerDraw_DrawItem(object sender, DrawItemEventArgs
e)
{
MenuItem menu = sender as MenuItem;
e.Graphics.DrawString( menu.Text, this.Font,
SystemBrushes.ControlText, e.Bounds.X + 15, e.Bounds.Y );
}


private void mnuOwnerDraw_MeasureItem(objec­t sender,
MeasureItemEventArgs e)
{
MenuItem menu = sender as MenuItem;
string text = menu.Text;
e.ItemWidth = (int)(e.Graphics.MeasureString­(text,
this.Font).Width) + 3;
e.ItemHeight = (int)(e.Graphics.MeasureString­(text,
this.Font).Height) + 2;
}
}


public class TextBoxTest: TextBox
{
public TextBoxTest()
{
base.ContextMenu = new ContextMenu();


MenuItem mnuOwnerDraw = new MenuItem();
mnuOwnerDraw.Text = "This text WILL appear on a Textbox!";
mnuOwnerDraw.OwnerDraw = true;
mnuOwnerDraw.DrawItem +=new
DrawItemEventHandler(mnuOwnerD­raw_DrawItem);
mnuOwnerDraw.MeasureItem +=new
MeasureItemEventHandler(mnuOwn­erDraw_MeasureItem);
base.ContextMenu.MenuItems.Add­(0, mnuOwnerDraw);


MenuItem mnuNormalDraw = new MenuItem();
mnuNormalDraw.Text = "This text WILL appear!";
mnuNormalDraw.OwnerDraw = false;
base.ContextMenu.MenuItems.Add­(0, mnuNormalDraw);
}


private void mnuOwnerDraw_DrawItem(object sender, DrawItemEventArgs
e)
{
MenuItem menu = sender as MenuItem;
e.Graphics.DrawString( menu.Text, this.Font,
SystemBrushes.ControlText, e.Bounds.X + 15, e.Bounds.Y );
}


private void mnuOwnerDraw_MeasureItem(objec­t sender,
MeasureItemEventArgs e)
{
MenuItem menu = sender as MenuItem;
string text = menu.Text;
e.ItemWidth = (int)(e.Graphics.MeasureString­(text,
this.Font).Width) + 3;
e.ItemHeight = (int)(e.Graphics.MeasureString­(text,
this.Font).Height) + 2;
}
}
 

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