1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2006 Novell, Inc.
23 // Jordi Mas i Hernandez, jordi@ximian.com
24 // Mike Kestner <mkestner@novell.com>
25 // Daniel Nauck (dna(at)mono-project(dot)de)
28 using System.Collections;
29 using System.ComponentModel;
30 using System.ComponentModel.Design;
31 using System.ComponentModel.Design.Serialization;
33 using System.Globalization;
34 using System.Reflection;
35 using System.Runtime.InteropServices;
37 namespace System.Windows.Forms
39 [DefaultProperty("Items")]
40 [DefaultEvent("SelectedIndexChanged")]
41 [Designer ("System.Windows.Forms.Design.ComboBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
43 [DefaultBindingProperty ("Text")]
44 [ClassInterface (ClassInterfaceType.AutoDispatch)]
47 public class ComboBox : ListControl
49 private DrawMode draw_mode = DrawMode.Normal;
50 private ComboBoxStyle dropdown_style;
51 private int dropdown_width = -1;
52 private int selected_index = -1;
53 private ObjectCollection items;
54 private bool suspend_ctrlupdate;
55 private int maxdrop_items = 8;
56 private bool integral_height = true;
58 private int max_length;
59 private ComboListBox listbox_ctrl;
60 private ComboTextBox textbox_ctrl;
61 private bool process_textchanged_event = true;
62 private bool item_height_specified;
63 private int item_height;
64 private int requested_height = -1;
65 private Hashtable item_heights;
66 private bool show_dropdown_button;
67 private ButtonState button_state = ButtonState.Normal;
68 private bool dropped_down;
69 private Rectangle text_area;
70 private Rectangle button_area;
71 private Rectangle listbox_area;
72 private const int button_width = 16;
74 private AutoCompleteStringCollection auto_complete_custom_source = null;
75 private AutoCompleteMode auto_complete_mode = AutoCompleteMode.None;
76 private AutoCompleteSource auto_complete_source = AutoCompleteSource.None;
77 private int drop_down_height;
78 private FlatStyle flat_style;
82 public class ChildAccessibleObject : AccessibleObject {
84 public ChildAccessibleObject (ComboBox owner, IntPtr handle)
89 public override string Name {
98 items = new ObjectCollection (this);
99 DropDownStyle = ComboBoxStyle.DropDown;
100 item_height = FontHeight + 2;
101 BackColor = ThemeEngine.Current.ColorWindow;
102 border_style = BorderStyle.None;
105 drop_down_height = 106;
106 flat_style = FlatStyle.Standard;
110 MouseDown += new MouseEventHandler (OnMouseDownCB);
111 MouseUp += new MouseEventHandler (OnMouseUpCB);
112 MouseMove += new MouseEventHandler (OnMouseMoveCB);
113 MouseWheel += new MouseEventHandler (OnMouseWheelCB);
114 KeyDown +=new KeyEventHandler(OnKeyDownCB);
120 [EditorBrowsable (EditorBrowsableState.Never)]
121 public new event EventHandler BackgroundImageChanged {
122 add { base.BackgroundImageChanged += value; }
123 remove { base.BackgroundImageChanged -= value; }
129 [EditorBrowsable (EditorBrowsableState.Never)]
130 public new event EventHandler BackgroundImageLayoutChanged
132 add { base.BackgroundImageLayoutChanged += value; }
133 remove { base.BackgroundImageLayoutChanged -= value; }
137 [EditorBrowsable (EditorBrowsableState.Never)]
138 public new event EventHandler DoubleClick
140 add { base.DoubleClick += value; }
141 remove { base.DoubleClick -= value; }
145 static object DrawItemEvent = new object ();
146 static object DropDownEvent = new object ();
147 static object DropDownStyleChangedEvent = new object ();
148 static object MeasureItemEvent = new object ();
149 static object SelectedIndexChangedEvent = new object ();
150 static object SelectionChangeCommittedEvent = new object ();
152 static object DropDownClosedEvent = new object ();
153 static object TextUpdateEvent = new object ();
156 public event DrawItemEventHandler DrawItem {
157 add { Events.AddHandler (DrawItemEvent, value); }
158 remove { Events.RemoveHandler (DrawItemEvent, value); }
161 public event EventHandler DropDown {
162 add { Events.AddHandler (DropDownEvent, value); }
163 remove { Events.RemoveHandler (DropDownEvent, value); }
166 public event EventHandler DropDownClosed
168 add { Events.AddHandler (DropDownClosedEvent, value); }
169 remove { Events.RemoveHandler (DropDownClosedEvent, value); }
173 public event EventHandler DropDownStyleChanged {
174 add { Events.AddHandler (DropDownStyleChangedEvent, value); }
175 remove { Events.RemoveHandler (DropDownStyleChangedEvent, value); }
178 public event MeasureItemEventHandler MeasureItem {
179 add { Events.AddHandler (MeasureItemEvent, value); }
180 remove { Events.RemoveHandler (MeasureItemEvent, value); }
184 [EditorBrowsable (EditorBrowsableState.Never)]
185 public new event EventHandler PaddingChanged
187 add { base.PaddingChanged += value; }
188 remove { base.PaddingChanged -= value; }
193 [EditorBrowsable (EditorBrowsableState.Never)]
194 public new event PaintEventHandler Paint {
195 add { base.Paint += value; }
196 remove { base.Paint -= value; }
199 public event EventHandler SelectedIndexChanged {
200 add { Events.AddHandler (SelectedIndexChangedEvent, value); }
201 remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
204 public event EventHandler SelectionChangeCommitted {
205 add { Events.AddHandler (SelectionChangeCommittedEvent, value); }
206 remove { Events.RemoveHandler (SelectionChangeCommittedEvent, value); }
209 public event EventHandler TextUpdate
211 add { Events.AddHandler (TextUpdateEvent, value); }
212 remove { Events.RemoveHandler (TextUpdateEvent, value); }
218 #region Public Properties
220 [MonoTODO("AutoCompletion algorithm is currently not implemented.")]
221 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
223 [EditorBrowsable (EditorBrowsableState.Always)]
225 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design,
226 "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
227 public AutoCompleteStringCollection AutoCompleteCustomSource {
229 if(auto_complete_custom_source == null) {
230 auto_complete_custom_source = new AutoCompleteStringCollection ();
231 auto_complete_custom_source.CollectionChanged += new CollectionChangeEventHandler (OnAutoCompleteCustomSourceChanged);
233 return auto_complete_custom_source;
236 if(auto_complete_custom_source == value)
239 if(auto_complete_custom_source != null) //remove eventhandler from old collection
240 auto_complete_custom_source.CollectionChanged -= new CollectionChangeEventHandler (OnAutoCompleteCustomSourceChanged);
242 auto_complete_custom_source = value;
244 if(auto_complete_custom_source != null)
245 auto_complete_custom_source.CollectionChanged += new CollectionChangeEventHandler (OnAutoCompleteCustomSourceChanged);
249 [MonoTODO("AutoCompletion algorithm is currently not implemented.")]
251 [EditorBrowsable (EditorBrowsableState.Always)]
252 [DefaultValue (AutoCompleteMode.None)]
253 public AutoCompleteMode AutoCompleteMode {
254 get { return auto_complete_mode; }
256 if(auto_complete_mode == value)
259 if((value < AutoCompleteMode.None) || (value > AutoCompleteMode.SuggestAppend))
260 throw new InvalidEnumArgumentException (Locale.GetText ("Enum argument value '{0}' is not valid for AutoCompleteMode", value));
262 auto_complete_mode = value;
266 [MonoTODO("AutoCompletion algorithm is currently not implemented.")]
268 [EditorBrowsable (EditorBrowsableState.Always)]
269 [DefaultValue (AutoCompleteSource.None)]
270 public AutoCompleteSource AutoCompleteSource {
271 get { return auto_complete_source; }
273 if(auto_complete_source == value)
276 if(!Enum.IsDefined (typeof (AutoCompleteSource), value))
277 throw new InvalidEnumArgumentException (Locale.GetText ("Enum argument value '{0}' is not valid for AutoCompleteSource", value));
279 auto_complete_source = value;
283 public override Color BackColor {
284 get { return base.BackColor; }
286 if (base.BackColor == value)
288 base.BackColor = value;
294 [EditorBrowsable (EditorBrowsableState.Never)]
295 public override Image BackgroundImage {
296 get { return base.BackgroundImage; }
298 if (base.BackgroundImage == value)
300 base.BackgroundImage = value;
307 [EditorBrowsable (EditorBrowsableState.Never)]
308 public override ImageLayout BackgroundImageLayout {
309 get { return base.BackgroundImageLayout; }
310 set { base.BackgroundImageLayout = value; }
314 protected override CreateParams CreateParams {
315 get { return base.CreateParams;}
319 [DefaultValue ((string)null)]
320 [AttributeProvider (typeof (IListSource))]
321 [RefreshProperties (RefreshProperties.Repaint)]
322 public new object DataSource {
323 get { return base.DataSource; }
324 set { base.DataSource = value; }
328 protected override Size DefaultSize {
329 get { return new Size (121, 21); }
332 [RefreshProperties(RefreshProperties.Repaint)]
333 [DefaultValue (DrawMode.Normal)]
334 public DrawMode DrawMode {
335 get { return draw_mode; }
337 if (!Enum.IsDefined (typeof (DrawMode), value))
338 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
340 if (draw_mode == value)
343 if (draw_mode == DrawMode.OwnerDrawVariable)
346 if (draw_mode == DrawMode.OwnerDrawVariable)
347 item_heights = new Hashtable ();
355 [EditorBrowsable (EditorBrowsableState.Always)]
356 public int DropDownHeight {
358 return drop_down_height;
362 throw new ArgumentOutOfRangeException ("DropDownHeight", "DropDownHeight must be greater than 0.");
364 drop_down_height = value;
365 IntegralHeight = false;
370 [DefaultValue (ComboBoxStyle.DropDown)]
371 [RefreshProperties(RefreshProperties.Repaint)]
372 public ComboBoxStyle DropDownStyle {
373 get { return dropdown_style; }
375 if (!Enum.IsDefined (typeof (ComboBoxStyle), value))
376 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ComboBoxStyle", value));
378 if (dropdown_style == value)
383 if (dropdown_style == ComboBoxStyle.Simple) {
384 if (listbox_ctrl != null) {
385 Controls.RemoveImplicit (listbox_ctrl);
386 listbox_ctrl.Dispose ();
391 dropdown_style = value;
393 if (dropdown_style == ComboBoxStyle.DropDownList && textbox_ctrl != null) {
394 Controls.RemoveImplicit (textbox_ctrl);
395 textbox_ctrl.Dispose ();
399 if (dropdown_style == ComboBoxStyle.Simple) {
400 show_dropdown_button = false;
402 CreateComboListBox ();
404 if (IsHandleCreated) {
405 Controls.AddImplicit (listbox_ctrl);
406 listbox_ctrl.Visible = true;
409 show_dropdown_button = true;
410 button_state = ButtonState.Normal;
413 if (dropdown_style != ComboBoxStyle.DropDownList && textbox_ctrl == null) {
414 textbox_ctrl = new ComboTextBox (this);
415 object selected_item = SelectedItem;
416 if (selected_item != null)
417 textbox_ctrl.Text = GetItemText (selected_item);
418 textbox_ctrl.BorderStyle = BorderStyle.None;
419 textbox_ctrl.TextChanged += new EventHandler (OnTextChangedEdit);
420 textbox_ctrl.Click += new EventHandler (OnTextBoxClick);
422 if (IsHandleCreated == true)
423 Controls.AddImplicit (textbox_ctrl);
427 OnDropDownStyleChanged (EventArgs.Empty);
430 UpdateComboBoxBounds ();
435 public int DropDownWidth {
437 if (dropdown_width == -1)
440 return dropdown_width;
443 if (dropdown_width == value)
448 throw new ArgumentOutOfRangeException ("DropDownWidth",
449 "The DropDownWidth value is less than one.");
451 throw new ArgumentException ("The DropDownWidth value is less than one.");
454 dropdown_width = value;
459 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
460 public bool DroppedDown {
462 if (dropdown_style == ComboBoxStyle.Simple)
468 if (dropdown_style == ComboBoxStyle.Simple || dropped_down == value)
474 listbox_ctrl.Hide ();
479 [DefaultValue (FlatStyle.Standard)]
481 public FlatStyle FlatStyle {
482 get { return flat_style; }
484 if (!Enum.IsDefined (typeof (FlatStyle), value))
485 throw new InvalidEnumArgumentException ("FlatStyle", (int) value, typeof (FlatStyle));
494 public override bool Focused {
495 get { return base.Focused; }
498 public override Color ForeColor {
499 get { return base.ForeColor; }
501 if (base.ForeColor == value)
503 base.ForeColor = value;
508 [DefaultValue (true)]
510 public bool IntegralHeight {
511 get { return integral_height; }
513 if (integral_height == value)
515 integral_height = value;
516 UpdateComboBoxBounds ();
522 public int ItemHeight {
524 if (item_height == -1) {
525 SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font);
526 item_height = (int) sz.Height;
533 throw new ArgumentOutOfRangeException ("ItemHeight",
534 "The item height value is less than one.");
536 throw new ArgumentException ("The item height value is less than one.");
539 item_height_specified = true;
542 UpdateComboBoxBounds ();
548 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
550 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
552 [MergableProperty (false)]
554 public ComboBox.ObjectCollection Items {
555 get { return items; }
560 public int MaxDropDownItems {
561 get { return maxdrop_items; }
563 if (maxdrop_items == value)
565 maxdrop_items = value;
570 public override Size MaximumSize {
571 get { return base.MaximumSize; }
573 base.MaximumSize = new Size (value.Width, 0);
580 public int MaxLength {
581 get { return max_length; }
583 if (max_length == value)
588 if (dropdown_style != ComboBoxStyle.DropDownList) {
592 textbox_ctrl.MaxLength = value;
598 public override Size MinimumSize {
599 get { return base.MinimumSize; }
601 base.MinimumSize = new Size (value.Width, 0);
605 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
606 [EditorBrowsable (EditorBrowsableState.Never)]
608 public new Padding Padding {
609 get { return base.Padding; }
610 set { base.Padding = value; }
614 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
616 public int PreferredHeight {
618 return ItemHeight + 5;
623 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
624 public override int SelectedIndex {
625 get { return selected_index; }
627 if (selected_index == value)
630 if (value <= -2 || value >= Items.Count)
631 throw new ArgumentOutOfRangeException ("Index of out range");
632 selected_index = value;
634 if (dropdown_style != ComboBoxStyle.DropDownList) {
638 SetControlText (GetItemText (Items [value]));
641 if (DropDownStyle == ComboBoxStyle.DropDownList)
644 if (listbox_ctrl != null)
645 listbox_ctrl.HighlightedIndex = value;
647 OnSelectedValueChanged (new EventArgs ());
648 OnSelectedIndexChanged (new EventArgs ());
649 OnSelectedItemChanged (new EventArgs ());
654 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
656 public object SelectedItem {
657 get { return selected_index == -1 ? null : Items [selected_index]; }
659 object item = selected_index == -1 ? null : Items [selected_index];
662 SelectedIndex = Items.IndexOf (value);
667 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
668 public string SelectedText {
670 if (dropdown_style == ComboBoxStyle.DropDownList)
673 return textbox_ctrl.SelectedText;
676 if (dropdown_style == ComboBoxStyle.DropDownList)
678 textbox_ctrl.SelectedText = value;
683 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
684 public int SelectionLength {
686 if (dropdown_style == ComboBoxStyle.DropDownList)
689 int result = textbox_ctrl.SelectionLength;
690 return result == -1 ? 0 : result;
693 if (dropdown_style == ComboBoxStyle.DropDownList)
695 if (textbox_ctrl.SelectionLength == value)
697 textbox_ctrl.SelectionLength = value;
702 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
703 public int SelectionStart {
705 if (dropdown_style == ComboBoxStyle.DropDownList)
707 return textbox_ctrl.SelectionStart;
710 if (dropdown_style == ComboBoxStyle.DropDownList)
712 if (textbox_ctrl.SelectionStart == value)
714 textbox_ctrl.SelectionStart = value;
718 [DefaultValue (false)]
720 get { return sorted; }
735 public override string Text {
737 if (dropdown_style != ComboBoxStyle.DropDownList) {
738 if (textbox_ctrl != null) {
739 return textbox_ctrl.Text;
743 if (SelectedItem != null)
744 return GetItemText (SelectedItem);
750 if (SelectedIndex == -1) {
751 if (dropdown_style != ComboBoxStyle.DropDownList)
759 // do nothing if value exactly matches text of selected item
760 if (SelectedItem != null && string.Compare (value, GetItemText (SelectedItem), false, CultureInfo.CurrentCulture) == 0)
763 // find exact match using case-sensitive comparison, and if does
764 // not result in any match then use case-insensitive comparison
765 int index = FindStringExact (value, -1, false);
767 index = FindStringExact (value, -1, true);
770 SelectedIndex = index;
774 if (dropdown_style != ComboBoxStyle.DropDownList)
775 textbox_ctrl.Text = GetItemText (value);
779 #endregion Public Properties
781 #region Public Methods
783 [Obsolete ("This method has been deprecated")]
785 protected virtual void AddItemsCore (object[] value)
790 public void BeginUpdate ()
792 suspend_ctrlupdate = true;
796 protected override AccessibleObject CreateAccessibilityInstance ()
798 return base.CreateAccessibilityInstance ();
801 protected override void CreateHandle ()
803 base.CreateHandle ();
807 protected override void Dispose (bool disposing)
810 if (listbox_ctrl != null) {
811 listbox_ctrl.Dispose ();
812 Controls.RemoveImplicit (listbox_ctrl);
816 if (textbox_ctrl != null) {
817 Controls.RemoveImplicit (textbox_ctrl);
818 textbox_ctrl.Dispose ();
823 base.Dispose (disposing);
826 public void EndUpdate ()
828 suspend_ctrlupdate = false;
833 public int FindString (string s)
835 return FindString (s, -1);
838 public int FindString (string s, int startIndex)
840 if (s == null || Items.Count == 0)
844 if (startIndex < -1 || startIndex >= Items.Count)
846 if (startIndex < -1 || startIndex >= Items.Count - 1)
848 throw new ArgumentOutOfRangeException ("startIndex");
852 if (i == (Items.Count - 1))
857 if (string.Compare (s, 0, GetItemText (Items [i]), 0, s.Length, true) == 0)
859 if (i == (Items.Count - 1))
861 } while (i != startIndex);
866 public int FindStringExact (string s)
868 return FindStringExact (s, -1);
871 public int FindStringExact (string s, int startIndex)
873 return FindStringExact (s, startIndex, true);
876 private int FindStringExact (string s, int startIndex, bool ignoreCase)
878 if (s == null || Items.Count == 0)
882 if (startIndex < -1 || startIndex >= Items.Count)
884 if (startIndex < -1 || startIndex >= Items.Count - 1)
886 throw new ArgumentOutOfRangeException ("startIndex");
890 if (i == (Items.Count - 1))
895 if (string.Compare (s, GetItemText (Items [i]), ignoreCase, CultureInfo.CurrentCulture) == 0)
897 if (i == (Items.Count - 1))
899 } while (i != startIndex);
904 public int GetItemHeight (int index)
906 if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated) {
908 if (index < 0 || index >= Items.Count )
909 throw new ArgumentOutOfRangeException ("The item height value is less than zero");
911 object item = Items [index];
912 if (item_heights.Contains (item))
913 return (int) item_heights [item];
915 MeasureItemEventArgs args = new MeasureItemEventArgs (DeviceContext, index, ItemHeight);
916 OnMeasureItem (args);
917 item_heights [item] = args.ItemHeight;
918 return args.ItemHeight;
924 protected override bool IsInputKey (Keys keyData)
940 protected override void OnBackColorChanged (EventArgs e)
942 base.OnBackColorChanged (e);
945 protected override void OnDataSourceChanged (EventArgs e)
947 base.OnDataSourceChanged (e);
950 if (DataSource == null || DataManager == null) {
954 SelectedIndex = DataManager.Position;
958 protected override void OnDisplayMemberChanged (EventArgs e)
960 base.OnDisplayMemberChanged (e);
962 if (DataManager == null || !IsHandleCreated)
966 SelectedIndex = DataManager.Position;
969 protected virtual void OnDrawItem (DrawItemEventArgs e)
972 case DrawMode.OwnerDrawFixed:
973 case DrawMode.OwnerDrawVariable:
974 DrawItemEventHandler eh = (DrawItemEventHandler)(Events [DrawItemEvent]);
979 ThemeEngine.Current.DrawComboBoxItem (this, e);
984 protected virtual void OnDropDown (EventArgs e)
986 EventHandler eh = (EventHandler)(Events [DropDownEvent]);
992 protected virtual void OnDropDownClosed (EventArgs e)
994 EventHandler eh = (EventHandler) Events [DropDownClosedEvent];
1000 protected virtual void OnDropDownStyleChanged (EventArgs e)
1002 EventHandler eh = (EventHandler)(Events [DropDownStyleChangedEvent]);
1007 protected override void OnFontChanged (EventArgs e)
1009 base.OnFontChanged (e);
1011 if (textbox_ctrl != null)
1012 textbox_ctrl.Font = Font;
1014 if (!item_height_specified) {
1015 SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font);
1016 item_height = (int) sz.Height;
1020 UpdateComboBoxBounds ();
1025 protected override void OnForeColorChanged (EventArgs e)
1027 base.OnForeColorChanged (e);
1030 [EditorBrowsable(EditorBrowsableState.Advanced)]
1031 protected override void OnGotFocus (EventArgs e)
1033 if (dropdown_style == ComboBoxStyle.DropDownList) {
1034 // We draw DDL styles manually, so they require a
1035 // refresh to have their selection drawn
1039 if (textbox_ctrl != null) {
1040 textbox_ctrl.SetSelectable (false);
1041 textbox_ctrl.ShowSelection = true;
1042 textbox_ctrl.ActivateCaret (true);
1043 textbox_ctrl.SelectAll ();
1046 base.OnGotFocus (e);
1049 [EditorBrowsable(EditorBrowsableState.Advanced)]
1050 protected override void OnLostFocus (EventArgs e)
1052 if (dropdown_style == ComboBoxStyle.DropDownList) {
1053 // We draw DDL styles manually, so they require a
1054 // refresh to have their selection drawn
1058 if (listbox_ctrl != null && dropped_down) {
1059 listbox_ctrl.HideWindow ();
1062 if (textbox_ctrl != null) {
1063 textbox_ctrl.SetSelectable (true);
1064 textbox_ctrl.ActivateCaret (false);
1065 textbox_ctrl.ShowSelection = false;
1068 base.OnLostFocus (e);
1071 protected override void OnHandleCreated (EventArgs e)
1073 base.OnHandleCreated (e);
1075 if (listbox_ctrl != null) {
1076 Controls.AddImplicit (listbox_ctrl);
1077 listbox_ctrl.Visible = true;
1080 if (textbox_ctrl != null)
1081 Controls.AddImplicit (textbox_ctrl);
1086 protected override void OnHandleDestroyed (EventArgs e)
1088 base.OnHandleDestroyed (e);
1091 protected override void OnKeyPress (KeyPressEventArgs e)
1093 // int index = FindStringCaseInsensitive (e.KeyChar.ToString (), SelectedIndex);
1095 // SelectedIndex = index;
1097 base.OnKeyPress (e);
1100 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
1102 MeasureItemEventHandler eh = (MeasureItemEventHandler)(Events [MeasureItemEvent]);
1107 protected override void OnParentBackColorChanged (EventArgs e)
1109 base.OnParentBackColorChanged (e);
1112 protected override void OnResize (EventArgs e)
1115 if (listbox_ctrl != null)
1116 listbox_ctrl.CalcListBoxArea ();
1119 protected override void OnSelectedIndexChanged (EventArgs e)
1121 base.OnSelectedIndexChanged (e);
1123 EventHandler eh = (EventHandler)(Events [SelectedIndexChangedEvent]);
1128 protected virtual void OnSelectedItemChanged (EventArgs e)
1132 protected override void OnSelectedValueChanged (EventArgs e)
1134 base.OnSelectedValueChanged (e);
1137 protected virtual void OnSelectionChangeCommitted (EventArgs e)
1139 EventHandler eh = (EventHandler)(Events [SelectionChangeCommittedEvent]);
1144 protected override void RefreshItem (int index)
1146 if (index < 0 || index >= Items.Count)
1147 throw new ArgumentOutOfRangeException ("Index of out range");
1149 if (draw_mode == DrawMode.OwnerDrawVariable)
1150 item_heights.Remove (Items [index]);
1154 public override void ResetText ()
1156 Text = String.Empty;
1159 protected override bool ProcessKeyEventArgs (ref Message m)
1161 return base.ProcessKeyEventArgs (ref m);
1164 [EditorBrowsable (EditorBrowsableState.Advanced)]
1165 protected override void OnKeyDown (KeyEventArgs e)
1170 [EditorBrowsable (EditorBrowsableState.Advanced)]
1171 protected override void OnValidating (CancelEventArgs e)
1173 base.OnValidating (e);
1176 [EditorBrowsable (EditorBrowsableState.Advanced)]
1177 protected override void OnTextChanged (EventArgs e)
1179 base.OnTextChanged (e);
1183 protected virtual void OnTextUpdate (EventArgs e)
1185 EventHandler eh = (EventHandler) Events [TextUpdateEvent];
1190 protected override void OnMouseLeave (EventArgs e)
1193 if (flat_style == FlatStyle.Popup)
1196 base.OnMouseLeave (e);
1199 protected override void OnMouseEnter (EventArgs e)
1202 if (flat_style == FlatStyle.Popup)
1205 base.OnMouseEnter (e);
1209 public void Select (int start, int length)
1212 throw new ArgumentException ("Start cannot be less than zero");
1215 throw new ArgumentException ("length cannot be less than zero");
1217 if (dropdown_style == ComboBoxStyle.DropDownList)
1220 textbox_ctrl.Select (start, length);
1223 public void SelectAll ()
1225 if (dropdown_style == ComboBoxStyle.DropDownList)
1228 if (textbox_ctrl != null) {
1229 textbox_ctrl.ShowSelection = true;
1230 textbox_ctrl.SelectAll ();
1234 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
1236 if ((specified & BoundsSpecified.Height) != 0) {
1237 requested_height = height;
1239 if (DropDownStyle == ComboBoxStyle.Simple && height > PreferredHeight) {
1240 if (IntegralHeight) {
1241 int border = ThemeEngine.Current.Border3DSize.Height;
1242 int lb_height = height - PreferredHeight - 2;
1243 if (lb_height - 2 * border > ItemHeight) {
1244 int partial = (lb_height - 2 * border) % ItemHeight;
1247 height = PreferredHeight;
1250 height = PreferredHeight;
1253 base.SetBoundsCore (x, y, width, height, specified);
1256 protected override void SetItemCore (int index, object value)
1258 if (index < 0 || index >= Items.Count)
1261 Items[index] = value;
1264 protected override void SetItemsCore (IList value)
1269 Items.AddRange (value);
1275 public override string ToString ()
1277 return base.ToString () + ", Items.Count:" + Items.Count;
1280 protected override void WndProc (ref Message m)
1282 switch ((Msg) m.Msg) {
1284 case Msg.WM_KEYDOWN:
1285 Keys keys = (Keys) m.WParam.ToInt32 ();
1286 if (keys == Keys.Up || keys == Keys.Down)
1288 goto case Msg.WM_CHAR;
1290 if (textbox_ctrl != null)
1291 XplatUI.SendMessage (textbox_ctrl.Handle, (Msg) m.Msg, m.WParam, m.LParam);
1293 case Msg.WM_MOUSE_LEAVE:
1294 Point location = PointToClient (Control.MousePosition);
1295 if (ClientRectangle.Contains (location))
1301 base.WndProc (ref m);
1304 #endregion Public Methods
1306 #region Private Methods
1308 void OnAutoCompleteCustomSourceChanged(object sender, CollectionChangeEventArgs e) {
1309 if(auto_complete_source == AutoCompleteSource.CustomSource) {
1310 //FIXME: handle add, remove and refresh events in AutoComplete algorithm.
1315 internal override bool InternalCapture {
1316 get { return Capture; }
1320 void LayoutComboBox ()
1322 int border = ThemeEngine.Current.Border3DSize.Width;
1324 text_area = ClientRectangle;
1325 text_area.Height = PreferredHeight;
1327 listbox_area = ClientRectangle;
1328 listbox_area.Y = text_area.Bottom + 3;
1329 listbox_area.Height -= (text_area.Height + 2);
1331 Rectangle prev_button_area = button_area;
1333 if (DropDownStyle == ComboBoxStyle.Simple)
1334 button_area = Rectangle.Empty;
1336 button_area = text_area;
1337 button_area.X = text_area.Right - button_width - border;
1338 button_area.Y = text_area.Y + border;
1339 button_area.Width = button_width;
1340 button_area.Height = text_area.Height - 2 * border;
1342 if (flat_style == FlatStyle.Popup || flat_style == FlatStyle.Flat) {
1343 button_area.Inflate (1, 1);
1345 button_area.Width -= 2;
1350 if (button_area != prev_button_area) {
1351 prev_button_area.Y -= border;
1352 prev_button_area.Width += border;
1353 prev_button_area.Height += 2 * border;
1354 Invalidate (prev_button_area);
1355 Invalidate (button_area);
1358 if (textbox_ctrl != null) {
1359 textbox_ctrl.Location = new Point (text_area.X + border, text_area.Y + border);
1360 textbox_ctrl.Width = text_area.Width - button_area.Width - border * 2;
1361 textbox_ctrl.Height = text_area.Height - border * 2;
1364 if (listbox_ctrl != null && dropdown_style == ComboBoxStyle.Simple) {
1365 listbox_ctrl.Location = listbox_area.Location;
1366 listbox_ctrl.CalcListBoxArea ();
1370 private void CreateComboListBox ()
1372 listbox_ctrl = new ComboListBox (this);
1373 listbox_ctrl.HighlightedIndex = SelectedIndex;
1376 internal void Draw (Rectangle clip, Graphics dc)
1378 Theme theme = ThemeEngine.Current;
1379 FlatStyle style = FlatStyle.Standard;
1380 bool is_flat = false;
1383 style = this.FlatStyle;
1384 is_flat = style == FlatStyle.Flat || style == FlatStyle.Popup;
1387 if (DropDownStyle == ComboBoxStyle.Simple)
1388 dc.FillRectangle (theme.ResPool.GetSolidBrush (Parent.BackColor), ClientRectangle);
1390 if (style == FlatStyle.Popup && (is_entered || Focused)) {
1391 Rectangle area = text_area;
1394 dc.DrawRectangle (theme.ResPool.GetPen (SystemColors.ControlDark), area);
1395 dc.DrawLine (theme.ResPool.GetPen (SystemColors.ControlDark), button_area.X - 1, button_area.Top, button_area.X - 1, button_area.Bottom);
1397 if (!is_flat && clip.IntersectsWith (text_area))
1398 ControlPaint.DrawBorder3D (dc, text_area, Border3DStyle.Sunken);
1400 int border = theme.Border3DSize.Width;
1402 // No edit control, we paint the edit ourselves
1403 if (dropdown_style == ComboBoxStyle.DropDownList) {
1404 DrawItemState state = DrawItemState.None;
1405 Rectangle item_rect = text_area;
1406 item_rect.X += border;
1407 item_rect.Y += border;
1408 item_rect.Width -= (button_area.Width + 2 * border);
1409 item_rect.Height -= 2 * border;
1412 state = DrawItemState.Selected;
1413 state |= DrawItemState.Focus;
1416 state |= DrawItemState.ComboBoxEdit;
1417 OnDrawItem (new DrawItemEventArgs (dc, Font, item_rect, SelectedIndex, state, ForeColor, BackColor));
1420 if (show_dropdown_button) {
1421 dc.FillRectangle (theme.ResPool.GetSolidBrush (theme.ColorControl), button_area);
1424 button_state = ButtonState.Inactive;
1427 theme.DrawFlatStyleComboButton (dc, button_area, button_state);
1429 theme.CPDrawComboButton (dc, button_area, button_state);
1434 internal void DropDownListBox ()
1436 if (DropDownStyle == ComboBoxStyle.Simple)
1439 if (listbox_ctrl == null)
1440 CreateComboListBox ();
1442 listbox_ctrl.Location = PointToScreen (new Point (text_area.X, text_area.Y + text_area.Height));
1444 if (listbox_ctrl.ShowWindow ())
1445 dropped_down = true;
1447 button_state = ButtonState.Pushed;
1448 if (dropdown_style == ComboBoxStyle.DropDownList)
1449 Invalidate (text_area);
1452 internal void DropDownListBoxFinished ()
1454 if (DropDownStyle == ComboBoxStyle.Simple)
1457 button_state = ButtonState.Normal;
1458 Invalidate (button_area);
1459 dropped_down = false;
1461 OnDropDownClosed (EventArgs.Empty);
1465 private int FindStringCaseInsensitive (string search)
1467 if (search.Length == 0) {
1471 for (int i = 0; i < Items.Count; i++)
1473 if (String.Compare (GetItemText (Items[i]), 0, search, 0, search.Length, true) == 0)
1480 internal int FindStringCaseInsensitive (string search, int start_index)
1482 if (search.Length == 0) {
1486 for (int i = 0; i < Items.Count; i++) {
1487 int index = (i + start_index) % Items.Count;
1488 if (String.Compare (GetItemText (Items [index]), 0, search, 0, search.Length, true) == 0)
1495 private void OnKeyDownCB(object sender, KeyEventArgs e)
1497 if (Items.Count == 0)
1503 SelectedIndex = Math.Max(SelectedIndex-1, 0);
1507 SelectedIndex = Math.Min(SelectedIndex+1, Items.Count-1);
1511 if (listbox_ctrl != null)
1512 SelectedIndex = Math.Max(SelectedIndex- (listbox_ctrl.page_size-1), 0);
1516 if (listbox_ctrl != null)
1517 SelectedIndex = Math.Min(SelectedIndex+(listbox_ctrl.page_size-1), Items.Count-1);
1525 void OnMouseDownCB (object sender, MouseEventArgs e)
1528 if (DropDownStyle == ComboBoxStyle.DropDownList)
1529 area = ClientRectangle;
1533 if (area.Contains (e.X, e.Y)) {
1535 Invalidate (button_area);
1541 void OnMouseMoveCB (object sender, MouseEventArgs e)
1543 if (DropDownStyle == ComboBoxStyle.Simple)
1546 if (listbox_ctrl != null && listbox_ctrl.Visible) {
1547 Point location = listbox_ctrl.PointToClient (Control.MousePosition);
1548 if (listbox_ctrl.ClientRectangle.Contains (location))
1549 listbox_ctrl.Capture = true;
1553 void OnMouseUpCB (object sender, MouseEventArgs e)
1556 OnClick (EventArgs.Empty);
1559 listbox_ctrl.Capture = true;
1562 private void OnMouseWheelCB (object sender, MouseEventArgs me)
1564 if (Items.Count == 0)
1567 if (listbox_ctrl != null && listbox_ctrl.Visible) {
1568 int lines = me.Delta / 120 * SystemInformation.MouseWheelScrollLines;
1569 listbox_ctrl.Scroll (-lines);
1571 int lines = me.Delta / 120;
1572 int index = SelectedIndex - lines;
1575 else if (index >= Items.Count)
1576 index = Items.Count - 1;
1577 SelectedIndex = index;
1581 internal override void OnPaintInternal (PaintEventArgs pevent)
1583 if (suspend_ctrlupdate)
1586 Draw (ClientRectangle, pevent.Graphics);
1589 private void OnTextBoxClick (object sender, EventArgs e)
1594 private void OnTextChangedEdit (object sender, EventArgs e)
1596 if (process_textchanged_event == false)
1599 OnTextChanged (EventArgs.Empty);
1601 int item = FindStringCaseInsensitive (textbox_ctrl.Text);
1606 // TODO: THIS IS BROKEN-ISH
1607 // I don't think we should hilight, and setting the top item does weirdness
1608 // when there is no scrollbar
1610 if (listbox_ctrl != null) {
1611 listbox_ctrl.SetTopItem (item);
1612 listbox_ctrl.HighlightedIndex = item;
1615 base.Text = textbox_ctrl.Text;
1618 internal void SetControlText (string s)
1620 process_textchanged_event = false;
1621 textbox_ctrl.Text = s;
1622 process_textchanged_event = true;
1625 void UpdateComboBoxBounds ()
1627 if (requested_height == -1)
1630 // Save the requested height since set bounds can destroy it
1631 int save_height = requested_height;
1632 SetBounds (0, 0, 0, requested_height, BoundsSpecified.Height);
1633 requested_height = save_height;
1636 private void UpdatedItems ()
1638 if (listbox_ctrl != null) {
1639 listbox_ctrl.UpdateLastVisibleItem ();
1640 listbox_ctrl.CalcListBoxArea ();
1641 listbox_ctrl.Refresh ();
1645 #endregion Private Methods
1647 [ListBindableAttribute (false)]
1648 public class ObjectCollection : IList, ICollection, IEnumerable
1651 private ComboBox owner;
1652 internal ArrayList object_items = new ArrayList ();
1654 public ObjectCollection (ComboBox owner)
1659 #region Public Properties
1661 get { return object_items.Count; }
1664 public bool IsReadOnly {
1665 get { return false; }
1669 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1670 public virtual object this [int index] {
1672 if (index < 0 || index >= Count)
1673 throw new ArgumentOutOfRangeException ("Index of out range");
1675 return object_items[index];
1678 if (index < 0 || index >= Count)
1679 throw new ArgumentOutOfRangeException ("Index of out range");
1681 throw new ArgumentNullException ("value");
1683 object_items[index] = value;
1684 if (owner.listbox_ctrl != null)
1685 owner.listbox_ctrl.InvalidateItem (index);
1686 if (index == owner.SelectedIndex) {
1687 if (owner.textbox_ctrl == null)
1690 owner.textbox_ctrl.SelectedText = value.ToString ();
1695 bool ICollection.IsSynchronized {
1696 get { return false; }
1699 object ICollection.SyncRoot {
1700 get { return this; }
1703 bool IList.IsFixedSize {
1704 get { return false; }
1707 #endregion Public Properties
1709 #region Public Methods
1710 public int Add (object item)
1714 idx = AddItem (item);
1715 owner.UpdatedItems ();
1719 public void AddRange (object[] items)
1722 throw new ArgumentNullException ("items");
1724 foreach (object mi in items)
1727 owner.UpdatedItems ();
1730 public void Clear ()
1732 owner.selected_index = -1;
1733 object_items.Clear ();
1734 owner.UpdatedItems ();
1738 public bool Contains (object value)
1741 throw new ArgumentNullException ("value");
1743 return object_items.Contains (value);
1746 public void CopyTo (object[] dest, int arrayIndex)
1748 object_items.CopyTo (dest, arrayIndex);
1751 void ICollection.CopyTo (Array dest, int index)
1753 object_items.CopyTo (dest, index);
1756 public IEnumerator GetEnumerator ()
1758 return object_items.GetEnumerator ();
1761 int IList.Add (object item)
1766 public int IndexOf (object value)
1769 throw new ArgumentNullException ("value");
1771 return object_items.IndexOf (value);
1774 public void Insert (int index, object item)
1776 if (index < 0 || index > Count)
1777 throw new ArgumentOutOfRangeException ("Index of out range");
1779 throw new ArgumentNullException ("item");
1781 owner.BeginUpdate ();
1786 object_items.Insert (index, item);
1788 owner.EndUpdate (); // Calls UpdatedItems
1791 public void Remove (object value)
1796 if (IndexOf (value) == owner.SelectedIndex)
1797 owner.SelectedIndex = -1;
1799 RemoveAt (IndexOf (value));
1802 public void RemoveAt (int index)
1804 if (index < 0 || index >= Count)
1805 throw new ArgumentOutOfRangeException ("Index of out range");
1807 if (index == owner.SelectedIndex)
1808 owner.SelectedIndex = -1;
1810 object_items.RemoveAt (index);
1811 owner.UpdatedItems ();
1813 #endregion Public Methods
1815 #region Private Methods
1816 private int AddItem (object item)
1819 throw new ArgumentNullException ("item");
1823 foreach (object o in object_items) {
1824 if (String.Compare (item.ToString (), o.ToString ()) < 0) {
1825 object_items.Insert (index, item);
1831 object_items.Add (item);
1832 return object_items.Count - 1;
1835 internal void AddRange (IList items)
1837 foreach (object mi in items)
1840 owner.UpdatedItems ();
1843 internal void Sort ()
1845 object_items.Sort ();
1848 #endregion Private Methods
1851 internal class ComboTextBox : TextBox {
1853 private ComboBox owner;
1855 public ComboTextBox (ComboBox owner)
1858 ShowSelection = false;
1861 internal void SetSelectable (bool selectable)
1863 SetStyle (ControlStyles.Selectable, selectable);
1866 internal void ActivateCaret (bool active)
1869 document.CaretHasFocus ();
1871 document.CaretLostFocus ();
1875 internal override void OnTextUpdate ()
1877 base.OnTextUpdate ();
1878 owner.OnTextUpdate (EventArgs.Empty);
1882 protected override void OnGotFocus (EventArgs e)
1884 owner.Select (false, true);
1887 protected override void OnLostFocus (EventArgs e)
1889 owner.Select (false, true);
1893 internal class ComboListBox : Control
1895 private ComboBox owner;
1896 private VScrollBarLB vscrollbar_ctrl;
1897 private int top_item; /* First item that we show the in the current page */
1898 private int last_item; /* Last visible item */
1899 internal int page_size; /* Number of listbox items per page */
1900 private Rectangle textarea_drawable; /* Rectangle of the drawable text area */
1902 internal enum ItemNavigation
1912 class VScrollBarLB : VScrollBar
1914 public VScrollBarLB ()
1918 internal override bool InternalCapture {
1919 get { return Capture; }
1923 public void FireMouseDown (MouseEventArgs e)
1928 e = TranslateEvent (e);
1932 public void FireMouseUp (MouseEventArgs e)
1937 e = TranslateEvent (e);
1941 public void FireMouseMove (MouseEventArgs e)
1946 e = TranslateEvent (e);
1950 MouseEventArgs TranslateEvent (MouseEventArgs e)
1952 Point loc = PointToClient (Control.MousePosition);
1953 return new MouseEventArgs (e.Button, e.Clicks, loc.X, loc.Y, e.Delta);
1957 public ComboListBox (ComboBox owner)
1964 MouseWheel += new MouseEventHandler (OnMouseWheelCLB);
1966 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
1967 SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
1969 this.is_visible = false;
1970 Hwnd.ObjectFromHandle (this.Handle).no_activate = true;
1972 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1973 InternalBorderStyle = BorderStyle.Fixed3D;
1975 InternalBorderStyle = BorderStyle.FixedSingle;
1978 protected override CreateParams CreateParams
1981 CreateParams cp = base.CreateParams;
1982 if (owner == null || owner.DropDownStyle == ComboBoxStyle.Simple)
1985 cp.Style ^= (int) WindowStyles.WS_CHILD;
1986 cp.Style |= (int) WindowStyles.WS_POPUP;
1987 cp.ExStyle |= (int) WindowExStyles.WS_EX_TOOLWINDOW | (int) WindowExStyles.WS_EX_TOPMOST;
1992 protected override void Select (bool directed, bool forward)
1994 // Do nothing, we never want to be selected
1997 internal override bool InternalCapture {
2006 #region Private Methods
2008 // Calcs the listbox area
2009 internal void CalcListBoxArea ()
2012 bool show_scrollbar = false;
2014 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
2015 Rectangle area = owner.listbox_area;
2017 height = area.Height;
2019 else { // DropDown or DropDownList
2021 width = owner.DropDownWidth;
2022 int count = (owner.Items.Count <= owner.MaxDropDownItems) ? owner.Items.Count : owner.MaxDropDownItems;
2024 if (owner.DrawMode == DrawMode.OwnerDrawVariable) {
2026 for (int i = 0; i < count; i++) {
2027 height += owner.GetItemHeight (i);
2032 height = owner.DropDownHeight;
2034 height = owner.ItemHeight * count;
2039 page_size = height / owner.ItemHeight;
2041 if (owner.Items.Count <= owner.MaxDropDownItems) {
2042 if (vscrollbar_ctrl != null)
2043 vscrollbar_ctrl.Visible = false;
2045 /* Need vertical scrollbar */
2046 if (vscrollbar_ctrl == null) {
2047 vscrollbar_ctrl = new VScrollBarLB ();
2048 vscrollbar_ctrl.Minimum = 0;
2049 vscrollbar_ctrl.SmallChange = 1;
2050 vscrollbar_ctrl.LargeChange = 1;
2051 vscrollbar_ctrl.Maximum = 0;
2052 vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
2053 Controls.AddImplicit (vscrollbar_ctrl);
2056 vscrollbar_ctrl.Dock = DockStyle.Right;
2058 vscrollbar_ctrl.Maximum = owner.Items.Count - 2;
2059 int large = (owner.DropDownStyle == ComboBoxStyle.Simple ? page_size : owner.maxdrop_items) - 1;
2062 vscrollbar_ctrl.LargeChange = large;
2063 show_scrollbar = vscrollbar_ctrl.Visible = true;
2065 int hli = HighlightedIndex;
2067 hli = Math.Min (hli, vscrollbar_ctrl.Maximum);
2068 vscrollbar_ctrl.Value = hli;
2072 Size = new Size (width, height);
2073 textarea_drawable = ClientRectangle;
2074 textarea_drawable.Width = width;
2075 textarea_drawable.Height = height;
2077 if (vscrollbar_ctrl != null && show_scrollbar)
2078 textarea_drawable.Width -= vscrollbar_ctrl.Width;
2080 last_item = LastVisibleItem ();
2083 private void Draw (Rectangle clip, Graphics dc)
2085 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (owner.BackColor), clip);
2087 if (owner.Items.Count > 0) {
2089 for (int i = top_item; i <= last_item; i++) {
2090 Rectangle item_rect = GetItemDisplayRectangle (i, top_item);
2092 if (!clip.IntersectsWith (item_rect))
2095 DrawItemState state = DrawItemState.None;
2097 if (i == HighlightedIndex) {
2098 state |= DrawItemState.Selected;
2100 if (owner.DropDownStyle == ComboBoxStyle.DropDownList) {
2101 state |= DrawItemState.Focus;
2105 owner.OnDrawItem (new DrawItemEventArgs (dc, owner.Font, item_rect,
2106 i, state, owner.ForeColor, owner.BackColor));
2111 int highlighted_index = -1;
2113 public int HighlightedIndex {
2114 get { return highlighted_index; }
2116 if (highlighted_index == value)
2119 if (highlighted_index != -1 && highlighted_index < this.owner.Items.Count)
2120 Invalidate (GetItemDisplayRectangle (highlighted_index, top_item));
2121 highlighted_index = value;
2122 if (highlighted_index != -1)
2123 Invalidate (GetItemDisplayRectangle (highlighted_index, top_item));
2127 private Rectangle GetItemDisplayRectangle (int index, int top_index)
2129 if (index < 0 || index >= owner.Items.Count)
2130 throw new ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
2132 Rectangle item_rect = new Rectangle ();
2133 int height = owner.GetItemHeight (index);
2136 item_rect.Width = textarea_drawable.Width;
2137 if (owner.DrawMode == DrawMode.OwnerDrawVariable) {
2139 for (int i = top_index; i < index; i++)
2140 item_rect.Y += owner.GetItemHeight (i);
2142 item_rect.Y = height * (index - top_index);
2144 item_rect.Height = height;
2148 public void HideWindow ()
2150 if (owner.DropDownStyle == ComboBoxStyle.Simple)
2155 owner.DropDownListBoxFinished ();
2158 private int IndexFromPointDisplayRectangle (int x, int y)
2160 for (int i = top_item; i <= last_item; i++) {
2161 if (GetItemDisplayRectangle (i, top_item).Contains (x, y) == true)
2168 public void InvalidateItem (int index)
2171 Invalidate (GetItemDisplayRectangle (index, top_item));
2174 private int LastVisibleItem ()
2176 Rectangle item_rect;
2177 int top_y = textarea_drawable.Y + textarea_drawable.Height;
2180 for (i = top_item; i < owner.Items.Count; i++) {
2181 item_rect = GetItemDisplayRectangle (i, top_item);
2182 if (item_rect.Y + item_rect.Height > top_y) {
2189 public void SetTopItem (int item)
2191 if (top_item == item)
2194 UpdateLastVisibleItem ();
2198 bool scrollbar_grabbed = false;
2202 if (vscrollbar_ctrl == null || !vscrollbar_ctrl.is_visible)
2205 return vscrollbar_ctrl.Bounds.Contains (PointToClient (Control.MousePosition));
2209 protected override void OnMouseDown (MouseEventArgs e)
2212 vscrollbar_ctrl.FireMouseDown (e);
2213 scrollbar_grabbed = true;
2217 protected override void OnMouseMove (MouseEventArgs e)
2219 if (owner.DropDownStyle == ComboBoxStyle.Simple)
2222 if (scrollbar_grabbed || (!Capture && InScrollBar)) {
2223 vscrollbar_ctrl.FireMouseMove (e);
2227 Point pt = PointToClient (Control.MousePosition);
2228 int index = IndexFromPointDisplayRectangle (pt.X, pt.Y);
2231 HighlightedIndex = index;
2234 protected override void OnMouseUp (MouseEventArgs e)
2236 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
2238 if (scrollbar_grabbed) {
2239 vscrollbar_ctrl.FireMouseUp (e);
2240 scrollbar_grabbed = false;
2242 HighlightedIndex = index;
2251 owner.SelectedIndex = index;
2252 owner.OnSelectionChangeCommitted (new EventArgs ());
2256 internal override void OnPaintInternal (PaintEventArgs pevent)
2258 Draw (pevent.ClipRectangle,pevent.Graphics);
2261 public bool ShowWindow ()
2263 if (owner.DropDownStyle == ComboBoxStyle.Simple && owner.Items.Count == 0)
2266 HighlightedIndex = owner.SelectedIndex;
2272 owner.OnDropDown (EventArgs.Empty);
2276 public void UpdateLastVisibleItem ()
2278 last_item = LastVisibleItem ();
2281 public void Scroll (int delta)
2283 if (delta == 0 || vscrollbar_ctrl == null || !vscrollbar_ctrl.Visible)
2286 int max = owner.Items.Count - page_size;
2288 int val = vscrollbar_ctrl.Value + delta;
2291 else if (val < vscrollbar_ctrl.Minimum)
2292 val = vscrollbar_ctrl.Minimum;
2293 vscrollbar_ctrl.Value = val;
2296 private void OnMouseWheelCLB (object sender, MouseEventArgs me)
2298 if (owner.Items.Count == 0)
2301 int lines = me.Delta / 120 * SystemInformation.MouseWheelScrollLines;
2306 private void VerticalScrollEvent (object sender, EventArgs e)
2308 if (top_item == vscrollbar_ctrl.Value)
2311 top_item = vscrollbar_ctrl.Value;
2312 UpdateLastVisibleItem ();
2316 protected override void WndProc(ref Message m) {
2317 if (m.Msg == (int)Msg.WM_SETFOCUS) {
2318 if (m.WParam != IntPtr.Zero) {
2319 XplatUI.SetFocus(m.WParam);
2322 base.WndProc (ref m);
2325 #endregion Private Methods