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

📄 menucontrol.cs

📁 chaoshi guan li xitong
💻 CS
📖 第 1 页 / 共 3 页
字号:
				_popupMenu.TrackPopup(screenPos, 
									  aboveScreenPos,
									  _direction,
									  dc.MenuCommand.MenuCommands, 
									  borderGap,
									  selectFirst,
									  this,
									  ref returnDir);

				// Generate event so that caller has chance to modify MenuCommand contents
				OnPopupEnd(dc.MenuCommand);
			}

			// Remove unwanted object
			_popupMenu = null;

			// Was arrow key used to dismiss the submenu?
			if (returnDir != 0)
			{
				// Using keyboard movements means we should have the focus
				if (!_manualFocus)
				{
					_manualFocus = true;

					GrabTheFocus();
				}

				if (returnDir < 0)
				{
					// Shift selection left one
					ProcessMoveLeft(true);
				}
				else
				{
					// Shift selection right one
					ProcessMoveRight(true);
				}

				// A WM_MOUSEMOVE is generated when we open up the new submenu for 
				// display, ignore this as it causes the selection to move
				_ignoreMouseMove = true;
			}
			else
			{
				// Only if the submenu was dismissed at the request of the submenu
				// should the selection mode be cancelled, otherwise keep selection mode
				if (!_dismissTransfer)
				{
					// This item is no longer selected
					_selected = false;
					_drawUpwards = false;

					// Should we stop tracking this item
					if (trackRemove)
					{
						ReturnTheFocus();

						// Unselect the current item
						_trackItem = SwitchTrackingItem(_trackItem, -1);
					}
					else
					{
						// Repaint the item
						DrawCommand(_trackItem, true);
					}
				}
				else
				{
					// Do not change _selected status
					_dismissTransfer = false;
				}
			}
		}

		protected void GrabTheFocus()
		{	
			// Remember the current focus location
			_oldFocus = WindowsAPI.GetFocus();

			// Grab the focus
			this.Focus();
		}

		protected void ReturnTheFocus()
		{
			// Do we remember where it came from?
			if (_oldFocus != IntPtr.Zero)
			{
				// Send the focus back
				WindowsAPI.SetFocus(_oldFocus);

				// No need to remember old focus anymore
				_oldFocus = IntPtr.Zero;
			}

			// We lost the focus
			_manualFocus = false;
		}

		protected override void OnLostFocus(EventArgs e)
		{
			// We lost the focus
			_manualFocus = false;

			// Remove tracking of any item
			_trackItem = SwitchTrackingItem(_trackItem, -1);

			// No need to remember old focus anymore
			_oldFocus = IntPtr.Zero;

			// When we lose focus we sometimes miss the WM_MOUSELEAVE message
			_mouseOver = false;

			base.OnLostFocus(e);
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			DrawAllCommands(e.Graphics);
			base.OnPaint(e);
		}

		protected override void OnKeyDown(KeyEventArgs e)
		{
			switch(e.KeyCode)
			{
			case Keys.Escape:
				// Is an item being tracked
				if (_trackItem != -1)
				{
					// Is that item also selected
					if (_selected)
					{
						// Is it also showing a submenu
						if (_popupMenu == null)
						{
							// Deselect the item
							_selected = false;
							_drawUpwards = false;

							// Repaint the item
							DrawCommand(_trackItem, true);

							ReturnTheFocus();

							// Key has been processed
							e.Handled = true;
						}
						else
						{
							// The popup menu will swallow the escape
							_ignoreEscapeUp = true;
						}
					}
				}
				break;
			case Keys.Left:
				if (_direction == Direction.Horizontal)
					ProcessMoveLeft(false);

				if (_selected)
					_ignoreMouseMove = true;
				break;
			case Keys.Right:
				if (_direction == Direction.Horizontal)
					ProcessMoveRight(false);
				else
					ProcessMoveDown();

				if (_selected)
					_ignoreMouseMove = true;
				break;
			case Keys.Down:
				if (_direction == Direction.Horizontal)
					ProcessMoveDown();
				else
					ProcessMoveRight(false);
				break;
			case Keys.Up:
				if (_direction == Direction.Vertical)
					ProcessMoveLeft(false);

				break;
			}

			base.OnKeyDown(e);
		}


		protected override void OnKeyUp(KeyEventArgs e)
		{
			switch(e.KeyCode)
			{
				case Keys.Escape:
					if (_manualFocus)
					{
						if (!_selected)
						{
							// Did we see the key down for escape? If not then the 
							// escape must have been used to dismiss a popup menu
							if (!_ignoreEscapeUp)
							{
								// No longer in manual focus mode
								_manualFocus = false;			
								
								// Remove tracking of any item
								_trackItem = SwitchTrackingItem(_trackItem, -1);

								// Send the focus back to origin				
								ReturnTheFocus();
							}
						}
					}
			
					_ignoreEscapeUp = false;

					break;
				default:
					ProcessMnemonicKey((char)e.KeyValue);

					if (_selected)
						_ignoreMouseMove = true;
					break;
			}

			base.OnKeyUp(e);
		}

		protected void ProcessMoveLeft(bool select)
		{
			if (_popupMenu == null)
			{
				int newItem = _trackItem;
				int startItem = newItem;

				for(int i=0; i<_drawCommands.Count; i++)
				{
					// Move to previous item
					newItem--;

					// Have we looped all the way around all choices
					if (newItem == startItem)
						return;

					// Check limits
					if (newItem < 0)
						newItem = _drawCommands.Count - 1;

					DrawCommand dc = _drawCommands[newItem] as DrawCommand;

					// Can we select this item?
					if (!dc.Separator && (dc.Chevron || dc.MenuCommand.Enabled))
					{
						// If a change has occured
						if (newItem != _trackItem)
						{
							// Modify the display of the two items 
							_trackItem = SwitchTrackingItem(_trackItem, newItem);
							
							if (_selected)
							{
								if (dc.Chevron || (dc.MenuCommand.MenuCommands.Count > 0))
									WindowsAPI.PostMessage(this.Handle, WM_OPERATEMENU, 0, 1);
							}

							break;
						}
					}
				}
			}
		}

		protected void ProcessMoveRight(bool select)
		{
			if (_popupMenu == null)
			{
				int newItem = _trackItem;
				int startItem = newItem;

				for(int i=0; i<_drawCommands.Count; i++)
				{
					// Move to previous item
					newItem++;

					// Check limits
					if (newItem >= _drawCommands.Count)
						newItem = 0;

					DrawCommand dc = _drawCommands[newItem] as DrawCommand;

					// Can we select this item?
					if (!dc.Separator && (dc.Chevron || dc.MenuCommand.Enabled))
					{
						// If a change has occured
						if (newItem != _trackItem)
						{
							// Modify the display of the two items 
							_trackItem = SwitchTrackingItem(_trackItem, newItem);

							if (_selected)
							{
								if (dc.Chevron || (dc.MenuCommand.MenuCommands.Count > 0))
									WindowsAPI.PostMessage(this.Handle, WM_OPERATEMENU, 0, 1);
							}

							break;
						}
					}
				}
			}
		}

		protected void ProcessMoveDown()
		{
			if (_popupMenu == null)
			{
				// Are we tracking an item?
				if (_trackItem != -1)
				{
					// The item must not already be selected
					if (!_selected)
					{
						DrawCommand dc = _drawCommands[_trackItem] as DrawCommand;

						// Is there a submenu to show?
						if (dc.Chevron || (dc.MenuCommand.MenuCommands.Count > 0))
						{
							// Select the tracked item
							_selected = true;
							_drawUpwards = false;
										
							// Update display to show as selected
							DrawCommand(_trackItem, true);

							// Show the submenu
							WindowsAPI.PostMessage(this.Handle, WM_OPERATEMENU, 0, 1);
						}
					}
				}
			}
		}

		protected bool ProcessMnemonicKey(char key)
		{
			// We should always gain focus
			if (!_manualFocus)
			{
				// We keep the focus until they move it
				_manualFocus = true;
									
				GrabTheFocus();
			}

			// No current selection
			if (!_selected)
			{
				// Search for an item that matches
				for(int i=0; i<_drawCommands.Count; i++)
				{
					DrawCommand dc = _drawCommands[i] as DrawCommand;

					// Only interested in enabled items
					if ((dc.MenuCommand != null) && dc.MenuCommand.Enabled)
					{
						// Does the character match?
						if (key == dc.Mnemonic)
						{
							// Select the tracked item
							_selected = true;
							_drawUpwards = false;
										
							// Is there a change in tracking?
							if (_trackItem != i)
							{
								// Modify the display of the two items 
								_trackItem = SwitchTrackingItem(_trackItem, i);
							}
							else
							{
								// Update display to show as selected
								DrawCommand(_trackItem, true);
							}

							// Is there a submenu to show?
							if (dc.Chevron || (dc.MenuCommand.MenuCommands.Count > 0))
								WindowsAPI.PostMessage(this.Handle, WM_OPERATEMENU, 0, 1);
							else
							{
								// No, pulse the Click event for the command
								dc.MenuCommand.OnClick(EventArgs.Empty);
							}

							return true;
						}
					}
				}
			}

			return false;
		}

		public bool PreFilterMessage(ref Message msg)
		{
			Form parentForm = this.FindForm();

			// Only interested if the Form we are on is activate (i.e. contains focus)
			if ((parentForm != null) && parentForm.ContainsFocus)
			{		
				switch(msg.Msg)
				{
					case (int)Win32.Msg.WM_MDISETMENU:
					case (int)Win32.Msg.WM_MDIREFRESHMENU:
						return true;
					case (int)Win32.Msg.WM_KEYUP:
						{	
							// Find up/down state of shift and control keys
							ushort shiftKey = WindowsAPI.GetKeyState((int)Win32.VirtualKeys.VK_SHIFT);
							ushort controlKey = WindowsAPI.GetKeyState((int)Win32.VirtualKeys.VK_CONTROL);

							// Basic code we are looking for is the key pressed...
							int code = (int)msg.WParam;

							// ...plus the modifier for SHIFT...
							if (((int)shiftKey & 0x00008000) != 0)
								code += 0x00010000;

							// ...plus the modifier for CONTROL
							if (((int)controlKey & 0x00008000) != 0)
								code += 0x00020000;

							// Construct shortcut from keystate and keychar
							Shortcut sc = (Shortcut)(code);
							
							// Search for a matching command
							return GenerateShortcut(sc, _menuCommands);
						}
					case (int)Win32.Msg.WM_SYSKEYUP:
						if ((int)msg.WParam == (int)Win32.VirtualKeys.VK_MENU)
						{
							// If not already in manual focus mode
							if (!_manualFocus)
							{
								// Are there any menu commands?
								if (_drawCommands.Count > 0)
								{
									// If no item is currently tracked then...
									if (_trackItem == -1)
									{
										// ...start tracking the first valid command
										for(int i=0; i<_drawCommands.Count; i++)
										{
											DrawCommand dc = _drawCommands[i] as DrawCommand;
											
											if (!dc.Separator && (dc.Chevron || dc.MenuCommand.Enabled))
											{
												_trackItem = SwitchTrackingItem(-1, i);
												break;
											}
										}
									}
											
									// We keep the focus until they move it
									_manualFocus = true;
				
									// Grab the focus for key events						
									GrabTheFocus();							
								}

								return true;
							}
						}
						else
						{
							// Construct shortcut from ALT + keychar
							Shortcut sc = (Shortcut)(0x00040000 + (int)msg.WParam);
	
							if (GenerateShortcut(sc, _menuCommands))
								return true;
							
							// Last resort is treat as a potential mnemonic
							return ProcessMnemonicKey((char)msg.WParam);
						}
						break;
					default:
						break;
				}
			}

			return false;
		}

		protected bool GenerateShortcut(Shortcut sc, MenuCommandCollection mcc)
		{
			foreach(MenuCommand mc in mcc)
			{
				// Does the command match?
				if (mc.Enabled && (mc.Shortcut == sc))
				{
					// Generate event for command
					mc.OnClick(EventArgs.Empty);

					return true;
				}
				else
				{
					// Any child items to test?
					if (mc.MenuCommands.Count > 0)
					{
						// Recursive descent of all collections
						if (GenerateShortcut(sc, mc.MenuCommands))
							return true;
					}
				}
			}

			return false;
		}

		protected void OnWM_OPERATEMENU(ref Message m)
		{
			// Is there a valid item being tracted?
			if (_trackItem != -1)
			{
				DrawCommand dc = _drawCommands[_trackItem] as DrawCommand;

				OperateSubMenu(dc, (m.LParam != IntPtr.Zero), (m.WParam != IntPtr.Zero));
			}
		}

		protected void OnWM_GETDLGCODE(ref Message m)
		{
			// We want to the Form to provide all keyboard input to us
			m.Result = (IntPtr)Win32.DialogCodes.DLGC_WANTALLKEYS;
		}

		protected override void WndProc(ref Message m)
		{
			// WM_OPERATEMENU is not a constant and so cannot be in a switch
			if (m.Msg == WM_OPERATEMENU)
				OnWM_OPERATEMENU(ref m);
			else
			{
				switch(m.Msg)
				{
				case (int)Win32.Msg.WM_GETDLGCODE:
					OnWM_GETDLGCODE(ref m);
					return;
				}
			}

			base.WndProc(ref m);
		}
	}
}

⌨️ 快捷键说明

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