Rebar.cs
上传用户:nnpulika
上传日期:2013-02-15
资源大小:597k
文件大小:19k
- using System;
- using System.Windows.Forms;
- using System.Drawing;
- using System.Collections;
- using System.Diagnostics;
- using System.Runtime.InteropServices;
- using System.ComponentModel;
- using UtilityLibrary.Collections;
- using UtilityLibrary.Win32;
- using UtilityLibrary.General;
- using UtilityLibrary.Designers;
- namespace UtilityLibrary.CommandBars
- {
-
- /// <summary>
- /// Summary description for Rebar.
- /// </summary>
- [ToolboxBitmap(typeof(UtilityLibrary.CommandBars.ReBar),
- "UtilityLibrary.CommandBars.ReBar.bmp")]
- [Designer(typeof(UtilityLibrary.Designers.ReBarDesigner))]
- public class ReBar : Control, IMessageFilter
- {
- #region Class Variables
- RebarBandCollection bands = null;
- static bool needsColorUpdate = false;
- bool bGotIsCommonCtrl6 = false;
- bool isCommonCtrl6 = false;
- const int MINIMUM_HEIGHT = 30;
-
- // Designer Support
- ToolBarEx placeHolderToolBar = null;
- bool placeHolderAdded = false;
- ReBarDesigner rebarDesigner = null;
- bool addPlaceHolderToolBar = false;
- bool designerInTransaction = false;
- #endregion
- #region Constructors
- public ReBar()
- {
- Initialize();
- }
- void Initialize()
- {
- SetStyle(ControlStyles.UserPaint, false);
- TabStop = false;
- Dock = DockStyle.Top;
- bands = new RebarBandCollection(this);
- bands.Changed += new EventHandler(Bands_Changed);
- addPlaceHolderToolBar = true;
- }
- #endregion
- #region Overrides
- protected override void OnMouseMove(MouseEventArgs e)
- {
- base.OnMouseMove(e);
- if ( Capture )
- return;
- bool hit = HitGripper(e);
- if ( hit )
- {
- if ( ShowMoveCursor(e) )
- Cursor.Current = Cursors.SizeAll;
- else
- Cursor.Current = Cursors.SizeWE;
- }
- else
- Cursor.Current = Cursors.Default;
- }
- protected override void OnMouseDown(MouseEventArgs e)
- {
- base.OnMouseDown(e);
- bool hit = HitGripper(e);
- if ( hit )
- {
- Capture = true;
- if ( ShowMoveCursor(e) )
- Cursor.Current = Cursors.SizeAll;
- else
- Cursor.Current = Cursors.VSplit;
- }
- else
- Cursor.Current = Cursors.Default;
- }
- protected override void OnMouseUp(MouseEventArgs e)
- {
- base.OnMouseUp(e);
- bool hit = HitGripper(e);
- Capture = false;
- if ( hit )
- {
- if ( ShowMoveCursor(e) )
- Cursor.Current = Cursors.SizeAll;
- else
- Cursor.Current = Cursors.SizeWE;
- }
- else
- Cursor.Current = Cursors.Default;
-
- }
- protected override void Dispose(bool disposing)
- {
- if ( disposing )
- bands.Changed -= new EventHandler(Bands_Changed);
- }
- protected override void OnHandleCreated(EventArgs e)
- {
- base.OnHandleCreated(e);
- RealizeBands();
- }
-
- protected override void WndProc(ref Message m)
- {
- base.WndProc(ref m);
- switch (m.Msg)
- {
- case (int)Msg.WM_PAINT:
- PaintBackground();
- break;
- case (int)Msg.WM_NOTIFY:
- case (int)((int)Msg.WM_NOTIFY + (int)Msg.WM_REFLECT):
- {
- NMHDR note = (NMHDR)m.GetLParam(typeof(NMHDR));
- switch (note.code)
- {
- case (int)RebarNotifications.RBN_HEIGHTCHANGE:
- UpdateSize();
- break;
- case (int)RebarNotifications.RBN_CHEVRONPUSHED:
- NotifyChevronPushed(ref m);
- break;
-
- case (int)RebarNotifications.RBN_CHILDSIZE:
- NotifyChildSize();
- break;
- case (int)NotificationMessages.NM_NCHITTEST:
- break;
- }
- }
- break;
- }
- }
- protected override void OnParentChanged(EventArgs e)
- {
- if (Parent != null)
- Application.AddMessageFilter(this);
- else
- Application.RemoveMessageFilter(this);
- }
- protected override Size DefaultSize
- {
- get
- {
- return new Size(100, 44);
- }
- }
- protected override void CreateHandle()
- {
- if (!RecreatingHandle)
- {
- INITCOMMONCONTROLSEX icex = new INITCOMMONCONTROLSEX();
- icex.dwSize = Marshal.SizeOf(typeof(INITCOMMONCONTROLSEX));
- icex.dwICC = (CommonControlInitFlags.ICC_BAR_CLASSES | CommonControlInitFlags.ICC_COOL_CLASSES);
- bool fail = WindowsAPI.InitCommonControlsEx(icex);
- }
- base.CreateHandle();
- }
-
- protected override CreateParams CreateParams
- {
- get
- {
- CreateParams createParams = base.CreateParams;
- createParams.ClassName = WindowsAPI.REBARCLASSNAME;
- createParams.Style = (int)(WindowStyles.WS_CHILD | WindowStyles.WS_VISIBLE
- | WindowStyles.WS_CLIPCHILDREN | WindowStyles.WS_CLIPSIBLINGS);
- createParams.Style |= (int)(CommonControlStyles.CCS_NODIVIDER | CommonControlStyles.CCS_NOPARENTALIGN);
- createParams.Style |= (int)(RebarStyles.RBS_VARHEIGHT | RebarStyles.RBS_AUTOSIZE);
- return createParams;
- }
- }
-
- public override bool PreProcessMessage(ref Message msg)
- {
- foreach (Control band in bands)
- {
- if (band.PreProcessMessage(ref msg))
- return true;
- }
- return false;
- }
- #endregion
- #region Properties
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
- public RebarBandCollection Bands
- {
- get { return bands; }
- }
- internal bool PlaceHolderAdded
- {
- get { return placeHolderAdded; }
- }
- internal bool AddPlaceHolderToolBar
- {
- set { addPlaceHolderToolBar = value; }
- get { return addPlaceHolderToolBar; }
- }
- internal ToolBarEx PlaceHolderToolBar
- {
- get { return placeHolderToolBar; }
- }
- internal ReBarDesigner RebarDesigner
- {
- set { rebarDesigner = value; }
- get { return rebarDesigner; }
- }
- internal bool DesignerInTransaction
- {
- set { designerInTransaction = value; }
- get { return designerInTransaction; }
- }
-
- #endregion
- #region Methods
- public void UpdateBackgroundColor()
- {
- for ( int i = 0; i < bands.Count; i++ )
- {
- // Update Rebar band information
- // This make sure that the background color and foreground color
- // of the bands are set to the new system colors
- UpdateBand(i);
- ToolBarEx toolBar = (ToolBarEx)bands[i];
- toolBar.Invalidate();
- }
- Invalidate();
- }
- static public void UpdateBandsColors(object sender, EventArgs e)
- {
- needsColorUpdate = true;
- }
-
- #endregion
- #region Implementation
- private bool IsCommonCtrl6()
- {
- // Cache this value for efficenty
- if ( bGotIsCommonCtrl6 == false )
- {
- isCommonCtrl6 = WindowsAPI.IsCommonCtrl6();
- }
- return isCommonCtrl6;
- }
- internal void PassMsg(ref Message m)
- {
- WndProc(ref m);
- }
- internal void AddPlaceHolder()
- {
- placeHolderAdded = true;
- // Add place holder toolBar for designer support
- if ( placeHolderToolBar == null )
- {
- placeHolderToolBar = new ToolBarEx();
- placeHolderToolBar.parentRebar = this;
- }
-
- REBARBANDINFO bandInfo = GetBandInfo(0, placeHolderToolBar);
- int result = WindowsAPI.SendMessage(Handle, RebarMessages.RB_INSERTBANDW, 0, ref bandInfo);
- }
- internal void RemovePlaceHolder()
- {
- placeHolderAdded = false;
- REBARBANDINFO bandInfo = GetBandInfo(0, placeHolderToolBar);
- int result = WindowsAPI.SendMessage(Handle, (int)RebarMessages.RB_DELETEBAND, 0, 0);
- }
- internal void RemoveBand(int index)
- {
- // index is base on the Band collection
- // but we need the actual index used in the native Rebar control
- int actualIndex = GetBandActualIndex(index);
- int result = WindowsAPI.SendMessage(Handle, (int)RebarMessages.RB_DELETEBAND, actualIndex, 0);
- }
- private void PaintBackground()
- {
- // This is for the very first time the ToolBarEx place holder is added
- if ( bands.Count == 0 && addPlaceHolderToolBar == true)
- {
- addPlaceHolderToolBar = false;
- AddPlaceHolder();
- }
-
- if ( needsColorUpdate)
- {
- needsColorUpdate = false;
- for ( int i = 0; i < bands.Count; i++ )
- {
- // Update toolbar specific information
- // This update is to guarantee that the toolbar can resize
- // the buttons appropiately in case the SystemMenuFont was
- // changed along with the system colors
- ToolBarEx toolBar = (ToolBarEx)bands[i];
- toolBar.UpdateToolBarItems();
- }
- for ( int i = 0; i < bands.Count; i++ )
- {
- // Update Rebar band information
- // This make sure that the background color and foreground color
- // of the bands are set to the new system colors
- UpdateBand(i);
- }
- }
- // We don't need to paint the gripper if we are going
- // to let the operating system do the painting
- if ( IsCommonCtrl6())
- return;
-
- Control c = null;
- Rectangle rc;
- for ( int i = 0; i < bands.Count; i++ )
- {
- Graphics g = CreateGraphics();
- c = bands[i];
- RectangleF rf = g.ClipBounds;
- rc = c.Bounds;
- if ( rf.Contains(rc) )
- {
- ToolBarEx toolBar = (ToolBarEx)bands[i];
- if ( toolBar.BarType == BarType.MenuBar )
- {
- // The menu bar height is smaller that the other toolbars
- // and if the menubar is in the same row with a toolbar that is bigger in height
- // the toolbar gripper will not be painted correctly if we use the actual height
- // of the menubar. Instead ajust the rectangle to compensate for the actual height
- // of the band
- Rectangle menuRect = GetBandRect(i);
- int offset = (menuRect.Height - rc.Height)/2-1;
- rc = new Rectangle(rc.Left, rc.Top-offset, menuRect.Width, menuRect.Height-2);
- }
- DrawGripper(g, rc, c.BackColor);
- }
- g.Dispose();
- }
- }
- private void DrawGripper(Graphics g, Rectangle bounds, Color backColor)
- {
- bounds.X = bounds.Left - 7;
- bounds.Width = 7;
- using ( Brush b = new SolidBrush(backColor) )
- {
- g.FillRectangle(b, bounds);
- }
- int nHeight = bounds.Height;
- for ( int i = 2; i < nHeight-1; i++)
- {
- if ( ColorUtil.UsingCustomColor )
- {
- using ( Pen p = new Pen(ColorUtil.VSNetBorderColor, 1))
- {
- g.DrawLine(p, bounds.Left, bounds.Top+i, bounds.Left+3, bounds.Top+i);
- }
- }
- else
- {
- using ( Pen p = new Pen(SystemColors.ControlDark, 1))
- {
- g.DrawLine(p, bounds.Left, bounds.Top+i, bounds.Left+3, bounds.Top+i);
- }
- }
- i++;
- }
- }
- protected bool HitGripper(MouseEventArgs e)
- {
- // Find out if we hit the gripper
- Point mousePoint = new Point(e.X, e.Y);
- Control c = null;
- Rectangle bounds;
- for ( int i = 0; i < bands.Count; i++ )
- {
- c = bands[i];
- bounds = c.Bounds;
-
- // adjust to gripper area
- bounds.X = bounds.Left - 7;
- bounds.Width = 7;
-
- if ( bounds.Contains(mousePoint) )
- return true;
- }
- return false;
- }
- private bool ShowMoveCursor(MouseEventArgs e)
- {
- // Even though we can actually move the toolbars around always
- // sometimes it is more intuive to show the "Move" cursor depending
- // how many bars are in the same row that always showing the resize cursor
- Point mousePoint = new Point(e.X, e.Y);
- Control c = null;
- Rectangle bounds;
- for ( int i = 0; i < bands.Count; i++ )
- {
- c = bands[i];
- bounds = c.Bounds;
-
- // adjust to gripper area
- bounds.X = bounds.Left - 7;
- bounds.Width = 7;
-
- if ( bounds.Contains(mousePoint) )
- {
- if ( bounds.Left <= 5 )
- { // The left value would be actually at least 2 if the toolbar
- // is on the edge of the main window as opossed to be somewhere in the middle of the
- // strip. The assumption here is that the gripper starts approximately 2 pixel from the edge
- return true;
- }
- }
- }
-
- return false;
- }
-
- void NotifyChevronPushed(ref Message m)
- {
- NMREBARCHEVRON nrch = (NMREBARCHEVRON) m.GetLParam(typeof(NMREBARCHEVRON));
- REBARBANDINFO rb;
- int bandIndex = nrch.uBand;
- rb = GetRebarInfo(bandIndex);
- int actualIndex = rb.wID;
- Control band = (Control)bands[actualIndex];
- Point point = new Point(nrch.rc.left, nrch.rc.bottom);
- (band as IChevron).Show(this, point);
-
- }
- void NotifyChildSize()
- {
- for ( int i = 0; i < bands.Count; i++ )
- {
- // Update toolbar specific information
- // This update is to guarantee that the toolbar can resize
- // the buttons appropiately in case the SystemMenuFont was
- // changed along with the system colors
- ToolBarEx toolBar = (ToolBarEx)bands[i];
- toolBar.ToolbarSizeChanged();
- }
- }
- void BeginUpdate()
- {
- WindowsAPI.SendMessage(Handle, Msg.WM_SETREDRAW, 0, 0);
- }
- void EndUpdate()
- {
- WindowsAPI.SendMessage(Handle, Msg.WM_SETREDRAW, 1, 0);
- }
- bool IMessageFilter.PreFilterMessage(ref Message message)
- {
- ArrayList handles = new ArrayList();
- IntPtr handle = Handle;
- while (handle != IntPtr.Zero)
- {
- handles.Add(handle);
- handle = WindowsAPI.GetParent(handle);
- }
- handle = message.HWnd;
- while (handle != IntPtr.Zero)
- {
- Msg currentMessage = (Msg)message.Msg;
- if (handles.Contains(handle))
- return PreProcessMessage(ref message);
- handle = WindowsAPI.GetParent(handle);
- }
-
- return false;
- }
- void RealizeBands()
- {
- ReleaseBands();
- BeginUpdate();
-
- for (int i = 0; i < bands.Count; i++)
- {
- REBARBANDINFO bandInfo = GetBandInfo(i, null);
- WindowsAPI.SendMessage(Handle, RebarMessages.RB_INSERTBANDW, i, ref bandInfo);
- }
- UpdateSize();
- EndUpdate();
- CaptureBands();
- if ( bands.Count == 0 && addPlaceHolderToolBar )
- {
- if ( designerInTransaction == false )
- {
- // If the designer is engage in a transaction
- // don't add the place holder toolbar here, defer the
- // addition to the PaintBackground routine so that
- // we avoid some painting problems
- addPlaceHolderToolBar = false;
- AddPlaceHolder();
- }
- }
- }
- internal void UpdateBand(int index)
- {
- if (!IsHandleCreated) return;
-
- BeginUpdate();
- // Make sure we get the right index according to the band position in the rebar
- // and not to the index in the toolbar collections which can or cannot match the order
- // in the rebar control
- int actualIndex = GetBandActualIndex(index);
- REBARBANDINFO rbbi = GetBandInfo(actualIndex, null);
- ToolBarEx tb = (ToolBarEx)bands[actualIndex];
- int idealSize = tb.GetIdealSize();
- rbbi.cxIdeal = idealSize;
- WindowsAPI.SendMessage(Handle, RebarMessages.RB_SETBANDINFOW, index, ref rbbi);
- UpdateSize();
- EndUpdate();
- }
- int GetBandActualIndex(int bandIndex)
- {
- // This maps between the indexes in the band collection and the actual
- // indexes in the rebar that can actually change as the user moves
- // the bands around
- REBARBANDINFO rb;
- rb = GetRebarInfo(bandIndex);
- return rb.wID;
- }
- void UpdateSize()
- {
- Height = WindowsAPI.SendMessage(Handle, (int)RebarMessages.RB_GETBARHEIGHT, 0, 0) + 1;
- if ( Height == 1 )
- {
- // Give it some size
- RECT rc = new RECT();
- rc.bottom = 24;
- WindowsAPI.SendMessage(Handle, (int)RebarMessages.RB_SIZETORECT, 0, ref rc);
- }
- }
- public int GetRebarHeight()
- {
- int height = WindowsAPI.SendMessage(Handle, (int)RebarMessages.RB_GETBARHEIGHT, 0, 0) + 1;
- return height;
- }
- public Rectangle GetBandRect(int bandIndex)
- {
- RECT rect = new RECT();
- int index = GetBandActualIndex(bandIndex);
- WindowsAPI.SendMessage(Handle, (int)RebarMessages.RB_GETRECT, bandIndex, ref rect);
- return new Rectangle(rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top);
- }
- REBARBANDINFO GetRebarInfo(int index)
- {
- REBARBANDINFO rbbi = new REBARBANDINFO();
- rbbi.cbSize = Marshal.SizeOf(typeof(REBARBANDINFO));
- rbbi.fMask = RebarInfoMask.RBBIM_ID|RebarInfoMask.RBBIM_IDEALSIZE;
- WindowsAPI.SendMessage(Handle, RebarMessages.RB_GETBANDINFOW, index, ref rbbi);
- return rbbi;
- }
-
- REBARBANDINFO GetBandInfo(int index, Control currentBand)
- {
- bool placeHolder = false;
- Control band;
- if ( currentBand != null )
- {
- placeHolder = true;
- band = currentBand;
- }
- else
- band = bands[index];
- REBARBANDINFO rbbi = new REBARBANDINFO();
- rbbi.cbSize = Marshal.SizeOf(typeof(REBARBANDINFO));
-
- if ( !IsCommonCtrl6() )
- {
- rbbi.fMask = RebarInfoMask.RBBIM_COLORS;
- Color toolBarBackColor = band.BackColor;
- rbbi.clrBack = (int)ColorUtil.RGB(toolBarBackColor.R,
- toolBarBackColor.G, toolBarBackColor.B);
- rbbi.clrFore = (int)ColorUtil.RGB(255,0,255);
- }
- rbbi.iImage = 0;
- if ( band.BackgroundImage != null )
- {
- Bitmap bitmap = band.BackgroundImage as Bitmap;
- if ( bitmap != null )
- {
- rbbi.hbmBack = bitmap.GetHbitmap();
- rbbi.fMask = RebarInfoMask.RBBIM_BACKGROUND;
- }
- }
- else
- rbbi.hbmBack = IntPtr.Zero;
- rbbi.lParam = 0;
- rbbi.cxHeader = 0;
- rbbi.fMask |= RebarInfoMask.RBBIM_ID;
- rbbi.wID = index;
-
- if ((band.Text != null) && (band.Text != string.Empty))
- {
- rbbi.fMask |= RebarInfoMask.RBBIM_TEXT;
- rbbi.lpText = Marshal.StringToHGlobalAnsi(band.Text);
- rbbi.cch = (band.Text == null) ? 0 : band.Text.Length;
- }
-
- rbbi.fMask |= RebarInfoMask.RBBIM_STYLE;
- rbbi.fStyle = RebarStylesEx.RBBS_CHILDEDGE | RebarStylesEx.RBBS_FIXEDBMP;
- if ( placeHolder == false )
- rbbi.fStyle |= RebarStylesEx.RBBS_GRIPPERALWAYS;
- ToolBarEx tb = (ToolBarEx)band;
- if ( tb.UseNewRow == true)
- rbbi.fStyle |= RebarStylesEx.RBBS_BREAK;
- rbbi.fStyle |= (band is IChevron) ? RebarStylesEx.RBBS_USECHEVRON : 0;
- rbbi.fMask |= RebarInfoMask.RBBIM_CHILD;
- rbbi.hwndChild = band.Handle;
-
- rbbi.fMask |= RebarInfoMask.RBBIM_CHILDSIZE;
- rbbi.cyMinChild = band.Height;
- rbbi.cxMinChild = 0;
- rbbi.cyChild = 0;
- rbbi.cyMaxChild = 0;
- rbbi.cyIntegral = 0;
-
- rbbi.fMask |= RebarInfoMask.RBBIM_SIZE;
- rbbi.cx = band.Width;
- rbbi.fMask |= RebarInfoMask.RBBIM_IDEALSIZE;
- rbbi.cxIdeal = band.Width;
-
- return rbbi;
- }
- internal void UpdateBands()
- {
- if (IsHandleCreated)
- {
- RecreateHandle();
- }
- }
- void Bands_Changed(Object s, EventArgs e)
- {
- UpdateBands();
- }
- void Band_HandleCreated(Object s, EventArgs e)
- {
- ReleaseBands();
-
- ToolBarEx band = (ToolBarEx) s;
- UpdateBand(bands.IndexOf(band));
-
- CaptureBands();
- }
-
- void Band_TextChanged(Object s, EventArgs e)
- {
- ToolBarEx band = (ToolBarEx) s;
- UpdateBand(bands.IndexOf(band));
- }
- void CaptureBands()
- {
- foreach (Control band in bands)
- {
- band.HandleCreated += new EventHandler(Band_HandleCreated);
- band.TextChanged += new EventHandler(Band_TextChanged);
- }
- }
-
- void ReleaseBands()
- {
- foreach (Control band in bands)
- {
- band.HandleCreated -= new EventHandler(Band_HandleCreated);
- band.TextChanged -= new EventHandler(Band_TextChanged);
- }
- }
- }
- #endregion
- }