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

Fix titlebar color when using backdrop in WPF Window #1122

Merged
merged 1 commit into from
Jun 10, 2024
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
5 changes: 5 additions & 0 deletions src/Wpf.Ui/Appearance/WindowBackgroundManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ WindowBackdropType backdrop
}

_ = WindowBackdrop.ApplyBackdrop(window, backdrop);

if (applicationTheme is ApplicationTheme.Dark)
{
ApplyDarkThemeToWindow(window);
Expand All @@ -109,6 +110,8 @@ WindowBackdropType backdrop
RemoveDarkThemeFromWindow(window);
}

_ = WindowBackdrop.RemoveTitlebarBackground(window);

foreach (object? subWindow in window.OwnedWindows)
{
if (subWindow is Window windowSubWindow)
Expand All @@ -123,6 +126,8 @@ WindowBackdropType backdrop
{
RemoveDarkThemeFromWindow(windowSubWindow);
}

_ = WindowBackdrop.RemoveTitlebarBackground(window);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/Wpf.Ui/Controls/FluentWindow/FluentWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ protected virtual void OnBackdropTypeChanged(WindowBackdropType oldValue, Window
if (WindowBackdrop.IsSupported(newValue) && WindowBackdrop.RemoveBackground(this))
{
_ = WindowBackdrop.ApplyBackdrop(this, newValue);

_ = WindowBackdrop.RemoveTitlebarBackground(this);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,8 @@ protected override ItemRange UpdateItemRange()
int rowCountInCacheBefore = (int)(cacheBeforeInPixel / GetHeight(ChildSize));
int rowCountInCacheAfter =
(
(int)Math.Ceiling(
(int)
Math.Ceiling(
(offsetInPixel + viewportHeight + cacheAfterInPixel) / GetHeight(ChildSize)
)
) - (int)Math.Ceiling((offsetInPixel + viewportHeight) / GetHeight(ChildSize));
Expand Down
38 changes: 36 additions & 2 deletions src/Wpf.Ui/Controls/Window/WindowBackdrop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static bool IsSupported(WindowBackdropType backdropType)
/// <param name="window">The window to which the backdrop effect will be applied.</param>
/// <param name="backdropType">The type of backdrop effect to apply. Determines the visual appearance of the window's backdrop.</param>
/// <returns><see langword="true"/> if the operation was successful; otherwise, <see langword="false"/>.</returns>
public static bool ApplyBackdrop(System.Windows.Window window, WindowBackdropType backdropType)
public static bool ApplyBackdrop(System.Windows.Window? window, WindowBackdropType backdropType)
{
if (window is null)
{
Expand Down Expand Up @@ -216,6 +216,40 @@ public static bool RemoveBackground(System.Windows.Window? window)
return true;
}

public static bool RemoveTitlebarBackground(System.Windows.Window? window)
{
if (window is null)
{
return false;
}

IntPtr windowHandle = new WindowInteropHelper(window).Handle;

if (windowHandle == IntPtr.Zero)
{
return false;
}

HwndSource? windowSource = HwndSource.FromHwnd(windowHandle);

// Remove background from client area
if (windowSource?.Handle != IntPtr.Zero && windowSource?.CompositionTarget != null)
{
// NOTE: https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
// Specifying DWMWA_COLOR_DEFAULT (value 0xFFFFFFFF) for the color will reset the window back to using the system's default behavior for the caption color.
uint titlebarPvAttribute = 0xFFFFFFFE;

Dwmapi.DwmSetWindowAttribute(
windowSource.Handle,
Dwmapi.DWMWINDOWATTRIBUTE.DWMWA_CAPTION_COLOR,
ref titlebarPvAttribute,
Marshal.SizeOf(typeof(uint))
);
}

return true;
}

private static bool ApplyDwmwWindowAttrubute(IntPtr hWnd, Dwmapi.DWMSBT dwmSbt)
{
if (hWnd == IntPtr.Zero)
Expand All @@ -228,7 +262,7 @@ private static bool ApplyDwmwWindowAttrubute(IntPtr hWnd, Dwmapi.DWMSBT dwmSbt)
return false;
}

var backdropPvAttribute = (int)dwmSbt;
int backdropPvAttribute = (int)dwmSbt;

var dwmApiResult = Dwmapi.DwmSetWindowAttribute(
hWnd,
Expand Down
16 changes: 16 additions & 0 deletions src/Wpf.Ui/Interop/Dwmapi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,22 @@ public static extern int DwmSetWindowAttribute(
[In] int cbAttribute
);

/// <summary>
/// Sets the value of Desktop Window Manager (DWM) non-client rendering attributes for a window.
/// </summary>
/// <param name="hWnd">The handle to the window for which the attribute value is to be set.</param>
/// <param name="dwAttribute">A flag describing which value to set, specified as a value of the DWMWINDOWATTRIBUTE enumeration.</param>
/// <param name="pvAttribute">A pointer to an object containing the attribute value to set.</param>
/// <param name="cbAttribute">The size, in bytes, of the attribute value being set via the <c>pvAttribute</c> parameter.</param>
/// <returns>If the function succeeds, it returns <c>S_OK</c>. Otherwise, it returns an <c>HRESULT</c> error code.</returns>
[DllImport(Libraries.Dwmapi)]
public static extern int DwmSetWindowAttribute(
[In] IntPtr hWnd,
[In] DWMWINDOWATTRIBUTE dwAttribute,
[In] ref uint pvAttribute,
[In] int cbAttribute
);

/// <summary>
/// Retrieves the current value of a specified Desktop Window Manager (DWM) attribute applied to a window. For programming guidance, and code examples, see Controlling non-client region rendering.
/// </summary>
Expand Down
4 changes: 1 addition & 3 deletions src/Wpf.Ui/Interop/UnsafeNativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -376,9 +376,7 @@ public static Color GetDwmColor()

return Color.FromArgb(255, values[2], values[1], values[0]);
}
catch
{
}
catch { }
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/Wpf.Ui/Markup/Design.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ public static class Design
/// </summary>
private static bool InDesignMode =>
_inDesignMode ??=
(bool)DependencyPropertyDescriptor
(bool)
DependencyPropertyDescriptor
.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(FrameworkElement))
.Metadata.DefaultValue
|| System.Diagnostics.Process.GetCurrentProcess()
|| System
.Diagnostics.Process.GetCurrentProcess()
.ProcessName.StartsWith(DesignProcessName, StringComparison.Ordinal);

public static readonly DependencyProperty BackgroundProperty = DependencyProperty.RegisterAttached(
Expand Down
17 changes: 8 additions & 9 deletions src/Wpf.Ui/UiApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ public UiApplication(Application application)
_application = application;

System.Diagnostics.Debug.WriteLine(
$"INFO | {typeof(UiApplication)} application is {_application}",
"Wpf.Ui"
$"INFO | {typeof(UiApplication)} application is {_application}",
"Wpf.Ui"
);
}

Expand Down Expand Up @@ -95,14 +95,11 @@ public ResourceDictionary Resources
_resources.MergedDictionaries.Add(themesDictionary);
_resources.MergedDictionaries.Add(controlsDictionary);
}
catch
{
}
catch { }
}

return _application?.Resources ?? _resources;
}

set
{
if (_application is not null)
Expand Down Expand Up @@ -132,8 +129,10 @@ public void Shutdown()

private static bool ApplicationHasResources(Application application)
{
return application.Resources.MergedDictionaries
.Where(e => e.Source is not null)
.Any(e => e.Source.ToString().ToLower().Contains(Appearance.ApplicationThemeManager.LibraryNamespace));
return application
.Resources.MergedDictionaries.Where(e => e.Source is not null)
.Any(e =>
e.Source.ToString().ToLower().Contains(Appearance.ApplicationThemeManager.LibraryNamespace)
);
}
}