// // System.Windows.Forms.StatusBar.cs // // Author: // stubbed out by Daniel Carrera (dcarrera@math.toronto.edu) // stubbed out by Richard Baumann (biochem333@nyc.rr.com) // Dennis Hayes (dennish@Raytek.com) // Aleksey Ryabchuk (ryabchuk@yahoo.com) // // (C) 2002 Ximian, Inc // using System; using System.Collections; using System.Drawing; using System.ComponentModel; using System.Runtime.InteropServices; namespace System.Windows.Forms { // // Represents a Windows status bar control. // public class StatusBar : Control { private bool sizingGrip; private bool showPanels; private StatusBarPanelCollection panels; private string stext; private const int GripSize = 16; // FIXME: get size from SystemMetrics private const int PanelGap = 2; // FIXME: get size from StatusBar private const int TextOffset = 3; internal DockStyle dockstyle; public StatusBar() : base() { Dock = DockStyle.Bottom; showPanels = false; sizingGrip = true; Size = DefaultSize; } public override string ToString() { string str = "System.Windows.Forms.StatusBar, Panels.Count: "; str += Panels.Count; for ( int i = 0; i < Panels.Count ; i++ ) { str += ", Panels[" + i + "]: " + Panels[i].ToString ( ); } return str; } [MonoTODO] protected override void CreateHandle() { base.CreateHandle(); } protected virtual void OnDrawItem(StatusBarDrawItemEventArgs e) { if( DrawItem != null) DrawItem ( this, e ); } protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); SetPanelsImpl ( ); } [MonoTODO] protected override void OnHandleDestroyed(EventArgs e) { //FIXME: base.OnHandleDestroyed(e); } [MonoTODO] protected override void OnLayout(LayoutEventArgs e) { //FIXME: base.OnLayout(e); } [MonoTODO] protected override void OnMouseDown(MouseEventArgs e) { //FIXME: base.OnMouseDown(e); } protected virtual void OnPanelClick(StatusBarPanelClickEventArgs e) { if ( PanelClick != null ) PanelClick ( this , e ); } [MonoTODO] protected override void OnResize(EventArgs e) { UpdatePanels( true, false, null ); base.OnResize(e); } [MonoTODO] protected override void WndProc(ref Message m) { switch ( m.Msg ) { case Msg.WM_DRAWITEM: DRAWITEMSTRUCT dis = new DRAWITEMSTRUCT(); dis = (DRAWITEMSTRUCT)Marshal.PtrToStructure( m.LParam, dis.GetType() ); if ( dis.itemID < Panels.Count ) { OnDrawItem ( new StatusBarDrawItemEventArgs ( Graphics.FromHdc ( dis.hDC ), Font, new Rectangle( dis.rcItem.left, dis.rcItem.top, dis.rcItem.right - dis.rcItem.left, dis.rcItem.bottom - dis.rcItem.top), dis.itemID, (DrawItemState)dis.itemState, Panels[dis.itemID] ) ); } m.Result = (IntPtr)1; break; case Msg.WM_NOTIFY: // FIXME break; default: base.WndProc(ref m); break; } } public event StatusBarDrawItemEventHandler DrawItem; public event StatusBarPanelClickEventHandler PanelClick; public override Color BackColor { get { return base.BackColor; } set { base.BackColor = value; } } public override Image BackgroundImage { get { return base.BackgroundImage; } set { base.BackgroundImage = value; } } //FIXME: [MonoTODO] public override DockStyle Dock { get { return dockstyle; } set { dockstyle = value; } } public override Font Font { get { return base.Font; } set { base.Font = value; } } public override Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; } } public new ImeMode ImeMode { get { return DefaultImeMode; } set { } } public StatusBar.StatusBarPanelCollection Panels { get { if( panels == null ) panels = new StatusBar.StatusBarPanelCollection( this ); return panels; } } public bool ShowPanels { get { return showPanels; } set { showPanels = value; SetPanelsImpl ( ); } } [MonoTODO] public bool SizingGrip { get { return sizingGrip; } set { // the only way to get rid of the grip dynamically // is to recreate window bool recreate = sizingGrip != value; sizingGrip = value; if ( IsHandleCreated && recreate ) RecreateHandle(); } } [MonoTODO] public new bool TabStop { get { return false; } set { } } [MonoTODO] public override string Text { get { // should reuse base.Text ? return stext; } set { stext = value; if ( IsHandleCreated ) UpdateStatusText ( ); } } // // --- Protected Properties // [MonoTODO] protected override CreateParams CreateParams { get { CreateParams createParams = new CreateParams (); createParams.Caption = Text; createParams.ClassName = "msctls_statusbar32"; createParams.X = Left; createParams.Y = Top; createParams.Width = Width; createParams.Height = Height; createParams.ClassStyle = 0; createParams.ExStyle = 0; createParams.Param = 0; createParams.Parent = Parent.Handle; createParams.Style = (int) ( WindowStyles.WS_CHILD | WindowStyles.WS_VISIBLE | WindowStyles.WS_OVERLAPPED | WindowStyles.WS_CLIPCHILDREN | WindowStyles.WS_CLIPCHILDREN ); if( SizingGrip ) createParams.Style |= (int)StatusbarControlStyles.SBARS_SIZEGRIP; createParams.Style |= (int)StatusbarControlStyles.SBT_TOOLTIPS; return createParams; } } protected override ImeMode DefaultImeMode { get { return ImeMode.Disable; } } protected override Size DefaultSize { get { return new Size ( 100, 22 ); } } internal void UpdateParts ( ) { if ( Panels.Count > 0) { int[] array = new int[ panels.Count ]; CalculatePanelWidths ( array ); int size = array.Length; IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( size ) * size ); Marshal.Copy( array, 0, buffer, size ); Win32.SendMessage( Handle, (int)StatusbarMessages.SB_SETPARTS, size, buffer.ToInt32() ); Win32.SendMessage( Handle, (int)StatusbarMessages.SB_SIMPLE, 0, 0 ); Marshal.FreeCoTaskMem( buffer ); } else { Win32.SendMessage( Handle, (int)StatusbarMessages.SB_SIMPLE, 1, 0 ); UpdateStatusText ( ); } } internal void UpdateText ( StatusBarPanel p ) { // if p is not null then this call is request to // update text in some specific panel for (int i = 0; i < panels.Count; i++ ) { if ( p != null && p != panels[i] ) continue; int DrawStyle = i; if ( panels[i].Style == StatusBarPanelStyle.OwnerDraw ) DrawStyle |= (int)StatusbarDrawType.SBT_OWNERDRAW; switch ( panels[i].BorderStyle ) { case StatusBarPanelBorderStyle.None: DrawStyle |= (int)StatusbarDrawType.SBT_NOBORDERS; break; case StatusBarPanelBorderStyle.Raised: DrawStyle |= (int)StatusbarDrawType.SBT_POPOUT; break; } string TextToSet; switch ( panels[i].Alignment ) { case HorizontalAlignment.Center: TextToSet = panels[i].Text.Insert( 0, "\t" ); break; case HorizontalAlignment.Right: TextToSet = panels[i].Text.Insert( 0, "\t\t" ); break; default: TextToSet = panels[i].Text; break; } Win32.SendMessage( Handle, (int)StatusbarMessages.SB_SETTEXT, DrawStyle, TextToSet ); } } internal void UpdateToolTips ( StatusBarPanel p ) { // if p == null set tooltips for each panel for (int i = 0; i < panels.Count; i++ ) { if ( p != null && p != panels[i] ) continue; Win32.SendMessage ( Handle, (int)StatusbarMessages.SB_SETTIPTEXT, i , panels[i].ToolTipText ); } } internal void UpdatePanels ( bool updateParts, bool updateText, StatusBarPanel p ) { if ( IsHandleCreated ) { if ( updateParts ) UpdateParts ( ); if ( updateText ) UpdateText( p ); Invalidate( ); } } protected void CalculatePanelWidths ( int[] array ) { int[] WidthArray = new int[panels.Count]; int FixedWidth = ClientSize.Width - (SizingGrip == true ? GripSize : 0); int NumSpringPanels = 0; for (int i = 0; i < panels.Count; i++ ) { switch ( panels[i].AutoSize ) { case StatusBarPanelAutoSize.None: WidthArray[i] = panels[i].Width + (PanelGap + TextOffset)*2; break; case StatusBarPanelAutoSize.Contents: WidthArray[i] = panels[i].GetContentWidth( ) + (PanelGap + TextOffset)*2; break; default: WidthArray[i] = 0; NumSpringPanels++; break; } FixedWidth -= WidthArray[i]; } int SpringPanelLength = 0; if ( NumSpringPanels > 0 && FixedWidth > 0) SpringPanelLength = FixedWidth / NumSpringPanels; for (int i = 0; i < panels.Count; i++ ) { if ( panels[i].AutoSize == StatusBarPanelAutoSize.Spring) WidthArray[i] = SpringPanelLength > panels[i].MinWidth ? SpringPanelLength : panels[i].MinWidth; } for (int i = 0; i < panels.Count; i++ ) array[i] = WidthArray[i] + (i == 0 ? 0 : array[i - 1]); } internal void UpdateStatusText ( ){ Win32.SendMessage( Handle, (int)StatusbarMessages.SB_SETTEXT, 255 | (int)StatusbarDrawType.SBT_NOBORDERS, Text ); } internal void SetPanelsImpl ( ) { if( IsHandleCreated ) { if ( base.Font.ToHfont ( ) != IntPtr.Zero ) Win32.SendMessage ( Handle, Msg.WM_SETFONT, base.Font.ToHfont().ToInt32(), 0 ); if( panels == null || panels.Count == 0 || showPanels == false) { Win32.SendMessage( Handle, (int)StatusbarMessages.SB_SIMPLE, 1, 0 ); UpdateStatusText ( ); } else { UpdatePanels ( true, true, null ); UpdateToolTips ( null ); } } } // // System.Windows.Forms.StatusBar.StatusBarPanelCollection // // Author: // stubbed out by Richard Baumann (biochem333@nyc.rr.com) // stub ammended by Jaak Simm (jaaksimm@firm.ee) // Implemented by Richard Baumann // (C) Ximian, Inc., 2002 // // // Represents the collection of panels in a StatusBar control. // public class StatusBarPanelCollection : IList, ICollection, IEnumerable { private ArrayList list; private StatusBar owner; public StatusBarPanelCollection( StatusBar owner ) : base() { list = new ArrayList(); this.owner = owner; } public virtual int Add( StatusBarPanel value ) { if (value == null) throw new ArgumentNullException("value"); if (value.Parent != null) throw new ArgumentException("Object already has a parent.", "value"); value.SetParent( owner ); int Index = list.Add( value ); owner.UpdatePanels ( true, true, null ); return Index; } public virtual StatusBarPanel Add( string text ) { StatusBarPanel panel = new StatusBarPanel(); panel.Text = text; this.Add ( panel ); return panel; } public virtual void AddRange(StatusBarPanel[] panels) { if (panels == null) throw new ArgumentNullException("panels"); // do we need to check for panel.Parent // like it is done in Add(StatusBarPanel) ? for (int i = 0; i < panels.Length; i++) panels[i].SetParent( owner ); list.AddRange(panels); owner.UpdatePanels ( true, true, null ); } public virtual void Clear() { for (int i = 0; i < list.Count; i++ ) ((StatusBarPanel)list[i]).SetParent ( null ); list.Clear(); owner.UpdatePanels ( true, true, null ); } public bool Contains(StatusBarPanel panel) { return list.Contains(panel); } public IEnumerator GetEnumerator() { return list.GetEnumerator(); } public int IndexOf(StatusBarPanel panel) { return list.IndexOf(panel); } public virtual void Insert(int index, StatusBarPanel value) { if (value == null) throw new ArgumentNullException ( "value" ); if (value.Parent != null) throw new ArgumentException ( "Object already has a parent.", "value" ); if (index < 0 || index > Count ) throw new ArgumentOutOfRangeException( "index" ); // very strange place to check autosize property :-)) if ( !Enum.IsDefined ( typeof(StatusBarPanelAutoSize), value.AutoSize ) ) throw new InvalidEnumArgumentException( "AutoSize", (int)value.AutoSize, typeof(StatusBarPanelAutoSize)); list.Insert(index, value); value.SetParent ( owner ); owner.UpdatePanels ( true, true , null ); } public virtual void Remove(StatusBarPanel value) { if (value == null) throw new ArgumentNullException( "value" ); list.Remove( value ); value.SetParent ( null ); } public virtual void RemoveAt(int index) { if (index < 0 || index > Count ) throw new ArgumentOutOfRangeException( "index" ); StatusBarPanel p = (StatusBarPanel)list[index]; list.RemoveAt(index); p.SetParent ( null ); owner.UpdatePanels( true, true, null ); } [MonoTODO] // This member supports the .NET Framework void ICollection.CopyTo(Array array, int index) { if (array == null) throw new ArgumentNullException ( "array" ); if (index < 0) throw new ArgumentOutOfRangeException ( "index" ); if (array.Rank != 1 || index >= array.Length || Count+index >= array.Length) throw new ArgumentException ( ); // FIXME: messages // easier/quicker to let the runtime throw the invalid cast exception if necessary for (int i = 0; index < array.Length; i++, index++) array.SetValue(list[i], index); } [MonoTODO] int IList.Add(object panel) { if (!(panel is StatusBarPanel)) throw new ArgumentException();//FIXME: message return Add((StatusBarPanel) panel); } bool IList.Contains(object panel) { if (!(panel is StatusBarPanel)) return false; return Contains((StatusBarPanel) panel); } int IList.IndexOf(object panel) { if (!(panel is StatusBarPanel)) return -1; return IndexOf((StatusBarPanel) panel); } [MonoTODO] void IList.Insert(int index, object panel) { if (!(panel is StatusBarPanel)) throw new ArgumentException();//FIXME: message Insert(index, (StatusBarPanel) panel); } [MonoTODO] void IList.Remove(object panel) { if (!(panel is StatusBarPanel)) throw new ArgumentException(); //FIXME: message Remove((StatusBarPanel) panel); } public int Count { get { return list.Count; } } public bool IsReadOnly { get { return false; } } object IList.this[int index] { get { return this[index]; } set { this[index]= (StatusBarPanel)value; } } public virtual StatusBarPanel this[int index] { get { // The same checks are done by the list, so this is redundant // This is left here in case you prefer better exception messages over performance //string method_string = "get_Item(int) "; //if (index < 0) //{ // throw new ArgumentOutOfRangeException(class_string + method_string + "index < 0"); //} //if (index >= Count) //{ // throw new ArgumentOutOfRangeException(class_string + method_string + "index >= Count"); //} return (StatusBarPanel)list[index]; } set { // The same checks are done by the list, so this is redundant // This is left here in case you prefer better exception messages over performance //string method_string = "set_Item(int,StatusBarPanel) "; //if (index < 0) //{ // throw new ArgumentOutOfRangeException(class_string + method_string + "index < 0"); //} //if (index >= Count) //{ // throw new ArgumentOutOfRangeException(class_string + method_string + "index >= Count"); //} //if (value == null) //{ // throw new ArgumentNullException(class_string + method_string + "panel == null"); //} list[index] = value; } } bool IList.IsFixedSize { [MonoTODO] get { throw new NotImplementedException (); } } object ICollection.SyncRoot { [MonoTODO] get { throw new NotImplementedException (); } } bool ICollection.IsSynchronized { [MonoTODO] get { throw new NotImplementedException (); } } private bool IsFixedSize { get { return false; } } } } }