Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / WinForms / Managed / System / WinForms / StatusBar.cs / 1 / StatusBar.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* */ namespace System.Windows.Forms { using System.Runtime.Serialization.Formatters; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.ComponentModel; using System.Diagnostics; using System; using System.Security.Permissions; using System.Drawing; using System.Collections; using Microsoft.Win32; using System.Windows.Forms.VisualStyles; using System.Globalization; ////// /// [ ComVisible(true), ClassInterface(ClassInterfaceType.AutoDispatch), DefaultEvent("PanelClick"), DefaultProperty("Text"), Designer("System.Windows.Forms.Design.StatusBarDesigner, " + AssemblyRef.SystemDesign), ] public class StatusBar : Control { private int sizeGripWidth = 0; private const int SIMPLE_INDEX = 0xFF; private static readonly object EVENT_PANELCLICK = new object(); private static readonly object EVENT_SBDRAWITEM = new object(); private bool showPanels; private bool layoutDirty; private int panelsRealized; private bool sizeGrip = true; private string simpleText; private Point lastClick = new Point(0, 0); private IList panels = new ArrayList(); private StatusBarPanelCollection panelsCollection; private ControlToolTip tooltips; private ToolTip mainToolTip = null; private bool toolTipSet = false; ////// Represents a Windows status bar control. /// ////// /// public StatusBar() : base() { base.SetStyle(ControlStyles.UserPaint | ControlStyles.Selectable, false); Dock = DockStyle.Bottom; TabStop = false; } private static VisualStyleRenderer renderer = null; ////// Initializes a new default instance of the ///class. /// /// A VisualStyleRenderer we can use to get information about the current UI theme /// private static VisualStyleRenderer VisualStyleRenderer { get { if (VisualStyleRenderer.IsSupported) { if (renderer == null) { renderer = new VisualStyleRenderer(VisualStyleElement.ToolBar.Button.Normal); } } else { renderer = null; } return renderer; } } private int SizeGripWidth { get { if (sizeGripWidth == 0) { if (Application.RenderWithVisualStyles && VisualStyleRenderer != null){ // VSWhidbey 207045: need to build up accurate gripper width to avoid cutting off other panes. VisualStyleRenderer vsRenderer = VisualStyleRenderer; VisualStyleElement thisElement; Size elementSize; // gripper pane width... thisElement = VisualStyleElement.Status.GripperPane.Normal; vsRenderer.SetParameters(thisElement); elementSize = vsRenderer.GetPartSize(Graphics.FromHwndInternal(this.Handle), ThemeSizeType.True); sizeGripWidth = elementSize.Width; // ...plus gripper width thisElement = VisualStyleElement.Status.Gripper.Normal; vsRenderer.SetParameters(thisElement); elementSize = vsRenderer.GetPartSize(Graphics.FromHwndInternal(this.Handle), ThemeSizeType.True); sizeGripWidth += elementSize.Width; // Either GetPartSize could have returned a width of zero, so make sure we have a reasonable number: sizeGripWidth = Math.Max(sizeGripWidth, 16); } else { sizeGripWidth = 16; } } return sizeGripWidth; } } ////// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public override Color BackColor { get { // not supported, always return CONTROL return SystemColors.Control; } set { // no op, not supported. } } ////// The background color of this control. This is an ambient property and will /// always return a non-null value. /// ////// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] new public event EventHandler BackColorChanged { add { base.BackColorChanged += value; } remove { base.BackColorChanged -= value; } } /// /// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public override Image BackgroundImage { get { return base.BackgroundImage; } set { base.BackgroundImage = value; } } ////// Gets or sets the image rendered on the background of the /// ////// control. /// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] new public event EventHandler BackgroundImageChanged { add { base.BackgroundImageChanged += value; } remove { base.BackgroundImageChanged -= value; } } /// /// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public override ImageLayout BackgroundImageLayout { get { return base.BackgroundImageLayout; } set { base.BackgroundImageLayout = value; } } ///[To be supplied.] ////// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] new public event EventHandler BackgroundImageLayoutChanged { add { base.BackgroundImageLayoutChanged += value; } remove { base.BackgroundImageLayoutChanged -= value; } } /// /// /// protected override CreateParams CreateParams { [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] get { CreateParams cp = base.CreateParams; cp.ClassName = NativeMethods.WC_STATUSBAR; if (this.sizeGrip) { cp.Style |= NativeMethods.SBARS_SIZEGRIP; } else { cp.Style &= (~NativeMethods.SBARS_SIZEGRIP); } cp.Style |= NativeMethods.CCS_NOPARENTALIGN | NativeMethods.CCS_NORESIZE; return cp; } } ////// Returns the CreateParams used to create the handle for this control. /// Inheriting classes should call base.getCreateParams in the manor below: /// ///protected override ImeMode DefaultImeMode { get { return ImeMode.Disable; } } /// /// /// Deriving classes can override this to configure a default size for their control. /// This is more efficient than setting the size in the control's constructor. /// protected override Size DefaultSize { get { return new Size(100, 22); } } ////// /// This property is overridden and hidden from statement completion /// on controls that are based on Win32 Native Controls. /// [EditorBrowsable(EditorBrowsableState.Never)] protected override bool DoubleBuffered { get { return base.DoubleBuffered; } set { base.DoubleBuffered = value; } } ////// /// [ Localizable(true), DefaultValue(DockStyle.Bottom) ] public override DockStyle Dock { get { return base.Dock; } set { base.Dock = value; } } ////// Gets or sets the docking behavior of the ///control. /// /// /// [ Localizable(true) ] public override Font Font { get { return base.Font;} set { base.Font = value; SetPanelContentsWidths(false); } } ////// Gets or sets the font the ////// control will use to display /// information. /// /// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public override Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; } } ////// Gets or sets /// the forecolor for the control. /// ////// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] new public event EventHandler ForeColorChanged { add { base.ForeColorChanged += value; } remove { base.ForeColorChanged -= value; } } /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] new public ImeMode ImeMode { get { return base.ImeMode; } set { base.ImeMode = value; } } /// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler ImeModeChanged { add { base.ImeModeChanged += value; } remove { base.ImeModeChanged -= value; } } /// /// /// [ DesignerSerializationVisibility(DesignerSerializationVisibility.Content), SRDescription(SR.StatusBarPanelsDescr), Localizable(true), SRCategory(SR.CatAppearance), MergableProperty(false) ] public StatusBarPanelCollection Panels { get { if (panelsCollection == null) { panelsCollection = new StatusBarPanelCollection(this); } return panelsCollection; } } ////// Gets the collection of ////// panels contained within the /// control. /// /// /// [ Localizable(true) ] public override string Text { get { if (simpleText == null) { return ""; } else { return simpleText; } } set { SetSimpleText(value); if (simpleText != value) { simpleText = value; OnTextChanged(EventArgs.Empty); } } } /* No one is calling this, so it is ok to comment it out private IntPtr ToolTipHandle { get { EnumChildren c = new EnumChildren( this ); UnsafeNativeMethods.EnumChildWindows(new HandleRef(null, UnsafeNativeMethods.GetDesktopWindow()), new NativeMethods.EnumChildrenProc(c.Callback), NativeMethods.NullHandleRef); return c.hWndFound; } } */ ////// The status bar text. /// ////// /// [ SRCategory(SR.CatBehavior), DefaultValue(false), SRDescription(SR.StatusBarShowPanelsDescr) ] public bool ShowPanels { get { return showPanels; } set { if (showPanels != value) { showPanels = value; layoutDirty = true; if (IsHandleCreated) { int bShowPanels = (!showPanels) ? 1 : 0; SendMessage(NativeMethods.SB_SIMPLE, bShowPanels, 0); if (showPanels) { PerformLayout(); RealizePanels(); } else if (tooltips != null) { for (int i=0; i/// Gets or sets a value indicating whether panels should be shown. /// ////// /// [ SRCategory(SR.CatAppearance), DefaultValue(true), SRDescription(SR.StatusBarSizingGripDescr) ] public bool SizingGrip { get { return sizeGrip; } set { if (value != sizeGrip) { sizeGrip = value; RecreateHandle(); } } } ////// Gets or sets a value indicating whether a sizing grip /// will be rendered on the corner of the ////// control. /// /// /// [DefaultValue(false)] new public bool TabStop { get { return base.TabStop; } set { base.TabStop = value; } } internal bool ToolTipSet { get { return toolTipSet; } } internal ToolTip MainToolTip { get { return mainToolTip; } } ////// Gets or sets a value indicating whether the user will be able to tab to the /// ///. /// /// /// [SRCategory(SR.CatBehavior), SRDescription(SR.StatusBarDrawItem)] public event StatusBarDrawItemEventHandler DrawItem { add { Events.AddHandler(EVENT_SBDRAWITEM, value); } remove { Events.RemoveHandler(EVENT_SBDRAWITEM, value); } } ////// Occurs when a visual aspect of an owner-drawn status bar changes. /// ////// /// [SRCategory(SR.CatMouse), SRDescription(SR.StatusBarOnPanelClickDescr)] public event StatusBarPanelClickEventHandler PanelClick { add { Events.AddHandler(EVENT_PANELCLICK, value); } remove { Events.RemoveHandler(EVENT_PANELCLICK, value); } } ////// Occurs when a panel on the status bar is clicked. /// ////// /// StatusBar Onpaint. /// ///[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event PaintEventHandler Paint { add { base.Paint += value; } remove { base.Paint -= value; } } /// /// /// Tells whether the panels have been realized. /// ///internal bool ArePanelsRealized() { return this.showPanels && IsHandleCreated; } /// /// /// ///internal void DirtyLayout() { layoutDirty = true; } /// /// /// Makes the panel according to the sizes in the panel list. /// ///private void ApplyPanelWidths() { // This forces handle creation every time any time the StatusBar // has to be re-laidout. // if (!IsHandleCreated) return; StatusBarPanel panel = null; int length = this.panels.Count; if (length == 0) { Size sz = Size; int[] offsets = new int[1]; offsets[0] = sz.Width; if (sizeGrip) { offsets[0] -= SizeGripWidth; } UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.SB_SETPARTS, 1, offsets); SendMessage(NativeMethods.SB_SETICON, 0, IntPtr.Zero); return; } int[] offsets2 = new int[length]; int currentOffset = 0; for (int i = 0; i < length; i++) { panel = (StatusBarPanel) this.panels[i]; currentOffset += panel.Width; offsets2[i] = currentOffset; panel.Right = offsets2[i]; } UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.SB_SETPARTS, length, offsets2); // Tooltip setup... // for (int i=0; i /// /// ///protected override void CreateHandle() { if (!RecreatingHandle) { IntPtr userCookie = UnsafeNativeMethods.ThemingScope.Activate(); try { NativeMethods.INITCOMMONCONTROLSEX icc = new NativeMethods.INITCOMMONCONTROLSEX(); icc.dwICC = NativeMethods.ICC_BAR_CLASSES; SafeNativeMethods.InitCommonControlsEx(icc); } finally { UnsafeNativeMethods.ThemingScope.Deactivate(userCookie); } } base.CreateHandle(); } /// /// /// Disposes this control /// protected override void Dispose(bool disposing) { if (disposing) { if (panelsCollection != null) { StatusBarPanel[] panelCopy = new StatusBarPanel[panelsCollection.Count]; ((ICollection)panelsCollection).CopyTo(panelCopy, 0); panelsCollection.Clear(); foreach(StatusBarPanel p in panelCopy) { p.Dispose(); } } } base.Dispose(disposing); } ////// /// Forces the panels to be updated, location, repainting, etc. /// ///private void ForcePanelUpdate() { if (ArePanelsRealized()) { layoutDirty = true; SetPanelContentsWidths(true); PerformLayout(); RealizePanels(); } } /// /// /// protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); if (!DesignMode) { tooltips = new ControlToolTip(this); } if (!this.showPanels) { SendMessage(NativeMethods.SB_SIMPLE, 1, 0); SetSimpleText(simpleText); } else { ForcePanelUpdate(); } } ////// Raises the ////// event. /// /// /// protected override void OnHandleDestroyed(EventArgs e) { base.OnHandleDestroyed(e); if (tooltips != null) { tooltips.Dispose(); tooltips = null; } } /* Not used ////// Raises the ///event. /// /// /// private sealed class EnumChildren { public IntPtr hWndFound = IntPtr.Zero; private StatusBar peer; public EnumChildren( StatusBar peer ) { if (peer == null) throw new ArgumentNullException("peer"); this.peer = peer; } public bool Callback(IntPtr hWnd, IntPtr lparam) { if (UnsafeNativeMethods.GetParent(new HandleRef(null, hWnd)) == peer.Handle) { hWndFound = hWnd; return false; } return true; } }*/ ////// /// protected override void OnMouseDown(MouseEventArgs e) { lastClick.X = e.X; lastClick.Y = e.Y; base.OnMouseDown(e); } ////// Raises the ///event. /// /// /// protected virtual void OnPanelClick(StatusBarPanelClickEventArgs e) { StatusBarPanelClickEventHandler handler = (StatusBarPanelClickEventHandler)Events[EVENT_PANELCLICK]; if (handler != null) handler(this,e); } ////// Raises the ///event. /// /// /// protected override void OnLayout(LayoutEventArgs levent) { if (this.showPanels) { LayoutPanels(); if (IsHandleCreated && panelsRealized != panels.Count) { RealizePanels(); } } base.OnLayout(levent); } ////// Raises the Layout event. /// ////// /// This function sets up all the panel on the status bar according to /// the internal this.panels List. /// ///internal void RealizePanels() { StatusBarPanel panel = null; int length = this.panels.Count; int old = panelsRealized; panelsRealized = 0; if (length == 0) { SendMessage(NativeMethods.SB_SETTEXT, 0, ""); } int i; for (i = 0; i < length; i++) { panel = (StatusBarPanel) this.panels[i]; try { panel.Realize(); panelsRealized++; } catch { } } for (; i /// /// Remove the internal list of panels without updating the control. /// ///internal void RemoveAllPanelsWithoutUpdate() { int size = this.panels.Count; // remove the parent reference for (int i = 0; i < size; i++) { StatusBarPanel sbp = (StatusBarPanel) this.panels[i]; sbp.ParentInternal = null; } this.panels.Clear(); if (this.showPanels == true) { ApplyPanelWidths(); ForcePanelUpdate(); } } /// /// /// Sets the widths of any panels that have the /// StatusBarPanelAutoSize.CONTENTS property set. /// ///internal void SetPanelContentsWidths(bool newPanels) { int size = panels.Count; bool changed = false; for (int i = 0; i < size; i++) { StatusBarPanel sbp = (StatusBarPanel) panels[i]; if (sbp.AutoSize == StatusBarPanelAutoSize.Contents) { int newWidth = sbp.GetContentsWidth(newPanels); if (sbp.Width != newWidth) { sbp.Width = newWidth; changed = true; } } } if (changed) { DirtyLayout(); PerformLayout(); } } private void SetSimpleText(string simpleText) { if (!showPanels && IsHandleCreated) { int wparam = SIMPLE_INDEX + NativeMethods.SBT_NOBORDERS; if (RightToLeft == RightToLeft.Yes) { wparam |= NativeMethods.SBT_RTLREADING; } SendMessage(NativeMethods.SB_SETTEXT, wparam, simpleText); } } /// /// /// Sizes the the panels appropriately. It looks at the SPRING AutoSize /// property. /// ///private void LayoutPanels() { StatusBarPanel panel = null; int barPanelWidth = 0; int springNum = 0; StatusBarPanel[] pArray = new StatusBarPanel[this.panels.Count]; bool changed = false; for (int i = 0; i < pArray.Length; i++) { panel = (StatusBarPanel) this.panels[i]; if (panel.AutoSize == StatusBarPanelAutoSize.Spring) { pArray[springNum] = panel; springNum++; } else barPanelWidth += panel.Width; } if (springNum > 0) { Rectangle rect = Bounds; int springPanelsLeft = springNum; int leftoverWidth = rect.Width - barPanelWidth; if (sizeGrip) { leftoverWidth -= SizeGripWidth; } int copyOfLeftoverWidth = unchecked((int)0x80000000); while (springPanelsLeft > 0) { int widthOfSpringPanel = (leftoverWidth) / springPanelsLeft; if (leftoverWidth == copyOfLeftoverWidth) break; copyOfLeftoverWidth = leftoverWidth; for (int i = 0; i < springNum; i++) { panel = pArray[i]; if (panel == null) continue; if (widthOfSpringPanel < panel.MinWidth) { if (panel.Width != panel.MinWidth) { changed = true; } panel.Width = panel.MinWidth; pArray[i] = null; springPanelsLeft --; leftoverWidth -= panel.MinWidth; } else { if (panel.Width != widthOfSpringPanel) { changed = true; } panel.Width = widthOfSpringPanel; } } } } if (changed || layoutDirty) { ApplyPanelWidths(); } } /// /// /// protected virtual void OnDrawItem(StatusBarDrawItemEventArgs sbdievent) { StatusBarDrawItemEventHandler handler = (StatusBarDrawItemEventHandler)Events[EVENT_SBDRAWITEM]; if (handler != null) handler(this,sbdievent); } ////// Raises the ////// event. /// /// /// protected override void OnResize(EventArgs e) { Invalidate(); base.OnResize(e); } ////// Raises the ////// event. /// /// /// public override string ToString() { string s = base.ToString(); if (Panels != null) { s += ", Panels.Count: " + Panels.Count.ToString(CultureInfo.CurrentCulture); if (Panels.Count > 0) s += ", Panels[0]: " + Panels[0].ToString(); } return s; } //call this when System.Windows.forms.toolTip is Associated with Statusbar.... internal void SetToolTip(ToolTip t) { this.mainToolTip = t; toolTipSet = true; } internal void UpdateTooltip(StatusBarPanel panel) { if (tooltips == null) { if (IsHandleCreated && !DesignMode) { //This shouldn't happen: tooltips should've already been set. The best we can //do here is reset it. tooltips = new ControlToolTip(this); } else { return; } } if (panel.Parent == this && panel.ToolTipText.Length > 0) { int border = SystemInformation.Border3DSize.Width; ControlToolTip.Tool t = tooltips.GetTool(panel); if (t == null) { t = new ControlToolTip.Tool(); } t.text = panel.ToolTipText; t.rect = new Rectangle(panel.Right-panel.Width + border, 0, panel.Width - border, Height); tooltips.SetTool(panel, t); } else { tooltips.SetTool(panel, null); } } private void UpdatePanelIndex() { int length = panels.Count; for (int i=0; i/// Returns a string representation for this control. /// ////// /// /// Processes messages for ownerdraw panels. /// private void WmDrawItem(ref Message m) { NativeMethods.DRAWITEMSTRUCT dis = (NativeMethods.DRAWITEMSTRUCT)m.GetLParam(typeof(NativeMethods.DRAWITEMSTRUCT)); int length = this.panels.Count; if (dis.itemID < 0 || dis.itemID >= length) Debug.Fail("OwnerDraw item out of range"); StatusBarPanel panel = (StatusBarPanel) this.panels[dis.itemID]; Graphics g = Graphics.FromHdcInternal(dis.hDC); Rectangle r = Rectangle.FromLTRB(dis.rcItem.left, dis.rcItem.top, dis.rcItem.right, dis.rcItem.bottom); //The itemstate is not defined for a statusbar control OnDrawItem(new StatusBarDrawItemEventArgs(g, Font, r, dis.itemID, DrawItemState.None, panel, this.ForeColor, this.BackColor)); g.Dispose(); } ////// /// /// private void WmNotifyNMClick(NativeMethods.NMHDR note) { if (!showPanels) { return; } int size = panels.Count; int currentOffset = 0; int index = -1; for (int i = 0; i < size; i++) { StatusBarPanel panel = (StatusBarPanel) panels[i]; currentOffset += panel.Width; if (lastClick.X < currentOffset) { // this is where the mouse was clicked. index = i; break; } } if (index != -1) { MouseButtons button = MouseButtons.Left; int clicks = 0; switch (note.code) { case NativeMethods.NM_CLICK: button = MouseButtons.Left; clicks = 1; break; case NativeMethods.NM_RCLICK: button = MouseButtons.Right; clicks = 1; break; case NativeMethods.NM_DBLCLK: button = MouseButtons.Left; clicks = 2; break; case NativeMethods.NM_RDBLCLK: button = MouseButtons.Right; clicks = 2; break; } Point pt = lastClick; StatusBarPanel panel = (StatusBarPanel) panels[index]; StatusBarPanelClickEventArgs sbpce = new StatusBarPanelClickEventArgs(panel, button, clicks, pt.X, pt.Y); OnPanelClick(sbpce); } } private void WmNCHitTest(ref Message m) { int x = NativeMethods.Util.LOWORD(m.LParam); Rectangle bounds = Bounds; bool callSuper = true; // The default implementation of the statusbar // : will let you size the form when it is docked on the bottom, // : but when it is anywhere else, the statusbar will be resized. // : to prevent that we provide a little bit a sanity to only // : allow resizing, when it would resize the form. // if (x > bounds.X + bounds.Width - SizeGripWidth) { Control parent = ParentInternal; if (parent != null && parent is Form) { FormBorderStyle bs = ((Form)parent).FormBorderStyle; if (bs != FormBorderStyle.Sizable && bs != FormBorderStyle.SizableToolWindow) { callSuper = false; } if (!((Form)parent).TopLevel || Dock != DockStyle.Bottom) { callSuper = false; } if (callSuper) { Control.ControlCollection children = parent.Controls; int c = children.Count; for (int i=0; iTop) { callSuper = false; break; } } } } } else { callSuper = false; } } if (callSuper) { base.WndProc(ref m); } else { m.Result = (IntPtr)NativeMethods.HTCLIENT; } } /// /// /// [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] protected override void WndProc(ref Message m) { switch (m.Msg) { case NativeMethods.WM_NCHITTEST: WmNCHitTest(ref m); break; case NativeMethods.WM_REFLECT + NativeMethods.WM_DRAWITEM: WmDrawItem(ref m); break; case NativeMethods.WM_NOTIFY: case NativeMethods.WM_NOTIFY + NativeMethods.WM_REFLECT: NativeMethods.NMHDR note = (NativeMethods.NMHDR)m.GetLParam(typeof(NativeMethods.NMHDR)); switch (note.code) { case NativeMethods.NM_CLICK: case NativeMethods.NM_RCLICK: case NativeMethods.NM_DBLCLK: case NativeMethods.NM_RDBLCLK: WmNotifyNMClick(note); break; default: base.WndProc(ref m); break; } break; default: base.WndProc(ref m); break; } } ////// Base wndProc. All messages are sent to wndProc after getting filtered through /// the preProcessMessage function. Inheriting controls should call base.wndProc /// for any messages that they don't handle. /// ////// /// [ ListBindable(false) ] public class StatusBarPanelCollection : IList { private StatusBar owner; /// A caching mechanism for key accessor /// We use an index here rather than control so that we don't have lifetime /// issues by holding on to extra references. private int lastAccessedIndex = -1; ////// The collection of StatusBarPanels that the StatusBar manages. /// event. /// ////// /// public StatusBarPanelCollection(StatusBar owner) { this.owner = owner; } ////// Constructor for the StatusBarPanelCollection class /// ////// /// This method will return an individual StatusBarPanel with the appropriate index. /// public virtual StatusBarPanel this[int index] { get { return(StatusBarPanel)owner.panels[index]; } set { if (value == null) throw new ArgumentNullException("StatusBarPanel"); owner.layoutDirty = true; if (value.Parent != null) { throw new ArgumentException(SR.GetString(SR.ObjectHasParent), "value"); } int length = owner.panels.Count; if (index < 0|| index >= length) throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); StatusBarPanel oldPanel = (StatusBarPanel) owner.panels[index]; oldPanel.ParentInternal = null; value.ParentInternal = owner; if (value.AutoSize == StatusBarPanelAutoSize.Contents) { value.Width = value.GetContentsWidth(true); } owner.panels[index] = value; value.Index = index; if (owner.ArePanelsRealized()) { owner.PerformLayout(); value.Realize(); } } } ////// object IList.this[int index] { get { return this[index]; } set { if (value is StatusBarPanel) { this[index] = (StatusBarPanel)value; } else { throw new ArgumentException(SR.GetString(SR.StatusBarBadStatusBarPanel), "value"); } } } /// /// /// public virtual StatusBarPanel this[string key] { get { // We do not support null and empty string as valid keys. if (string.IsNullOrEmpty(key)){ return null; } // Search for the key in our collection int index = IndexOfKey(key); if (IsValidIndex(index)) { return this[index]; } else { return null; } } } ///Retrieves the child control with the specified key. ////// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public int Count { get { return owner.panels.Count; } } ////// Returns an integer representing the number of StatusBarPanels /// in this collection. /// ////// object ICollection.SyncRoot { get { return this; } } /// /// bool ICollection.IsSynchronized { get { return false; } } /// /// bool IList.IsFixedSize { get { return false; } } /// /// /// public bool IsReadOnly { get { return false; } } ///[To be supplied.] ////// /// public virtual StatusBarPanel Add(string text) { StatusBarPanel panel = new StatusBarPanel(); panel.Text = text; Add(panel); return panel; } ////// Adds a StatusBarPanel to the collection. /// ////// /// public virtual int Add(StatusBarPanel value) { int index = owner.panels.Count; Insert(index, value); return index; } ////// Adds a StatusBarPanel to the collection. /// ////// int IList.Add(object value) { if (value is StatusBarPanel) { return Add((StatusBarPanel)value); } else { throw new ArgumentException(SR.GetString(SR.StatusBarBadStatusBarPanel), "value"); } } /// /// /// public virtual void AddRange(StatusBarPanel[] panels) { if (panels == null) { throw new ArgumentNullException("panels"); } foreach(StatusBarPanel panel in panels) { Add(panel); } } ///[To be supplied.] ////// /// public bool Contains(StatusBarPanel panel) { return IndexOf(panel) != -1; } ///[To be supplied.] ////// bool IList.Contains(object panel) { if (panel is StatusBarPanel) { return Contains((StatusBarPanel)panel); } else { return false; } } /// /// /// public virtual bool ContainsKey(string key) { return IsValidIndex(IndexOfKey(key)); } ///Returns true if the collection contains an item with the specified key, false otherwise. ////// /// public int IndexOf(StatusBarPanel panel) { for(int index=0; index < Count; ++index) { if (this[index] == panel) { return index; } } return -1; } ///[To be supplied.] ////// int IList.IndexOf(object panel) { if (panel is StatusBarPanel) { return IndexOf((StatusBarPanel)panel); } else { return -1; } } /// /// /// public virtual int IndexOfKey(String key) { // Step 0 - Arg validation if (string.IsNullOrEmpty(key)){ return -1; // we dont support empty or null keys. } // step 1 - check the last cached item if (IsValidIndex(lastAccessedIndex)) { if (WindowsFormsUtils.SafeCompareStrings(this[lastAccessedIndex].Name, key, /* ignoreCase = */ true)) { return lastAccessedIndex; } } // step 2 - search for the item for (int i = 0; i < this.Count; i ++) { if (WindowsFormsUtils.SafeCompareStrings(this[i].Name, key, /* ignoreCase = */ true)) { lastAccessedIndex = i; return i; } } // step 3 - we didn't find it. Invalidate the last accessed index and return -1. lastAccessedIndex = -1; return -1; } ///The zero-based index of the first occurrence of value within the entire CollectionBase, if found; otherwise, -1. ////// /// public virtual void Insert(int index, StatusBarPanel value) { //check for the value not to be null if (value == null) throw new ArgumentNullException("value"); //end check owner.layoutDirty = true; if (value.Parent != owner && value.Parent != null) throw new ArgumentException(SR.GetString(SR.ObjectHasParent), "value"); int length = owner.panels.Count; if (index < 0 || index > length) throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); value.ParentInternal = owner; switch (value.AutoSize) { case StatusBarPanelAutoSize.None: case StatusBarPanelAutoSize.Spring: break; case StatusBarPanelAutoSize.Contents: value.Width = value.GetContentsWidth(true); break; } owner.panels.Insert(index, value); owner.UpdatePanelIndex(); owner.ForcePanelUpdate(); } ////// Inserts a StatusBarPanel in the collection. /// ////// void IList.Insert(int index, object value) { if (value is StatusBarPanel) { Insert(index, (StatusBarPanel)value); } else { throw new ArgumentException(SR.GetString(SR.StatusBarBadStatusBarPanel), "value"); } } /// /// /// ///Determines if the index is valid for the collection. ///private bool IsValidIndex(int index) { return ((index >= 0) && (index < this.Count)); } /// /// /// public virtual void Clear() { owner.RemoveAllPanelsWithoutUpdate(); owner.PerformLayout(); } ////// Removes all the StatusBarPanels in the collection. /// ////// /// public virtual void Remove(StatusBarPanel value) { //check for the value not to be null if (value == null) throw new ArgumentNullException("StatusBarPanel"); //end check if (value.Parent != owner) { return; } RemoveAt(value.Index); } ////// Removes an individual StatusBarPanel in the collection. /// ////// void IList.Remove(object value) { if (value is StatusBarPanel) { Remove((StatusBarPanel)value); } } /// /// /// public virtual void RemoveAt(int index) { int length = Count; if (index < 0 || index >= length) throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); // clear any tooltip // StatusBarPanel panel = (StatusBarPanel)owner.panels[index]; owner.panels.RemoveAt(index); panel.ParentInternal = null; // this will cause the panels tooltip to be removed since it's no longer a child // of this StatusBar. // owner.UpdateTooltip(panel); // V#41207 - [....], 4/1/1998 - We must reindex the panels after a removal... owner.UpdatePanelIndex(); owner.ForcePanelUpdate(); } ////// Removes an individual StatusBarPanel in the collection at the given index. /// ////// /// public virtual void RemoveByKey(string key) { int index = IndexOfKey(key); if (IsValidIndex(index)) { RemoveAt(index); } } ///Removes the child control with the specified key. ////// void ICollection.CopyTo(Array dest, int index) { owner.panels.CopyTo(dest, index); } /// /// /// public IEnumerator GetEnumerator() { if (owner.panels != null) { return owner.panels.GetEnumerator(); } else { return new StatusBarPanel[0].GetEnumerator(); } } } ////// Returns the Enumerator for this collection. /// ////// /// This is a tooltip control that provides tips for a single /// control. Each "tool" region is defined by a rectangle and /// the string that should be displayed. This implementation /// is based on System.Windows.Forms.ToolTip, but this control /// is lighter weight and provides less functionality... however /// this control binds to rectangular regions, instead of /// full controls. /// [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] private class ControlToolTip { ///public class Tool { /// public Rectangle rect = Rectangle.Empty; /// public string text; internal IntPtr id = new IntPtr(-1); } private Hashtable tools = new Hashtable(); private ToolTipNativeWindow window = null; private Control parent = null; private int nextId = 0; /// /// /// Creates a new ControlToolTip. /// public ControlToolTip(Control parent) { window = new ToolTipNativeWindow(this); this.parent = parent; } ////// /// Returns the createParams to create the window. /// protected CreateParams CreateParams { get { NativeMethods.INITCOMMONCONTROLSEX icc = new NativeMethods.INITCOMMONCONTROLSEX(); icc.dwICC = NativeMethods.ICC_TAB_CLASSES; SafeNativeMethods.InitCommonControlsEx(icc); CreateParams cp = new CreateParams(); cp.Parent = IntPtr.Zero; cp.ClassName = NativeMethods.TOOLTIPS_CLASS; cp.Style |= NativeMethods.TTS_ALWAYSTIP; cp.ExStyle = 0; cp.Caption = null; return cp; } } ////// /// public IntPtr Handle { get { if (window.Handle == IntPtr.Zero) { CreateHandle(); } return window.Handle; } } private bool IsHandleCreated { get { return window.Handle != IntPtr.Zero;} } private void AssignId(Tool tool) { tool.id = (IntPtr)nextId; nextId++; } ////// /// Sets the tool for the specified key. Keep in mind /// that as soon as setTool is called, the handle for /// the ControlToolTip is created, and the handle for /// the parent control is also created. If the parent /// handle is recreated in the future, all tools must /// be re-added. The old tool for the specified key /// will be removed. Passing null in for the /// tool parameter will result in the tool /// region being removed. /// public void SetTool(object key, Tool tool) { bool remove = false; bool add = false; bool update = false; Tool toRemove = null; if (tools.ContainsKey(key)) { toRemove = (Tool)tools[key]; } if (toRemove != null) { remove = true; } if (tool != null) { add = true; } if (tool != null && toRemove != null && tool.id == toRemove.id) { update = true; } if (update) { UpdateTool(tool); } else { if (remove) { RemoveTool(toRemove); } if (add) { AddTool(tool); } } if (tool != null) { tools[key] = tool; } else { tools.Remove(key); } } ////// /// Returns the tool associated with the specified key, /// or null if there is no area. /// public Tool GetTool(object key) { return(Tool)tools[key]; } private void AddTool(Tool tool) { if (tool != null && tool.text != null && tool.text.Length > 0) { int ret; StatusBar p = (StatusBar)parent; if (p.ToolTipSet) { ret = (int)UnsafeNativeMethods.SendMessage(new HandleRef(p.MainToolTip, p.MainToolTip.Handle), NativeMethods.TTM_ADDTOOL, 0, GetTOOLINFO(tool)); } else { ret = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_ADDTOOL, 0, GetTOOLINFO(tool)); } if (ret == 0) { throw new InvalidOperationException(SR.GetString(SR.StatusBarAddFailed)); } } } private void RemoveTool(Tool tool) { if (tool != null && tool.text != null && tool.text.Length > 0 && (int)tool.id >= 0) { UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_DELTOOL, 0, GetMinTOOLINFO(tool)); } } private void UpdateTool(Tool tool) { if (tool != null && tool.text != null && tool.text.Length > 0 && (int)tool.id >= 0) { UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_SETTOOLINFO, 0, GetTOOLINFO(tool)); } } ////// /// Creates the handle for the control. /// protected void CreateHandle() { if (IsHandleCreated) { return; } window.CreateHandle(CreateParams); SafeNativeMethods.SetWindowPos(new HandleRef(this, Handle), NativeMethods.HWND_TOPMOST, 0, 0, 0, 0, NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOSIZE | NativeMethods.SWP_NOACTIVATE); // Setting the max width has the added benefit of enabling multiline // tool tips! // UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_SETMAXTIPWIDTH, 0, SystemInformation.MaxWindowTrackSize.Width); } ////// /// Destroys the handle for this control. /// protected void DestroyHandle() { if (IsHandleCreated) { window.DestroyHandle(); tools.Clear(); } } ////// /// Disposes of the component. Call dispose when the component is no longer needed. /// This method removes the component from its container (if the component has a site) /// and triggers the dispose event. /// public void Dispose() { DestroyHandle(); } ////// /// Returns a new instance of the TOOLINFO_T structure with the minimum /// required data to uniquely identify a region. This is used primarily /// for delete operations. NOTE: This cannot force the creation of a handle. /// private NativeMethods.TOOLINFO_T GetMinTOOLINFO(Tool tool) { NativeMethods.TOOLINFO_T ti = new NativeMethods.TOOLINFO_T(); ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_T)); ti.hwnd = parent.Handle; if ((int)tool.id < 0) { AssignId(tool); } StatusBar p = (StatusBar)parent; if (p != null && p.ToolTipSet) { ti.uId = parent.Handle; } else { ti.uId = tool.id; } return ti; } ////// /// Returns a detailed TOOLINFO_T structure that represents the specified /// region. NOTE: This may force the creation of a handle. /// private NativeMethods.TOOLINFO_T GetTOOLINFO(Tool tool) { NativeMethods.TOOLINFO_T ti = GetMinTOOLINFO(tool); ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_T)); ti.uFlags |= NativeMethods.TTF_TRANSPARENT | NativeMethods.TTF_SUBCLASS; // RightToLeft reading order // Control richParent = parent; if (richParent != null && richParent.RightToLeft == RightToLeft.Yes) { ti.uFlags |= NativeMethods.TTF_RTLREADING; } ti.lpszText = tool.text; ti.rect = NativeMethods.RECT.FromXYWH(tool.rect.X, tool.rect.Y, tool.rect.Width, tool.rect.Height); return ti; } ////// /// ~ControlToolTip() { DestroyHandle(); } ////// /// WNDPROC /// protected void WndProc(ref Message msg) { switch (msg.Msg) { case NativeMethods.WM_SETFOCUS: // bug 120872, the COMCTL StatusBar passes WM_SETFOCUS on to the DefWndProc, so // it will take keyboard focus. We don't want it doing this, so we eat // the message. // return; default: window.DefWndProc(ref msg); break; } } ////// /// private class ToolTipNativeWindow : NativeWindow { ControlToolTip control; internal ToolTipNativeWindow(ControlToolTip control) { this.control = control; } protected override void WndProc(ref Message m) { if (control != null) { control.WndProc(ref m); } } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* */ namespace System.Windows.Forms { using System.Runtime.Serialization.Formatters; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.ComponentModel; using System.Diagnostics; using System; using System.Security.Permissions; using System.Drawing; using System.Collections; using Microsoft.Win32; using System.Windows.Forms.VisualStyles; using System.Globalization; ////// /// [ ComVisible(true), ClassInterface(ClassInterfaceType.AutoDispatch), DefaultEvent("PanelClick"), DefaultProperty("Text"), Designer("System.Windows.Forms.Design.StatusBarDesigner, " + AssemblyRef.SystemDesign), ] public class StatusBar : Control { private int sizeGripWidth = 0; private const int SIMPLE_INDEX = 0xFF; private static readonly object EVENT_PANELCLICK = new object(); private static readonly object EVENT_SBDRAWITEM = new object(); private bool showPanels; private bool layoutDirty; private int panelsRealized; private bool sizeGrip = true; private string simpleText; private Point lastClick = new Point(0, 0); private IList panels = new ArrayList(); private StatusBarPanelCollection panelsCollection; private ControlToolTip tooltips; private ToolTip mainToolTip = null; private bool toolTipSet = false; ////// Represents a Windows status bar control. /// ////// /// public StatusBar() : base() { base.SetStyle(ControlStyles.UserPaint | ControlStyles.Selectable, false); Dock = DockStyle.Bottom; TabStop = false; } private static VisualStyleRenderer renderer = null; ////// Initializes a new default instance of the ///class. /// /// A VisualStyleRenderer we can use to get information about the current UI theme /// private static VisualStyleRenderer VisualStyleRenderer { get { if (VisualStyleRenderer.IsSupported) { if (renderer == null) { renderer = new VisualStyleRenderer(VisualStyleElement.ToolBar.Button.Normal); } } else { renderer = null; } return renderer; } } private int SizeGripWidth { get { if (sizeGripWidth == 0) { if (Application.RenderWithVisualStyles && VisualStyleRenderer != null){ // VSWhidbey 207045: need to build up accurate gripper width to avoid cutting off other panes. VisualStyleRenderer vsRenderer = VisualStyleRenderer; VisualStyleElement thisElement; Size elementSize; // gripper pane width... thisElement = VisualStyleElement.Status.GripperPane.Normal; vsRenderer.SetParameters(thisElement); elementSize = vsRenderer.GetPartSize(Graphics.FromHwndInternal(this.Handle), ThemeSizeType.True); sizeGripWidth = elementSize.Width; // ...plus gripper width thisElement = VisualStyleElement.Status.Gripper.Normal; vsRenderer.SetParameters(thisElement); elementSize = vsRenderer.GetPartSize(Graphics.FromHwndInternal(this.Handle), ThemeSizeType.True); sizeGripWidth += elementSize.Width; // Either GetPartSize could have returned a width of zero, so make sure we have a reasonable number: sizeGripWidth = Math.Max(sizeGripWidth, 16); } else { sizeGripWidth = 16; } } return sizeGripWidth; } } ////// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public override Color BackColor { get { // not supported, always return CONTROL return SystemColors.Control; } set { // no op, not supported. } } ////// The background color of this control. This is an ambient property and will /// always return a non-null value. /// ////// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] new public event EventHandler BackColorChanged { add { base.BackColorChanged += value; } remove { base.BackColorChanged -= value; } } /// /// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public override Image BackgroundImage { get { return base.BackgroundImage; } set { base.BackgroundImage = value; } } ////// Gets or sets the image rendered on the background of the /// ////// control. /// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] new public event EventHandler BackgroundImageChanged { add { base.BackgroundImageChanged += value; } remove { base.BackgroundImageChanged -= value; } } /// /// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public override ImageLayout BackgroundImageLayout { get { return base.BackgroundImageLayout; } set { base.BackgroundImageLayout = value; } } ///[To be supplied.] ////// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] new public event EventHandler BackgroundImageLayoutChanged { add { base.BackgroundImageLayoutChanged += value; } remove { base.BackgroundImageLayoutChanged -= value; } } /// /// /// protected override CreateParams CreateParams { [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] get { CreateParams cp = base.CreateParams; cp.ClassName = NativeMethods.WC_STATUSBAR; if (this.sizeGrip) { cp.Style |= NativeMethods.SBARS_SIZEGRIP; } else { cp.Style &= (~NativeMethods.SBARS_SIZEGRIP); } cp.Style |= NativeMethods.CCS_NOPARENTALIGN | NativeMethods.CCS_NORESIZE; return cp; } } ////// Returns the CreateParams used to create the handle for this control. /// Inheriting classes should call base.getCreateParams in the manor below: /// ///protected override ImeMode DefaultImeMode { get { return ImeMode.Disable; } } /// /// /// Deriving classes can override this to configure a default size for their control. /// This is more efficient than setting the size in the control's constructor. /// protected override Size DefaultSize { get { return new Size(100, 22); } } ////// /// This property is overridden and hidden from statement completion /// on controls that are based on Win32 Native Controls. /// [EditorBrowsable(EditorBrowsableState.Never)] protected override bool DoubleBuffered { get { return base.DoubleBuffered; } set { base.DoubleBuffered = value; } } ////// /// [ Localizable(true), DefaultValue(DockStyle.Bottom) ] public override DockStyle Dock { get { return base.Dock; } set { base.Dock = value; } } ////// Gets or sets the docking behavior of the ///control. /// /// /// [ Localizable(true) ] public override Font Font { get { return base.Font;} set { base.Font = value; SetPanelContentsWidths(false); } } ////// Gets or sets the font the ////// control will use to display /// information. /// /// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public override Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; } } ////// Gets or sets /// the forecolor for the control. /// ////// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] new public event EventHandler ForeColorChanged { add { base.ForeColorChanged += value; } remove { base.ForeColorChanged -= value; } } /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] new public ImeMode ImeMode { get { return base.ImeMode; } set { base.ImeMode = value; } } /// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler ImeModeChanged { add { base.ImeModeChanged += value; } remove { base.ImeModeChanged -= value; } } /// /// /// [ DesignerSerializationVisibility(DesignerSerializationVisibility.Content), SRDescription(SR.StatusBarPanelsDescr), Localizable(true), SRCategory(SR.CatAppearance), MergableProperty(false) ] public StatusBarPanelCollection Panels { get { if (panelsCollection == null) { panelsCollection = new StatusBarPanelCollection(this); } return panelsCollection; } } ////// Gets the collection of ////// panels contained within the /// control. /// /// /// [ Localizable(true) ] public override string Text { get { if (simpleText == null) { return ""; } else { return simpleText; } } set { SetSimpleText(value); if (simpleText != value) { simpleText = value; OnTextChanged(EventArgs.Empty); } } } /* No one is calling this, so it is ok to comment it out private IntPtr ToolTipHandle { get { EnumChildren c = new EnumChildren( this ); UnsafeNativeMethods.EnumChildWindows(new HandleRef(null, UnsafeNativeMethods.GetDesktopWindow()), new NativeMethods.EnumChildrenProc(c.Callback), NativeMethods.NullHandleRef); return c.hWndFound; } } */ ////// The status bar text. /// ////// /// [ SRCategory(SR.CatBehavior), DefaultValue(false), SRDescription(SR.StatusBarShowPanelsDescr) ] public bool ShowPanels { get { return showPanels; } set { if (showPanels != value) { showPanels = value; layoutDirty = true; if (IsHandleCreated) { int bShowPanels = (!showPanels) ? 1 : 0; SendMessage(NativeMethods.SB_SIMPLE, bShowPanels, 0); if (showPanels) { PerformLayout(); RealizePanels(); } else if (tooltips != null) { for (int i=0; i/// Gets or sets a value indicating whether panels should be shown. /// ////// /// [ SRCategory(SR.CatAppearance), DefaultValue(true), SRDescription(SR.StatusBarSizingGripDescr) ] public bool SizingGrip { get { return sizeGrip; } set { if (value != sizeGrip) { sizeGrip = value; RecreateHandle(); } } } ////// Gets or sets a value indicating whether a sizing grip /// will be rendered on the corner of the ////// control. /// /// /// [DefaultValue(false)] new public bool TabStop { get { return base.TabStop; } set { base.TabStop = value; } } internal bool ToolTipSet { get { return toolTipSet; } } internal ToolTip MainToolTip { get { return mainToolTip; } } ////// Gets or sets a value indicating whether the user will be able to tab to the /// ///. /// /// /// [SRCategory(SR.CatBehavior), SRDescription(SR.StatusBarDrawItem)] public event StatusBarDrawItemEventHandler DrawItem { add { Events.AddHandler(EVENT_SBDRAWITEM, value); } remove { Events.RemoveHandler(EVENT_SBDRAWITEM, value); } } ////// Occurs when a visual aspect of an owner-drawn status bar changes. /// ////// /// [SRCategory(SR.CatMouse), SRDescription(SR.StatusBarOnPanelClickDescr)] public event StatusBarPanelClickEventHandler PanelClick { add { Events.AddHandler(EVENT_PANELCLICK, value); } remove { Events.RemoveHandler(EVENT_PANELCLICK, value); } } ////// Occurs when a panel on the status bar is clicked. /// ////// /// StatusBar Onpaint. /// ///[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new event PaintEventHandler Paint { add { base.Paint += value; } remove { base.Paint -= value; } } /// /// /// Tells whether the panels have been realized. /// ///internal bool ArePanelsRealized() { return this.showPanels && IsHandleCreated; } /// /// /// ///internal void DirtyLayout() { layoutDirty = true; } /// /// /// Makes the panel according to the sizes in the panel list. /// ///private void ApplyPanelWidths() { // This forces handle creation every time any time the StatusBar // has to be re-laidout. // if (!IsHandleCreated) return; StatusBarPanel panel = null; int length = this.panels.Count; if (length == 0) { Size sz = Size; int[] offsets = new int[1]; offsets[0] = sz.Width; if (sizeGrip) { offsets[0] -= SizeGripWidth; } UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.SB_SETPARTS, 1, offsets); SendMessage(NativeMethods.SB_SETICON, 0, IntPtr.Zero); return; } int[] offsets2 = new int[length]; int currentOffset = 0; for (int i = 0; i < length; i++) { panel = (StatusBarPanel) this.panels[i]; currentOffset += panel.Width; offsets2[i] = currentOffset; panel.Right = offsets2[i]; } UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.SB_SETPARTS, length, offsets2); // Tooltip setup... // for (int i=0; i /// /// ///protected override void CreateHandle() { if (!RecreatingHandle) { IntPtr userCookie = UnsafeNativeMethods.ThemingScope.Activate(); try { NativeMethods.INITCOMMONCONTROLSEX icc = new NativeMethods.INITCOMMONCONTROLSEX(); icc.dwICC = NativeMethods.ICC_BAR_CLASSES; SafeNativeMethods.InitCommonControlsEx(icc); } finally { UnsafeNativeMethods.ThemingScope.Deactivate(userCookie); } } base.CreateHandle(); } /// /// /// Disposes this control /// protected override void Dispose(bool disposing) { if (disposing) { if (panelsCollection != null) { StatusBarPanel[] panelCopy = new StatusBarPanel[panelsCollection.Count]; ((ICollection)panelsCollection).CopyTo(panelCopy, 0); panelsCollection.Clear(); foreach(StatusBarPanel p in panelCopy) { p.Dispose(); } } } base.Dispose(disposing); } ////// /// Forces the panels to be updated, location, repainting, etc. /// ///private void ForcePanelUpdate() { if (ArePanelsRealized()) { layoutDirty = true; SetPanelContentsWidths(true); PerformLayout(); RealizePanels(); } } /// /// /// protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); if (!DesignMode) { tooltips = new ControlToolTip(this); } if (!this.showPanels) { SendMessage(NativeMethods.SB_SIMPLE, 1, 0); SetSimpleText(simpleText); } else { ForcePanelUpdate(); } } ////// Raises the ////// event. /// /// /// protected override void OnHandleDestroyed(EventArgs e) { base.OnHandleDestroyed(e); if (tooltips != null) { tooltips.Dispose(); tooltips = null; } } /* Not used ////// Raises the ///event. /// /// /// private sealed class EnumChildren { public IntPtr hWndFound = IntPtr.Zero; private StatusBar peer; public EnumChildren( StatusBar peer ) { if (peer == null) throw new ArgumentNullException("peer"); this.peer = peer; } public bool Callback(IntPtr hWnd, IntPtr lparam) { if (UnsafeNativeMethods.GetParent(new HandleRef(null, hWnd)) == peer.Handle) { hWndFound = hWnd; return false; } return true; } }*/ ////// /// protected override void OnMouseDown(MouseEventArgs e) { lastClick.X = e.X; lastClick.Y = e.Y; base.OnMouseDown(e); } ////// Raises the ///event. /// /// /// protected virtual void OnPanelClick(StatusBarPanelClickEventArgs e) { StatusBarPanelClickEventHandler handler = (StatusBarPanelClickEventHandler)Events[EVENT_PANELCLICK]; if (handler != null) handler(this,e); } ////// Raises the ///event. /// /// /// protected override void OnLayout(LayoutEventArgs levent) { if (this.showPanels) { LayoutPanels(); if (IsHandleCreated && panelsRealized != panels.Count) { RealizePanels(); } } base.OnLayout(levent); } ////// Raises the Layout event. /// ////// /// This function sets up all the panel on the status bar according to /// the internal this.panels List. /// ///internal void RealizePanels() { StatusBarPanel panel = null; int length = this.panels.Count; int old = panelsRealized; panelsRealized = 0; if (length == 0) { SendMessage(NativeMethods.SB_SETTEXT, 0, ""); } int i; for (i = 0; i < length; i++) { panel = (StatusBarPanel) this.panels[i]; try { panel.Realize(); panelsRealized++; } catch { } } for (; i /// /// Remove the internal list of panels without updating the control. /// ///internal void RemoveAllPanelsWithoutUpdate() { int size = this.panels.Count; // remove the parent reference for (int i = 0; i < size; i++) { StatusBarPanel sbp = (StatusBarPanel) this.panels[i]; sbp.ParentInternal = null; } this.panels.Clear(); if (this.showPanels == true) { ApplyPanelWidths(); ForcePanelUpdate(); } } /// /// /// Sets the widths of any panels that have the /// StatusBarPanelAutoSize.CONTENTS property set. /// ///internal void SetPanelContentsWidths(bool newPanels) { int size = panels.Count; bool changed = false; for (int i = 0; i < size; i++) { StatusBarPanel sbp = (StatusBarPanel) panels[i]; if (sbp.AutoSize == StatusBarPanelAutoSize.Contents) { int newWidth = sbp.GetContentsWidth(newPanels); if (sbp.Width != newWidth) { sbp.Width = newWidth; changed = true; } } } if (changed) { DirtyLayout(); PerformLayout(); } } private void SetSimpleText(string simpleText) { if (!showPanels && IsHandleCreated) { int wparam = SIMPLE_INDEX + NativeMethods.SBT_NOBORDERS; if (RightToLeft == RightToLeft.Yes) { wparam |= NativeMethods.SBT_RTLREADING; } SendMessage(NativeMethods.SB_SETTEXT, wparam, simpleText); } } /// /// /// Sizes the the panels appropriately. It looks at the SPRING AutoSize /// property. /// ///private void LayoutPanels() { StatusBarPanel panel = null; int barPanelWidth = 0; int springNum = 0; StatusBarPanel[] pArray = new StatusBarPanel[this.panels.Count]; bool changed = false; for (int i = 0; i < pArray.Length; i++) { panel = (StatusBarPanel) this.panels[i]; if (panel.AutoSize == StatusBarPanelAutoSize.Spring) { pArray[springNum] = panel; springNum++; } else barPanelWidth += panel.Width; } if (springNum > 0) { Rectangle rect = Bounds; int springPanelsLeft = springNum; int leftoverWidth = rect.Width - barPanelWidth; if (sizeGrip) { leftoverWidth -= SizeGripWidth; } int copyOfLeftoverWidth = unchecked((int)0x80000000); while (springPanelsLeft > 0) { int widthOfSpringPanel = (leftoverWidth) / springPanelsLeft; if (leftoverWidth == copyOfLeftoverWidth) break; copyOfLeftoverWidth = leftoverWidth; for (int i = 0; i < springNum; i++) { panel = pArray[i]; if (panel == null) continue; if (widthOfSpringPanel < panel.MinWidth) { if (panel.Width != panel.MinWidth) { changed = true; } panel.Width = panel.MinWidth; pArray[i] = null; springPanelsLeft --; leftoverWidth -= panel.MinWidth; } else { if (panel.Width != widthOfSpringPanel) { changed = true; } panel.Width = widthOfSpringPanel; } } } } if (changed || layoutDirty) { ApplyPanelWidths(); } } /// /// /// protected virtual void OnDrawItem(StatusBarDrawItemEventArgs sbdievent) { StatusBarDrawItemEventHandler handler = (StatusBarDrawItemEventHandler)Events[EVENT_SBDRAWITEM]; if (handler != null) handler(this,sbdievent); } ////// Raises the ////// event. /// /// /// protected override void OnResize(EventArgs e) { Invalidate(); base.OnResize(e); } ////// Raises the ////// event. /// /// /// public override string ToString() { string s = base.ToString(); if (Panels != null) { s += ", Panels.Count: " + Panels.Count.ToString(CultureInfo.CurrentCulture); if (Panels.Count > 0) s += ", Panels[0]: " + Panels[0].ToString(); } return s; } //call this when System.Windows.forms.toolTip is Associated with Statusbar.... internal void SetToolTip(ToolTip t) { this.mainToolTip = t; toolTipSet = true; } internal void UpdateTooltip(StatusBarPanel panel) { if (tooltips == null) { if (IsHandleCreated && !DesignMode) { //This shouldn't happen: tooltips should've already been set. The best we can //do here is reset it. tooltips = new ControlToolTip(this); } else { return; } } if (panel.Parent == this && panel.ToolTipText.Length > 0) { int border = SystemInformation.Border3DSize.Width; ControlToolTip.Tool t = tooltips.GetTool(panel); if (t == null) { t = new ControlToolTip.Tool(); } t.text = panel.ToolTipText; t.rect = new Rectangle(panel.Right-panel.Width + border, 0, panel.Width - border, Height); tooltips.SetTool(panel, t); } else { tooltips.SetTool(panel, null); } } private void UpdatePanelIndex() { int length = panels.Count; for (int i=0; i/// Returns a string representation for this control. /// ////// /// /// Processes messages for ownerdraw panels. /// private void WmDrawItem(ref Message m) { NativeMethods.DRAWITEMSTRUCT dis = (NativeMethods.DRAWITEMSTRUCT)m.GetLParam(typeof(NativeMethods.DRAWITEMSTRUCT)); int length = this.panels.Count; if (dis.itemID < 0 || dis.itemID >= length) Debug.Fail("OwnerDraw item out of range"); StatusBarPanel panel = (StatusBarPanel) this.panels[dis.itemID]; Graphics g = Graphics.FromHdcInternal(dis.hDC); Rectangle r = Rectangle.FromLTRB(dis.rcItem.left, dis.rcItem.top, dis.rcItem.right, dis.rcItem.bottom); //The itemstate is not defined for a statusbar control OnDrawItem(new StatusBarDrawItemEventArgs(g, Font, r, dis.itemID, DrawItemState.None, panel, this.ForeColor, this.BackColor)); g.Dispose(); } ////// /// /// private void WmNotifyNMClick(NativeMethods.NMHDR note) { if (!showPanels) { return; } int size = panels.Count; int currentOffset = 0; int index = -1; for (int i = 0; i < size; i++) { StatusBarPanel panel = (StatusBarPanel) panels[i]; currentOffset += panel.Width; if (lastClick.X < currentOffset) { // this is where the mouse was clicked. index = i; break; } } if (index != -1) { MouseButtons button = MouseButtons.Left; int clicks = 0; switch (note.code) { case NativeMethods.NM_CLICK: button = MouseButtons.Left; clicks = 1; break; case NativeMethods.NM_RCLICK: button = MouseButtons.Right; clicks = 1; break; case NativeMethods.NM_DBLCLK: button = MouseButtons.Left; clicks = 2; break; case NativeMethods.NM_RDBLCLK: button = MouseButtons.Right; clicks = 2; break; } Point pt = lastClick; StatusBarPanel panel = (StatusBarPanel) panels[index]; StatusBarPanelClickEventArgs sbpce = new StatusBarPanelClickEventArgs(panel, button, clicks, pt.X, pt.Y); OnPanelClick(sbpce); } } private void WmNCHitTest(ref Message m) { int x = NativeMethods.Util.LOWORD(m.LParam); Rectangle bounds = Bounds; bool callSuper = true; // The default implementation of the statusbar // : will let you size the form when it is docked on the bottom, // : but when it is anywhere else, the statusbar will be resized. // : to prevent that we provide a little bit a sanity to only // : allow resizing, when it would resize the form. // if (x > bounds.X + bounds.Width - SizeGripWidth) { Control parent = ParentInternal; if (parent != null && parent is Form) { FormBorderStyle bs = ((Form)parent).FormBorderStyle; if (bs != FormBorderStyle.Sizable && bs != FormBorderStyle.SizableToolWindow) { callSuper = false; } if (!((Form)parent).TopLevel || Dock != DockStyle.Bottom) { callSuper = false; } if (callSuper) { Control.ControlCollection children = parent.Controls; int c = children.Count; for (int i=0; iTop) { callSuper = false; break; } } } } } else { callSuper = false; } } if (callSuper) { base.WndProc(ref m); } else { m.Result = (IntPtr)NativeMethods.HTCLIENT; } } /// /// /// [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] protected override void WndProc(ref Message m) { switch (m.Msg) { case NativeMethods.WM_NCHITTEST: WmNCHitTest(ref m); break; case NativeMethods.WM_REFLECT + NativeMethods.WM_DRAWITEM: WmDrawItem(ref m); break; case NativeMethods.WM_NOTIFY: case NativeMethods.WM_NOTIFY + NativeMethods.WM_REFLECT: NativeMethods.NMHDR note = (NativeMethods.NMHDR)m.GetLParam(typeof(NativeMethods.NMHDR)); switch (note.code) { case NativeMethods.NM_CLICK: case NativeMethods.NM_RCLICK: case NativeMethods.NM_DBLCLK: case NativeMethods.NM_RDBLCLK: WmNotifyNMClick(note); break; default: base.WndProc(ref m); break; } break; default: base.WndProc(ref m); break; } } ////// Base wndProc. All messages are sent to wndProc after getting filtered through /// the preProcessMessage function. Inheriting controls should call base.wndProc /// for any messages that they don't handle. /// ////// /// [ ListBindable(false) ] public class StatusBarPanelCollection : IList { private StatusBar owner; /// A caching mechanism for key accessor /// We use an index here rather than control so that we don't have lifetime /// issues by holding on to extra references. private int lastAccessedIndex = -1; ////// The collection of StatusBarPanels that the StatusBar manages. /// event. /// ////// /// public StatusBarPanelCollection(StatusBar owner) { this.owner = owner; } ////// Constructor for the StatusBarPanelCollection class /// ////// /// This method will return an individual StatusBarPanel with the appropriate index. /// public virtual StatusBarPanel this[int index] { get { return(StatusBarPanel)owner.panels[index]; } set { if (value == null) throw new ArgumentNullException("StatusBarPanel"); owner.layoutDirty = true; if (value.Parent != null) { throw new ArgumentException(SR.GetString(SR.ObjectHasParent), "value"); } int length = owner.panels.Count; if (index < 0|| index >= length) throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); StatusBarPanel oldPanel = (StatusBarPanel) owner.panels[index]; oldPanel.ParentInternal = null; value.ParentInternal = owner; if (value.AutoSize == StatusBarPanelAutoSize.Contents) { value.Width = value.GetContentsWidth(true); } owner.panels[index] = value; value.Index = index; if (owner.ArePanelsRealized()) { owner.PerformLayout(); value.Realize(); } } } ////// object IList.this[int index] { get { return this[index]; } set { if (value is StatusBarPanel) { this[index] = (StatusBarPanel)value; } else { throw new ArgumentException(SR.GetString(SR.StatusBarBadStatusBarPanel), "value"); } } } /// /// /// public virtual StatusBarPanel this[string key] { get { // We do not support null and empty string as valid keys. if (string.IsNullOrEmpty(key)){ return null; } // Search for the key in our collection int index = IndexOfKey(key); if (IsValidIndex(index)) { return this[index]; } else { return null; } } } ///Retrieves the child control with the specified key. ////// /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public int Count { get { return owner.panels.Count; } } ////// Returns an integer representing the number of StatusBarPanels /// in this collection. /// ////// object ICollection.SyncRoot { get { return this; } } /// /// bool ICollection.IsSynchronized { get { return false; } } /// /// bool IList.IsFixedSize { get { return false; } } /// /// /// public bool IsReadOnly { get { return false; } } ///[To be supplied.] ////// /// public virtual StatusBarPanel Add(string text) { StatusBarPanel panel = new StatusBarPanel(); panel.Text = text; Add(panel); return panel; } ////// Adds a StatusBarPanel to the collection. /// ////// /// public virtual int Add(StatusBarPanel value) { int index = owner.panels.Count; Insert(index, value); return index; } ////// Adds a StatusBarPanel to the collection. /// ////// int IList.Add(object value) { if (value is StatusBarPanel) { return Add((StatusBarPanel)value); } else { throw new ArgumentException(SR.GetString(SR.StatusBarBadStatusBarPanel), "value"); } } /// /// /// public virtual void AddRange(StatusBarPanel[] panels) { if (panels == null) { throw new ArgumentNullException("panels"); } foreach(StatusBarPanel panel in panels) { Add(panel); } } ///[To be supplied.] ////// /// public bool Contains(StatusBarPanel panel) { return IndexOf(panel) != -1; } ///[To be supplied.] ////// bool IList.Contains(object panel) { if (panel is StatusBarPanel) { return Contains((StatusBarPanel)panel); } else { return false; } } /// /// /// public virtual bool ContainsKey(string key) { return IsValidIndex(IndexOfKey(key)); } ///Returns true if the collection contains an item with the specified key, false otherwise. ////// /// public int IndexOf(StatusBarPanel panel) { for(int index=0; index < Count; ++index) { if (this[index] == panel) { return index; } } return -1; } ///[To be supplied.] ////// int IList.IndexOf(object panel) { if (panel is StatusBarPanel) { return IndexOf((StatusBarPanel)panel); } else { return -1; } } /// /// /// public virtual int IndexOfKey(String key) { // Step 0 - Arg validation if (string.IsNullOrEmpty(key)){ return -1; // we dont support empty or null keys. } // step 1 - check the last cached item if (IsValidIndex(lastAccessedIndex)) { if (WindowsFormsUtils.SafeCompareStrings(this[lastAccessedIndex].Name, key, /* ignoreCase = */ true)) { return lastAccessedIndex; } } // step 2 - search for the item for (int i = 0; i < this.Count; i ++) { if (WindowsFormsUtils.SafeCompareStrings(this[i].Name, key, /* ignoreCase = */ true)) { lastAccessedIndex = i; return i; } } // step 3 - we didn't find it. Invalidate the last accessed index and return -1. lastAccessedIndex = -1; return -1; } ///The zero-based index of the first occurrence of value within the entire CollectionBase, if found; otherwise, -1. ////// /// public virtual void Insert(int index, StatusBarPanel value) { //check for the value not to be null if (value == null) throw new ArgumentNullException("value"); //end check owner.layoutDirty = true; if (value.Parent != owner && value.Parent != null) throw new ArgumentException(SR.GetString(SR.ObjectHasParent), "value"); int length = owner.panels.Count; if (index < 0 || index > length) throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); value.ParentInternal = owner; switch (value.AutoSize) { case StatusBarPanelAutoSize.None: case StatusBarPanelAutoSize.Spring: break; case StatusBarPanelAutoSize.Contents: value.Width = value.GetContentsWidth(true); break; } owner.panels.Insert(index, value); owner.UpdatePanelIndex(); owner.ForcePanelUpdate(); } ////// Inserts a StatusBarPanel in the collection. /// ////// void IList.Insert(int index, object value) { if (value is StatusBarPanel) { Insert(index, (StatusBarPanel)value); } else { throw new ArgumentException(SR.GetString(SR.StatusBarBadStatusBarPanel), "value"); } } /// /// /// ///Determines if the index is valid for the collection. ///private bool IsValidIndex(int index) { return ((index >= 0) && (index < this.Count)); } /// /// /// public virtual void Clear() { owner.RemoveAllPanelsWithoutUpdate(); owner.PerformLayout(); } ////// Removes all the StatusBarPanels in the collection. /// ////// /// public virtual void Remove(StatusBarPanel value) { //check for the value not to be null if (value == null) throw new ArgumentNullException("StatusBarPanel"); //end check if (value.Parent != owner) { return; } RemoveAt(value.Index); } ////// Removes an individual StatusBarPanel in the collection. /// ////// void IList.Remove(object value) { if (value is StatusBarPanel) { Remove((StatusBarPanel)value); } } /// /// /// public virtual void RemoveAt(int index) { int length = Count; if (index < 0 || index >= length) throw new ArgumentOutOfRangeException("index", SR.GetString(SR.InvalidArgument, "index", index.ToString(CultureInfo.CurrentCulture))); // clear any tooltip // StatusBarPanel panel = (StatusBarPanel)owner.panels[index]; owner.panels.RemoveAt(index); panel.ParentInternal = null; // this will cause the panels tooltip to be removed since it's no longer a child // of this StatusBar. // owner.UpdateTooltip(panel); // V#41207 - [....], 4/1/1998 - We must reindex the panels after a removal... owner.UpdatePanelIndex(); owner.ForcePanelUpdate(); } ////// Removes an individual StatusBarPanel in the collection at the given index. /// ////// /// public virtual void RemoveByKey(string key) { int index = IndexOfKey(key); if (IsValidIndex(index)) { RemoveAt(index); } } ///Removes the child control with the specified key. ////// void ICollection.CopyTo(Array dest, int index) { owner.panels.CopyTo(dest, index); } /// /// /// public IEnumerator GetEnumerator() { if (owner.panels != null) { return owner.panels.GetEnumerator(); } else { return new StatusBarPanel[0].GetEnumerator(); } } } ////// Returns the Enumerator for this collection. /// ////// /// This is a tooltip control that provides tips for a single /// control. Each "tool" region is defined by a rectangle and /// the string that should be displayed. This implementation /// is based on System.Windows.Forms.ToolTip, but this control /// is lighter weight and provides less functionality... however /// this control binds to rectangular regions, instead of /// full controls. /// [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] private class ControlToolTip { ///public class Tool { /// public Rectangle rect = Rectangle.Empty; /// public string text; internal IntPtr id = new IntPtr(-1); } private Hashtable tools = new Hashtable(); private ToolTipNativeWindow window = null; private Control parent = null; private int nextId = 0; /// /// /// Creates a new ControlToolTip. /// public ControlToolTip(Control parent) { window = new ToolTipNativeWindow(this); this.parent = parent; } ////// /// Returns the createParams to create the window. /// protected CreateParams CreateParams { get { NativeMethods.INITCOMMONCONTROLSEX icc = new NativeMethods.INITCOMMONCONTROLSEX(); icc.dwICC = NativeMethods.ICC_TAB_CLASSES; SafeNativeMethods.InitCommonControlsEx(icc); CreateParams cp = new CreateParams(); cp.Parent = IntPtr.Zero; cp.ClassName = NativeMethods.TOOLTIPS_CLASS; cp.Style |= NativeMethods.TTS_ALWAYSTIP; cp.ExStyle = 0; cp.Caption = null; return cp; } } ////// /// public IntPtr Handle { get { if (window.Handle == IntPtr.Zero) { CreateHandle(); } return window.Handle; } } private bool IsHandleCreated { get { return window.Handle != IntPtr.Zero;} } private void AssignId(Tool tool) { tool.id = (IntPtr)nextId; nextId++; } ////// /// Sets the tool for the specified key. Keep in mind /// that as soon as setTool is called, the handle for /// the ControlToolTip is created, and the handle for /// the parent control is also created. If the parent /// handle is recreated in the future, all tools must /// be re-added. The old tool for the specified key /// will be removed. Passing null in for the /// tool parameter will result in the tool /// region being removed. /// public void SetTool(object key, Tool tool) { bool remove = false; bool add = false; bool update = false; Tool toRemove = null; if (tools.ContainsKey(key)) { toRemove = (Tool)tools[key]; } if (toRemove != null) { remove = true; } if (tool != null) { add = true; } if (tool != null && toRemove != null && tool.id == toRemove.id) { update = true; } if (update) { UpdateTool(tool); } else { if (remove) { RemoveTool(toRemove); } if (add) { AddTool(tool); } } if (tool != null) { tools[key] = tool; } else { tools.Remove(key); } } ////// /// Returns the tool associated with the specified key, /// or null if there is no area. /// public Tool GetTool(object key) { return(Tool)tools[key]; } private void AddTool(Tool tool) { if (tool != null && tool.text != null && tool.text.Length > 0) { int ret; StatusBar p = (StatusBar)parent; if (p.ToolTipSet) { ret = (int)UnsafeNativeMethods.SendMessage(new HandleRef(p.MainToolTip, p.MainToolTip.Handle), NativeMethods.TTM_ADDTOOL, 0, GetTOOLINFO(tool)); } else { ret = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_ADDTOOL, 0, GetTOOLINFO(tool)); } if (ret == 0) { throw new InvalidOperationException(SR.GetString(SR.StatusBarAddFailed)); } } } private void RemoveTool(Tool tool) { if (tool != null && tool.text != null && tool.text.Length > 0 && (int)tool.id >= 0) { UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_DELTOOL, 0, GetMinTOOLINFO(tool)); } } private void UpdateTool(Tool tool) { if (tool != null && tool.text != null && tool.text.Length > 0 && (int)tool.id >= 0) { UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_SETTOOLINFO, 0, GetTOOLINFO(tool)); } } ////// /// Creates the handle for the control. /// protected void CreateHandle() { if (IsHandleCreated) { return; } window.CreateHandle(CreateParams); SafeNativeMethods.SetWindowPos(new HandleRef(this, Handle), NativeMethods.HWND_TOPMOST, 0, 0, 0, 0, NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOSIZE | NativeMethods.SWP_NOACTIVATE); // Setting the max width has the added benefit of enabling multiline // tool tips! // UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.TTM_SETMAXTIPWIDTH, 0, SystemInformation.MaxWindowTrackSize.Width); } ////// /// Destroys the handle for this control. /// protected void DestroyHandle() { if (IsHandleCreated) { window.DestroyHandle(); tools.Clear(); } } ////// /// Disposes of the component. Call dispose when the component is no longer needed. /// This method removes the component from its container (if the component has a site) /// and triggers the dispose event. /// public void Dispose() { DestroyHandle(); } ////// /// Returns a new instance of the TOOLINFO_T structure with the minimum /// required data to uniquely identify a region. This is used primarily /// for delete operations. NOTE: This cannot force the creation of a handle. /// private NativeMethods.TOOLINFO_T GetMinTOOLINFO(Tool tool) { NativeMethods.TOOLINFO_T ti = new NativeMethods.TOOLINFO_T(); ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_T)); ti.hwnd = parent.Handle; if ((int)tool.id < 0) { AssignId(tool); } StatusBar p = (StatusBar)parent; if (p != null && p.ToolTipSet) { ti.uId = parent.Handle; } else { ti.uId = tool.id; } return ti; } ////// /// Returns a detailed TOOLINFO_T structure that represents the specified /// region. NOTE: This may force the creation of a handle. /// private NativeMethods.TOOLINFO_T GetTOOLINFO(Tool tool) { NativeMethods.TOOLINFO_T ti = GetMinTOOLINFO(tool); ti.cbSize = Marshal.SizeOf(typeof(NativeMethods.TOOLINFO_T)); ti.uFlags |= NativeMethods.TTF_TRANSPARENT | NativeMethods.TTF_SUBCLASS; // RightToLeft reading order // Control richParent = parent; if (richParent != null && richParent.RightToLeft == RightToLeft.Yes) { ti.uFlags |= NativeMethods.TTF_RTLREADING; } ti.lpszText = tool.text; ti.rect = NativeMethods.RECT.FromXYWH(tool.rect.X, tool.rect.Y, tool.rect.Width, tool.rect.Height); return ti; } ////// /// ~ControlToolTip() { DestroyHandle(); } ////// /// WNDPROC /// protected void WndProc(ref Message msg) { switch (msg.Msg) { case NativeMethods.WM_SETFOCUS: // bug 120872, the COMCTL StatusBar passes WM_SETFOCUS on to the DefWndProc, so // it will take keyboard focus. We don't want it doing this, so we eat // the message. // return; default: window.DefWndProc(ref msg); break; } } ////// /// private class ToolTipNativeWindow : NativeWindow { ControlToolTip control; internal ToolTipNativeWindow(ControlToolTip control) { this.control = control; } protected override void WndProc(ref Message m) { if (control != null) { control.WndProc(ref m); } } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- EasingFunctionBase.cs
- ExtensionWindowHeader.cs
- NativeMethods.cs
- WebPartMenuStyle.cs
- RootProfilePropertySettingsCollection.cs
- ValidationError.cs
- PngBitmapDecoder.cs
- WpfKnownMember.cs
- DataObjectCopyingEventArgs.cs
- EntityParameter.cs
- ActivityDesignerResources.cs
- MobileUserControlDesigner.cs
- DataRecordObjectView.cs
- SubstitutionDesigner.cs
- EncoderFallback.cs
- XPathQilFactory.cs
- ColumnHeader.cs
- HttpRequest.cs
- XmlQueryType.cs
- KeyValueConfigurationElement.cs
- SamlNameIdentifierClaimResource.cs
- CompilationUtil.cs
- PeerObject.cs
- RelatedCurrencyManager.cs
- XmlILTrace.cs
- LayoutEvent.cs
- CustomTrackingRecord.cs
- XmlSecureResolver.cs
- X509Extension.cs
- SchemaTableColumn.cs
- EntityDesignPluralizationHandler.cs
- _DisconnectOverlappedAsyncResult.cs
- TraceEventCache.cs
- FixedDocumentSequencePaginator.cs
- ProgressBar.cs
- WriteFileContext.cs
- CodeNamespace.cs
- IgnorePropertiesAttribute.cs
- ICollection.cs
- Deflater.cs
- DataListItemEventArgs.cs
- MaskInputRejectedEventArgs.cs
- DataGridItem.cs
- SqlDataReader.cs
- FormView.cs
- ResourceDisplayNameAttribute.cs
- OleAutBinder.cs
- SqlCacheDependency.cs
- AttributeCollection.cs
- CryptoStream.cs
- TimeSpan.cs
- TableCellCollection.cs
- SQLByte.cs
- ToolStripDropDownDesigner.cs
- InitialServerConnectionReader.cs
- BamlReader.cs
- CaseInsensitiveOrdinalStringComparer.cs
- DataBoundControlDesigner.cs
- XhtmlBasicImageAdapter.cs
- ChannelManager.cs
- SqlProviderManifest.cs
- PriorityQueue.cs
- IntSecurity.cs
- CodeRegionDirective.cs
- BuildResultCache.cs
- Screen.cs
- CompletionProxy.cs
- SessionEndingCancelEventArgs.cs
- MemoryStream.cs
- InternalControlCollection.cs
- CategoryState.cs
- OdbcConnectionString.cs
- LifetimeServices.cs
- IndexOutOfRangeException.cs
- WebPartDisplayMode.cs
- PhotoPrintingIntent.cs
- CssClassPropertyAttribute.cs
- IpcManager.cs
- XMLDiffLoader.cs
- RegexReplacement.cs
- SimpleType.cs
- ExpressionWriter.cs
- Int32RectConverter.cs
- XPathException.cs
- PeerObject.cs
- querybuilder.cs
- ValueTypePropertyReference.cs
- BulletedList.cs
- RawMouseInputReport.cs
- Queue.cs
- SafeNativeMethodsOther.cs
- ConnectionManagementSection.cs
- XMLSchema.cs
- SmiXetterAccessMap.cs
- XmlSchemaExternal.cs
- EncoderExceptionFallback.cs
- SqlUDTStorage.cs
- nulltextcontainer.cs
- CalloutQueueItem.cs
- PagePropertiesChangingEventArgs.cs