我有一個類似於Popup或Menu的控件。我想顯示它,當用戶在框的邊界外單擊時,讓它自己隱藏。我已經使用Mouse.Capture(這個,CaptureMode.SubTree)以及以OnLostMouseCapture的Menu/Popup方式重新獲取捕獲。釋放鼠標捕獲並讓鼠標點擊通過
當用戶單擊控件的邊界外時,我釋放鼠標捕獲在OnPreviewMouseDown。我沒有把電話處理爲真實。鼠標單擊將使其在主UI上的其他控件上,但不會顯示在窗口的關閉按鈕(紅色X)上。它需要2次點擊關閉應用程序。
有沒有辦法告訴WPF重新啓動鼠標點擊或發送重複的鼠標點擊事件?
這是我的代碼。注意我將它重命名爲MainMenuControl - 我沒有構建菜單,所以Menu/MenuItem和Popup不是選項。
public class MainMenuControl : Control
{
static MainMenuControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MainMenuControl), new FrameworkPropertyMetadata(typeof(MainMenuControl)));
}
public MainMenuControl()
{
this.Loaded += new RoutedEventHandler(MainMenuControl_Loaded);
Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(this, OnPreviewMouseDownOutsideCapturedElementHandler);
}
void MainMenuControl_Loaded(object sender, RoutedEventArgs e)
{
this.IsVisibleChanged += new DependencyPropertyChangedEventHandler(MainMenuControl_IsVisibleChanged);
}
void MainMenuControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (this.IsVisible)
{
Mouse.Capture(this, CaptureMode.SubTree);
Debug.WriteLine("Mouse.Capture");
}
}
// I was doing this in OnPreviewMouseDown, but changing to this didn't have any effect
private void OnPreviewMouseDownOutsideCapturedElementHandler(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("OnPreviewMouseDownOutsideCapturedElementHandler");
if (!this.IsMouseInBounds())
{
if (Mouse.Captured == this)
{
Mouse.Capture(this, CaptureMode.None);
Debug.WriteLine("Mouse.Capture released");
}
Debug.WriteLine("Close Menu");
}
}
protected override void OnLostMouseCapture(MouseEventArgs e)
{
base.OnLostMouseCapture(e);
Debug.WriteLine("OnLostMouseCapture");
MainMenuControl reference = e.Source as MainMenuControl;
if (Mouse.Captured != reference)
{
if (e.OriginalSource == reference)
{
if ((Mouse.Captured == null) || (!reference.IsAncestorOf(Mouse.Captured as DependencyObject)))
{
//TODO: Close
Debug.WriteLine("Close Menu");
}
}
// if a child caused use to lose the capture, then recapture.
else if (reference.IsAncestorOf(e.OriginalSource as DependencyObject))
{
if (Mouse.Captured == null)
{
Mouse.Capture(reference, CaptureMode.SubTree);
Debug.WriteLine("Mouse.Capture");
e.Handled = true;
}
}
else
{
//TODO: Close
Debug.WriteLine("Close Menu");
}
}
}
private bool IsMouseInBounds()
{
Point point = Mouse.GetPosition(this);
Rect bounds = new Rect(0, 0, this.Width, this.Height);
return bounds.Contains(point);
}
}
您的建議效果很好。我把它全部放在一個行爲中 - 當在主窗口之外移動時釋放捕獲,並訂閱App.Current.MainWindow.MouseEnter以重新捕獲鼠標。你也是對的,WPF和Windows不共享相同的消息泵 - 我比較了WPF和非WPF菜單行爲,並看到點擊的不同。您的解決方案提供了我想要的正確(非WPF)行爲。謝謝! – 2011-04-24 17:25:52