팝업 또는 메뉴와 유사한 컨트롤이 있습니다. 그것을 표시하고 사용자가 상자 경계를 클릭하면 숨길 수 있습니다. 나는 Mouse.Capture (this, CaptureMode.SubTree)를 사용하고 Menu/Popup이 OnLostMouseCapture에서와 같은 방식으로 캡처를 다시 획득했습니다.마우스 캡쳐 해제 및 마우스 클릭 통과
사용자가 컨트롤 경계를 클릭하면 OnPreviewMouseDown에서 마우스 캡처를 해제합니다. 나는 e.Handled를 true로 설정하지 않았습니다. 마우스를 클릭하면 기본 UI의 다른 컨트롤로 이동하지만 윈도우의 닫기 버튼 (빨간색 X)은 클릭하지 않습니다. 앱을 닫으려면 2 번 클릭해야합니다.
WPF에 마우스 클릭을 다시 시작하거나 반복 된 마우스 클릭 이벤트를 보내도록 지시하는 방법이 있습니까?
여기 내 코드가 있습니다. 참고 MainMenuControl으로 이름을 변경했습니다. Menu를 작성하지 않으므로 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가 아닌) 올바른 동작을 제공합니다. 감사! –