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: Fix crash when setting the Title or Icon of a borderless window. #2358

Merged
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
56 changes: 40 additions & 16 deletions src/Eto.Wpf/Forms/WpfWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ static class WpfWindow
internal static readonly object Maximizable_Key = new object();
internal static readonly object Closeable_Key = new object();
internal static readonly object Resizable_Key = new object();
internal static readonly object Icon_Key = new object();
}

public abstract class WpfWindow<TControl, TWidget, TCallback> : WpfPanel<TControl, TWidget, TCallback>, Window.IHandler, IWpfWindow, IInputBindingHost
where TControl : sw.Window
where TWidget : Window
where TCallback : Window.ICallback
{
Icon icon;
MenuBar menu;
Eto.Forms.ToolBar toolBar;
swc.DockPanel main;
Expand Down Expand Up @@ -484,13 +484,18 @@ public MenuBar Menu

public Icon Icon
{
get { return icon ?? (icon = Control.Icon.ToEtoIcon()); }
get => Widget.Properties.Get<Icon>(WpfWindow.Icon_Key, () => {
var icon = Control.Icon.ToEtoIcon();
Widget.Properties.Set(WpfWindow.Icon_Key, icon);
return icon;
});
set
{
icon = value;
if (value != null)
if (Widget.Properties.TrySet<Icon>(WpfWindow.Icon_Key, value))
{
Control.Icon = (swm.ImageSource)icon.ControlObject;
var style = SaveWindowStyle();
Control.Icon = (swm.ImageSource)value?.ControlObject;
RestoreWindowStyle(style);
}
}
}
Expand Down Expand Up @@ -697,7 +702,12 @@ public override Size Size
public string Title
{
get { return Control.Title; }
set { Control.Title = value ?? string.Empty; }
set
{
var style = SaveWindowStyle();
Control.Title = value ?? string.Empty;
RestoreWindowStyle(style);
}
}

protected bool LocationSet
Expand Down Expand Up @@ -886,10 +896,11 @@ public WindowStyle WindowStyle
}
}

void SetWindowChrome(bool enabled)
uint? SaveWindowStyle()
{
if (!isSourceInitialized)
return;
return null;

// Annoyingly, WPF gets an AritheticOverflow if the window style has WS_POPUP in it as it treats it as an int
// So, we remove that style then re-apply it after.
uint? oldStyle = null;
Expand All @@ -900,6 +911,26 @@ void SetWindowChrome(bool enabled)
oldStyle = style & (uint)(0x80000000);
Win32.SetWindowLong(NativeHandle, Win32.GWL.STYLE, style & 0x7FFFFFFF);
}
return oldStyle;
}

void RestoreWindowStyle(uint? oldStyle)
{
if (oldStyle == null)
return;

// reapply the old style bit
var style = Win32.GetWindowLong(NativeHandle, Win32.GWL.STYLE);
style |= oldStyle.Value;
Win32.SetWindowLong(NativeHandle, Win32.GWL.STYLE, style);
}

void SetWindowChrome(bool enabled)
{
if (!isSourceInitialized)
return;
var oldStyle = SaveWindowStyle();

if (enabled)
{
var windowChrome = new sw.Shell.WindowChrome
Expand All @@ -913,14 +944,7 @@ void SetWindowChrome(bool enabled)
{
Control.ClearValue(sw.Shell.WindowChrome.WindowChromeProperty);
}

if (oldStyle != null)
{
// reapply the old style bit
style = Win32.GetWindowLong(NativeHandle, Win32.GWL.STYLE);
style |= oldStyle.Value;
Win32.SetWindowLong(NativeHandle, Win32.GWL.STYLE, style);
}
RestoreWindowStyle(oldStyle);
}

public void BringToFront()
Expand Down