123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- using System.ComponentModel;
- namespace System.Windows.Forms
- {
- // In WinForms, ContextMenuStrip must be a descendant of ToolStripDropDown.
- // However in WPF these two classes use different approaches (Popup vs ContextMenu).
- // That's why we use IPopupWrapper which supplies correct implementation.
- public partial class ToolStripDropDown : ToolStrip
- {
- private IPopupWrapper popup;
- private bool isOpened;
- private int closedTicks;
- internal IPopupWrapper Popup => popup ??= InitPopup();
- public new bool Visible => isOpened || (Environment.TickCount - closedTicks) < 300;
- public event CancelEventHandler Opening;
- public event EventHandler Opened;
- public event ToolStripDropDownClosedEventHandler Closed;
- protected virtual void OnOpening(CancelEventArgs e) => Opening?.Invoke(this, e);
- protected virtual void OnOpened(EventArgs e) => Opened?.Invoke(this, e);
- protected virtual void OnClosed(ToolStripDropDownClosedEventArgs e) => Closed?.Invoke(this, e);
- internal virtual IPopupWrapper CreatePopup() => new PopupWrapper(this);
-
- private IPopupWrapper InitPopup()
- {
- var popup = CreatePopup();
- popup.Opened += (s, e) =>
- {
- OnOpened(e);
- isOpened = true;
- };
- popup.Closed += (s, e) =>
- {
- OnClosed(new ToolStripDropDownClosedEventArgs(ToolStripDropDownCloseReason.ItemClicked));
- isOpened = false;
- closedTicks = Environment.TickCount;
- };
- return popup;
- }
- private void OpenPopup()
- {
- if (isOpened)
- {
- Close();
- return;
- }
- Popup.FixupDpi();
- var args = new CancelEventArgs();
- OnOpening(args);
- if (!args.Cancel)
- Popup.IsOpen = true;
- }
- public void Show(int x, int y)
- {
- Popup.Placement = Windows.Controls.Primitives.PlacementMode.Absolute;
- Popup.HorizontalOffset = x / DpiScale;
- Popup.VerticalOffset = y / DpiScale;
- OpenPopup();
- }
- public void Show(System.Drawing.Point screenLocation) => Show(screenLocation.X, screenLocation.Y);
- public void Show(Control control, int x, int y)
- {
- x = (int)(x / control.DpiScale);
- y = (int)(y / control.DpiScale);
- Popup.Placement = Windows.Controls.Primitives.PlacementMode.Relative;
- Popup.PlacementTarget = control.control;
- Popup.HorizontalOffset = control.control.FlowDirection == FlowDirection.RightToLeft ? control.Width / control.DpiScale - x : x;
- Popup.VerticalOffset = y;
- OpenPopup();
- }
- public void Show(Control control, System.Drawing.Point position) => Show(control, position.X, position.Y);
- internal void Show(Control control)
- {
- Popup.Placement = Windows.Controls.Primitives.PlacementMode.Bottom;
- Popup.PlacementTarget = control.control;
- OpenPopup();
- }
- public void Close()
- {
- // do not close not-yet-opened popup. Case: DataColumnDropDown control
- if (isOpened)
- {
- Popup.IsOpen = false;
- isOpened = false;
- }
- }
- // TODO? reason param
- public void Close(ToolStripDropDownCloseReason reason) => Close();
- internal override void AddChild(Control child) => Popup.AddChild(child);
- internal override void RemoveChild(Control child) => Popup.RemoveChild(child);
- internal override void SetChildIndex(Control child, int index) => Popup.SetChildIndex(child, index);
- }
- }
|