forked from AvaloniaUI/Avalonia
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adjust icon sizes to account for requested DPI (AvaloniaUI#14564)
Refresh icons when window DPI changes Provide ICON_SMALL icons Fixed Win32Icon.Size being incorrect when the exact size couldn't be found in the icon
- Loading branch information
1 parent
acb91d9
commit cca8914
Showing
9 changed files
with
373 additions
and
120 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,88 @@ | ||
using System; | ||
using System.Drawing; | ||
using System.IO; | ||
using Avalonia.Platform; | ||
using Avalonia.Win32.Interop; | ||
|
||
namespace Avalonia.Win32 | ||
{ | ||
class IconImpl : IWindowIconImpl | ||
internal class IconImpl : IWindowIconImpl, IDisposable | ||
{ | ||
private readonly Win32Icon _icon; | ||
private readonly byte[] _iconData; | ||
private readonly Win32Icon _smallIcon; | ||
private readonly Win32Icon _bigIcon; | ||
|
||
public IconImpl(Win32Icon icon, byte[] iconData) | ||
private static readonly int s_taskbarIconSize = Win32Platform.WindowsVersion < PlatformConstants.Windows10 ? 32 : 24; | ||
|
||
public IconImpl(Stream smallIcon, Stream bigIcon) | ||
{ | ||
_smallIcon = CreateIconImpl(smallIcon); | ||
_bigIcon = CreateIconImpl(bigIcon); | ||
} | ||
|
||
public IconImpl(Stream icon) | ||
{ | ||
_smallIcon = _bigIcon = CreateIconImpl(icon); | ||
} | ||
|
||
private static Win32Icon CreateIconImpl(Stream stream) | ||
{ | ||
if (stream.CanSeek) | ||
{ | ||
stream.Position = 0; | ||
} | ||
|
||
if (stream is MemoryStream memoryStream) | ||
{ | ||
var iconData = memoryStream.ToArray(); | ||
|
||
return new Win32Icon(iconData); | ||
} | ||
else | ||
{ | ||
using var ms = new MemoryStream(); | ||
stream.CopyTo(ms); | ||
|
||
ms.Position = 0; | ||
|
||
var iconData = ms.ToArray(); | ||
|
||
return new Win32Icon(iconData); | ||
} | ||
} | ||
|
||
// GetSystemMetrics returns values scaled for the primary monitor, as of the time at which the process started. | ||
// This is no good for a per-monitor DPI aware application. GetSystemMetricsForDpi would solve the problem, | ||
// but is only available in Windows 10 version 1607 and later. So instead, we just hard-code the 96dpi icon sizes. | ||
|
||
public Win32Icon LoadSmallIcon(double scaleFactor) => new(_smallIcon, GetScaledSize(16, scaleFactor)); | ||
|
||
public Win32Icon LoadBigIcon(double scaleFactor) | ||
{ | ||
var targetSize = GetScaledSize(s_taskbarIconSize, scaleFactor); | ||
var icon = new Win32Icon(_bigIcon, targetSize); | ||
|
||
// The exact size of a taskbar icon in Windows 10 and later is 24px @ 96dpi. But if an ICO file doesn't have | ||
// that size, 16px can be selected instead. If this happens, fall back to a 32 pixel icon. Windows will downscale it. | ||
if (s_taskbarIconSize == 24 && icon.Size.Width < targetSize.Width) | ||
{ | ||
icon.Dispose(); | ||
icon = new(_bigIcon, GetScaledSize(32, scaleFactor)); | ||
} | ||
|
||
return icon; | ||
} | ||
|
||
private static PixelSize GetScaledSize(int baseSize, double factor) | ||
{ | ||
_icon = icon; | ||
_iconData = iconData; | ||
var scaled = (int)Math.Ceiling(baseSize * factor); | ||
return new(scaled, scaled); | ||
} | ||
|
||
public IntPtr HIcon => _icon.Handle; | ||
public void Save(Stream outputStream) => _bigIcon.CopyTo(outputStream); | ||
|
||
public void Save(Stream outputStream) | ||
public void Dispose() | ||
{ | ||
outputStream.Write(_iconData, 0, _iconData.Length); | ||
_smallIcon.Dispose(); | ||
_bigIcon.Dispose(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.