Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wpf/WinForms: Fix more window active issues. #2135

Merged
merged 2 commits into from
Feb 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Eto.WinForms/Forms/DialogHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ public Button DefaultButton
public void ShowModal()
{
ReloadButtons();
var owner = Widget.Owner;
if (owner != null && !owner.HasFocus)
owner.Focus();

Control.ShowDialog();
Control.Owner = null; // without this, the dialog is still active as part of the owner form
Expand Down
6 changes: 6 additions & 0 deletions src/Eto.WinForms/Forms/FormHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ protected override void Initialize()
Resizable = true;
}

internal override void InternalClosing()
{
base.InternalClosing();
SetOwner(null);
}

public void Show()
{
Control.Show();
Expand Down
23 changes: 4 additions & 19 deletions src/Eto.WinForms/Forms/HwndFormHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -442,35 +442,20 @@ public void Invalidate(Eto.Drawing.Rectangle rect, bool invalidateChildren)

public void SuspendLayout()
{
throw new NotImplementedException();
}

public void ResumeLayout()
{
throw new NotImplementedException();
}

public void Focus()
{
throw new NotImplementedException();
}
public void Focus() => Win32.SetActiveWindow(Control);

public bool HasFocus
{
get { throw new NotImplementedException(); }
}
public bool HasFocus => Win32.GetActiveWindow() == Control;

public bool Visible
{
get
{
return Win32.IsWindowVisible(Control);
}
set
{
Win32.ShowWindow(Control, value ? Win32.SW.SHOWNA : Win32.SW.HIDE);
}

get => Win32.IsWindowVisible(Control);
set => Win32.ShowWindow(Control, value ? Win32.SW.SHOWNA : Win32.SW.HIDE);
}

public void OnPreLoad(EventArgs e)
Expand Down
61 changes: 41 additions & 20 deletions src/Eto.WinForms/Forms/WindowHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public interface IWindowHandler
public class WindowHandler : Window.IWindowHandler
{
internal static readonly object MovableByWindowBackground_Key = new object();
internal static readonly object IsClosing_Key = new object();

public Window FromPoint(PointF point)
{
Expand Down Expand Up @@ -246,21 +247,7 @@ public override void AttachEvent(string id)
Control.FormClosed += (sender, e) => Callback.OnClosed(Widget, EventArgs.Empty);
break;
case Window.ClosingEvent:
Control.FormClosing += delegate(object sender, swf.FormClosingEventArgs e)
{
var args = new CancelEventArgs(e.Cancel);
Callback.OnClosing(Widget, args);

if (!e.Cancel && swf.Application.OpenForms.Count <= 1
|| e.CloseReason == swf.CloseReason.ApplicationExitCall
|| e.CloseReason == swf.CloseReason.WindowsShutDown)
{
var app = ((ApplicationHandler)Application.Instance.Handler);
app.Callback.OnTerminating(app.Widget, args);
}

e.Cancel = args.Cancel;
};
Control.FormClosing += Control_FormClosing;
break;
case Eto.Forms.Control.ShownEvent:
Control.Shown += delegate
Expand All @@ -275,10 +262,7 @@ public override void AttachEvent(string id)
};
break;
case Eto.Forms.Control.LostFocusEvent:
Control.Deactivate += delegate
{
Callback.OnLostFocus(Widget, EventArgs.Empty);
};
Control.Deactivate += (sender, e) => Application.Instance.AsyncInvoke(() => Callback.OnLostFocus(Widget, EventArgs.Empty));
break;
case Window.WindowStateChangedEvent:
var oldState = Control.WindowState;
Expand All @@ -300,6 +284,39 @@ public override void AttachEvent(string id)
}
}

bool IsClosing
{
get => Widget.Properties.Get<bool>(WindowHandler.IsClosing_Key);
set => Widget.Properties.Set(WindowHandler.IsClosing_Key, value);
}

