2 // System.Windows.Forms.StatusBar.cs
5 // stubbed out by Daniel Carrera (dcarrera@math.toronto.edu)
6 // stubbed out by Richard Baumann (biochem333@nyc.rr.com)
7 // Dennis Hayes (dennish@Raytek.com)
8 // Aleksey Ryabchuk (ryabchuk@yahoo.com)
10 // (C) 2002/3 Ximian, Inc
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System
.Collections
;
37 using System
.ComponentModel
;
38 using System
.Runtime
.InteropServices
;
40 namespace System
.Windows
.Forms
{
43 // Represents a Windows status bar control.
45 public class StatusBar
: Control
{
47 private bool sizingGrip
;
48 private bool showPanels
;
49 private StatusBarPanelCollection panels
;
51 private const int GripSize
= 16; // FIXME: get size from SystemMetrics
52 private const int PanelGap
= 2; // FIXME: get size from StatusBar
53 private const int TextOffset
= 3;
54 internal DockStyle dockstyle
;
56 public StatusBar() : base()
58 Dock
= DockStyle
.Bottom
;
64 public override string ToString()
66 string str
= "System.Windows.Forms.StatusBar, Panels.Count: ";
68 for ( int i
= 0; i
< Panels
.Count
; i
++ ) {
70 str
+= ", Panels[" + i
+ "]: " + Panels
[i
].ToString ( );
75 protected override void CreateHandle()
77 initCommonControlsLibrary ( );
82 protected override void Dispose(bool disposing
) {
84 base.Dispose(disposing
);
87 protected virtual void OnDrawItem(StatusBarDrawItemEventArgs e
)
93 protected override void OnHandleCreated(EventArgs e
)
95 base.OnHandleCreated(e
);
100 protected override void OnHandleDestroyed(EventArgs e
)
103 base.OnHandleDestroyed(e
);
107 protected override void OnLayout(LayoutEventArgs e
)
110 if ( IsHandleCreated
)
115 protected override void OnMouseDown(MouseEventArgs e
)
121 protected virtual void OnPanelClick(StatusBarPanelClickEventArgs e
)
123 if ( PanelClick
!= null )
124 PanelClick ( this , e
);
128 protected override void OnResize(EventArgs e
)
130 UpdatePanels( true, false, null );
135 protected override void WndProc(ref Message m
)
137 switch ((Msg
) m
.Msg
) {
138 case Msg
.WM_DRAWITEM
:
139 DRAWITEMSTRUCT dis
= new DRAWITEMSTRUCT();
140 dis
= (DRAWITEMSTRUCT
)Marshal
.PtrToStructure( m
.LParam
, dis
.GetType() );
142 if ( dis
.itemID
< Panels
.Count
) {
144 new StatusBarDrawItemEventArgs (
145 Graphics
.FromHdc ( dis
.hDC
),
147 new Rectangle( dis
.rcItem
.left
,
149 dis
.rcItem
.right
- dis
.rcItem
.left
,
150 dis
.rcItem
.bottom
- dis
.rcItem
.top
),
152 (DrawItemState
)dis
.itemState
,
153 Panels
[dis
.itemID
] ) );
155 m
.Result
= (IntPtr
)1;
166 public event StatusBarDrawItemEventHandler DrawItem
;
167 public event StatusBarPanelClickEventHandler PanelClick
;
169 public override Color BackColor
{
170 get { return base.BackColor; }
171 set { base.BackColor = value; }
174 public override Image BackgroundImage
{
175 get { return base.BackgroundImage; }
176 set { base.BackgroundImage = value; }
181 public override DockStyle Dock
{
190 public override Font Font
{
192 get { return base.Font; }
193 set { base.Font = value; }
196 public override Color ForeColor
{
198 get { return base.ForeColor; }
199 set { base.ForeColor = value; }
202 public new ImeMode ImeMode
{
204 get { return DefaultImeMode; }
208 public StatusBar
.StatusBarPanelCollection Panels
{
211 panels
= new StatusBar
.StatusBarPanelCollection( this );
216 public bool ShowPanels
{
217 get { return showPanels; }
225 public bool SizingGrip
227 get { return sizingGrip; }
229 // the only way to get rid of the grip dynamically
230 // is to recreate window
231 bool recreate
= sizingGrip
!= value;
233 if ( IsHandleCreated
&& recreate
)
239 public new bool TabStop
{
240 get { return false; }
245 public override string Text
{
246 get { // should reuse base.Text ?
251 if ( IsHandleCreated
)
252 UpdateStatusText ( );
257 // --- Protected Properties
260 protected override CreateParams CreateParams
{
262 CreateParams createParams
= base.CreateParams
;
264 createParams
.ClassName
= "msctls_statusbar32";
266 createParams
.Style
= (int) (
267 WindowStyles
.WS_CHILD
|
268 WindowStyles
.WS_VISIBLE
|
269 WindowStyles
.WS_OVERLAPPED
|
270 WindowStyles
.WS_CLIPCHILDREN
|
271 WindowStyles
.WS_CLIPCHILDREN
) |
272 (int)( CommonControlStyles
.CCS_NORESIZE
);
275 createParams
.Style
|= (int)StatusbarControlStyles
.SBARS_SIZEGRIP
;
277 createParams
.Style
|= (int)StatusbarControlStyles
.SBT_TOOLTIPS
;
283 protected override ImeMode DefaultImeMode
{
284 get { return ImeMode.Disable; }
287 protected override Size DefaultSize
{
288 get { return new Size ( 100, 22 ); }
291 internal void UpdateParts ( ) {
292 if ( Panels
.Count
> 0) {
293 int[] array
= new int[ panels
.Count
];
295 CalculatePanelWidths ( array
);
296 int size
= array
.Length
;
298 IntPtr buffer
= Marshal
.AllocHGlobal ( Marshal
.SizeOf( size
) * size
);
299 Marshal
.Copy( array
, 0, buffer
, size
);
300 Win32
.SendMessage( Handle
, (int)StatusbarMessages
.SB_SETPARTS
, size
, buffer
.ToInt32() );
301 Win32
.SendMessage( Handle
, (int)StatusbarMessages
.SB_SIMPLE
, 0, 0 );
302 Marshal
.FreeHGlobal ( buffer
);
305 Win32
.SendMessage( Handle
, (int)StatusbarMessages
.SB_SIMPLE
, 1, 0 );
306 UpdateStatusText ( );
310 internal void UpdateText ( StatusBarPanel p
) {
311 // if p is not null then this call is request to
312 // update text in some specific panel
313 for (int i
= 0; i
< panels
.Count
; i
++ ) {
314 if ( p
!= null && p
!= panels
[i
] )
319 if ( panels
[i
].Style
== StatusBarPanelStyle
.OwnerDraw
)
320 DrawStyle
|= (int)StatusbarDrawType
.SBT_OWNERDRAW
;
322 switch ( panels
[i
].BorderStyle
)
324 case StatusBarPanelBorderStyle
.None
:
325 DrawStyle
|= (int)StatusbarDrawType
.SBT_NOBORDERS
;
327 case StatusBarPanelBorderStyle
.Raised
:
328 DrawStyle
|= (int)StatusbarDrawType
.SBT_POPOUT
;
334 switch ( panels
[i
].Alignment
) {
335 case HorizontalAlignment
.Center
:
336 TextToSet
= panels
[i
].Text
.Insert( 0, "\t" );
338 case HorizontalAlignment
.Right
:
339 TextToSet
= panels
[i
].Text
.Insert( 0, "\t\t" );
342 TextToSet
= panels
[i
].Text
;
346 Win32
.SendMessage( Handle
, (int)StatusbarMessages
.SB_SETTEXT
, DrawStyle
,
351 internal void UpdateToolTips ( StatusBarPanel p
) {
352 // if p == null set tooltips for each panel
353 for (int i
= 0; i
< panels
.Count
; i
++ ) {
354 if ( p
!= null && p
!= panels
[i
] )
357 Win32
.SendMessage ( Handle
, (int)StatusbarMessages
.SB_SETTIPTEXT
, i
,
358 panels
[i
].ToolTipText
);
362 internal void UpdatePanels ( bool updateParts
, bool updateText
, StatusBarPanel p
) {
363 if ( IsHandleCreated
) {
374 protected void CalculatePanelWidths ( int[] array
) {
375 int[] WidthArray
= new int[panels
.Count
];
377 int FixedWidth
= ClientSize
.Width
- (SizingGrip
== true ? GripSize
: 0);
378 int NumSpringPanels
= 0;
380 for (int i
= 0; i
< panels
.Count
; i
++ ) {
381 switch ( panels
[i
].AutoSize
) {
382 case StatusBarPanelAutoSize
.None
:
383 WidthArray
[i
] = panels
[i
].Width
+ (PanelGap
+ TextOffset
)*2;
385 case StatusBarPanelAutoSize
.Contents
:
386 WidthArray
[i
] = panels
[i
].GetContentWidth( ) + (PanelGap
+ TextOffset
)*2;
393 FixedWidth
-= WidthArray
[i
];
396 int SpringPanelLength
= 0;
397 if ( NumSpringPanels
> 0 && FixedWidth
> 0)
398 SpringPanelLength
= FixedWidth
/ NumSpringPanels
;
400 for (int i
= 0; i
< panels
.Count
; i
++ ) {
401 if ( panels
[i
].AutoSize
== StatusBarPanelAutoSize
.Spring
)
402 WidthArray
[i
] = SpringPanelLength
> panels
[i
].MinWidth
?
403 SpringPanelLength
: panels
[i
].MinWidth
;
406 for (int i
= 0; i
< panels
.Count
; i
++ )
407 array
[i
] = WidthArray
[i
] + (i
== 0 ? 0 : array
[i
- 1]);
410 internal void UpdateStatusText ( ){
411 Win32
.SendMessage( Handle
, (int)StatusbarMessages
.SB_SETTEXT
,
412 255 | (int)StatusbarDrawType
.SBT_NOBORDERS
, Text
);
415 internal void SetPanelsImpl ( ) {
416 if( IsHandleCreated
) {
417 if ( base.Font
.ToHfont ( ) != IntPtr
.Zero
)
418 Win32
.SendMessage ( Handle
, Msg
.WM_SETFONT
, base.Font
.ToHfont().ToInt32(), 0 );
420 if( panels
== null || panels
.Count
== 0 || showPanels
== false) {
421 Win32
.SendMessage( Handle
, (int)StatusbarMessages
.SB_SIMPLE
, 1, 0 );
422 UpdateStatusText ( );
425 UpdatePanels ( true, true, null );
426 UpdateToolTips ( null );
431 private void initCommonControlsLibrary ( ) {
432 if ( !RecreatingHandle
) {
433 INITCOMMONCONTROLSEX initEx
= new INITCOMMONCONTROLSEX();
434 initEx
.dwICC
= CommonControlInitFlags
.ICC_BAR_CLASSES
;
435 Win32
.InitCommonControlsEx(initEx
);
440 // System.Windows.Forms.StatusBar.StatusBarPanelCollection
443 // stubbed out by Richard Baumann (biochem333@nyc.rr.com)
444 // stub ammended by Jaak Simm (jaaksimm@firm.ee)
445 // Implemented by Richard Baumann <biochem333@nyc.rr.com>
446 // (C) Ximian, Inc., 2002
449 // Represents the collection of panels in a StatusBar control.
451 public class StatusBarPanelCollection
: IList
, ICollection
, IEnumerable
{
452 private ArrayList list
;
453 private StatusBar owner
;
455 public StatusBarPanelCollection( StatusBar owner
) : base() {
456 list
= new ArrayList();
460 public virtual int Add( StatusBarPanel
value ) {
462 throw new ArgumentNullException("value");
464 if (value.Parent
!= null)
465 throw new ArgumentException("Object already has a parent.", "value");
467 value.SetParent( owner
);
468 int Index
= list
.Add( value );
470 owner
.UpdatePanels ( true, true, null );
474 public virtual StatusBarPanel
Add( string text
) {
475 StatusBarPanel panel
= new StatusBarPanel();
481 public virtual void AddRange(StatusBarPanel
[] panels
) {
483 throw new ArgumentNullException("panels");
485 // do we need to check for panel.Parent
486 // like it is done in Add(StatusBarPanel) ?
488 for (int i
= 0; i
< panels
.Length
; i
++)
489 panels
[i
].SetParent( owner
);
491 list
.AddRange(panels
);
492 owner
.UpdatePanels ( true, true, null );
495 public virtual void Clear() {
496 for (int i
= 0; i
< list
.Count
; i
++ )
497 ((StatusBarPanel
)list
[i
]).SetParent ( null );
500 owner
.UpdatePanels ( true, true, null );
503 public bool Contains(StatusBarPanel panel
) {
504 return list
.Contains(panel
);
507 public IEnumerator
GetEnumerator() {
508 return list
.GetEnumerator();
511 public int IndexOf(StatusBarPanel panel
) {
512 return list
.IndexOf(panel
);
515 public virtual void Insert(int index
, StatusBarPanel
value) {
517 throw new ArgumentNullException ( "value" );
519 if (value.Parent
!= null)
520 throw new ArgumentException ( "Object already has a parent.", "value" );
522 if (index
< 0 || index
> Count
)
523 throw new ArgumentOutOfRangeException( "index" );
525 // very strange place to check autosize property :-))
526 if ( !Enum
.IsDefined ( typeof(StatusBarPanelAutoSize
), value.AutoSize
) )
527 throw new InvalidEnumArgumentException( "AutoSize",
529 typeof(StatusBarPanelAutoSize
));
531 list
.Insert(index
, value);
532 value.SetParent ( owner
);
533 owner
.UpdatePanels ( true, true , null );
536 public virtual void Remove(StatusBarPanel
value) {
538 throw new ArgumentNullException( "value" );
540 list
.Remove( value );
541 value.SetParent ( null );
544 public virtual void RemoveAt(int index
) {
545 if (index
< 0 || index
> Count
)
546 throw new ArgumentOutOfRangeException( "index" );
548 StatusBarPanel p
= (StatusBarPanel
)list
[index
];
549 list
.RemoveAt(index
);
550 p
.SetParent ( null );
551 owner
.UpdatePanels( true, true, null );
555 // This member supports the .NET Framework
556 void ICollection
.CopyTo(Array array
, int index
) {
558 throw new ArgumentNullException ( "array" );
561 throw new ArgumentOutOfRangeException ( "index" );
563 if (array
.Rank
!= 1 || index
>= array
.Length
|| Count
+index
>= array
.Length
)
564 throw new ArgumentException ( ); // FIXME: messages
566 // easier/quicker to let the runtime throw the invalid cast exception if necessary
567 for (int i
= 0; index
< array
.Length
; i
++, index
++)
568 array
.SetValue(list
[i
], index
);
572 int IList
.Add(object panel
)
574 if (!(panel
is StatusBarPanel
))
575 throw new ArgumentException();//FIXME: message
576 return Add((StatusBarPanel
) panel
);
579 bool IList
.Contains(object panel
)
581 if (!(panel
is StatusBarPanel
))
583 return Contains((StatusBarPanel
) panel
);
586 int IList
.IndexOf(object panel
) {
587 if (!(panel
is StatusBarPanel
))
589 return IndexOf((StatusBarPanel
) panel
);
593 void IList
.Insert(int index
, object panel
)
595 if (!(panel
is StatusBarPanel
))
596 throw new ArgumentException();//FIXME: message
598 Insert(index
, (StatusBarPanel
) panel
);
602 void IList
.Remove(object panel
)
604 if (!(panel
is StatusBarPanel
))
605 throw new ArgumentException(); //FIXME: message
607 Remove((StatusBarPanel
) panel
);
612 get { return list.Count; }
615 public bool IsReadOnly
{
616 get { return false; }
619 object IList
.this[int index
] {
620 get { return this[index]; }
621 set { this[index]= (StatusBarPanel)value; }
624 public virtual StatusBarPanel
this[int index
] {
627 // The same checks are done by the list, so this is redundant
628 // This is left here in case you prefer better exception messages over performance
629 //string method_string = "get_Item(int) ";
632 // throw new ArgumentOutOfRangeException(class_string + method_string + "index < 0");
634 //if (index >= Count)
636 // throw new ArgumentOutOfRangeException(class_string + method_string + "index >= Count");
638 return (StatusBarPanel
)list
[index
];
642 // The same checks are done by the list, so this is redundant
643 // This is left here in case you prefer better exception messages over performance
644 //string method_string = "set_Item(int,StatusBarPanel) ";
647 // throw new ArgumentOutOfRangeException(class_string + method_string + "index < 0");
649 //if (index >= Count)
651 // throw new ArgumentOutOfRangeException(class_string + method_string + "index >= Count");
655 // throw new ArgumentNullException(class_string + method_string + "panel == null");
661 bool IList
.IsFixedSize
{
662 [MonoTODO
] get { throw new NotImplementedException (); }
665 object ICollection
.SyncRoot
{
667 [MonoTODO
] get { throw new NotImplementedException (); }
670 bool ICollection
.IsSynchronized
{
672 [MonoTODO
] get { throw new NotImplementedException (); }
675 private bool IsFixedSize { get { return false; }
}