2 // System.Windows.Forms.ComboBox.cs
5 // stubbed out by Jaak Simm (jaaksimm@firm.ee)
6 // Dennis Hayes (dennish@Raytek.com)
7 // Alexandre Pigolkine (pigolkine@gmx.de)
9 // (C) Ximian, Inc., 2002/3
12 using System.ComponentModel;
13 using System.Collections;
15 using System.Runtime.InteropServices;
17 namespace System.Windows.Forms {
20 /// Represents a Windows combo box control.
24 public class ComboBox : ListControl {
28 ComboBoxStyle dropDownStyle;
32 Image backgroundImage;
33 ControlStyles controlStyles;
39 private ComboBox.ObjectCollection Items_ = null;
43 bool updateing; // true when begin update has been called. do not paint when true;
44 // --- Constructor ---
45 public ComboBox() : base()
53 //controlStyles = null;
54 drawMode = DrawMode.Normal;
55 dropDownStyle = ComboBoxStyle.DropDown;
57 integralHeight = true;
59 backgroundImage = null;
60 Items_ = new ComboBox.ObjectCollection(this);
63 SubClassWndProc_ = true;
70 public override Color BackColor {
72 return base.BackColor;
75 if(BackColor.A != 255){
77 (controlStyles & ControlStyles.SupportsTransparentBackColor) !=
78 ControlStyles.SupportsTransparentBackColor
81 ArgumentOutOfRangeException("BackColor", BackColor, "Transparant background color not allowed.");
84 base.BackColor = value;
88 public override Image BackgroundImage {
90 return backgroundImage;
93 backgroundImage = value;
97 internal int getDropDownHeight() {
98 // FIXME: use PreferredHeight instead of DefaultSize.Height ?
99 // FIXME: those calculations probably wrong
100 return DefaultSize.Height + (maxDropDownItems + 1) * itemHeight_ - (itemHeight_ / 2);
104 protected override CreateParams CreateParams {
106 CreateParams createParams = base.CreateParams;
108 createParams.ClassName = "ComboBox";
110 if( DropDownStyle == ComboBoxStyle.Simple) {
111 createParams.Height = Height;
114 createParams.Height = getDropDownHeight();
117 createParams.ExStyle = (int)( WindowExStyles.WS_EX_RIGHTSCROLLBAR | WindowExStyles.WS_EX_NOPARENTNOTIFY);
119 createParams.Style = (int) (
120 (int)WindowStyles.WS_CHILD |
121 (int)WindowStyles.WS_VISIBLE |
122 (int)WindowStyles.WS_VSCROLL |
123 (int)WindowStyles.WS_TABSTOP |
124 (int)ComboBoxStyles.CBS_HASSTRINGS );
127 case DrawMode.OwnerDrawFixed:
128 createParams.Style |= (int)ComboBoxStyles.CBS_OWNERDRAWFIXED;
130 case DrawMode.OwnerDrawVariable:
131 createParams.Style |= (int)ComboBoxStyles.CBS_OWNERDRAWVARIABLE;
135 switch(DropDownStyle) {
136 case ComboBoxStyle.Simple:
137 createParams.Style |= (int)ComboBoxStyles.CBS_SIMPLE;
139 case ComboBoxStyle.DropDown:
140 createParams.Style |= (int)ComboBoxStyles.CBS_DROPDOWN;
142 case ComboBoxStyle.DropDownList:
143 createParams.Style |= (int)ComboBoxStyles.CBS_DROPDOWNLIST;
146 if( !integralHeight) {
147 createParams.Style |= (int)ComboBoxStyles.CBS_NOINTEGRALHEIGHT;
150 * Keep Control unsorted, but sort data in Items (ArrayList)
152 createParams.Style |= (int)ComboBoxStyles.CBS_SORT;
159 protected override Size DefaultSize {
161 return new Size(121,21);//correct size
165 public new Size Size {
166 //FIXME: should we return client size or someother size???
172 if( dropDownStyle == ComboBoxStyle.Simple) {
174 sz.Height += maxDropDownItems * itemHeight_;
183 public DrawMode DrawMode {
188 if( drawMode != value) {
195 public ComboBoxStyle DropDownStyle {
197 return dropDownStyle;
200 if( dropDownStyle != value) {
201 dropDownStyle = value;
203 OnDropDownStyleChanged( new EventArgs());
209 public int DropDownWidth {
211 throw new NotImplementedException ();
218 public bool DroppedDown {
228 public override bool Focused {
230 if (IsHandleCreated) {
231 IntPtr focusedWindow = Win32.GetFocus();
232 if (focusedWindow == Handle)
234 if( Win32.GetParent(focusedWindow) == Handle)
242 public override Color ForeColor {
245 return base.ForeColor;
249 base.ForeColor = value;
253 public bool IntegralHeight {
255 return integralHeight;
258 if( integralHeight != value) {
259 integralHeight = value;
260 if( IsHandleCreated) {
261 if( integralHeight) {
262 Win32.UpdateWindowStyle(Handle, (int)ComboBoxStyles.CBS_NOINTEGRALHEIGHT, 0);
265 Win32.UpdateWindowStyle(Handle, 0, (int)ComboBoxStyles.CBS_NOINTEGRALHEIGHT);
273 public int ItemHeight {
279 if( IsHandleCreated) {
280 if( DrawMode != DrawMode.OwnerDrawVariable) {
281 Win32.SendMessage(Handle, (int)ComboBoxMessages.CB_SETITEMHEIGHT, 0, itemHeight_);
284 for( int i = 0; i < Items.Count; i++) {
285 Win32.SendMessage(Handle, (int)ComboBoxMessages.CB_SETITEMHEIGHT, i, itemHeight_);
288 Win32.SendMessage(Handle, (int)ComboBoxMessages.CB_SETITEMHEIGHT, -1, itemHeight_);
294 public ComboBox.ObjectCollection Items {
301 public int MaxDropDownItems {
303 return maxDropDownItems;
306 if( maxDropDownItems != value) {
307 maxDropDownItems = value;
308 if( DropDownStyle != ComboBoxStyle.Simple) {
309 Height = getDropDownHeight();
316 public int MaxLength {
318 throw new NotImplementedException ();
326 public int PreferredHeight {
328 return 20; //FIXME: this is the default, good as any?
333 public override int SelectedIndex {
335 if( IsHandleCreated) {
336 return Win32.SendMessage(Handle, (int)ComboBoxMessages.CB_GETCURSEL, 0, 0);
339 return selectedIndex;
343 if( selectedIndex != value) {
344 //FIXME: set exception parameters
345 if( value >= Items_.Count) {
346 throw new ArgumentOutOfRangeException();
348 selectedIndex = value;
349 if( IsHandleCreated) {
350 Win32.SendMessage(Handle, (int)ComboBoxMessages.CB_SETCURSEL, selectedIndex, 0);
352 OnSelectedIndexChanged(new EventArgs());
358 public object SelectedItem {
360 if( IsHandleCreated) {
361 return Items_[Win32.SendMessage(Handle, (int)ComboBoxMessages.CB_GETCURSEL, 0, 0)];
364 return Items_[selectedIndex];
373 public string SelectedText {
375 throw new NotImplementedException ();
383 public int SelectionLength {
385 throw new NotImplementedException ();
393 public int SelectionStart {
395 throw new NotImplementedException ();
407 if( sorted != value) {
409 if( IsHandleCreated) {
411 object[] items = new object[Items.Count];
412 Items.CopyTo(items, 0);
414 Items.AddRange(items);
423 public override string Text {
429 if (value == null || value == String.Empty) {
436 /// internal .NET framework supporting methods, not stubbed out:
438 internal void populateControl( ICollection items) {
439 if( IsHandleCreated && items != null) {
440 foreach( object obj in items) {
441 // CHECKME : shall we check for null here or in Add/Insert functions
443 Win32.SendMessage(Handle, (int)ComboBoxMessages.CB_ADDSTRING, 0, getDisplayMemberOfObj(obj));
449 protected override void Dispose(bool disposing) {
450 base.Dispose(disposing);
454 protected override void OnSelectedValueChanged(EventArgs e){ // .NET V1.1 Beta
456 base.OnSelectedValueChanged(e);
460 protected override void SetItemCore(int index,object value){
464 protected virtual void AddItemsCore(object[] value) {
469 public void BeginUpdate()
475 public void EndUpdate()
481 public int FindString(string s)
483 throw new NotImplementedException ();
487 public int FindString(string s,int startIndex)
489 throw new NotImplementedException ();
493 public int FindStringExact(string s)
495 throw new NotImplementedException ();
499 public int FindStringExact(string s,int startIndex)
501 throw new NotImplementedException ();
505 public int GetItemHeight(int index)
507 throw new NotImplementedException ();
511 protected override bool IsInputKey(Keys keyData)
514 return base.IsInputKey(keyData);
517 /// [methods for events]
519 protected override void OnBackColorChanged(EventArgs e)
522 base.OnBackColorChanged(e);
526 protected override void OnDataSourceChanged(EventArgs e)
529 base.OnDataSourceChanged(e);
533 protected override void OnDisplayMemberChanged(EventArgs e)
536 base.OnDisplayMemberChanged(e);
540 protected virtual void OnDrawItem(DrawItemEventArgs e)
542 if( DrawItem != null) {
548 protected virtual void OnDropDown(EventArgs e)
554 protected virtual void OnDropDownStyleChanged(EventArgs e)
556 if( DropDownStyleChanged != null) {
557 DropDownStyleChanged(this, e);
562 protected override void OnFontChanged(EventArgs e)
565 base.OnFontChanged(e);
569 protected override void OnForeColorChanged(EventArgs e)
572 base.OnForeColorChanged(e);
576 protected override void OnHandleCreated(EventArgs e)
579 base.OnHandleCreated(e);
580 populateControl(Items_);
581 if (DropDownStyle != ComboBoxStyle.DropDown || Text == String.Empty) {
582 if (selectedIndex == -1 && Items.Count != 0) {
585 Win32.SendMessage(Handle, (int)ComboBoxMessages.CB_SETCURSEL, selectedIndex, 0);
590 protected override void OnHandleDestroyed(EventArgs e)
593 base.OnHandleDestroyed(e);
597 protected override void OnKeyPress(KeyPressEventArgs e)
604 protected virtual void OnMeasureItem(MeasureItemEventArgs e)
606 if(MeasureItem != null) {
607 MeasureItem(this, e);
612 protected override void OnParentBackColorChanged(EventArgs e)
615 base.OnParentBackColorChanged(e);
619 protected override void OnResize(EventArgs e)
626 protected override void OnSelectedIndexChanged(EventArgs e)
628 if( SelectedIndexChanged != null) {
629 SelectedIndexChanged( this, e);
634 protected virtual void OnSelectedItemChanged(EventArgs e) {
639 protected virtual void OnSelectionChangeCommitted(EventArgs e)
643 /// end of [methods for events]
647 protected override void RefreshItem(int index)
654 public void Select(int start,int length)
660 public void SelectAll()
666 protected override void SetBoundsCore(int x,int y,int width,int height,BoundsSpecified specified)
669 // If DropDownStyle == ComboBoxStyle.Simple, the heigth is a real window height - no control over it
671 // if Handle created - specify complete height, ComboBox-control will adjust window rectangle
672 // else - set the height to Default.
673 if(DropDownStyle != ComboBoxStyle.Simple) {
674 if( IsHandleCreated) {
675 height = getDropDownHeight();
678 height = DefaultSize.Height;
681 if ( (specified & BoundsSpecified.X) == 0) x = Left;
682 if ( (specified & BoundsSpecified.Y) == 0) y = Top;
683 if ( (specified & BoundsSpecified.Width) == 0) width = Width;
684 //if ( (specified & BoundsSpecified.Height) == 0) height = Height;
686 if (IsHandleCreated){
687 SetWindowPosFlags flags = SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_FRAMECHANGED | SetWindowPosFlags.SWP_DRAWFRAME;
688 Win32.SetWindowPos (Handle, SetWindowPosZOrder.HWND_NOTOPMOST, x, y, width, height, flags);
690 RECT rect = new RECT();
691 Win32.GetWindowRect (Handle, ref rect);
693 if( Parent != null) {
695 Win32.ScreenToClient(Parent.Handle, ref rect);
703 width = rect.right - rect.left;
705 height = rect.bottom - rect.top;
709 UpdateBounds (x, y, width, height);
711 // FIXME: this is needed, otherwise painting is not correct
712 if( dropDownStyle == ComboBoxStyle.Simple ) {
713 Win32.InvalidateRect(Handle, IntPtr.Zero, 0);
714 Win32.UpdateWindow(Handle);
718 // for IList interface
719 // FIXME not sure how to handle this
721 //protected override void SetItemsCore(IList value)
723 // throw new NotImplementedException ();
727 public override string ToString()
730 return base.ToString();
734 protected override void WndProc(ref Message m)
736 switch ((Msg) m.Msg) {
737 case Msg.WM_MEASUREITEM: {
738 MEASUREITEMSTRUCT mis = new MEASUREITEMSTRUCT();
739 mis = (MEASUREITEMSTRUCT)Marshal.PtrToStructure(m.LParam, mis.GetType());
740 MeasureItemEventArgs args = new MeasureItemEventArgs(CreateGraphics(),mis.itemID);
741 args.ItemHeight = mis.itemHeight;
742 args.ItemWidth = mis.itemWidth;
743 OnMeasureItem( args);
744 mis.itemHeight = args.ItemHeight;
745 mis.itemWidth = args.ItemWidth;
746 Marshal.StructureToPtr(mis, m.LParam, false);
747 m.Result = (IntPtr)1;
750 case Msg.WM_DRAWITEM: {
751 DRAWITEMSTRUCT dis = new DRAWITEMSTRUCT();
752 dis = (DRAWITEMSTRUCT)Marshal.PtrToStructure(m.LParam, dis.GetType());
753 Rectangle rect = new Rectangle(dis.rcItem.left, dis.rcItem.top, dis.rcItem.right - dis.rcItem.left, dis.rcItem.bottom - dis.rcItem.top);
754 DrawItemEventArgs args = new DrawItemEventArgs(Graphics.FromHdc(dis.hDC), Font,
755 rect, dis.itemID, (DrawItemState)dis.itemState);
757 //Marshal.StructureToPtr(dis, m.LParam, false);
758 m.Result = (IntPtr)1;
762 case Msg.WM_COMPAREITEM: {
768 if( m.LParam != Handle) {
772 switch(m.HiWordWParam) {
773 case (uint)ComboBoxNotification.CBN_SELCHANGE:
774 SelectedIndex = Win32.SendMessage(Handle, (int)ComboBoxMessages.CB_GETCURSEL, 0, 0);
775 m.Result = IntPtr.Zero;
778 m.Result = IntPtr.Zero;
783 case Msg.WM_CTLCOLOREDIT :
784 CallControlWndProc ( ref m );
793 protected override void SetItemsCore (IList value){
796 /// --- Button events ---
797 /// commented out, cause it only supports the .NET Framework infrastructure
799 public event DrawItemEventHandler DrawItem;
802 public event EventHandler DropDown;
805 public event EventHandler DropDownStyleChanged;
808 public event MeasureItemEventHandler MeasureItem;
810 /* only supports .NET framework
812 public new event PaintEventHandler Paint;
816 public event EventHandler SelectedIndexChanged;
819 public event EventHandler SelectionChangeCommitted;
822 public class ChildAccessibleObject : AccessibleObject {
823 /// the class is not stubbed, cause it's only used for .NET framework
828 /// sub-class: ComboBox.ObjectCollection
830 /// Represents the collection of items in a ComboBox.
833 public class ObjectCollection : IList, ICollection, IEnumerable {
834 private ArrayList collection_ = new ArrayList ();
835 private ComboBox owner_ = null;
837 /// --- ObjectCollection.constructor ---
839 public ObjectCollection (ComboBox owner) {
843 /// --- ObjectCollection Properties ---
847 return collection_.Count;
852 public bool IsReadOnly {
854 return collection_.IsReadOnly;
858 object IList.this[int index] {
859 get { return collection_[index]; }
860 set { collection_[index] = value; }
864 public object this[int index] {
865 get { return collection_[index]; }
866 set { collection_[index] = value; }
869 /// --- ICollection properties ---
871 bool IList.IsFixedSize {
872 [MonoTODO] get { return collection_.IsFixedSize; }
876 object ICollection.SyncRoot {
877 get { return collection_.SyncRoot; }
880 bool ICollection.IsSynchronized {
882 [MonoTODO] get { return collection_.IsSynchronized; }
886 /// --- ObjectCollection Methods ---
887 /// Note: IList methods are stubbed out, otherwise IList interface cannot be implemented
889 public int Add(object item) {
890 // FIXME: not optimal
891 int idx = collection_.Add(item);
893 ListControl.ListControlComparer cic = new ListControl.ListControlComparer(owner_);
894 collection_.Sort(cic);
895 idx = collection_.BinarySearch(item,cic);
896 if( owner_.IsHandleCreated) {
897 Win32.SendMessage(owner_.Handle, (int)ComboBoxMessages.CB_INSERTSTRING, idx, owner_.getDisplayMemberOfObj(item));
901 if( owner_.IsHandleCreated) {
902 Win32.SendMessage(owner_.Handle, (int)ComboBoxMessages.CB_ADDSTRING, 0, owner_.getDisplayMemberOfObj(item));
909 public void AddRange(object[] items)
911 // FIXME: not optimal
912 foreach(object item in items) {
915 // owner_.populateControl(items);
916 // collection_.AddRange(items);
923 Win32.SendMessage(owner_.Handle, (int)ComboBoxMessages.CB_RESETCONTENT, 0, 0);
927 public bool Contains(object value)
929 return collection_.Contains(value);
933 public void CopyTo(object[] dest,int arrayIndex)
935 collection_.CopyTo(dest, arrayIndex);
940 void ICollection.CopyTo(Array dest,int index)
942 collection_.CopyTo(dest, index);
946 public IEnumerator GetEnumerator()
948 return collection_.GetEnumerator();
952 public int IndexOf(object value)
954 return collection_.IndexOf(value);
958 public void Insert(int index,object item)
964 public void Remove(object value)
970 public void RemoveAt(int index)
974 } // --- end of ComboBox.ObjectCollection ---