private void Control_FormClosing(object sender, swf.FormClosingEventArgs e)
{
IsClosing = true;
var args = new CancelEventArgs(e.Cancel);
Callback.OnClosing(Widget, args);

if (!e.Cancel && swf.Application.OpenForms.Count <= 1
|| e.CloseReason == swf.CloseReason.ApplicationExitCall
|| e.CloseReason == swf.CloseReason.WindowsShutDown)
{
var app = ((ApplicationHandler)Application.Instance.Handler);
app.Callback.OnTerminating(app.Widget, args);
}

e.Cancel = args.Cancel;
IsClosing = !e.Cancel;

if (!e.Cancel)
{
InternalClosing();
}
}

internal virtual void InternalClosing()
{
}

public MenuBar Menu
{
get
Expand Down Expand Up @@ -389,7 +406,11 @@ public Eto.Forms.ToolBar ToolBar
}
}

public void Close() => Control.Close();
public void Close()
{
if (!IsClosing)
Control.Close();
}

public Icon Icon
{
Expand Down
6 changes: 6 additions & 0 deletions src/Eto.WinForms/Win32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,12 @@ public static MouseButtons GetMouseButtonWParam(IntPtr wParam)
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ShowWindow(IntPtr hWnd, SW nCmdShow);

[DllImport("user32.dll")]
public static extern IntPtr GetActiveWindow();

[DllImport("user32.dll")]
public static extern IntPtr SetActiveWindow(IntPtr hWnd);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
Expand Down
141 changes: 74 additions & 67 deletions src/Eto.Wpf/Forms/DialogHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ public class DialogHandler : WpfWindow<sw.Window, Dialog, Dialog.ICallback>, Dia
{
Button defaultButton;
Rectangle? parentWindowBounds;
swc.DockPanel dockMain;
swc.Grid gridButtons;
swc.DockPanel dockMain;
swc.Grid gridButtons;

public DialogHandler() : this(new sw.Window()) { }

Expand All @@ -34,35 +34,42 @@ public DialogHandler(sw.Window window)
gridButtons.Margin = new sw.Thickness();
}

public override void SetContainerContent(sw.FrameworkElement content)
{
this.content.Children.Add(dockMain);
swc.DockPanel.SetDock(gridButtons, swc.Dock.Bottom);
dockMain.Children.Add(gridButtons);
dockMain.Children.Add(content);
}
public override void SetContainerContent(sw.FrameworkElement content)
{
this.content.Children.Add(dockMain);
swc.DockPanel.SetDock(gridButtons, swc.Dock.Bottom);
dockMain.Children.Add(gridButtons);
dockMain.Children.Add(content);
}

public DialogDisplayMode DisplayMode { get; set; }
public DialogDisplayMode DisplayMode { get; set; }

public void ShowModal()
{
ReloadButtons();
ReloadButtons();

var owner = Widget.Owner;

if (LocationSet)
{
Control.WindowStartupLocation = sw.WindowStartupLocation.Manual;
}
else if (Widget.Owner != null)
else if (owner != null)
{
// CenterOwner does not work in certain cases (e.g. with autosizing)
Control.WindowStartupLocation = sw.WindowStartupLocation.Manual;
parentWindowBounds = Widget.Owner.Bounds;
parentWindowBounds = owner.Bounds;
Control.Loaded += HandleLoaded;
}

// if the owner doesn't have focus, windows changes the owner's z-order after the dialog closes.
if (owner != null && !owner.HasFocus)
owner.Focus();

Control.ShowDialog();
WpfFrameworkElementHelper.ShouldCaptureMouse = false;

ClearButtons();
ClearButtons();
}

void Control_PreviewKeyDown(object sender, sw.Input.KeyEventArgs e)
Expand Down Expand Up @@ -99,59 +106,59 @@ void HandleLoaded(object sender, EventArgs e)
}

private void ClearButtons()
{
gridButtons.ColumnDefinitions.Clear();
gridButtons.Children.Clear();
}

