using System; using System.Drawing; using System.Windows.Forms; using System.ComponentModel; using System.Diagnostics; using CustomControls.HelperClasses; using CustomControls.Enumerations; namespace CustomControls.BaseClasses { public class DropDownListBase:Control,ISupportInitialize,IMessageFilter { #region "Variable Declaration" public event EventHandler BeginInitialization; public event EventHandler EndInitialization; protected DropdownFormBase dropDownForm; private int buttonWidth=14; protected Control _HostedControl; protected EditControl editControl; private Form hostForm; private StringFormat strFormat; private HorizontalAlignment _TextAlign=HorizontalAlignment.Left; private Enumerations.CustomBorderStyle _CustomBorderStyle=Enumerations.CustomBorderStyle.Hot; private bool _DroppedDown=false; private int _ListWidth=120; private int _ListHeight=20; private Enumerations.State _State=State.Normal; private Color _BackColor=SystemColors.Window; private ComboBoxStyle _DropDownStyle=ComboBoxStyle.DropDown; private bool _Initialized=false; #endregion #region "Properties" [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool Initialized { get{return _Initialized;} } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual bool DroppedDown { get{return _DroppedDown;} set { if (value!=_DroppedDown) { _DroppedDown=value; OnDropDownChanged(new EventArgs()); } } } [Category("Appearance")] [DefaultValue(typeof(ComboBoxStyle),"DropDown")] public virtual ComboBoxStyle DropDownStyle { get{return _DropDownStyle;} set { if (value!=_DropDownStyle) { _DropDownStyle=value; OnDropDownStyleChanged(new EventArgs()); } } } protected virtual Control HostedControl { get{return _HostedControl;} } public override string Text { get { return editControl.Text; } set { if(value !=editControl.Text) { editControl.Text = value; //OnTextChanged(new EventArgs()); Invalidate(); } } } [DefaultValue(typeof(Enumerations.CustomBorderStyle),"Hot")] [Category("Appearance")] public virtual Enumerations.CustomBorderStyle CustomBorderStyle { get{return _CustomBorderStyle;} set { if (value!=_CustomBorderStyle) { _CustomBorderStyle=value; RefreshEditRectangle(); this.Invalidate(); } } } protected int Listwidth { get{return _ListWidth;} set { if (value !=_ListWidth) { _ListWidth=value; } } } protected int ListHeight { get{return _ListHeight;} set { if (value !=_ListHeight) { _ListHeight=value; } } } public override Color BackColor { get { return _BackColor; } set { if (value !=_BackColor) { _BackColor = value; Invalidate(); } } } protected Enumerations.State State { get{return _State;} set { if (value!=_State) { _State=value; OnStateChanged(new EventArgs()); } } } protected override Size DefaultSize { get { return new Size(120,20); } } protected new Rectangle ClientRectangle { get { if (CustomBorderStyle==Enumerations.CustomBorderStyle.None) { return base.ClientRectangle; } else { return new Rectangle(1,1,base.ClientRectangle.Width-2,base.ClientRectangle.Height-2); } } } [Category("Appearance")] [DefaultValue(typeof(HorizontalAlignment),"Left")] public HorizontalAlignment TextAlign { get{return _TextAlign;} set { if (value!=_TextAlign) { _TextAlign=value; editControl.TextAlign=value; Invalidate(); } } } protected Rectangle EditRectangle { get { if (DropDownStyle!=ComboBoxStyle.Simple) { Rectangle cr=ClientRectangle; return new Rectangle(cr.X,cr.Y,cr.Width-buttonWidth-1,cr.Height); } else{return ClientRectangle;} } } protected Rectangle ButtonRectangle { get { if (DropDownStyle!=ComboBoxStyle.Simple) { Rectangle cr=ClientRectangle; return new Rectangle(cr.Right-buttonWidth,cr.Top,buttonWidth,cr.Height); } else { return Rectangle.Empty; } } } #endregion #region "Constructor" public DropDownListBase() { SetStyle(ControlStyles.AllPaintingInWmPaint,true); SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.DoubleBuffer, true); SetStyle(ControlStyles.FixedHeight,true); SetStyle(ControlStyles.FixedWidth, true); SetStyle(ControlStyles.ResizeRedraw, true); SetStyle(ControlStyles.Selectable, false); editControl= new EditControl(); editControl.AutoSize=false; RefreshEditRectangle(); editControl.MouseEnter+= new EventHandler(TopMouseEnter); editControl.MouseLeave+=new EventHandler(TopMouseLeave); editControl.GotFocus+= new EventHandler(TopGotFocus); editControl.LostFocus+= new EventHandler(TopLostFocus); editControl.MouseDown+=new MouseEventHandler(TopMouseDown); editControl.TextChanged+= new EventHandler(editControl_TextChanged); this.Controls.Add(editControl); dropDownForm = new DropdownFormBase(); dropDownForm.FormBorderStyle = FormBorderStyle.None; dropDownForm.StartPosition = FormStartPosition.Manual; dropDownForm.TopMost = true; dropDownForm.ShowInTaskbar = false; dropDownForm.BackColor = SystemColors.Window; dropDownForm.TabStop=false; dropDownForm.Size=GetDefaultSize(); dropDownForm.LostFocus+= new EventHandler(dropDownForm_LostFocus); if (HostedControl!=null) { HostedControl.Location=new Point(2,2); HostedControl.Size=new Size(dropDownForm.Width-4,dropDownForm.Height-4); HostedControl.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right |AnchorStyles.Top; HostedControl.Parent=dropDownForm; HostedControl.LostFocus+=new EventHandler(dropDownForm_LostFocus); } strFormat= new StringFormat(StringFormatFlags.NoWrap); Application.AddMessageFilter(this); } #endregion #region "Overrides" protected override void OnPaint(PaintEventArgs e) { DrawButton(e.Graphics); DrawBorder(e.Graphics); DrawButtonLLVLine(e.Graphics); if(DropDownStyle==ComboBoxStyle.DropDownList) { strFormat.Alignment= HAlignToStrAlign(TextAlign); DrawText(e.Graphics,Text,Font,EditRectangle,strFormat); } } private StringAlignment HAlignToStrAlign(HorizontalAlignment hAlign) { switch (hAlign) { case HorizontalAlignment.Center: { return StringAlignment.Center; } case HorizontalAlignment.Left: { return StringAlignment.Near; } case HorizontalAlignment.Right: { return StringAlignment.Far; } default : { return StringAlignment.Near; } } } protected override void OnPaintBackground(PaintEventArgs pevent) { using (SolidBrush backBrush= new SolidBrush(AppColors.WindowColor)) { if (!Enabled) { backBrush.Color=AppColors.ControlColor; } pevent.Graphics.FillRectangle(backBrush,ClientRectangle); } } protected override void OnResize(EventArgs e) { base.OnResize (e); RefreshEditRectangle(); Invalidate(); } protected override void OnMouseEnter(EventArgs e) { base.OnMouseEnter(e); TopMouseEnter(this,e); } private void TopMouseEnter(object sender, EventArgs e) { if (!DroppedDown ) { this.State=State.Hot; } } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); TopMouseLeave(this,e); } private void TopMouseLeave(object sender, EventArgs e) { if (!DroppedDown && !ContainsFocus && !editControl.Capture) { this.State=State.Normal; } } protected override void OnLostFocus(EventArgs e) { base.OnLostFocus(e); TopLostFocus(this,e); } private void TopLostFocus(object sender, EventArgs e) { if(!this.ContainsFocus && !dropDownForm.ContainsFocus ) { DroppedDown=false; this.State=State.Normal; } } protected override void OnGotFocus(EventArgs e) { //base.OnGotFocus(e); TopGotFocus(this,e); } private void TopGotFocus(object sender, EventArgs e) { base.OnGotFocus(e); editControl.Focus(); if(!DroppedDown){this.State=State.Hot;} } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown (e); TopMouseDown(this,e); } private void TopMouseDown(object sender, MouseEventArgs e) { Focus(); if (DropDownStyle==ComboBoxStyle.DropDown) { if (ButtonRectangle.Contains(new Point(e.X,e.Y))) { OnButtonClick(new EventArgs()); } } else { if(ClientRectangle.Contains(new Point(e.X,e.Y)) ) { OnButtonClick(new EventArgs()); } } if(DroppedDown && !this.DisplayRectangle.Contains(new Point(e.X,e.Y))) { DroppedDown=false; } } protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel (e); if (e.Delta<0){ OnNextItem();} else{OnPrevItem();} } protected override void OnLeave(EventArgs e) { base.OnLeave(e); OnItemSelected(DroppedDown); } protected override void OnEnabledChanged(EventArgs e) { base.OnEnabledChanged (e); if (Enabled){editControl.BackColor=AppColors.WindowColor;} else{editControl.BackColor=AppColors.ControlColor;} } #endregion #region "Virtual" protected virtual void OnPrevItem() {} protected virtual void OnNextItem() {} protected virtual void OnScrollUp() {} protected virtual void OnScrollDown() {} protected virtual void OnPgUp() {} protected virtual void OnPgDown() {} protected virtual void OnBeginInit(EventArgs e) { if(BeginInitialization!=null) { BeginInitialization(this,e); } } protected virtual void OnEndInit(EventArgs e) { if (EndInitialization!=null) { EndInitialization(this,e); } } protected virtual void DrawText(Graphics g,string text,Font font,Rectangle bounds,StringFormat strformat) { using (SolidBrush textBrush= new SolidBrush(BaseClasses.AppColors.TextColor)) { if(!Enabled){textBrush.Color=AppColors.ControlColorDark;} g.DrawString(text,font,textBrush,GetTextRectangle(font.Height,bounds),strFormat); } } protected virtual void OnDropDownChanged(EventArgs e) { if (DroppedDown){ShowDropDownForm();} else { if (ContainsFocus) {State=State.Hot;} else {State= State.Normal;} HideDropDownForm(); } } protected virtual void OnShowButtonChanged(EventArgs e) { RefreshEditRectangle(); Invalidate(); } protected virtual void OnStateChanged(EventArgs e) { Invalidate(); } protected virtual void OnDropDownStyleChanged(EventArgs e) { if(DropDownStyle==ComboBoxStyle.DropDownList) { editControl.Visible=false; SetStyle(ControlStyles.Selectable,true); } else { editControl.Visible=true; SetStyle(ControlStyles.Selectable,false); } RefreshEditRectangle(); Invalidate(); } protected virtual void OnButtonClick(EventArgs e) { DroppedDown=!_DroppedDown; if (DroppedDown) { State=State.DropDown; } else { State=State.Hot; } } protected virtual void OnItemSelected(bool Dropped) {} protected virtual void OnDropDown(System.EventArgs e) { dropDownForm.Size=new Size(this.Listwidth,this.ListHeight); } #endregion #region "Implementation" public bool PreFilterMessage(ref Message msg) { if(Enabled && (this.ContainsFocus || dropDownForm.ContainsFocus) ) { int code = (int)msg.WParam; switch (msg.Msg) { case (int)CustomControls.Enumerations.Msgs.WM_MOUSEWHEEL: { if((int)msg.WParam>0) { if(DroppedDown){OnScrollUp();} else{OnPrevItem();} } else { if(DroppedDown){OnScrollDown();} else{OnNextItem();} } return true; } case (int)CustomControls.Enumerations.Msgs.WM_LBUTTONDOWN: case(int)CustomControls.Enumerations.Msgs.WM_RBUTTONDOWN: { if (DroppedDown && (!this.RectangleToScreen(this.DisplayRectangle).Contains(Cursor.Position) && !dropDownForm.RectangleToScreen(dropDownForm.DisplayRectangle).Contains(Cursor.Position))) { DroppedDown=false; } return false; } case (int)CustomControls.Enumerations.Msgs.WM_SYSKEYUP: { if(ModifierKeys==Keys.Alt) { if (code==(int)Keys.Down ||code==(int)Keys.Up ) { DroppedDown=!DroppedDown; return true; } } break; } case(int)CustomControls.Enumerations.Msgs.WM_KEYDOWN: { if(DropDownStyle!=ComboBoxStyle.DropDownList){editControl.Focus();} if(code==(int)Keys.F4) { DroppedDown=!DroppedDown; return true; } else if(code ==(int)Keys.Escape && DroppedDown) { DroppedDown=false; return true; } else if(code ==(int)Keys.Enter ) { bool flag=false; if (DroppedDown) { flag=true; DroppedDown=false; } OnItemSelected(flag); return true; } else if(this.ContainsFocus ||dropDownForm.ContainsFocus) { if(code==(int)Keys.Down) { OnNextItem(); return true; } else if(code==(int)Keys.Up) { OnPrevItem(); return true; } else if(code==(int)Keys.PageUp) { OnPgUp(); return true; } else if(code==(int)Keys.PageDown) { OnPgDown(); return true; } } break; } } } return false; } public void BeginInit() { _Initialized=false; OnBeginInit(new EventArgs()); } public void EndInit() { hostForm=this.FindForm(); if (hostForm!=null) { hostForm.Move+=new EventHandler(hostForm_MoveResize); hostForm.Resize+=new EventHandler(hostForm_MoveResize); dropDownForm.Owner=hostForm; _Initialized=true; } OnEndInit(new EventArgs()); } private void hostForm_MoveResize(object sender, EventArgs e) { DroppedDown=false; } private void dropDownForm_LostFocus(object sender, EventArgs e) { if ( !this.ContainsFocus && !this.dropDownForm.ContainsFocus &&!this.RectangleToScreen(this.DisplayRectangle).Contains(Cursor.Position)) { DroppedDown=false; } } protected virtual void DrawBorder(Graphics g) { switch(CustomBorderStyle) { case Enumerations.CustomBorderStyle.None: { break; } case Enumerations.CustomBorderStyle.FixedSingle: { {g.DrawRectangle(Pens.Black,new Rectangle(0,0, this.DisplayRectangle.Width-1,this.DisplayRectangle.Height-1));} break; } case Enumerations.CustomBorderStyle.Hot: { if (!Enabled ) { { g.DrawRectangle(new Pen(CustomControls.BaseClasses.AppColors.ToolbarBackColor),new Rectangle(0,0, this.DisplayRectangle.Width-1,this.DisplayRectangle.Height-1));} } else { switch(State) { case State.Normal: { { Color borderColor=(this.Parent!=null)?Parent.BackColor:CustomControls.BaseClasses.AppColors.ControlColor; g.DrawRectangle(new Pen(borderColor),new Rectangle(0,0, this.DisplayRectangle.Width-1,this.DisplayRectangle.Height-1));} break; } case State.Hot: case State.DropDown: { {g.DrawRectangle(new Pen(CustomControls.BaseClasses.AppColors.HighlightColorDarkDark),new Rectangle(0,0, this.Width-1,this.Height-1));} break; } } } break; } } } protected virtual void DrawButton(Graphics g ) { if (DropDownStyle!=ComboBoxStyle.Simple) { Color backColor=(this.Parent!=null)?Parent.BackColor:CustomControls.BaseClasses.AppColors.ControlColor; Color arrowColor=CustomControls.BaseClasses.AppColors.TextColor; Rectangle backRect=ButtonRectangle; if (Enabled) { switch (State) { case State.Normal: { if (CustomBorderStyle!=Enumerations.CustomBorderStyle.FixedSingle) { backRect=new Rectangle(backRect.Left+1,backRect.Top+1,backRect.Width-2,backRect.Height-2); } break; } case State.Hot: { backColor=CustomControls.BaseClasses.AppColors.HighlightColor; break; } case State.DropDown: { backColor=CustomControls.BaseClasses.AppColors.HighlightColorDark; arrowColor=CustomControls.BaseClasses.AppColors.WindowColor; break; } } } else { if (CustomBorderStyle!=Enumerations.CustomBorderStyle.FixedSingle) { backRect=new Rectangle(backRect.Left+1,backRect.Top+1,backRect.Width-2,backRect.Height-2); } arrowColor=CustomControls.BaseClasses.AppColors.ControlColorDark; } g.FillRectangle(new SolidBrush(backColor), backRect); DrawArrow(g,backRect,arrowColor); } } private Point[] GetArrowPoligon(Rectangle ButtonRectangle) { Point[] pts = new Point[3]; pts[0] = new Point(ButtonRectangle.Left + ButtonRectangle.Width/2-2 , ButtonRectangle.Top + ButtonRectangle.Height/2-1); pts[1] = new Point(ButtonRectangle.Left + ButtonRectangle.Width/2 +3, ButtonRectangle.Top + ButtonRectangle.Height/2-1); pts[2] = new Point(ButtonRectangle.Left + ButtonRectangle.Width/2, (ButtonRectangle.Top + ButtonRectangle.Height/2-1) + 3); return pts; } private void DrawArrow(Graphics g,Rectangle bounds,Color ArrowColor) { g.FillPolygon(new SolidBrush(ArrowColor),GetArrowPoligon(bounds)); } private void DrawButtonLLVLine(Graphics g) { if(DropDownStyle!=ComboBoxStyle.Simple ) { bool drawLine=false; Color lineColor=SystemColors.ControlText; switch (CustomBorderStyle) { case Enumerations.CustomBorderStyle.FixedSingle: { drawLine=true; break; } case Enumerations.CustomBorderStyle.Hot: { if (Enabled ) { if(State!=State.Normal) { drawLine=true; lineColor=CustomControls.BaseClasses.AppColors.HighlightColorDarkDark; } } else { drawLine=true; lineColor=CustomControls.BaseClasses.AppColors.ToolbarBackColor; } break; } } if (drawLine) { Rectangle cr=ClientRectangle; Point pt= new Point(cr.Right-buttonWidth-1,cr.Top); Point pb= new Point(cr.Right-buttonWidth-1, cr.Bottom); g.DrawLine(new Pen(lineColor),pt, pb); } } } protected virtual void ShowDropDownForm() { if(!Initialized){EndInit();} dropDownForm.Location=GetBestDisplayPoint( PointToScreen(new Point(0,Height)),dropDownForm.Size,this.Height); OnDropDown(new System.EventArgs()); dropDownForm.Show(); if(DropDownStyle!=ComboBoxStyle.DropDownList){editControl.Focus();} else{this.Focus();} } protected virtual void HideDropDownForm() { dropDownForm.Hide(); } private Point GetBestDisplayPoint(Point OriginPoint, Size WindowSize, int yJump) { int tmpX=OriginPoint.X; int tmpY=OriginPoint.Y; int ScreenHeight=Screen.PrimaryScreen.WorkingArea.Height; int ScreenWidth=Screen.PrimaryScreen.WorkingArea.Width; if(ScreenHeight- tmpY-WindowSize.Height<0) { tmpY-=WindowSize.Height+yJump; } tmpX=Math.Min( Math.Max(0,tmpX),ScreenWidth-WindowSize.Width); return new Point(tmpX,tmpY); } private void RefreshEditRectangle() { editControl.Size= new Size(EditRectangle.Width,EditRectangle.Height); editControl.Location= new Point(ClientRectangle.Left, ClientRectangle.Top); } private void editControl_TextChanged(object sender,EventArgs e) { OnTextChanged(e); } private Size GetDefaultSize() { return new Size(this.Width,20); } protected RectangleF GetTextRectangle(int TextHeight,Rectangle bounds) { return new RectangleF(bounds.X+2 , bounds.Y + Math.Max(0, (bounds.Height - TextHeight) / 2), Math.Max(bounds.Width-4, 1), bounds.Height - Math.Max(0, (bounds.Height - TextHeight) / 2)); } #endregion } } namespace CustomControls.Enumerations { #region "Enumerations" public enum CustomBorderStyle { None=0, FixedSingle=1, Hot=2 } public enum State { Normal=0, Hot=1, DropDown=2 } public enum DisplayPosition { TopLeft=0, TopRight=1, BottonLeft=2, BottomRight=3 } public enum ButtonState { Normal=0, Hot=1, Pushed=2, DropDown=3 } #endregion }