问题
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