private void ReloadButtons()
{
gridButtons.ColumnDefinitions.Add(new swc.ColumnDefinition { Width = new sw.GridLength(100, sw.GridUnitType.Star) });
var negativeButtons = Widget.NegativeButtons;
var positiveButtons = Widget.PositiveButtons;
var hasButtons = negativeButtons.Count + positiveButtons.Count > 0;

for (int i = positiveButtons.Count - 1; i >= 0; i--)
AddButton(positiveButtons.Count - i, positiveButtons[i]);

for (int i = 0;i < negativeButtons.Count;i++)
AddButton(positiveButtons.Count + 1 + i, negativeButtons[i]);
gridButtons.Visibility = hasButtons ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden;
gridButtons.Margin = new sw.Thickness(hasButtons ? 8 : 0);
}

private void AddButton(int pos, Button button)
{
var native = button.ToNative();
native.Margin = new sw.Thickness(6, 0, 0, 0);

swc.Grid.SetColumn(native, pos);

gridButtons.ColumnDefinitions.Add(new swc.ColumnDefinition { Width = new sw.GridLength(1, sw.GridUnitType.Auto) });
gridButtons.Children.Add(native);
}

public void InsertDialogButton(bool positive, int index, Button item)
{
if(Widget.Visible)
{
ClearButtons();
ReloadButtons();
}
}

public void RemoveDialogButton(bool positive, int index, Button item)
{
if (Widget.Visible)
{
ClearButtons();
ReloadButtons();
}
}

public Button DefaultButton
{
gridButtons.ColumnDefinitions.Clear();
gridButtons.Children.Clear();
}

private void ReloadButtons()
{
gridButtons.ColumnDefinitions.Add(new swc.ColumnDefinition { Width = new sw.GridLength(100, sw.GridUnitType.Star) });

var negativeButtons = Widget.NegativeButtons;
var positiveButtons = Widget.PositiveButtons;
var hasButtons = negativeButtons.Count + positiveButtons.Count > 0;

for (int i = positiveButtons.Count - 1; i >= 0; i--)
AddButton(positiveButtons.Count - i, positiveButtons[i]);

for (int i = 0; i < negativeButtons.Count; i++)
AddButton(positiveButtons.Count + 1 + i, negativeButtons[i]);

gridButtons.Visibility = hasButtons ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden;
gridButtons.Margin = new sw.Thickness(hasButtons ? 8 : 0);
}

private void AddButton(int pos, Button button)
{
var native = button.ToNative();
native.Margin = new sw.Thickness(6, 0, 0, 0);

swc.Grid.SetColumn(native, pos);

gridButtons.ColumnDefinitions.Add(new swc.ColumnDefinition { Width = new sw.GridLength(1, sw.GridUnitType.Auto) });
gridButtons.Children.Add(native);
}

public void InsertDialogButton(bool positive, int index, Button item)
{
if (Widget.Visible)
{
ClearButtons();
ReloadButtons();
}
}

public void RemoveDialogButton(bool positive, int index, Button item)
{
if (Widget.Visible)
{
ClearButtons();
ReloadButtons();
}
}

public Button DefaultButton
{
get { return defaultButton; }
set
Expand Down
3 changes: 1 addition & 2 deletions src/Eto.Wpf/Forms/FormHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,10 @@ public virtual void Show()
WpfFrameworkElementHelper.ShouldCaptureMouse = false;
}

protected override void InternalClose()
protected override void InternalClosing()
{
// Clear owner so WPF doesn't change the z-order of the parent when closing
SetOwner(null);
Control.Close();
}

public bool ShowActivated
Expand Down
10 changes: 8 additions & 2 deletions src/Eto.Wpf/Forms/WpfWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ private void Control_Closing(object sender, CancelEventArgs e)
e.Cancel = args.Cancel;
IsApplicationClosing = !e.Cancel && willShutDown;
IsClosing = !e.Cancel;
if (!e.Cancel)
{
InternalClosing();
}
}

float LastPixelSize
Expand Down Expand Up @@ -403,7 +407,9 @@ public Eto.Forms.ToolBar ToolBar
}
}

protected virtual void InternalClose() => Control.Close();
protected virtual void InternalClosing()
{
}

public void Close()
{
Expand All @@ -412,7 +418,7 @@ public void Close()
// prevent crash if we call this more than once..
if (!IsClosing)
{
InternalClose();
Control.Close();
}
}
else
Expand Down
Loading