// // System.Windows.Forms.TabControl.cs // // Author: // stubbed out by Jackson Harper (jackson@latitudegeo.com) // Dennis Hayes (dennish@Raytek.com) // implemented by Aleksey Ryabchuk (ryabchuk@yahoo.com) // (C) 2002 Ximian, Inc // using System.ComponentModel; using System.Collections; using System.Drawing; using System.Runtime.InteropServices; namespace System.Windows.Forms { public class TabControl : Control { public class ControlCollection : Control.ControlCollection { public ControlCollection ( TabControl owner ): base( owner ){ } public override void Add( Control c ) { if ( !( c is TabPage ) ) { throw new ArgumentException(); } base.Add(c); if ( owner.IsHandleCreated ) ((TabControl) owner).addPage ( c, Count - 1); } public override void Clear () { base.Clear ( ); if ( owner.IsHandleCreated ) ((TabControl) owner).removeAllTabs ( ); } public override void Remove ( Control value ) { int index = IndexOf ( value ); base.Remove ( value ); if ( index != -1 && owner.IsHandleCreated ) ((TabControl) owner).removeTab ( value, index ); } } private int selectedIndex; private TabAlignment tabAlignment; private bool multiline; private TabAppearance appearance; private TabDrawMode tabDrawMode; private bool hotTrack; private Point padding; private Size itemSize; private TabSizeMode sizeMode; private bool showTooltips; private ImageList imageList; public TabControl() { SubClassWndProc_ = true; selectedIndex = -1; multiline = false; tabAlignment = TabAlignment.Top; appearance = TabAppearance.Normal; tabDrawMode = TabDrawMode.Normal; hotTrack = false; padding = new Point ( 6, 3 ); itemSize = Size.Empty; sizeMode = TabSizeMode.Normal; showTooltips = false; } public TabAlignment Alignment { get { return tabAlignment; } set { if ( !Enum.IsDefined ( typeof(TabAlignment), value ) ) throw new InvalidEnumArgumentException( "Alignment", (int)value, typeof(TabAlignment)); if ( tabAlignment != value ) { if ( value == TabAlignment.Right || value == TabAlignment.Left ) multiline = true; tabAlignment = value; recreate ( ); } } } public TabAppearance Appearance { get { return appearance; } set { if ( !Enum.IsDefined ( typeof(TabAppearance), value ) ) throw new InvalidEnumArgumentException( "Appearance", (int)value, typeof(TabAppearance)); if ( appearance != value ) { appearance = value; recreate ( ); } } } [EditorBrowsable (EditorBrowsableState.Never)] public override Color BackColor { get { return base.BackColor; } set { base.BackColor = value; } } [EditorBrowsable (EditorBrowsableState.Never)] public override Image BackgroundImage { get { return base.BackgroundImage; } set { base.BackgroundImage = value;} } public override Rectangle DisplayRectangle { get { RECT rect = new RECT( ); Rectangle disp = base.DisplayRectangle; rect.left = disp.Left; rect.top = disp.Top; rect.right= disp.Right; rect.bottom = disp.Bottom; Win32.SendMessage ( Handle, (int)TabControlMessages.TCM_ADJUSTRECT, 0, ref rect ); return new Rectangle ( rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); } } public TabDrawMode DrawMode { get { return tabDrawMode; } set { if ( !Enum.IsDefined ( typeof(TabDrawMode), value ) ) throw new InvalidEnumArgumentException( "DrawMode", (int)value, typeof(TabDrawMode)); if ( tabDrawMode != value ) { tabDrawMode = value; recreate ( ); } } } [EditorBrowsable (EditorBrowsableState.Never)] public override Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; } } public bool HotTrack { get { return hotTrack; } set { if ( hotTrack != value ) { hotTrack = value; recreate ( ); } } } public ImageList ImageList { get { return imageList; } set { if ( imageList != value ) { imageList = value; if ( IsHandleCreated ) setImageList ( imageList != null ? imageList.Handle : IntPtr.Zero ); } } } [MonoTODO] public Size ItemSize { get { return itemSize; } // FIXME: don't know how to get size initially set { if ( itemSize != value ) { if ( value.Width < 0 || value.Height < 0 ) throw new ArgumentException ( ); // FIXME: message itemSize = value; if ( IsHandleCreated ) setItemSize ( ); } } } public bool Multiline { get { return multiline; } set { if ( multiline != value ) { multiline = value; if ( multiline == false && ( Alignment == TabAlignment.Left || Alignment == TabAlignment.Right ) ) tabAlignment = TabAlignment.Top; recreate ( ); } } } public Point Padding { get { return padding; } set { if ( padding != value ) { if ( value.X < 0 || value.Y < 0 ) throw new ArgumentException ( string.Format ( "'{0}' is not a valid value for 'Padding'.", value ) ); padding = value; if ( IsHandleCreated ) setPadding ( ); } } } public int RowCount { get { if ( TabCount == 0) return 0; if ( Multiline == false ) return 1; // referencing this property creates handle in ms.swf return Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_GETROWCOUNT, 0, 0); } } public int SelectedIndex { get { return selectedIndex; } set { if ( selectedIndex != value ) { if ( value < -1 ) throw new ArgumentException ( string.Format( " '{0}' is not a valid value for 'value'. 'value' must be greater than or equal to -1.", value ) ); selectedIndex = value; if ( IsHandleCreated ) selectPage ( selectedIndex ); } } } public TabPage SelectedTab { get { if ( SelectedIndex >= 0 ) return TabPages[ SelectedIndex ]; return null; } set { int index = TabPages.IndexOf ( value ); if ( index >= 0 ) SelectedIndex = index; } } public bool ShowToolTips { get { return showTooltips; } set { if ( showTooltips != value ) { showTooltips = value; recreate ( ); } } } public TabSizeMode SizeMode { get { return sizeMode; } set { if ( !Enum.IsDefined ( typeof(TabSizeMode), value ) ) throw new InvalidEnumArgumentException( "SizeMode", (int)value, typeof(TabSizeMode)); if ( sizeMode != value ) { sizeMode = value; recreate ( ); } } } public int TabCount { get { return Controls.Count; } } public TabControl.TabPageCollection TabPages { get { return new TabPageCollection ( this ); } } [EditorBrowsable (EditorBrowsableState.Never)] public override string Text { get { return base.Text; } set { base.Text = value;} } public Rectangle GetTabRect( int index ) { if ( index < 0 || index >= TabCount ) throw new ArgumentOutOfRangeException( "index" ); RECT rect = new RECT(); Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_GETITEMRECT, index, ref rect ); return new Rectangle( rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top ); } public override string ToString() { string str = GetType().FullName.ToString () + ", TabPages.Count: "; str += TabCount.ToString ( ); for ( int i = 0; i < TabPages.Count ; i++ ) { str += ", TabPage[" + i + "]: " + TabPages[i].ToString ( ); } return str; } public event DrawItemEventHandler DrawItem; public event EventHandler SelectedIndexChanged; [MonoTODO] protected override CreateParams CreateParams { get { CreateParams createParams = base.CreateParams; createParams.ClassName = Win32.TABCONTROL; createParams.Style = (int) ( WindowStyles.WS_CHILD | WindowStyles.WS_VISIBLE | WindowStyles.WS_OVERLAPPED ) | (int) ( TabControlStyles.TCS_RAGGEDRIGHT ); if ( Multiline ) createParams.Style |= (int) TabControlStyles.TCS_MULTILINE; if (DrawMode == TabDrawMode.OwnerDrawFixed) createParams.Style |= (int) TabControlStyles.TCS_OWNERDRAWFIXED; if ( HotTrack ) createParams.Style |= (int) TabControlStyles.TCS_HOTTRACK; if ( ShowToolTips ) createParams.Style |= (int) TabControlStyles.TCS_TOOLTIPS; switch ( Alignment ) { case TabAlignment.Bottom: createParams.Style |= (int) TabControlStyles.TCS_BOTTOM; break; case TabAlignment.Left: createParams.Style |= (int) TabControlStyles.TCS_VERTICAL; break; case TabAlignment.Right: createParams.Style |= (int) ( TabControlStyles.TCS_RIGHT | TabControlStyles.TCS_VERTICAL ); break; } switch ( Appearance ) { case TabAppearance.Buttons: createParams.Style |= (int) TabControlStyles.TCS_BUTTONS; break; case TabAppearance.FlatButtons: createParams.Style |= (int) TabControlStyles.TCS_FLATBUTTONS; break; case TabAppearance.Normal: createParams.Style |= (int) TabControlStyles.TCS_TABS; break; } switch ( SizeMode ) { case TabSizeMode.Fixed: createParams.Style |= (int) TabControlStyles.TCS_FIXEDWIDTH; break; case TabSizeMode.FillToRight: createParams.Style |= (int) TabControlStyles.TCS_RIGHTJUSTIFY; break; } return createParams; } } protected override Size DefaultSize { get { return new System.Drawing.Size(200, 100); } } protected override Control.ControlCollection CreateControlsInstance() { return new ControlCollection ( this ); } protected override void CreateHandle() { initCommonControlsLibrary ( ); base.CreateHandle(); } [MonoTODO] protected override void Dispose(bool disposing) { // .NET V1.1 Beta. .needs implmentation base.Dispose(disposing); } [MonoTODO] protected override bool IsInputKey(Keys keyData) { return false; } [MonoTODO] protected virtual void OnDrawItem(DrawItemEventArgs e) { throw new NotImplementedException (); } [MonoTODO] protected override void OnFontChanged(EventArgs e) { throw new NotImplementedException (); } [MonoTODO] protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated ( e ); setPages ( ); setPadding ( ); setItemSize ( ); if ( imageList != null ) setImageList ( imageList.Handle ); } [MonoTODO] protected override void OnHandleDestroyed(EventArgs e) { base.OnHandleDestroyed ( e ); } [MonoTODO] protected override void OnKeyDown(KeyEventArgs ke) { base.OnKeyDown( ke ); } [MonoTODO] protected override void OnResize(EventArgs e) { for ( int i = 0; i < Controls.Count; i++ ) Controls[ i ].SetBounds ( 0, 0, 0, 0, BoundsSpecified.None ); base.OnResize ( e ); } protected virtual void OnSelectedIndexChanged(EventArgs e) { if ( SelectedIndexChanged != null ) SelectedIndexChanged ( this, e ); } [MonoTODO] protected override void OnStyleChanged(EventArgs e) { throw new NotImplementedException (); } [MonoTODO] protected override bool ProcessKeyPreview(ref Message m) { return base.ProcessKeyPreview( ref m ); } protected void RemoveAll() { Controls.Clear ( ); } protected override void OnCreateControl () { // create pages as needed } [MonoTODO] protected override void WndProc(ref Message m) { switch ((Msg) m.Msg ) { case Msg.WM_NOTIFY: NMHDR nmhdr = (NMHDR)Marshal.PtrToStructure ( m.LParam, typeof ( NMHDR ) ); switch ( nmhdr.code ) { case (int)TabControlNotifications.TCN_SELCHANGE: selectedIndex = Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_GETCURSEL, 0, 0); updatePage ( selectedIndex , true ); OnSelectedIndexChanged ( EventArgs.Empty ); break; case (int)TabControlNotifications.TCN_SELCHANGING: m.Result = IntPtr.Zero; break; } break; default: base.WndProc ( ref m ); break; } } private void initCommonControlsLibrary ( ) { if ( !RecreatingHandle ) { INITCOMMONCONTROLSEX initEx = new INITCOMMONCONTROLSEX(); initEx.dwICC = CommonControlInitFlags.ICC_TAB_CLASSES; Win32.InitCommonControlsEx(initEx); } } private void update ( ) { } private void updatePage ( int index , bool doShowOrHide ) { if ( Controls.Count != 0 && index >=0 && index < Controls.Count ) { Control c = Controls[ index ]; if ( c.Created == false ) c.CreateControl ( ); c.SetBounds ( 0, 0, 0, 0, BoundsSpecified.None ); if ( doShowOrHide ) showOrHidePages( index ); } } private void setPages ( ) { for (int i = 0; i < Controls.Count; i++ ) addPage ( Controls[i], i ); } private void addPage ( Control page, int index ) { TabPage tabPage = page as TabPage; if ( tabPage.isAdded ) return; TCITEM header = new TCITEM(); header.mask = (uint) ( TabControlItemFlags.TCIF_TEXT | TabControlItemFlags.TCIF_IMAGE ); header.pszText = tabPage.Text; header.iImage = tabPage.ImageIndex; sendMessageHelper ( TabControlMessages.TCM_INSERTITEM, index, ref header ); tabPage.isAdded = true; if ( !RecreatingHandle && index == SelectedIndex ) selectPage ( index ); } internal void pageTextChanged ( TabPage page ) { if ( IsHandleCreated ) { int index = Controls.IndexOf ( page ); if ( index != -1 ) { TCITEM header = new TCITEM(); header.mask = (uint) TabControlItemFlags.TCIF_TEXT; header.pszText = page.Text; sendMessageHelper ( TabControlMessages.TCM_SETITEM, index, ref header ); } } } internal void pageImageIndexChanged ( TabPage page ) { if ( IsHandleCreated ) { int index = Controls.IndexOf ( page ); if ( index != -1 ) { TCITEM header = new TCITEM(); header.mask = (uint) TabControlItemFlags.TCIF_IMAGE; header.iImage = page.ImageIndex; sendMessageHelper ( TabControlMessages.TCM_SETITEM, index, ref header ); } } } private void sendMessageHelper ( TabControlMessages mes, int index, ref TCITEM hdr ) { if ( IsHandleCreated ) { IntPtr ptr = Marshal.AllocHGlobal ( Marshal.SizeOf ( hdr ) ); Marshal.StructureToPtr( hdr, ptr, false ); Win32.SendMessage ( Handle , (int)mes, index, ptr.ToInt32() ); Marshal.FreeHGlobal ( ptr ); } } private void setPadding ( ) { Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_SETPADDING, 0, Win32.MAKELONG ( Padding.X, Padding.Y ) ); } private void setItemSize ( ) { if ( ItemSize != Size.Empty ) { Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_SETITEMSIZE, 0, Win32.MAKELONG ( ItemSize.Width, ItemSize.Height ) ); } } private void selectPage ( int selectedIndex ) { if ( selectedIndex != -1 ) { if ( Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_SETCURSEL, selectedIndex, 0 ) != -1 ) OnSelectedIndexChanged ( EventArgs.Empty ); } updatePage ( selectedIndex != -1 ? selectedIndex : 0 , true ); } private void removeAllTabs ( ) { for (int i = 0; i < Controls.Count; i++ ) ( ( TabPage ) Controls[i] ).isAdded = false; if ( IsHandleCreated ) Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_DELETEALLITEMS, 0, 0 ); } private void removeTab ( Control c, int index ) { if ( IsHandleCreated ) Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_DELETEITEM, index, 0 ); ( ( TabPage ) c ).isAdded = false; } private void showOrHidePages ( int index ) { for (int i = 0; i < Controls.Count; i++ ) Controls[i].Visible = ( i == index ) ? true : false; } private void setImageList ( IntPtr handle ) { Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_SETIMAGELIST, 0, handle.ToInt32 ( ) ); int CurrentPage = SelectedIndex; updatePage ( CurrentPage, false ); if ( Controls.Count != 0 && CurrentPage >=0 && CurrentPage < Controls.Count ) Controls [ CurrentPage ].Invalidate ( true ); } private void recreate ( ) { removeAllTabs ( ); if ( IsHandleCreated ) { RecreateHandle ( ); selectPage ( SelectedIndex ); } } public class TabPageCollection : IList, ICollection, IEnumerable { TabControl owner; Control.ControlCollection collection; public TabPageCollection( TabControl owner ) { this.owner = owner; collection = owner.Controls; } public int Count { get { return collection.Count; } } public bool IsReadOnly { get { return collection.IsReadOnly; } } [MonoTODO] public virtual TabPage this[int index] { get { return collection[ index ] as TabPage; } set { ( (IList)collection )[ index ] = value; owner.update ( ); } } public void Add(TabPage value) { collection.Add ( value ); } public void AddRange( TabPage[] pages ) { collection.AddRange ( pages ); } public virtual void Clear() { collection.Clear ( ); } public bool Contains( TabPage page ) { return collection.Contains ( page ); } public IEnumerator GetEnumerator() { return collection.GetEnumerator ( ); } public int IndexOf( TabPage page ) { return collection.IndexOf ( page ); } public void Remove( TabPage value ) { collection.Remove ( value ); } public void RemoveAt(int index) { collection.RemoveAt ( index ); } /// /// IList Interface implmentation. /// bool IList.IsReadOnly{ get{ return this.IsReadOnly; } } bool IList.IsFixedSize{ get{ return (( IList )collection).IsFixedSize; } } object IList.this[int index]{ get{ return collection [ index ]; } set{ if ( ! (value is TabPage) ) throw new ArgumentException ( ); this[ index ] = (TabPage) value; owner.update ( ); } } void IList.Clear(){ this.Clear ( ); } [MonoTODO] int IList.Add( object value ) { TabPage page = value as TabPage; if ( page == null ) throw new ArgumentException ( ); this.Add ( page ); return this.IndexOf ( page ); } [MonoTODO] bool IList.Contains( object value ){ return this.Contains ( value as TabPage ); } [MonoTODO] int IList.IndexOf( object value ){ return this.IndexOf ( value as TabPage ); } [MonoTODO] void IList.Insert(int index, object value){ if ( ! (value is TabPage) ) throw new ArgumentException ( ); (( IList )collection).Insert ( index, value ); owner.update ( ); } void IList.Remove( object value ){ this.Remove ( value as TabPage ); } void IList.RemoveAt( int index){ this.RemoveAt ( index ); } // End of IList interface /// /// ICollection Interface implmentation. /// int ICollection.Count{ get{ return this.Count; } } bool ICollection.IsSynchronized{ get{ return ( (ICollection) collection).IsSynchronized; } } object ICollection.SyncRoot{ get{ return ( (ICollection) collection).SyncRoot; } } void ICollection.CopyTo(Array array, int index){ ( (ICollection) collection ).CopyTo ( array, index ); } // End Of ICollection } } }