我试图创建一个继承自 ComboBox 的自定义组合框,但在使用 DropDownBox 样式时遇到了一些困难。我在 codeproject.com 上找到了一些自定义组合框的代码,我对其进行了一些改进,因为组合框有一些问题。
我现在只有 1 个问题。当我在 Items 集合中添加项目时,这些项目在运行时不存在,因为它们没有像普通组合框一样保存在 Form1.design.cs 文件 (cheetahComboBox1.Items.AddRange) 中。我错过了什么吗?我应该添加一个属性吗?
更新:抱歉,由于长度原因,我不得不截断源代码,我已经排除了一些不属于 Items 集合的非必要代码这是组合框的源代码:
namespace Cheetah.UI.Custom
{
public class CheetahComboBox : ListControl
{
private bool hovered = false;
private bool pressed = false;
private bool resize = false;
private Color _backColor = Color.Black;
private Color _foreColor = Color.Yellow;
private Color _bordercolor = Color.Gray;
private int _dropDownHeight = 200;
private int _dropDownWidth = 0;
private int _maxDropDownItems = 8;
private int _selectedIndex = -1;
private bool _isDroppedDown = false;
private bool _popupclosedcalled = false;
private ComboBoxStyle _dropDownStyle = ComboBoxStyle.DropDownList;
private Rectangle rectBtn = new Rectangle(0, 0, 1, 1);
private Rectangle rectContent = new Rectangle(0, 0, 1, 1);
private ToolStripControlHost _controlHost;
private ListBox _listBox;
private ToolStripDropDown _popupControl;
private TextBox _textBox;
public Color BorderColor
{
get { return _bordercolor; }
set { _bordercolor = value; Invalidate(true); }
}
public int DropDownHeight
{
get { return _dropDownHeight; }
set { _dropDownHeight = value; }
}
[Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design", "System.Drawing.Design.UITypeEditor, System.Drawing")]
public ListBox.ObjectCollection Items
{
get { return _listBox.Items; }
}
public override Color ForeColor
{
get
{
return base.ForeColor;
}
set
{
base.ForeColor = value;
_listBox.ForeColor = value;
_textBox.ForeColor = value;
Invalidate();
}
}
public ComboBoxStyle DropDownStyle
{
get { return _dropDownStyle; }
set
{
_dropDownStyle = value;
if (_dropDownStyle == ComboBoxStyle.DropDownList)
{
if (_listBox.SelectedIndex < 0)
{
_textBox.Text = "";
base.Text = "";
}
_textBox.Visible = false;
}
else
{
_textBox.Visible = true;
}
Invalidate(true);
}
}
public new Color BackColor
{
get { return _backColor; }
set
{
this._backColor = value;
_textBox.BackColor = value;
_listBox.BackColor = value;
Invalidate(true);
}
}
public bool IsDroppedDown
{
get { return _isDroppedDown; }
set
{
if (_isDroppedDown == true && value == false )
{
if (_popupControl.IsDropDown)
{
_popupControl.Close();
}
}
_isDroppedDown = value;
if (_isDroppedDown)
{
_controlHost.Control.Width = _dropDownWidth;
_listBox.Refresh();
if (_listBox.Items.Count > 0)
{
int h = 0;
int i = 0;
int maxItemHeight = 0;
int highestItemHeight = 0;
foreach(object item in _listBox.Items)
{
int itHeight = _listBox.GetItemHeight(i);
if (highestItemHeight < itHeight)
{
highestItemHeight = itHeight;
}
h = h + itHeight;
if (i <= (_maxDropDownItems - 1))
{
maxItemHeight = h;
}
i = i + 1;
}
if (maxItemHeight > _dropDownHeight)
_listBox.Height = _dropDownHeight + 3;
else
{
if (maxItemHeight > highestItemHeight )
_listBox.Height = maxItemHeight + 3;
else
_listBox.Height = highestItemHeight + 3;
}
}
else
{
_listBox.Height = 15;
}
_popupControl.Show(this, CalculateDropPosition(), ToolStripDropDownDirection.BelowRight);
}
Invalidate();
if (_isDroppedDown)
OnDroppedDown(this, EventArgs.Empty);
}
}
public CheetahComboBox()
{
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.ContainerControl, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.Selectable, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
SetStyle(ControlStyles.UserMouse, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.Selectable, true);
base.BackColor = Color.Transparent;
this.Height = 21;
this.Width = 95;
this.SuspendLayout();
_textBox = new TextBox();
_textBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
_textBox.Location = new System.Drawing.Point(3, 4);
_textBox.Size = new System.Drawing.Size(60, 13);
_textBox.TabIndex = 0;
_textBox.ForeColor = Color.Yellow;
_textBox.BackColor = Color.Black;
_textBox.WordWrap = false;
_textBox.Margin = new Padding(0);
_textBox.Padding = new Padding(0);
_textBox.TextAlign = HorizontalAlignment.Left;
this.Controls.Add(_textBox);
this.ResumeLayout(false);
AdjustControls();
_listBox = new ListBox();
_listBox.IntegralHeight = true;
_listBox.BorderStyle = BorderStyle.FixedSingle;
_listBox.SelectionMode = SelectionMode.One;
_listBox.BindingContext = new BindingContext();
_controlHost = new ToolStripControlHost(_listBox);
_controlHost.Padding = new Padding(0);
_controlHost.Margin = new Padding(0);
_controlHost.AutoSize = false;
_popupControl = new ToolStripDropDown();
_popupControl.Padding = new Padding(0);
_popupControl.Margin = new Padding(0);
_popupControl.AutoSize = true;
_popupControl.DropShadowEnabled = false;
_popupControl.Items.Add(_controlHost);
_dropDownWidth = this.Width;
_listBox.MeasureItem += new MeasureItemEventHandler(_listBox_MeasureItem);
_listBox.DrawItem += new DrawItemEventHandler(_listBox_DrawItem);
_listBox.MouseClick += new MouseEventHandler(_listBox_MouseClick);
_listBox.MouseMove += new MouseEventHandler(_listBox_MouseMove);
_popupControl.Closed += new ToolStripDropDownClosedEventHandler(_popupControl_Closed);
_textBox.Resize += new EventHandler(_textBox_Resize);
_textBox.TextChanged += new EventHandler(_textBox_TextChanged);
}
protected override void OnDisplayMemberChanged(EventArgs e)
{
_listBox.DisplayMember = this.DisplayMember;
this.SelectedIndex = this.SelectedIndex;
base.OnDisplayMemberChanged(e);
}
protected override void OnEnabledChanged(EventArgs e)
{
Invalidate(true);
base.OnEnabledChanged(e);
}
protected override void OnForeColorChanged(EventArgs e)
{
_textBox.ForeColor = this.ForeColor;
base.OnForeColorChanged(e);
}
protected override void OnFormatInfoChanged(EventArgs e)
{
_listBox.FormatInfo = this.FormatInfo;
base.OnFormatInfoChanged(e);
}
protected override void OnFormatStringChanged(EventArgs e)
{
_listBox.FormatString = this.FormatString;
base.OnFormatStringChanged(e);
}
protected override void OnFormattingEnabledChanged(EventArgs e)
{
_listBox.FormattingEnabled = this.FormattingEnabled;
base.OnFormattingEnabledChanged(e);
}
public override Font Font
{
get
{
return base.Font;
}
set
{
resize = true;
_textBox.Font = value;
base.Font = value;
Invalidate(true);
}
}
protected override void OnControlAdded(ControlEventArgs e)
{
e.Control.MouseDown += new MouseEventHandler(Control_MouseDown);
e.Control.MouseEnter += new EventHandler(Control_MouseEnter);
e.Control.MouseLeave += new EventHandler(Control_MouseLeave);
e.Control.GotFocus += new EventHandler(Control_GotFocus);
e.Control.LostFocus += new EventHandler(Control_LostFocus);
base.OnControlAdded(e);
}
protected override void OnMouseEnter(EventArgs e)
{
hovered = true;
this.Invalidate(true);
base.OnMouseEnter(e);
}
protected override void OnMouseLeave(EventArgs e)
{
if (!this.RectangleToScreen(this.ClientRectangle).Contains(MousePosition))
{
hovered = false;
Invalidate(true);
}
base.OnMouseLeave(e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
if (_popupclosedcalled)
{
_popupclosedcalled = false;
return;
}
_textBox.Focus();
if ((this.RectangleToScreen(rectBtn).Contains(MousePosition) || (DropDownStyle == ComboBoxStyle.DropDownList)))
{
pressed = true;
this.Invalidate(true);
if (this.IsDroppedDown)
{
this.IsDroppedDown = false;
}
this.IsDroppedDown = true;
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
pressed = false;
if (! this.RectangleToScreen(this.ClientRectangle).Contains(MousePosition) )
hovered = false;
else
hovered = true;
Invalidate();
}
protected override void OnMouseWheel(MouseEventArgs e)
{
if (e.Delta < 0)
this.SelectedIndex = this.SelectedIndex + 1;
else if (e.Delta > 0)
{
if (this.SelectedIndex > 0)
this.SelectedIndex = this.SelectedIndex - 1;
}
base.OnMouseWheel(e);
}
protected override void OnGotFocus(EventArgs e)
{
Invalidate(true);
base.OnGotFocus(e);
}
protected override void OnLostFocus(EventArgs e)
{
if (!this.ContainsFocus)
{
Invalidate();
}
base.OnLostFocus(e);
}
protected override void OnSelectedIndexChanged(EventArgs e)
{
if(SelectedIndexChanged!=null)
SelectedIndexChanged(this, e);
base.OnSelectedIndexChanged(e);
}
protected override void OnValueMemberChanged(EventArgs e)
{
_listBox.ValueMember = this.ValueMember;
this.SelectedIndex = this.SelectedIndex;
base.OnValueMemberChanged(e);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
//draw component background
e.Graphics.FillRectangle(new SolidBrush(BackColor), Rectangle.FromLTRB(0, 0, Width, Height));
//text
if (DropDownStyle == ComboBoxStyle.DropDownList)
{
StringFormat sf = new StringFormat(StringFormatFlags.NoWrap);
sf.Alignment = StringAlignment.Near;
Rectangle rectText = _textBox.Bounds;
rectText.Offset(-3, 0);
SolidBrush foreBrush = new SolidBrush(ForeColor);
if (Enabled)
{
e.Graphics.DrawString(_textBox.Text, this.Font, foreBrush, rectText.Location);
}
//else
//{
// ControlPaint.DrawStringDisabled(e.Graphics, _textBox.Text, Font, BackColor, rectText, sf);
//}
}
//content border
Rectangle rectCont = rectContent;
rectCont.X += 1;
rectCont.Y += 1;
rectCont.Width -= 3;
rectCont.Height -= 3;
e.Graphics.DrawRectangle(new Pen(_bordercolor), Rectangle.FromLTRB(1, 1, Width - 2, Height - 2));
// if (this.SelectedIndex >= 0 && DropDownStyle == ComboBoxStyle.DropDownList)
// e.Graphics.DrawString(Items[this.SelectedIndex].ToString(), this.Font, new SolidBrush(this.ForeColor), new PointF(3, 3));
// e.Graphics.DrawImage(FUpButtonPicture, Rectangle.FromLTRB(Width - 17, 4, Width - 3, Height - 4));
//button border
Rectangle rectButton = rectBtn;
rectButton.X += 1;
rectButton.Y += 1;
rectButton.Width -= 3;
rectButton.Height -= 3;
if (IsDroppedDown)
{
if (FDownButtonPicture != null)
e.Graphics.DrawImage(FDownButtonPicture, Rectangle.FromLTRB(Width - 17, 4, Width - 3, Height - 4));
else
DrawButtonAndGlimph(e);
}
else
if (FUpButtonPicture != null)
e.Graphics.DrawImage(FUpButtonPicture, Rectangle.FromLTRB(Width - 17, 4, Width - 3, Height - 4));
else
DrawButtonAndGlimph(e);
e.Graphics.ResetTransform();
}
public override int SelectedIndex
{
get { return _selectedIndex; }
set
{
if(_listBox != null)
{
if (_listBox.Items.Count == 0)
return;
if ((this.DataSource != null) && value == -1)
return;
if (value <= (_listBox.Items.Count - 1) && value >= -1)
{
_listBox.SelectedIndex = value;
_selectedIndex = value;
//SelectedItem = _listBox.SelectedItem;
_textBox.Text = _listBox.GetItemText(_listBox.SelectedItem);
base.Text = _textBox.Text;
OnSelectedIndexChanged(EventArgs.Empty);
}
else
{
_textBox.Text = "";
base.Text = "";
OnSelectedIndexChanged(EventArgs.Empty);
}
Invalidate();
}
}
}
public object SelectedItem
{
get { return _listBox.SelectedItem; }
set
{
_listBox.SelectedItem = value;
this.SelectedIndex = _listBox.SelectedIndex;
if (SelectedIndex >= 0)
_textBox.Text = _listBox.Items[SelectedIndex].ToString();
else
_textBox.Text = "";
Invalidate();
}
}
public new object SelectedValue
{
get { return base.SelectedValue; }
set
{
base.SelectedValue = value;
}
}
protected override void RefreshItem(int index)
{
//throw new Exception("The method or operation is not implemented.");
}
protected override void SetItemsCore(IList items)
{
}
void Control_LostFocus(object sender, EventArgs e)
{
OnLostFocus(e);
}
void Control_GotFocus(object sender, EventArgs e)
{
OnGotFocus(e);
}
void Control_MouseLeave(object sender, EventArgs e)
{
OnMouseLeave(e);
}
void Control_MouseEnter(object sender, EventArgs e)
{
OnMouseEnter(e);
}
void Control_MouseDown(object sender, MouseEventArgs e)
{
OnMouseDown(e);
}
void _listBox_MouseMove(object sender, MouseEventArgs e)
{
int i;
for (i = 0; i < (_listBox.Items.Count); i++)
{
if (_listBox.GetItemRectangle(i).Contains(_listBox.PointToClient(MousePosition)))
{
_listBox.SelectedIndex = i;
return;
}
}
}
void _listBox_MouseClick(object sender, MouseEventArgs e)
{
if (_listBox.Items.Count == 0)
return;
if (_listBox.SelectedItems.Count != 1)
return;
this.SelectedIndex = _listBox.SelectedIndex;
if (DropDownStyle == ComboBoxStyle.DropDownList)
{
this.Invalidate(true);
}
IsDroppedDown = false;
}
void _popupControl_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
_isDroppedDown = false;
_popupclosedcalled = true;
pressed = false;
if (!this.RectangleToScreen(this.ClientRectangle).Contains(MousePosition))
{
hovered = false;
}
Invalidate(true);
}
void _textBox_TextChanged(object sender, EventArgs e)
{
OnTextChanged(e);
}
private void AdjustControls()
{
this.SuspendLayout();
resize = true;
_textBox.Top = 4;
_textBox.Left = 5;
this.Height = _textBox.Top + _textBox.Height + _textBox.Top;
rectBtn = new Rectangle(this.ClientRectangle.Width - 18, this.ClientRectangle.Top, 18, _textBox.Height + 2 * _textBox.Top);
_textBox.Width = rectBtn.Left - 1 - _textBox.Left;
rectContent = new Rectangle(ClientRectangle.Left, ClientRectangle.Top,
ClientRectangle.Width, _textBox.Height + 2 * _textBox.Top);
this.ResumeLayout();
Invalidate(true);
}
public virtual void OnDroppedDown(object sender, EventArgs e)
{
if (DroppedDown != null)
{
DroppedDown(this, e);
}
}
}
}