ToolBarEx.cs
上传用户:nnpulika
上传日期:2013-02-15
资源大小:597k
文件大小:44k
源码类别:

状态条

开发平台:

C#

  1. using System;
  2. using System.Collections;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Data;
  6. using System.Windows.Forms;
  7. using System.Runtime.InteropServices;
  8. using System.Drawing.Text;
  9. using System.Diagnostics;
  10. using System.Security;
  11. using UtilityLibrary.Collections;
  12. using UtilityLibrary.Win32;
  13. using UtilityLibrary.General;
  14. using UtilityLibrary.WinControls;
  15. using UtilityLibrary.Menus;
  16. namespace UtilityLibrary.CommandBars
  17. {
  18. #region Enumerations
  19. public enum BarType
  20. {
  21. ToolBar = 0,
  22. MenuBar = 1
  23. }
  24. #endregion
  25. #region Interfaces
  26. public interface IChevron
  27. {
  28. void Show(Control control, Point point);
  29. }
  30. #endregion
  31. #region Class ToolBarEx
  32. /// <summary>
  33. /// Summary description for ToolBarEx.
  34. /// </summary>
  35. [ToolboxItem(false)]
  36. public class ToolBarEx : System.Windows.Forms.Control, IChevron
  37. {
  38. #region Enumerations
  39. // To be used only when we have a menubar type
  40. enum State 
  41. None, 
  42. Hot, 
  43. HotTracking 
  44. }
  45. #endregion
  46. #region Class Variables
  47. // ToolBarItems
  48. ToolBarItemCollection items = new ToolBarItemCollection();
  49. ToolBarItem[] handledItems = new ToolBarItem[0];
  50. bool[] handledItemsVisible = new bool[0];
  51.         
  52. // Chevron Menu 
  53. ChevronMenu chevronMenu = new ChevronMenu();
  54. bool showingChevronMenu = false;
  55. // Bar Type --Standard or MenuBar
  56. BarType barType = BarType.ToolBar;
  57. // Helper Constans
  58. const int DROWPDOWN_ARROW_WIDTH = 14;
  59. const int MARGIN = 3;
  60. const int MENUTEXT_MARGIN = 8;
  61.    
  62. // Image List Support
  63. // -- not really used to draw the images in the ToolBarItem
  64. // but as a helper to size the ToolBarButtons
  65. ImageList imageListHelper = null;
  66. // The actual imageList that we associate with the ToolBar
  67. ImageList imageList = null;
  68. // Windows XP, using a manifest support
  69. bool bGotIsCommonCtrl6 = false;
  70. bool isCommonCtrl6 = false;
  71. // Menu bar tracking support
  72. State state = State.None;
  73. State lastState = State.None;
  74. Point lastMousePosition = new Point(0, 0);
  75. int trackHotItem = -1;
  76. int trackNextItem = -1;
  77. bool trackEscapePressed = false;
  78. IntPtr hookHandle = IntPtr.Zero;
  79. bool doKeyboardSelect = false;
  80. // Rebar interaction suport
  81. bool useNewRow = true;
  82. internal ReBar parentRebar = null;
  83. // Design Suppport
  84. internal ToolBarItem placeHolderToolBarItem = null;
  85. internal bool placeHolderAdded = false;
  86. #endregion
  87. #region Constructors
  88. public ToolBarEx()
  89. {
  90. InitializeToolBar();
  91. }
  92. public ToolBarEx(bool useNewRow)
  93. {
  94. InitializeToolBar();
  95. this.useNewRow = useNewRow;
  96. }
  97. public ToolBarEx(BarType type)
  98. {
  99. barType = type;
  100. InitializeToolBar();
  101. }
  102. public ToolBarEx(BarType type, bool useNewRow)
  103. {
  104. barType = type;
  105. InitializeToolBar();
  106. this.useNewRow = useNewRow;
  107. }
  108. private void InitializeToolBar()
  109. {
  110. items = new ToolBarItemCollection(this);
  111. // We'll let the toolbar to send us messages for drawing
  112. SetStyle(ControlStyles.UserPaint, false);
  113. TabStop = false;
  114. // Always on top
  115. Dock = DockStyle.Top;
  116. Attach();
  117. }
  118. ~ToolBarEx()
  119. {
  120. Detach();
  121. }
  122. #endregion
  123. #region Overrides
  124. [Browsable(false)]
  125. public override string Text 
  126. get { return ""; }
  127. }
  128. protected override void CreateHandle() 
  129. {
  130. // Make sure common control library initilizes toolbars and rebars
  131. if ( !RecreatingHandle )
  132. {
  133. INITCOMMONCONTROLSEX icex = new INITCOMMONCONTROLSEX();
  134. icex.dwSize = Marshal.SizeOf(typeof(INITCOMMONCONTROLSEX));
  135. icex.dwICC = CommonControlInitFlags.ICC_BAR_CLASSES | CommonControlInitFlags.ICC_COOL_CLASSES;
  136. WindowsAPI.InitCommonControlsEx(icex);
  137. }
  138. // Handle is being created or recreated, reset placeHolder flag
  139. placeHolderAdded = false;
  140. base.CreateHandle();
  141. }
  142. protected override CreateParams CreateParams
  143. {
  144. get
  145. {
  146. CreateParams createParams = base.CreateParams;
  147. createParams.ClassName = WindowsAPI.TOOLBARCLASSNAME;
  148. createParams.ExStyle = 0;
  149. // Windows specific flags
  150. createParams.Style = (int)(WindowStyles.WS_CHILD | WindowStyles.WS_VISIBLE |
  151. WindowStyles.WS_CLIPCHILDREN | WindowStyles.WS_CLIPSIBLINGS);
  152. // Common Control specific flags
  153. createParams.Style |= (int)(CommonControlStyles.CCS_NODIVIDER | CommonControlStyles.CCS_NORESIZE | 
  154. CommonControlStyles.CCS_NOPARENTALIGN);
  155. // ToolBar specific flags
  156. createParams.Style |= (int)(ToolBarStyles.TBSTYLE_TOOLTIPS);
  157. if ( parentRebar != null )
  158. {
  159. createParams.Style |= (int)(ToolBarStyles.TBSTYLE_FLAT | ToolBarStyles.TBSTYLE_TRANSPARENT);
  160.                 }
  161. if (HasText()) createParams.Style |= (int)ToolBarStyles.TBSTYLE_LIST;
  162. return createParams;
  163. }
  164. }
  165. protected override Size DefaultSize
  166. {
  167. get { return new Size(1, 1); }
  168. }
  169. protected override void OnHandleCreated(EventArgs e)
  170. {
  171. // Send message needed for the toolbar to work properly before any other messages are sent
  172. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_BUTTONSTRUCTSIZE, Marshal.SizeOf(typeof(TBBUTTON)), 0);
  173. // Setup extended styles
  174. int extendedStyle = (int)(ToolBarExStyles.TBSTYLE_EX_HIDECLIPPEDBUTTONS | 
  175. ToolBarExStyles.TBSTYLE_EX_DOUBLEBUFFER );
  176. if ( BarType == BarType.ToolBar ) extendedStyle |= (int)ToolBarExStyles.TBSTYLE_EX_DRAWDDARROWS;
  177. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_SETEXTENDEDSTYLE, 0, extendedStyle);
  178. RealizeItems();
  179. // Add Temporary place holder item so that the ToolBarEx has a height
  180. // when it is first inserted in the IDE designer, otherwise, it does not look right
  181. // -- only if there if there is a designer involved --
  182. if ( parentRebar != null && parentRebar.RebarDesigner != null && placeHolderAdded == false && items.Count == 0 )
  183. {
  184. AddPlaceHolderToolBarItem();
  185. }
  186. base.OnHandleCreated(e);
  187. }
  188. protected override void OnMouseMove(MouseEventArgs e)
  189. {
  190. if ( barType == BarType.MenuBar)
  191. {
  192. Point point = new Point(e.X, e.Y);
  193. if ( state == State.Hot )
  194. {
  195. int index = HitTest(point);
  196. if ((IsValid(index)) && ( point != lastMousePosition))
  197. SetHotItem(index);
  198. return;
  199. }
  200. lastMousePosition = point;
  201. }
  202. base.OnMouseMove(e);
  203. }
  204. protected override void OnMouseDown(MouseEventArgs e)
  205. {
  206. if ( barType == BarType.MenuBar)
  207. {
  208. if ((e.Button == MouseButtons.Left) && (e.Clicks == 1))
  209. {
  210. Point point = new Point(e.X, e.Y);
  211. int index = HitTest(point);
  212. if (IsValid(index) && items[index].Enabled)
  213. {
  214. TrackDropDown(index);
  215. return;
  216. }
  217. }
  218. }
  219. base.OnMouseDown(e);
  220. }
  221. protected override void WndProc(ref Message message)
  222. {
  223. base.WndProc(ref message);
  224.            
  225. int index = -1;
  226. ToolBarItem item = null;
  227. switch (message.Msg)
  228. {
  229. case (int)ReflectedMessages.OCM_COMMAND:
  230. index = (int) message.WParam & 0xFFFF;
  231. if ( items.Count != 0 )
  232. {
  233. item = items[index];
  234. item.RaiseClick();
  235. base.WndProc(ref message);
  236. ResetMouseEventArgs();
  237. }
  238. break;
  239. case (int)Msg.WM_MENUCHAR:
  240. MenuChar(ref message);
  241. break;
  242. case (int)Msg.WM_ERASEBKGND:
  243. break;
  244. case (int)Msg.WM_LBUTTONDOWN:
  245. // Pass it down to the parent Rebar so that
  246. // the rebar can select itself
  247. if ( parentRebar != null && parentRebar.Bands.Count == 0 && parentRebar.RebarDesigner != null )
  248. {
  249. // If the count for the RebarBand collections is zero
  250. // but we still get this messages, it means that it is the
  251. // "place holder" toolbar the one generating this message
  252. Point pt = new Point(message.LParam.ToInt32());
  253. pt = PointToScreen(pt);
  254. parentRebar.PointToClient(pt);
  255. parentRebar.RebarDesigner.PassMsg(ref message);
  256. }
  257. break;
  258. case (int)Msg.WM_NOTIFY:
  259. case (int)ReflectedMessages.OCM_NOTIFY:
  260. NMHDR nm = (NMHDR) message.GetLParam(typeof(NMHDR));
  261. switch (nm.code)
  262. {
  263. case (int)ToolBarNotifications.TTN_NEEDTEXTA:
  264. NotifyNeedTextA(ref message);
  265. break;
  266. case (int)ToolBarNotifications.TTN_NEEDTEXTW:
  267. NotifyNeedTextW(ref message);
  268. break;
  269. case (int)ToolBarNotifications.TBN_QUERYINSERT:
  270. message.Result = (IntPtr) 1;
  271. break;
  272. case (int)ToolBarNotifications.TBN_DROPDOWN:
  273. NMTOOLBAR nmt = (NMTOOLBAR) message.GetLParam(typeof(NMTOOLBAR));
  274. index = nmt.iItem;
  275. if ( items.Count != 0 )
  276. {
  277. item = items[index];
  278. item.Dropped = true;
  279. item.RaiseDropDown();
  280. }
  281. break;
  282. case (int)NotificationMessages.NM_CUSTOMDRAW:
  283. NotifyCustomDraw(ref message);
  284. break;
  285. case (int)ToolBarNotifications.TBN_HOTITEMCHANGE:
  286. break;
  287. }
  288. break;
  289. }
  290. }
  291. protected override void OnFontChanged(EventArgs e) 
  292. {
  293. base.OnFontChanged(e);
  294. UpdateItems();
  295. }
  296. public override bool PreProcessMessage(ref Message message)
  297. {
  298. if (message.Msg == (int)Msg.WM_KEYDOWN || message.Msg == (int)Msg.WM_SYSKEYDOWN)
  299. {
  300. // Check for shortcuts in ToolBarItems in this toolbar
  301. Keys keys = (Keys)(int) message.WParam  | ModifierKeys;
  302.                 if ( items.Count == 0 ) return true;
  303. ToolBarItem shortcutHit = items[keys];
  304. if (shortcutHit != null && shortcutHit.Enabled )
  305. {
  306. shortcutHit.RaiseClick();
  307. return true;
  308. }
  309. // Check for shortcuts in the menuitems of the popup menu
  310. // currently being displayed
  311. if ( barType == BarType.MenuBar )
  312. {
  313. MenuItem hitItem = null;
  314. foreach ( ToolBarItem tbi in items ) 
  315. {
  316. hitItem = FindShortcutItem(tbi.MenuItems, keys);
  317. if ( hitItem != null)
  318. break;
  319. }
  320. if ( hitItem != null )
  321. hitItem.PerformClick();
  322. }
  323.   
  324. //  Check if we have a mnemonic
  325. bool alt = ((keys & Keys.Alt) != 0);
  326. if ( alt )
  327. {
  328. Keys keyCode = keys & Keys.KeyCode;
  329. char key = (char)(int)keyCode;
  330. if ((Char.IsDigit(key) || (Char.IsLetter(key))))
  331. {
  332. ToolBarItem mnemonicsHit = items[key];        
  333. if ( mnemonicsHit != null ) 
  334. {
  335. if ( barType == BarType.MenuBar )
  336. TrackDropDown(mnemonicsHit.Index);
  337. else
  338. mnemonicsHit.RaiseClick();
  339. return true;
  340. }
  341. }
  342. }
  343. }
  344. return false;
  345. }
  346. #endregion
  347. #region Properties
  348. public bool UseNewRow
  349. {
  350. get { return useNewRow; }
  351. }
  352. [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
  353. public ToolBarItemCollection Items
  354. {
  355. get { return items; }
  356. }
  357. public BarType BarType
  358. {
  359. set { barType = value; }
  360. get { return barType; }
  361. }
  362. public ImageList ImageList
  363. {
  364. set { imageList = value; }
  365. get { return imageList; }
  366. }
  367. internal bool PlaceHolderAdded
  368. {
  369. set { placeHolderAdded = value; }
  370. get { return placeHolderAdded; }
  371. }
  372. #endregion
  373. #region Methods
  374. public void UpdateToolBarItems()
  375. {
  376. UpdateImageList();
  377. for (int i = 0; i < items.Count; i++)
  378. {
  379. // The toolbar handle is going to be destroy to correctly update the toolbar 
  380. // itself. We need to detach the toolbar as the parent of the comboboxes --otherwise the comboboxes
  381. // does not behave appropiately after we pull the plug on the parent
  382. // The combobox will again parented to the toolbar once the handle is recreated and when the
  383. // RealizeItem routine gets the information for the toolbaritems
  384. if ( items[i].Style == ToolBarItemStyle.ComboBox )
  385. {
  386. WindowsAPI.SetParent(items[i].ComboBox.Handle, IntPtr.Zero);
  387. items[i].ComboBox.Parent = null;
  388. }
  389. }
  390. UpdateItems();
  391. }
  392. #endregion
  393. #region Implementation
  394. internal void AddPlaceHolderToolBarItem()
  395. {
  396. placeHolderAdded = true;
  397. // Add it to the "native" ToolBar but not to the collection
  398. ToolBarItem item = new ToolBarItem();
  399. item.ToolBar = this;
  400.             TBBUTTON button = new TBBUTTON();
  401. button.idCommand = 0;
  402.             WindowsAPI.SendMessage(Handle, ToolBarMessages.TB_INSERTBUTTON, 0, ref button);
  403. TBBUTTONINFO tbi = GetButtonInfo(0, item);
  404. WindowsAPI.SendMessage(Handle, ToolBarMessages.TB_SETBUTTONINFOW, 0, ref tbi);
  405. UpdateSize();
  406. }
  407. internal void RemovePlaceHolderToolBarItem()
  408. {
  409. placeHolderAdded = false;
  410. int result = WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_DELETEBUTTON, 0, 0);
  411. }
  412. internal void RemoveToolBarItem(int index)
  413. {
  414. int result = WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_DELETEBUTTON, index, 0);
  415. }
  416. void Attach()
  417. {
  418. items.Changed += new EventHandler(Items_Changed);
  419. int count = Items.Count;
  420. handledItems = new ToolBarItem[count];
  421. handledItemsVisible = new bool[count];
  422. for (int i = 0; i < count; i++)
  423. {
  424. ToolBarItem item = Items[i];
  425. item.Changed += new EventHandler(Item_Changed);
  426. handledItems[i] = item;
  427. handledItemsVisible[i] = item.Visible;
  428. }
  429. }
  430. void Detach()
  431. {
  432. foreach (ToolBarItem item in handledItems)
  433. {
  434. item.Changed -= new EventHandler(Item_Changed);
  435. }
  436. handledItems = null;
  437. handledItemsVisible = null;
  438. items.Changed -= new EventHandler(Items_Changed);
  439. }
  440. private bool IsCommonCtrl6()
  441. {
  442. // Cache this value for efficenty
  443. if ( bGotIsCommonCtrl6 == false )
  444. {
  445. isCommonCtrl6 = WindowsAPI.IsCommonCtrl6();
  446. }
  447. return isCommonCtrl6;
  448. }
  449. private bool HasText()
  450. {
  451. for (int i = 0; i < items.Count; i++)
  452. {
  453. // check if we need to make this toolbar TBSTYLE_LIST
  454. if ( items[i].Text != null && items[i].Text != string.Empty )
  455. return true;
  456. }
  457. return false;
  458. }
  459. bool IsValid(int index)
  460. {
  461. int count = WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_BUTTONCOUNT, 0, 0);
  462. return ((index >= 0) && (index < count));
  463. }
  464. int HitTest(Point point)
  465. {
  466. POINT pt = new POINT();
  467. pt.x = point.X;
  468. pt.y = point.Y;
  469. int hit = WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_HITTEST, 0, ref pt);
  470. if (hit > 0)
  471. {
  472. point = PointToScreen(point);
  473. Rectangle bounds = RectangleToScreen(new Rectangle(0, 0, Width, Height));
  474. if ( !bounds.Contains(point) ) return -1;
  475. }
  476. return hit;
  477. }
  478. int GetNextItem(int index)
  479. {
  480. if (index == -1) throw new Exception();
  481. int count = WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_BUTTONCOUNT, 0, 0);
  482. index++;
  483. if (index >= count) index = 0;
  484. return index;
  485. }
  486. int GetPreviousItem(int index)
  487. {
  488. if (index == -1) throw new Exception();
  489. int count = WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_BUTTONCOUNT, 0, 0);
  490. index--;
  491. if (index < 0) index = count - 1;
  492. return index;
  493. }
  494. int GetHotItemIndex()
  495. {
  496. return WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_GETHOTITEM, 0, 0);
  497. }
  498. void SetHotItem(int index)
  499. {
  500. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_SETHOTITEM, index, 0);
  501. }
  502. void TrackDropDown(int index)
  503. {
  504. while ( index >= 0 )
  505. {
  506. trackNextItem = -1;
  507. BeginUpdate();
  508. // Raise event
  509. ToolBarItem item = (ToolBarItem)items[index];
  510. item.RaiseDropDown();
  511. // Item state
  512. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_PRESSBUTTON, index, -1);
  513. // Trick to get the first menu item selected
  514. if ( doKeyboardSelect )
  515. {
  516. WindowsAPI.PostMessage(Handle, (int)Msg.WM_KEYDOWN, (int) Keys.Down, 1);
  517. WindowsAPI.PostMessage(Handle, (int)Msg.WM_KEYUP, (int) Keys.Down, 1);
  518. }
  519. doKeyboardSelect = false;
  520. SetState(State.HotTracking, index);
  521. // Hook
  522. WindowsAPI.HookProc hookProc = new WindowsAPI.HookProc(DropDownHook);
  523. GCHandle hookProcHandle = GCHandle.Alloc(hookProc);
  524. hookHandle = WindowsAPI.SetWindowsHookEx(WindowsHookCodes.WH_MSGFILTER, 
  525. hookProc, IntPtr.Zero, WindowsAPI.GetCurrentThreadId());
  526. if ( hookHandle == IntPtr.Zero ) throw new SecurityException();
  527. // Ask for position
  528. RECT rect = new RECT();
  529. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_GETRECT, index, ref rect);
  530. Point position = new Point(rect.left, rect.bottom-1);
  531. EndUpdate();
  532. Update();
  533. CommandBarMenu menu = item.ToolBarItemMenu;
  534. if ( menu == null ) return;
  535. menu.Show(this, position);
  536. // Unhook
  537. WindowsAPI.UnhookWindowsHookEx(hookHandle);
  538. hookProcHandle.Free();
  539. hookHandle = IntPtr.Zero;
  540. // Item state
  541. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_PRESSBUTTON, index, 0);
  542. SetState(trackEscapePressed ? State.Hot : State.None, index);
  543. index = trackNextItem;
  544. }
  545. }
  546. void TrackDropDownNext(int index)
  547. {
  548. if (index != trackHotItem)
  549. {
  550. WindowsAPI.PostMessage(Handle, (int)Msg.WM_CANCELMODE, 0, 0);
  551. trackNextItem = index;
  552. }
  553. }
  554. IntPtr DropDownHook(int code, IntPtr wparam, IntPtr lparam) 
  555. {
  556. if (code == (int)MouseHookFilters.MSGF_MENU)
  557. {
  558. MSG msg = (MSG) Marshal.PtrToStructure(lparam, typeof(MSG));
  559. Message message = Message.Create(msg.hwnd, msg.message, msg.wParam, msg.lParam);
  560. if ( DropDownFilter(ref message) )
  561. return (IntPtr) 1;
  562. }
  563. return WindowsAPI.CallNextHookEx(hookHandle, code, wparam, lparam);
  564. }
  565. bool DropDownFilter(ref Message message)
  566. {
  567. if (state != State.HotTracking) throw new Exception();
  568. // comctl32 sometimes steals the hot item for unknown reasons.
  569. SetHotItem(trackHotItem);
  570. if (message.Msg == (int)Msg.WM_KEYDOWN)
  571. {
  572. Keys keyData = (Keys)(int) message.WParam | ModifierKeys;
  573. if ( keyData == Keys.Left || keyData == Keys.Right )
  574. doKeyboardSelect = true;
  575.                 
  576. if (keyData == Keys.Left)
  577. {
  578. TrackDropDownNext(GetPreviousItem(trackHotItem));
  579. return true;
  580. }
  581. // Only move right if there is no submenu on the current selected item.
  582. ToolBarItem item = items[trackHotItem];
  583. if ((keyData == Keys.Right) && ((item.ToolBarItemMenu.SelectedMenuItem == null) 
  584. || (item.ToolBarItemMenu.SelectedMenuItem.MenuItems.Count == 0)))
  585. {
  586. TrackDropDownNext(GetNextItem(trackHotItem));
  587. return true;
  588. }
  589. if (keyData == Keys.Escape)
  590. {
  591. trackEscapePressed = true;
  592. }
  593. }
  594. else if ((message.Msg == (int)Msg.WM_MOUSEMOVE) || (message.Msg == (int)Msg.WM_LBUTTONDOWN))
  595. {
  596. Point point = WindowsAPI.GetPointFromLPARAM((int)message.LParam);
  597. point = this.PointToClient(point);
  598. if (message.Msg == (int)Msg.WM_MOUSEMOVE)
  599. {
  600. if (point != lastMousePosition)
  601. {
  602. int index = HitTest(point);
  603. if ((IsValid(index)) && (index != trackHotItem))
  604. TrackDropDownNext(index);
  605. lastMousePosition = point;
  606. }
  607. }
  608. else if (message.Msg == (int)Msg.WM_LBUTTONDOWN)
  609. {
  610. if (HitTest(point) == trackHotItem)
  611. {
  612. TrackDropDownNext(-1);
  613. return true;
  614. }
  615. }
  616. }
  617. return false;
  618. }
  619. void SetState(State state, int index)
  620. {
  621. if (this.state != state)
  622. {
  623. if (state == State.None)
  624. index = -1;
  625. SetHotItem(index);
  626. if (state == State.HotTracking)
  627. {
  628. trackEscapePressed = false;
  629. trackHotItem = index;
  630. }
  631. }
  632. this.lastState = this.state;
  633. this.state = state;
  634. }
  635. void IChevron.Show(Control control, Point point)
  636. {
  637. if ( showingChevronMenu )
  638. {
  639. // Don't try to show it again
  640. // if we are showing it already
  641. return;
  642. }
  643.             
  644. showingChevronMenu = true;
  645. ToolBarItemCollection chevronItems = new ToolBarItemCollection();
  646. Size size = ClientSize;
  647. int currentCount = 0;
  648. bool addItem = true;
  649. ToolBarItem lastItem;
  650. bool hasComboBox = false;
  651. for (int i = 0; i < items.Count; i++)
  652. {
  653. bool IsSeparator = false;
  654. RECT rect = new RECT();
  655. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_GETITEMRECT, i, ref rect);
  656. if (rect.right > size.Width)
  657. {
  658. ToolBarItem item = items[i];
  659. if ( item.ComboBox != null )
  660. hasComboBox = true;
  661. IsSeparator = (item.Style == ToolBarItemStyle.Separator);
  662. if ( item.Visible ) 
  663. if ( (!IsSeparator ) || (chevronItems.Count != 0) )
  664. {
  665. // don't add it if previous item was a separator
  666. currentCount = chevronItems.Count;
  667. if ( currentCount > 0 ) 
  668. {
  669. lastItem = chevronItems[currentCount-1];
  670. if ( lastItem.Style == ToolBarItemStyle.Separator && IsSeparator )
  671. {
  672. addItem = false;
  673. }
  674. }
  675. if ( addItem )
  676. chevronItems.Add(item);
  677. addItem = true;
  678. }
  679. }
  680. }
  681. // Don't show a separator as the last item of the context menu
  682. int itemsCount = chevronItems.Count;
  683. if ( itemsCount > 0 )
  684. {
  685. lastItem = chevronItems[itemsCount-1];
  686. if ( lastItem.Style == ToolBarItemStyle.Separator )
  687. chevronItems.RemoveAt(itemsCount-1);
  688. }
  689. chevronMenu.Items = chevronItems;
  690. chevronMenu.Style = VisualStyle.IDE;
  691. chevronMenu.TrackPopup(control.PointToScreen(point));
  692. // Need to reparent the combobox to this toolbar in case
  693. // there was a combobox that was displayed by the popup menu
  694. if ( hasComboBox )
  695. {
  696. // Run the logic for combobox visibility before reposition it
  697. ToolbarSizeChanged();      
  698. for (int i = 0; i < items.Count; i++)
  699. {
  700. ToolBarItem item = items[i];
  701. if ( item.Style == ToolBarItemStyle.ComboBox )
  702. {
  703. WindowsAPI.SetParent(item.ComboBox.Handle, Handle);
  704. ComboBoxBase cbb = (ComboBoxBase)item.ComboBox;
  705. cbb.ToolBarUse = true;
  706. UpdateItem(i);
  707. cbb.Invalidate();
  708. }
  709. }
  710. }
  711. showingChevronMenu = false;
  712. }
  713. internal void ToolbarSizeChanged()
  714. {
  715. if ( BarType == BarType.MenuBar )
  716. return;
  717. // Make sure that comboboxes are either visible
  718. // or invisible depending wheater they are showing
  719. // all of the client area or they are partially hidden
  720. Size size = ClientSize;
  721. for (int i = 0; i < items.Count; i++)
  722. {
  723. ToolBarItem item = items[i];
  724. if ( item.Style == ToolBarItemStyle.ComboBox )
  725. {
  726. RECT rect = new RECT();
  727. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_GETITEMRECT, i, ref rect);
  728. if (rect.right > size.Width)
  729. item.ComboBox.Visible = false;
  730. else
  731. item.ComboBox.Visible = true;
  732. }
  733. }
  734. }
  735. void MenuChar(ref Message message)
  736. {
  737. ToolBarItem item = items[trackHotItem];
  738. Menu menu = item.ToolBarItemMenu.FindMenuItem(MenuItem.FindHandle, message.LParam);
  739. if (item.ToolBarItemMenu.Handle == message.LParam) menu = item.ToolBarItemMenu;
  740. if (menu != null)
  741. {
  742. char key = char.ToUpper((char) ((int) message.WParam & 0x0000FFFF));
  743. int index = 0;
  744. foreach (MenuItem menuItem in menu.MenuItems)
  745. {
  746. if ((menuItem != null) && (menuItem.OwnerDraw) && (menuItem.Mnemonic == key))
  747. {
  748. message.Result = (IntPtr) (((int)MenuCharReturnValues.MNC_EXECUTE << 16) | index);
  749. return;
  750. }
  751. if (menuItem.Visible) index++;
  752. }
  753. }
  754. }
  755. void NotifyNeedTextA(ref Message m)
  756. {
  757. TOOLTIPTEXTA ttt = (TOOLTIPTEXTA) m.GetLParam(typeof(TOOLTIPTEXTA));
  758. if ( items.Count == 0 )
  759. return;
  760. ToolBarItem item = (ToolBarItem) items[ttt.hdr.idFrom];
  761. string toolTip = item.ToolTip;
  762. if ( toolTip != null && toolTip != string.Empty )
  763. {
  764. ttt.szText = toolTip;
  765. ttt.hinst = IntPtr.Zero;
  766. if ( RightToLeft == RightToLeft.Yes ) ttt.flags |= ToolTipFlags.TTF_RTLREADING;
  767. Marshal.StructureToPtr(ttt, m.LParam, true);
  768. m.Result = (IntPtr) 1;
  769. }
  770. }
  771. void NotifyNeedTextW(ref Message m)
  772. {
  773. if (Marshal.SystemDefaultCharSize != 2) return;
  774. if ( items.Count == 0 )
  775. return;
  776. // This code is a duplicate of NotifyNeedTextA
  777. TOOLTIPTEXT ttt = (TOOLTIPTEXT) m.GetLParam(typeof(TOOLTIPTEXT));
  778. ToolBarItem item = (ToolBarItem) items[ttt.hdr.idFrom];
  779. string toolTip = item.ToolTip;
  780. if ( toolTip != null && toolTip != string.Empty )
  781. {
  782. ttt.szText = toolTip;
  783. ttt.hinst = IntPtr.Zero;
  784. if (RightToLeft == RightToLeft.Yes) ttt.uFlags |= (int)ToolTipFlags.TTF_RTLREADING;
  785. Marshal.StructureToPtr(ttt, m.LParam, true);
  786. m.Result = (IntPtr) 1;
  787. }
  788. }
  789. void NotifyCustomDraw(ref Message m)
  790. {
  791. m.Result = (IntPtr) CustomDrawReturnFlags.CDRF_DODEFAULT;
  792. NMTBCUSTOMDRAW tbcd = (NMTBCUSTOMDRAW)m.GetLParam(typeof(NMTBCUSTOMDRAW));
  793. switch (tbcd.nmcd.dwDrawStage)
  794. {
  795. case (int)CustomDrawDrawStateFlags.CDDS_PREPAINT:
  796. // Tell toolbar control that we want to do the painting ourselves
  797. m.Result = (IntPtr) CustomDrawReturnFlags.CDRF_NOTIFYITEMDRAW;
  798. break;
  799. case (int)CustomDrawDrawStateFlags.CDDS_ITEMPREPAINT:
  800. // Do custom painting
  801. NotifyCustomDrawToolBar(ref m);
  802. break;
  803. }
  804. }
  805. void NotifyCustomDrawToolBar(ref Message m)
  806. {
  807. // This toolbar could be the one that we are just using to provide
  808. // some "height" to the rebar control -- the place holder bar -- if
  809. // that is the case no need to do any painting
  810. // or it could be a ToolBar that has a ToolBarItem place holder, skip this case too
  811. if ( parentRebar != null && parentRebar.Bands.Count == 0 || items.Count == 0) 
  812. {
  813. m.Result = (IntPtr) CustomDrawReturnFlags.CDRF_SKIPDEFAULT;
  814. return;
  815. }
  816. m.Result = (IntPtr) CustomDrawReturnFlags.CDRF_DODEFAULT;
  817. // See if use wants the VSNet look or let XP dictate
  818. // the toolbar look
  819. if ( IsCommonCtrl6())
  820. {
  821. // Let the operating system do the drawing
  822. return;
  823. }
  824. NMTBCUSTOMDRAW tbcd = (NMTBCUSTOMDRAW) m.GetLParam(typeof(NMTBCUSTOMDRAW));
  825. RECT rc = tbcd.nmcd.rc;
  826. Rectangle rectangle = new Rectangle(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
  827. Graphics g = Graphics.FromHdc(tbcd.nmcd.hdc);
  828. int index = (int)tbcd.nmcd.dwItemSpec;
  829. ToolBarItem item = items[index];
  830. if ( item.Style == ToolBarItemStyle.ComboBox )
  831. {
  832. // ComboBoxes paint themselves
  833. // the combox new size, after changing the combobox font,
  834. // does not get updated until later in the drawing logic
  835. // pick up the right size here and update the combobox position
  836. UpdateComboBoxPosition(index);
  837. m.Result = (IntPtr) CustomDrawReturnFlags.CDRF_SKIPDEFAULT;
  838. return;
  839. }
  840. bool hot = (bool)((tbcd.nmcd.uItemState & (uint)CustomDrawItemStateFlags.CDIS_HOT) != 0);
  841. bool selected = (bool)((tbcd.nmcd.uItemState & (uint)CustomDrawItemStateFlags.CDIS_SELECTED) != 0);
  842. bool disabled = (bool)((tbcd.nmcd.uItemState & (uint)CustomDrawItemStateFlags.CDIS_DISABLED) != 0);
  843. string tempString = item.Text;
  844. bool hasText = (tempString != string.Empty && tempString != null);
  845. if (item.Checked) 
  846. {
  847. if ( hot )
  848. g.FillRectangle(new SolidBrush(ColorUtil.VSNetPressedColor), rectangle);
  849. else
  850. g.FillRectangle(new SolidBrush(ColorUtil.VSNetCheckedColor), rectangle);
  851. g.DrawRectangle(new Pen(new SolidBrush(ColorUtil.VSNetBorderColor), 1), 
  852. rectangle.Left, rectangle.Top, rectangle.Width-1, rectangle.Height-1);
  853. }
  854. else if (selected) 
  855. {
  856. if ( item.Style == ToolBarItemStyle.DropDownButton ) 
  857. {
  858. // Draw background
  859. g.FillRectangle(new SolidBrush(ColorUtil.VSNetSelectionColor), rectangle);
  860. g.FillRectangle(new SolidBrush(ColorUtil.VSNetPressedColor), rectangle.Left, rectangle.Top, 
  861. rectangle.Width-DROWPDOWN_ARROW_WIDTH+1, rectangle.Height);
  862. g.DrawRectangle(new Pen(new SolidBrush(ColorUtil.VSNetBorderColor), 1), 
  863. rectangle.Left, rectangle.Top, rectangle.Width-1, rectangle.Height-1);
  864. }
  865. else 
  866. {
  867. if ( barType == BarType.MenuBar)
  868. {
  869. g.FillRectangle(new SolidBrush(ColorUtil.VSNetControlColor), rectangle);
  870. if ( ColorUtil.UsingCustomColor )
  871. {
  872. // Use same color for both sides to make it look flat
  873. g.DrawRectangle(new Pen(ColorUtil.VSNetBorderColor), 
  874. rectangle.Left, rectangle.Top, rectangle.Width-1, rectangle.Height-1);
  875. }
  876. else 
  877. {
  878. ControlPaint.DrawBorder3D(g, rectangle.Left, rectangle.Top, rectangle.Width-1, 
  879. rectangle.Height-1, Border3DStyle.Flat, Border3DSide.Top | Border3DSide.Left | Border3DSide.Right);
  880. }
  881. }
  882. else 
  883. {
  884. g.FillRectangle(new SolidBrush(ColorUtil.VSNetPressedColor), rectangle);
  885. g.DrawRectangle(new Pen(new SolidBrush(ColorUtil.VSNetBorderColor), 1), 
  886. rectangle.Left, rectangle.Top, rectangle.Width-1, rectangle.Height-1);
  887. }
  888. }
  889. }
  890. else if ( item.Style == ToolBarItemStyle.DropDownButton && item.Dropped )
  891. {
  892. g.FillRectangle(new SolidBrush(ColorUtil.VSNetControlColor), rectangle);
  893. g.DrawRectangle(new Pen(new SolidBrush(SystemColors.ControlDark), 1), 
  894. rectangle.Left, rectangle.Top, rectangle.Width-1, rectangle.Height-1);
  895. }
  896. else if (hot)
  897. {
  898. g.FillRectangle(new SolidBrush(ColorUtil.VSNetSelectionColor), rectangle);
  899. g.DrawRectangle(new Pen(new SolidBrush(ColorUtil.VSNetBorderColor), 1), 
  900. rectangle.Left, rectangle.Top, rectangle.Width-1, rectangle.Height-1);
  901. }
  902. else 
  903. {
  904. if ( item.Style == ToolBarItemStyle.DropDownButton )
  905. {
  906. IntPtr hreBar = WindowsAPI.GetParent(Handle);
  907. IntPtr hMainWindow = IntPtr.Zero;
  908. bool mainHasFocus = false;
  909. if ( hreBar != IntPtr.Zero )
  910. {
  911. hMainWindow = WindowsAPI.GetParent(hreBar);
  912. if ( hMainWindow != IntPtr.Zero ) 
  913. mainHasFocus = ( hMainWindow == WindowsAPI.GetFocus());
  914. }
  915. if ( hMainWindow != IntPtr.Zero &&  mainHasFocus)
  916. {
  917. Point pos = Control.MousePosition;
  918. Point clientPoint = PointToClient(pos);
  919. if ( rectangle.Contains(clientPoint))
  920. {
  921. g.FillRectangle(new SolidBrush(ColorUtil.VSNetSelectionColor), rectangle);
  922. g.DrawRectangle(new Pen(new SolidBrush(ColorUtil.VSNetBorderColor), 1), 
  923. rectangle.Left, rectangle.Top, rectangle.Width-1, rectangle.Height-1);
  924. rc.right -= DROWPDOWN_ARROW_WIDTH;
  925. g.DrawLine(new Pen(new SolidBrush(ColorUtil.VSNetBorderColor), 1), 
  926. rc.right+1, rc.top, rc.right+1, rc.top + (rc.bottom-rc.top));
  927. rc.right += DROWPDOWN_ARROW_WIDTH;
  928. }
  929. }
  930. }
  931. }
  932. if ( item.Style == ToolBarItemStyle.DropDownButton ) 
  933. {
  934. DrawButtonArrowGlyph(g, rectangle, disabled);
  935. // Draw line that separates the arrow from the button
  936. rc.right -= DROWPDOWN_ARROW_WIDTH;
  937. if ( hot && !item.Dropped )
  938. g.DrawLine(new Pen(new SolidBrush(ColorUtil.VSNetBorderColor), 1), 
  939. rc.right+1, rc.top, rc.right+1, rc.top + (rc.bottom-rc.top));
  940. item.Dropped = false;
  941. }
  942. // If the toolBar has an assign image list use that instead
  943. Image image = null;
  944. if ( imageList != null && item.ImageListIndex != -1 )
  945. {
  946. if ( item.ImageListIndex < imageList.Images.Count )
  947. image = imageList.Images[item.ImageListIndex];
  948. }
  949. else
  950. {
  951. image = item.Image;
  952. }
  953. if (image != null)
  954. {
  955. Size size = image.Size;
  956. Point point = new Point(rc.left + ((rc.right - rc.left - size.Width) / 2), 
  957. rc.top + ((rc.bottom - rc.top - size.Height) / 2));
  958. if ( hasText ) point.X = rc.left + MARGIN;
  959. if ( disabled ) 
  960. ControlPaint.DrawImageDisabled(g, image, point.X, point.Y, ColorUtil.VSNetSelectionColor);
  961. else if ( hot && !selected && !item.Checked )
  962. {
  963. ControlPaint.DrawImageDisabled(g, image, point.X+1, point.Y, ColorUtil.VSNetSelectionColor);
  964. g.DrawImage(image, point.X, point.Y-1);
  965. }
  966. else 
  967. {
  968. if ( item.Checked  )
  969. {
  970. if  ( !selected ) point.Y -= 1;
  971. }
  972. g.DrawImage(image, point.X, point.Y);
  973. }
  974. }
  975. // Draw Text 
  976. if ( hasText )
  977. {
  978. string currentText = item.Text;
  979. int amperSandIndex = currentText.IndexOf('&');
  980. if ( barType == BarType.MenuBar && amperSandIndex != -1 )
  981. currentText = item.Text.Remove(amperSandIndex, 1);
  982. Size textSize = TextUtil.GetTextSize(g, currentText, SystemInformation.MenuFont);
  983. Point pos;
  984. if ( barType == BarType.MenuBar || image == null)
  985. {
  986. int offset = rc.left + ((rc.right - rc.left) - textSize.Width)/2;
  987. pos = new Point(offset, rc.top + ((rc.bottom - rc.top - textSize.Height) / 2));
  988. }
  989. else
  990. {
  991. pos = new Point(rc.left, rc.top + ((rc.bottom - rc.top - textSize.Height) / 2));
  992. pos.X = rc.left + MARGIN + image.Size.Width + MARGIN;
  993. }
  994. StringFormat stringFormat = new StringFormat();
  995. stringFormat.HotkeyPrefix = HotkeyPrefix.Show;
  996. Color brushTextColor = SystemColors.MenuText;
  997. if ( disabled )
  998. brushTextColor = Color.FromArgb(120, SystemColors.MenuText);
  999. using ( Brush b = new SolidBrush(brushTextColor) )
  1000. {
  1001. g.DrawString(item.Text, SystemInformation.MenuFont, b, pos, stringFormat); 
  1002. }
  1003. }
  1004. m.Result = (IntPtr) CustomDrawReturnFlags.CDRF_SKIPDEFAULT;
  1005. }
  1006. protected void DrawButtonArrowGlyph(Graphics g, Rectangle rectangle, bool disabled)
  1007. {
  1008. // Draw arrow glyph
  1009. Point[] pts = new Point[3];
  1010. int leftEdge = rectangle.Left + (rectangle.Width-DROWPDOWN_ARROW_WIDTH+1);
  1011. int middle = rectangle.Top + rectangle.Height/2-1;
  1012. pts[0] = new Point(leftEdge + 4, middle);
  1013. pts[1] = new Point(leftEdge + 9,  middle);
  1014. pts[2] = new Point(leftEdge + 6, middle+3);
  1015. Color brushColor = SystemColors.MenuText;
  1016. if ( disabled )
  1017. brushColor = Color.FromArgb(120, SystemColors.MenuText);
  1018. using ( Brush b = new SolidBrush(brushColor) )
  1019. {
  1020. g.FillPolygon(b, pts);
  1021. }
  1022. }
  1023. private MenuItem FindShortcutItem(MenuItemExCollection items, Keys keys)
  1024. {
  1025. MenuItem resultItem = null;
  1026. foreach (MenuItemEx item in items )
  1027. {
  1028. if ( ((int)item.Shortcut == (int)keys) && (item.Enabled) && (item.Visible) )
  1029. return item;
  1030. else
  1031. {
  1032. resultItem =  FindShortcutItem(item.MenuItems, keys);
  1033. if ( resultItem != null )
  1034. break;
  1035. }
  1036. }
  1037. return resultItem;
  1038. }
  1039. private MenuItem FindShortcutItem(Menu.MenuItemCollection collection, Keys keys)
  1040. {
  1041. int count = collection.Count;
  1042. foreach (MenuItem item in collection )
  1043. {
  1044. if ( ((int)item.Shortcut == (int)keys) && (item.Enabled) && (item.Visible) )
  1045. return item;
  1046. else
  1047. return FindShortcutItem(item.MenuItems, keys);
  1048. }
  1049. return null;
  1050. }
  1051. void Items_Changed(Object s, EventArgs e)
  1052. {
  1053. UpdateItems();
  1054. }
  1055. void Item_Changed(Object s, EventArgs e)
  1056. {
  1057. ToolBarItem[] handledItems = this.handledItems;
  1058. foreach (ToolBarItem item in handledItems)
  1059. {
  1060. if ( item == s )
  1061. {
  1062. if (item == null) return;
  1063. int index = items.IndexOf(item);
  1064. if (index == -1) return;
  1065. UpdateItem(index);
  1066. }
  1067. }
  1068. }
  1069. void BeginUpdate()
  1070. {
  1071. WindowsAPI.SendMessage(Handle, (int)Msg.WM_SETREDRAW, 0, 0);
  1072. }
  1073. void EndUpdate()
  1074. {
  1075. WindowsAPI.SendMessage(Handle, (int)Msg.WM_SETREDRAW, 1, 0);
  1076. }
  1077. void UpdateItems()
  1078. {
  1079. Detach();
  1080. Attach();
  1081. if (IsHandleCreated) RecreateHandle();
  1082. }
  1083. TBBUTTONINFO GetButtonInfo(int index, ToolBarItem currentItem)
  1084. {
  1085. ToolBarItem item = null;
  1086. if ( currentItem != null )
  1087. item = currentItem;
  1088. else
  1089.                 item = items[index];
  1090. TBBUTTONINFO tbi = new TBBUTTONINFO();
  1091. tbi.cbSize = Marshal.SizeOf(typeof(TBBUTTONINFO));
  1092. tbi.dwMask = (int)(ToolBarButtonInfoFlags.TBIF_IMAGE | ToolBarButtonInfoFlags.TBIF_STATE | 
  1093. ToolBarButtonInfoFlags.TBIF_STYLE | ToolBarButtonInfoFlags.TBIF_COMMAND | ToolBarButtonInfoFlags.TBIF_SIZE);
  1094. tbi.idCommand = index;
  1095. tbi.iImage = (int)ToolBarButtonInfoFlags.I_IMAGECALLBACK;
  1096. tbi.fsState = 0;
  1097. tbi.cx = 0;
  1098. tbi.lParam = IntPtr.Zero;
  1099. tbi.pszText = IntPtr.Zero;
  1100. tbi.cchText = 0;
  1101. if ( item.Style == ToolBarItemStyle.ComboBox )
  1102. {
  1103. if ( !item.ComboBox.IsDisposed )
  1104. {
  1105. tbi.fsStyle = (int)ToolBarButtonStyles.TBSTYLE_BUTTON ;
  1106. tbi.cx = (short)item.ComboBox.Width;
  1107. WindowsAPI.SetParent(item.ComboBox.Handle, Handle);
  1108. }
  1109. }
  1110. else if ( item.Text != null && item.Text != string.Empty )
  1111. {
  1112. tbi.fsStyle = (int)ToolBarButtonStyles.TBSTYLE_BUTTON;
  1113. tbi.cx = MARGIN;
  1114. if ( item.Image != null || imageList != null)
  1115. {
  1116. if ( imageList != null && item.ImageListIndex != -1 && item.ImageListIndex < imageList.Images.Count )
  1117. {
  1118. tbi.cx += (short)(imageList.ImageSize.Width + MARGIN);
  1119. }
  1120. else if ( item.Image != null )
  1121. {
  1122. tbi.cx += (short)(item.Image.Size.Width + MARGIN);
  1123. }
  1124. }
  1125. if ( item.Style == ToolBarItemStyle.DropDownButton )
  1126. tbi.cx += DROWPDOWN_ARROW_WIDTH;
  1127. Graphics g = CreateGraphics();
  1128. string currentText = item.Text;
  1129. int amperSandIndex = currentText.IndexOf('&');
  1130. if ( amperSandIndex != -1 )
  1131. currentText = item.Text.Remove(amperSandIndex, 1);
  1132. Size size = TextUtil.GetTextSize(g, currentText, SystemInformation.MenuFont);
  1133. g.Dispose();
  1134. if ( barType == BarType.MenuBar)
  1135. {
  1136. tbi.cx += (short)(size.Width + 2*MENUTEXT_MARGIN);
  1137. }
  1138. else
  1139. tbi.cx += (short)(size.Width + 2*MARGIN);
  1140. tbi.dwMask |= (int)ToolBarButtonInfoFlags.TBIF_TEXT;
  1141. tbi.pszText = Marshal.StringToHGlobalAuto(item.Text + "");
  1142. tbi.cchText = item.Text.Length;
  1143. if (  IsCommonCtrl6() && barType != BarType.MenuBar )
  1144. {
  1145. // If we let the operating system do the drawing
  1146. // the DROWPDOWN_ARROW_WIDTH is slightly bigger than
  1147. // the value we are using add some padding to compensate
  1148. tbi.cx += 6;
  1149. }
  1150. }
  1151. else 
  1152. {
  1153. tbi.fsStyle = (int)(ToolBarButtonStyles.TBSTYLE_BUTTON | ToolBarButtonStyles.TBSTYLE_AUTOSIZE);
  1154. tbi.cx = 0;
  1155. }
  1156. if (!item.Visible)
  1157. tbi.fsState |= (int)ToolBarButtonStates.TBSTATE_HIDDEN;
  1158. if (item.Style == ToolBarItemStyle.Separator)
  1159. {
  1160. tbi.fsStyle |= (int)(ToolBarButtonStyles.TBSTYLE_SEP);
  1161. }
  1162. else
  1163. {
  1164. if (item.Enabled)
  1165. tbi.fsState |= (int)ToolBarButtonStates.TBSTATE_ENABLED;
  1166. if ( item.Style == ToolBarItemStyle.DropDownButton )
  1167. tbi.fsStyle |= (int)(ToolBarButtonStyles.TBSTYLE_DROPDOWN);
  1168. if (item.Style == ToolBarItemStyle.PushButton)
  1169. if (item.Checked) 
  1170. tbi.fsState |= (int)ToolBarButtonStates.TBSTATE_CHECKED;
  1171. }
  1172. if (item.Style == ToolBarItemStyle.Separator )
  1173. tbi.iImage = (int)ToolBarButtonInfoFlags.I_IMAGENONE;
  1174. else if (item.Image != null || imageList != null)
  1175. tbi.iImage = index;
  1176. return tbi;
  1177. }
  1178. void RealizeItems()
  1179. {
  1180. UpdateImageList();
  1181. for (int i = 0; i < items.Count; i++)
  1182. {
  1183. items[i].Index = i;
  1184. items[i].ToolBar = this;
  1185. TBBUTTON button = new TBBUTTON();
  1186. button.idCommand = i;
  1187. WindowsAPI.SendMessage(Handle, ToolBarMessages.TB_INSERTBUTTON, i, ref button);
  1188. TBBUTTONINFO tbi = GetButtonInfo(i, null);
  1189. WindowsAPI.SendMessage(Handle, ToolBarMessages.TB_SETBUTTONINFOW, i, ref tbi);
  1190. if ( items[i].Style == ToolBarItemStyle.ComboBox ) UpdateComboBoxPosition(i);
  1191. }
  1192. UpdateSize();
  1193. }
  1194. void UpdateComboBoxPosition(int index)
  1195. {
  1196. RECT rect = new RECT();
  1197. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_GETRECT, index, ref rect);
  1198. int rectHeight = (rect.bottom-rect.top);
  1199. int cbHeight = Items[index].ComboBox.Bounds.Height;
  1200. int topOffset = rect.top+(rectHeight-cbHeight)/2;
  1201. Items[index].ComboBox.Bounds = new Rectangle(rect.left+1, topOffset, 
  1202. (rect.right-rect.left)-2, cbHeight);
  1203. // In case it was make invisible by the user minimizing the window
  1204. if ( !Items[index].ComboBox.Visible )
  1205. Items[index].ComboBox.Visible = true;
  1206. }
  1207. void UpdateImageList()
  1208. {
  1209. Size size = new Size(16, SystemInformation.MenuFont.Height);
  1210. for (int i = 0; i < items.Count; i++)
  1211. {
  1212. Image image = items[i].Image;
  1213. if (image != null)
  1214. {
  1215. if (image.Width > size.Width) size.Width = image.Width;
  1216. if (image.Height > size.Height) size.Height = image.Height;
  1217. }
  1218. }
  1219. imageListHelper = new ImageList();
  1220. if ( imageList == null )
  1221. imageListHelper.ImageSize = size;
  1222. else
  1223. imageListHelper.ImageSize = imageList.ImageSize;
  1224. imageListHelper.ColorDepth = ColorDepth.Depth32Bit;
  1225. for (int i = 0; i < items.Count; i++)
  1226. {
  1227. // Take combobox size into consideration too
  1228. if ( items[i].Style == ToolBarItemStyle.ComboBox )
  1229. {
  1230. // update combobox to use the current system menu font
  1231. items[i].ComboBox.Font = SystemInformation.MenuFont;
  1232. ComboBoxBase cbb = (ComboBoxBase)items[i].ComboBox;
  1233. int decrease = 2;
  1234. if ( SystemInformation.MenuFont.Height >= 20)
  1235. decrease = 5;
  1236. cbb.SetFontHeight(SystemInformation.MenuFont.Height-decrease);
  1237. }
  1238. Image image = items[i].Image;
  1239. imageListHelper.Images.Add((image != null) ? image : new Bitmap(size.Width, size.Height));
  1240. }
  1241. if ( parentRebar != null && parentRebar.RebarDesigner != null && items.Count == 0 )
  1242. {
  1243. // If we are faking the ToolBarItem, add at least one image
  1244. // so that the imageList has a size
  1245. imageListHelper.Images.Add(new Bitmap(size.Width, size.Height));
  1246. }
  1247. IntPtr handle = imageListHelper.Handle;
  1248. if ( IsCommonCtrl6() && barType == BarType.MenuBar )
  1249. handle = IntPtr.Zero;
  1250. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_SETIMAGELIST, 0, handle);
  1251. }
  1252. void UpdateSize()
  1253. {
  1254. Size size = new Size(0, 0);
  1255. for (int i = 0; i < items.Count; i++)
  1256. {
  1257. RECT rect = new RECT();
  1258. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_GETRECT, i, ref rect);
  1259. int height = rect.bottom - rect.top;
  1260. if (height > size.Height) size.Height = height;
  1261. size.Width += rect.right - rect.left;
  1262. }
  1263. if ( parentRebar != null && parentRebar.RebarDesigner != null && items.Count == 0 )
  1264. {
  1265. // If we are faking the ToolBarItem get the size for the ghost ToolBarItem
  1266. RECT rect = new RECT();
  1267. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_GETRECT, 0, ref rect);
  1268. int height = rect.bottom - rect.top;
  1269. if (height > size.Height) size.Height = height;
  1270. size.Width = rect.right - rect.left;
  1271. }
  1272. Size = size;
  1273. }
  1274. internal Rectangle GetItemRect(int index)
  1275. {
  1276. RECT rect = new RECT();
  1277. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_GETRECT, index, ref rect);
  1278. Rectangle r = new Rectangle(rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top);
  1279. return r;
  1280. }
  1281. internal int GetItemAtPoint(Point p)
  1282. {
  1283. for(int i = 0; i < items.Count; i++)
  1284. {
  1285. Rectangle rect = GetItemRect(i);
  1286. if( rect.Contains(p) )
  1287. return i;
  1288. }
  1289. return -1;
  1290. }
  1291. public int GetIdealSize()
  1292. {
  1293. Size size = new Size(0, 0);
  1294. for (int i = 0; i < items.Count; i++)
  1295. {
  1296. RECT rect = new RECT();
  1297. WindowsAPI.SendMessage(Handle, (int)ToolBarMessages.TB_GETRECT, i, ref rect);
  1298. int height = rect.bottom - rect.top;
  1299. if (height > size.Height) size.Height = height;
  1300. size.Width += rect.right - rect.left;
  1301. }
  1302. return size.Width;
  1303. }
  1304. void UpdateItem(int index)
  1305. {
  1306. if (!IsHandleCreated) return;
  1307. if ( items[index].Visible == handledItemsVisible[index] )
  1308. {
  1309. TBBUTTONINFO tbi = GetButtonInfo(index, null);
  1310. WindowsAPI.SendMessage(Handle, ToolBarMessages.TB_SETBUTTONINFOW, index, ref tbi);
  1311. if ( items[index].Style == ToolBarItemStyle.ComboBox ) UpdateComboBoxPosition(index);
  1312. // When in design mode the text is added after a ToolBarItem has been inserted producing
  1313. // a mismatch between the actual size of the toolbar and the size the Rebar think it is
  1314. // force size update if in design mode
  1315. if ( parentRebar.RebarDesigner != null )
  1316. {
  1317. UpdateSize();
  1318. parentRebar.UpdateBands();
  1319. }
  1320. }
  1321. else
  1322. {
  1323. UpdateItems();
  1324. }
  1325. }
  1326. internal void PassMsg(ref Message message)
  1327. {
  1328. WndProc(ref message);
  1329. }
  1330. #endregion
  1331. }
  1332. #endregion
  1333. }