问题
I have 2 windows. Lets call them A and B. A is opening B with a ShowDialog(). So I am opening B - When the user minimizes B or gets it into the back somehow and he tries clicking window A again its blocked (as it should be), but is there an Event that I can catch up onto when this happens ?
I am trying to achieve bringing the blocking window B into the front when hes trying to access window A with window B opened.
Codeexample:
Thats how Window A is opened from the Mainwindow
WindowA windowA = new WindowA();
windowA.Owner = Application.Current.MainWindow;
windowA.Show();
windowA.Activate();
And thats how Window B is opened
WindowB windowB = new WindowB();
windowB.Owner = this; //(this = windowA)
windowB.ShowDialog();
Both windows have no special properties set except
WindowStartupLocation="CenterScreen"
回答1:
If you want to restore second window when it is minimized and user does click on first(blocked) window, then you can go this way(add this code to the WindowB
):
public WindowB()
{
PreviewMouseDown += WindowB_PreviewMouseDown;
StateChanged += WindowB_StateChanged;
InitializeComponent();
LostMouseCapture += WindowB_LostMouseCapture;
}
private void WindowB_LostMouseCapture(object sender, MouseEventArgs e)
{
//You can also evaluate here a mouse coordinates.
if (WindowState == WindowState.Minimized)
{
e.Handled = true;
CaptureMouse();
}
}
private void WindowB_StateChanged(object sender, EventArgs e)
{
if (WindowState== WindowState.Minimized)
{
CaptureMouse();
}
else
{
ReleaseMouseCapture();
}
}
private void WindowB_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
WindowState = WindowState.Normal;
Debug.WriteLine("WindowB PreviewMouseDown");
}
So you have to start mouse capturing on second window on it being minimized, for if user does click on WindowA
this can be handled on WindowB
.
As window being minimized it going to lost a mouse capture(therefore you have to listen on LostMouseCapture
), that you have to prevent.
Left mouse button down on WindowA
does restore thenWindowB
.
回答2:
There is no managed event being raised when you click outside of a modal window but you should be able to handle this in the modal window using some p/invoke. Here is an example for you:
public sealed partial class ModalWindow : Window, IDisposable
{
[DllImport("User32.dll")]
public static extern IntPtr SetWindowsHookEx(int idHook, HookDelegate lpfn, IntPtr hmod, int dwThreadId);
[DllImport("User32.dll")]
public static extern IntPtr CallNextHookEx(IntPtr hHook, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll")]
public static extern IntPtr UnhookWindowsHookEx(IntPtr hHook);
[DllImport("user32.dll")]
public static extern bool GetCursorPos(out POINT lpPoint);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public static implicit operator Point(POINT point)
{
return new Point(point.X, point.Y);
}
}
public delegate IntPtr HookDelegate(int code, IntPtr wParam, IntPtr lParam);
private const int WH_MOUSE_LL = 14;
private const int WM_LBUTTONDOWN = 0x0201;
private HookDelegate mouseDelegate;
private IntPtr mouseHandle;
public ModalWindow()
{
InitializeComponent();
mouseDelegate = MouseHookDelegate;
mouseHandle = SetWindowsHookEx(WH_MOUSE_LL, mouseDelegate, IntPtr.Zero, 0);
}
private IntPtr MouseHookDelegate(int code, IntPtr wParam, IntPtr lParam)
{
if (code < 0)
return CallNextHookEx(mouseHandle, code, wParam, lParam);
switch ((int)wParam)
{
case WM_LBUTTONDOWN:
POINT lpPoint;
GetCursorPos(out lpPoint);
if (lpPoint.X < Left || lpPoint.X > (Left + Width) || lpPoint.Y < Top || lpPoint.Y > (Top + Height))
{
//Outside click detected...
}
break;
}
return CallNextHookEx(mouseHandle, code, wParam, lParam);
}
protected override void OnClosed(EventArgs e)
{
Dispose();
base.OnClosed(e);
}
public void Dispose()
{
if (mouseHandle != IntPtr.Zero)
UnhookWindowsHookEx(mouseHandle);
}
}
来源:https://stackoverflow.com/questions/55948944/is-there-an-event-or-something-i-can-use-when-a-showdialogwindow-is-blocking-the