⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 commandbar.cs

📁 c#源代码
💻 CS
📖 第 1 页 / 共 3 页
字号:
								nextIndex = (nextIndex + 1) % count;
						}
						while ((nextIndex != index) && (!items[nextIndex].IsVisible));
					 
						return nextIndex;
				}
					 
				private int GetPreviousItem(int index)
				{
						if (index < 0)
						{
								throw new ArgumentException("index");
						}

						int count = NativeMethods.SendMessage(this.Handle, NativeMethods.TB_BUTTONCOUNT, 0, 0);
					 
						int prevIndex = index;
						do
						{
								prevIndex = (prevIndex + count - 1) % count;
						}
						while ((prevIndex != index) && (!items[prevIndex].IsVisible));
					 
						return prevIndex;
				}

		private int GetHotItem()
		{
			return NativeMethods.SendMessage(Handle, NativeMethods.TB_GETHOTITEM, 0, 0);
		}
		
		private void SetHotItem(int index)
		{
			NativeMethods.SendMessage(Handle, NativeMethods.TB_SETHOTITEM, index, 0);
		}

		private void SetState(State state, int index)
		{
			if (this.state != state)
			{
				if (state == State.None)
				{
					index = -1;
				}
					
				this.SetHotItem(index);
				
				if (state == State.HotTracking)
				{
					this.trackEscapePressed = false;
					this.trackHotItem = index;
				}
			}

			this.lastState = this.state;
			this.state = state;
		}

		private void TrackDropDownNext(int index)
		{
			if (index != this.trackHotItem)
			{
				NativeMethods.PostMessage(Handle, NativeMethods.WM_CANCELMODE, 0, 0);
				this.trackNextItem = index;
			}
		}

		private void TrackDropDown(int index)
		{
			while (index >= 0)
			{
				this.trackNextItem = -1;

				this.BeginUpdate();

				CommandBarMenu menu = this.items[index] as CommandBarMenu;
				if (menu != null)
				{
					menu.PerformDropDown(EventArgs.Empty);
					this.contextMenu.Items.Clear();
					this.contextMenu.Items.AddRange(menu.Items); // = menu.Items;
					this.contextMenu.Mnemonics = true;
				}
				else
				{
					this.contextMenu.Items.Clear(); // .Items = new CommandBarItemCollection();
					this.contextMenu.Mnemonics = true;
				}

				// Item state
				NativeMethods.SendMessage(this.Handle, NativeMethods.TB_PRESSBUTTON, index, -1);

				// Trick to get the first menu item selected
				NativeMethods.PostMessage(this.Handle, NativeMethods.WM_KEYDOWN, (int) Keys.Down, 1);
				NativeMethods.PostMessage(this.Handle, NativeMethods.WM_KEYUP, (int) Keys.Down, 1);

				this.SetState(State.HotTracking, index);

				// Hook
				NativeMethods.HookProc hookProc = new NativeMethods.HookProc(DropDownHook);
				GCHandle hookProcHandle = GCHandle.Alloc(hookProc);
				this.hookHandle = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MSGFILTER, hookProc, IntPtr.Zero, NativeMethods.GetCurrentThreadId());
				if (this.hookHandle == IntPtr.Zero) 
				{
					throw new SecurityException();
				}

				// Ask for position
				NativeMethods.RECT rect = new NativeMethods.RECT();
				NativeMethods.SendMessage(Handle, NativeMethods.TB_GETRECT, index, ref rect);
				Point position = new Point(rect.left, rect.bottom);
				
				this.EndUpdate();
				this.Update();

				this.contextMenu.Show(this, position);

				// Unhook		
				NativeMethods.UnhookWindowsHookEx(hookHandle);
				hookProcHandle.Free();
				this.hookHandle = IntPtr.Zero;

				// Item state
				NativeMethods.SendMessage(Handle, NativeMethods.TB_PRESSBUTTON, index, 0);
				this.SetState(trackEscapePressed ? State.Hot : State.None, index);

				index = trackNextItem;
			}
		}				

		public void Show(Control control, Point point)
		{
			CommandBarItemCollection chevronItems = new CommandBarItemCollection();
			Size size = ClientSize;
			for (int i = 0; i < items.Count; i++)
			{
				NativeMethods.RECT rect = new NativeMethods.RECT();
				NativeMethods.SendMessage(Handle, NativeMethods.TB_GETITEMRECT, i, ref rect);
				if (rect.right > size.Width)
				{
					CommandBarItem item = items[i];
					if (item.IsVisible) 
					{
						if ((!(item is CommandBarSeparator)) || (chevronItems.Count != 0))
							chevronItems.Add(item);
					}
				}
			}

			this.contextMenu.Mnemonics = false;
			this.contextMenu.Items.Clear();
			this.contextMenu.Items.AddRange(chevronItems);
			this.contextMenu.Show(control, point);
		}

		private bool DropDownFilter(ref Message message)
		{
			if (state != State.HotTracking)
			{
				throw new InvalidOperationException();
			}

			// comctl32 sometimes steals the hot item for unknown reasons.
			this.SetHotItem(this.trackHotItem);

			if (message.Msg == NativeMethods.WM_KEYDOWN)
			{
				Keys keyData = (Keys)(int) message.WParam | ModifierKeys;

				if (keyData == Keys.Left)
				{
					this.TrackDropDownNext(this.GetPreviousItem(trackHotItem));
					return true;
				}

				// Only move right if there is no submenu on the current selected item.
				if ((keyData == Keys.Right) && ((this.contextMenu.SelectedMenuItem == null) || (this.contextMenu.SelectedMenuItem.MenuItems.Count == 0)))
				{
					this.TrackDropDownNext(GetNextItem(trackHotItem));
					return true;
				}

				if (keyData == Keys.Escape)
				{
					trackEscapePressed = true;
				}
			}
			else if ((message.Msg == NativeMethods.WM_MOUSEMOVE) || (message.Msg == NativeMethods.WM_LBUTTONDOWN))
			{
				Point point = new Point(((int) message.LParam) & 0xffff, ((int) message.LParam) >> 16);
				point = this.PointToClient(point);

				if (message.Msg == NativeMethods.WM_MOUSEMOVE)
				{
					if (point != lastMousePosition)
					{
						int index = HitTest(point);
						if ((this.IsValid(index)) && (index != trackHotItem))
							this.TrackDropDownNext(index);

						lastMousePosition = point;
					}
				}
				else if (message.Msg == NativeMethods.WM_LBUTTONDOWN)
				{
					if (HitTest(point) == trackHotItem)
					{
						this.TrackDropDownNext(-1);
						return true;
					}
				}
			}

			return false;
		}

		private IntPtr DropDownHook(int code, IntPtr wparam, IntPtr lparam) 
		{
			if (code == NativeMethods.MSGF_MENU)
			{
				NativeMethods.MSG msg = (NativeMethods.MSG) Marshal.PtrToStructure(lparam, typeof(NativeMethods.MSG));
				Message message = Message.Create(msg.hwnd, msg.message, msg.wParam, msg.lParam);
				if (this.DropDownFilter(ref message))
				{
					return (IntPtr)1;
				}
			}
	
			return NativeMethods.CallNextHookEx(this.hookHandle, code, wparam, lparam);
		}
	
		[SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
		protected override void WndProc(ref Message message)
		{
			base.WndProc(ref message);

			switch (message.Msg)
			{
				case NativeMethods.WM_COMMAND + NativeMethods.WM_REFLECT:
					int index = (int) message.WParam & 0xFFFF;
					this.PerformClick(this.items[index]);
					base.WndProc(ref message);
					this.ResetMouseEventArgs();
					break;

				case NativeMethods.WM_MENUCHAR:
					this.WmMenuChar(ref message);
					break;
	
				case NativeMethods.WM_NOTIFY:
				case NativeMethods.WM_NOTIFY + NativeMethods.WM_REFLECT:
					NativeMethods.NMHDR note = (NativeMethods.NMHDR) message.GetLParam(typeof(NativeMethods.NMHDR));
					switch (note.code)
					{
						case NativeMethods.TTN_NEEDTEXTA:
							NotifyNeedTextA(ref message);
							break;
		
						case NativeMethods.TTN_NEEDTEXTW:
							NotifyNeedTextW(ref message);
							break;				
		
						case NativeMethods.TBN_QUERYINSERT:
							message.Result = (IntPtr) 1;
							break;
		
						case NativeMethods.TBN_DROPDOWN:
							this.NotifyDropDown(ref message);
							break;
							
						case NativeMethods.NM_CUSTOMDRAW:
							this.NotifyCustomDraw(ref message);
							break;

						case NativeMethods.TBN_HOTITEMCHANGE:
							break;
					}
					break;
			}
		}

		private void NotifyCustomDrawMenuBar(ref Message m)		
		{
			m.Result = (IntPtr) NativeMethods.CDRF_DODEFAULT;
			NativeMethods.LPNMTBCUSTOMDRAW tbcd = (NativeMethods.LPNMTBCUSTOMDRAW) m.GetLParam(typeof(NativeMethods.LPNMTBCUSTOMDRAW));

			bool hot = ((tbcd.nmcd.uItemState & NativeMethods.CDIS_HOT) != 0);
			bool selected = ((tbcd.nmcd.uItemState & NativeMethods.CDIS_SELECTED) != 0);

			if (hot || selected)
			{
				NativeMethods.RECT rect = tbcd.nmcd.rc;

				using (Graphics graphics = Graphics.FromHdc(tbcd.nmcd.hdc))
				{
					graphics.FillRectangle(SystemBrushes.Highlight, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
				}

				using (TextGraphics textGraphics = new TextGraphics(tbcd.nmcd.hdc))
				{
					Font font = this.Font;
					string text = this.items[tbcd.nmcd.dwItemSpec].Text;
					Size size = textGraphics.MeasureText(text, font);
					Point point = new Point(rect.left + ((rect.right - rect.left - size.Width) / 2), rect.top + ((rect.bottom - rect.top - size.Height) / 2));
					textGraphics.DrawText(text, point, font, SystemColors.HighlightText);
				}

				m.Result = (IntPtr) NativeMethods.CDRF_SKIPDEFAULT;
			}
		}

		private void NotifyCustomDrawToolBar(ref Message m)
		{
			m.Result = (IntPtr) NativeMethods.CDRF_DODEFAULT;

			NativeMethods.DLLVERSIONINFO dvi = new NativeMethods.DLLVERSIONINFO();
			dvi.cbSize = Marshal.SizeOf(typeof(NativeMethods.DLLVERSIONINFO));
			NativeMethods.DllGetVersion(ref dvi);
			if (dvi.dwMajorVersion < 6)
			{
				NativeMethods.LPNMTBCUSTOMDRAW tbcd = (NativeMethods.LPNMTBCUSTOMDRAW)m.GetLParam(typeof(NativeMethods.LPNMTBCUSTOMDRAW));
				NativeMethods.RECT rc = tbcd.nmcd.rc;

				Rectangle rectangle = new Rectangle(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
//// Alex:graphics and image must be released - lots of calls
				using (Graphics graphics = Graphics.FromHdc(tbcd.nmcd.hdc)) {
					CommandBarItem item = items[tbcd.nmcd.dwItemSpec];

					bool hot = ((tbcd.nmcd.uItemState & NativeMethods.CDIS_HOT) != 0);
					bool selected = ((tbcd.nmcd.uItemState & NativeMethods.CDIS_SELECTED) != 0);
					bool disabled = ((tbcd.nmcd.uItemState & NativeMethods.CDIS_DISABLED) != 0);
		
					CommandBarCheckBox checkBox = item as CommandBarCheckBox;
					if ((checkBox != null) && (checkBox.IsChecked))
					{
						ControlPaint.DrawBorder3D(graphics, rectangle, Border3DStyle.SunkenOuter);
					}
					else if (selected)
					{
						ControlPaint.DrawBorder3D(graphics, rectangle, Border3DStyle.SunkenOuter);
					}
					else if (hot)
					{
						ControlPaint.DrawBorder3D(graphics, rectangle, Border3DStyle.RaisedInner);
					}
//// Alex: don't create references unnecessarily - lots of calls
					if (item.Image != null)
					{
						Size size = item.Image.Size;
						Point point = new Point(rc.left + ((rc.right - rc.left - size.Width) / 2), rc.top + ((rc.bottom - rc.top - size.Height) / 2));
						NativeMethods.DrawImage(graphics, item.Image, point, disabled);
					}
				}
				m.Result = (IntPtr)NativeMethods.CDRF_SKIPDEFAULT;
			}
		}

		private void NotifyCustomDraw(ref Message m)
		{
			m.Result = (IntPtr) NativeMethods.CDRF_DODEFAULT;
			NativeMethods.LPNMTBCUSTOMDRAW tbcd = (NativeMethods.LPNMTBCUSTOMDRAW) m.GetLParam(typeof(NativeMethods.LPNMTBCUSTOMDRAW));

			switch (tbcd.nmcd.dwDrawStage)
			{
				case NativeMethods.CDDS_PREPAINT:
					m.Result = (IntPtr) NativeMethods.CDRF_NOTIFYITEMDRAW;
					break;
	
				case NativeMethods.CDDS_ITEMPREPAINT:
					if (this.style == CommandBarStyle.Menu)
					{
						this.NotifyCustomDrawMenuBar(ref m);
					}
					if (this.style == CommandBarStyle.ToolBar)
					{
						this.NotifyCustomDrawToolBar(ref m);
					}
					break;
			}
		}

		private void WmMenuChar(ref Message message)
		{
			Menu menu = contextMenu.FindMenuItem(MenuItem.FindHandle, message.LParam);
			if (contextMenu.Handle == message.LParam)
			{
				menu = contextMenu;
			}

			if (menu != null)
			{
				char key = char.ToUpper((char) ((int) message.WParam & 0x0000FFFF), CultureInfo.InvariantCulture);
				int index = 0;
				foreach (MenuItem menuItem in menu.MenuItems)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -