feat: add modern app icon

This commit is contained in:
2026-07-21 10:36:02 +09:00
parent d9b477e543
commit 5ccf8b8ffd
16 changed files with 138 additions and 0 deletions

BIN
Assets/AppIcon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
Assets/AppIconMaster.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 432 B

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 456 B

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -18,6 +18,7 @@
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
<ApplicationManifest>app.manifest</ApplicationManifest>
<ApplicationIcon>..\..\Assets\AppIcon.ico</ApplicationIcon>
<PublishTrimmed>false</PublishTrimmed>
<PublishReadyToRun>false</PublishReadyToRun>
<ApplicationDisplayVersion>0.1.0</ApplicationDisplayVersion>
@@ -75,10 +76,18 @@
<Compile Include="..\..\LegacySceneRuntimeFactory.cs"
Link="Runtime\LegacySceneRuntimeFactory.cs" />
<Content Include="..\..\Assets\LockScreenLogo.scale-200.png" Link="Assets\LockScreenLogo.scale-200.png" />
<Content Include="..\..\Assets\AppIcon.ico" Link="Assets\AppIcon.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="..\..\Assets\SplashScreen.scale-200.png" Link="Assets\SplashScreen.scale-200.png" />
<Content Include="..\..\Assets\Square150x150Logo.scale-200.png" Link="Assets\Square150x150Logo.scale-200.png" />
<Content Include="..\..\Assets\Square44x44Logo.scale-200.png" Link="Assets\Square44x44Logo.scale-200.png" />
<Content Include="..\..\Assets\Square44x44Logo.targetsize-16_altform-unplated.png" Link="Assets\Square44x44Logo.targetsize-16_altform-unplated.png" />
<Content Include="..\..\Assets\Square44x44Logo.targetsize-24_altform-unplated.png" Link="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="..\..\Assets\Square44x44Logo.targetsize-32_altform-unplated.png" Link="Assets\Square44x44Logo.targetsize-32_altform-unplated.png" />
<Content Include="..\..\Assets\Square44x44Logo.targetsize-48_altform-unplated.png" Link="Assets\Square44x44Logo.targetsize-48_altform-unplated.png" />
<Content Include="..\..\Assets\Square44x44Logo.targetsize-256_altform-unplated.png" Link="Assets\Square44x44Logo.targetsize-256_altform-unplated.png" />
<Content Include="..\..\Assets\StoreLogo.png" Link="Assets\StoreLogo.png" />
<Content Include="..\..\Assets\Wide310x150Logo.scale-200.png" Link="Assets\Wide310x150Logo.scale-200.png" />
<Content Include="Web\**\*">

View File

@@ -257,6 +257,11 @@ public sealed partial class MainWindow : Window
var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(windowHandle);
var appWindow = AppWindow.GetFromWindowId(windowId);
appWindow.Title = "V-Stock 증권정보송출시스템 for 매일경제TV (26.03.26)";
var iconPath = Path.Combine(AppContext.BaseDirectory, "Assets", "AppIcon.ico");
if (File.Exists(iconPath))
{
appWindow.SetIcon(iconPath);
}
if (appWindow.Presenter is OverlappedPresenter presenter)
{

View File

@@ -0,0 +1,124 @@
using System.Buffers.Binary;
namespace MBN_STOCK_WEBVIEW.LegacyWeb.Tests;
public sealed class LegacyAppIconContractTests
{
private static readonly string RepositoryRoot = FindRepositoryRoot();
private static readonly string AssetsRoot = Path.Combine(RepositoryRoot, "Assets");
private static readonly string AppRoot = Path.Combine(
RepositoryRoot,
"src",
"MBN_STOCK_WEBVIEW.LegacyParityApp");
public static TheoryData<string, int, int> PackagePngAssets => new()
{
{ "LockScreenLogo.scale-200.png", 48, 48 },
{ "SplashScreen.scale-200.png", 1240, 600 },
{ "Square150x150Logo.scale-200.png", 300, 300 },
{ "Square44x44Logo.scale-200.png", 88, 88 },
{ "Square44x44Logo.targetsize-16_altform-unplated.png", 16, 16 },
{ "Square44x44Logo.targetsize-24_altform-unplated.png", 24, 24 },
{ "Square44x44Logo.targetsize-32_altform-unplated.png", 32, 32 },
{ "Square44x44Logo.targetsize-48_altform-unplated.png", 48, 48 },
{ "Square44x44Logo.targetsize-256_altform-unplated.png", 256, 256 },
{ "StoreLogo.png", 50, 50 },
{ "Wide310x150Logo.scale-200.png", 620, 300 }
};
[Theory]
[MemberData(nameof(PackagePngAssets))]
public void PackageIconsAreExactRgbaPngAssets(string fileName, int width, int height)
{
var bytes = File.ReadAllBytes(Path.Combine(AssetsRoot, fileName));
Assert.True(
bytes.Length > Math.Max(500, (width * height) / 10),
$"{fileName} still resembles an unrendered placeholder asset.");
Assert.Equal(new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 }, bytes[..8]);
Assert.Equal("IHDR", System.Text.Encoding.ASCII.GetString(bytes, 12, 4));
Assert.Equal(width, BinaryPrimitives.ReadInt32BigEndian(bytes.AsSpan(16, 4)));
Assert.Equal(height, BinaryPrimitives.ReadInt32BigEndian(bytes.AsSpan(20, 4)));
Assert.Equal(8, bytes[24]);
Assert.Equal(6, bytes[25]);
}
[Fact]
public void ExecutableIconContainsEveryRequiredWindowsSize()
{
var bytes = File.ReadAllBytes(Path.Combine(AssetsRoot, "AppIcon.ico"));
Assert.True(bytes.Length > 1000);
Assert.Equal((ushort)0, BinaryPrimitives.ReadUInt16LittleEndian(bytes.AsSpan(0, 2)));
Assert.Equal((ushort)1, BinaryPrimitives.ReadUInt16LittleEndian(bytes.AsSpan(2, 2)));
var count = BinaryPrimitives.ReadUInt16LittleEndian(bytes.AsSpan(4, 2));
Assert.Equal(6, count);
var sizes = new List<int>();
for (var index = 0; index < count; index++)
{
var width = bytes[6 + (index * 16)];
var height = bytes[7 + (index * 16)];
Assert.Equal(width, height);
sizes.Add(width == 0 ? 256 : width);
}
Assert.Equal(new[] { 16, 24, 32, 48, 64, 256 }, sizes.Order());
}
[Fact]
public void ProjectAndWindowUseTheSharedIconWithoutPackagingTheMasterArtwork()
{
var project = File.ReadAllText(Path.Combine(
AppRoot,
"MBN_STOCK_WEBVIEW.LegacyParityApp.csproj"));
var window = File.ReadAllText(Path.Combine(AppRoot, "MainWindow.xaml.cs"));
var manifest = File.ReadAllText(Path.Combine(AppRoot, "Package.appxmanifest"));
Assert.Contains("<ApplicationIcon>..\\..\\Assets\\AppIcon.ico</ApplicationIcon>",
project,
StringComparison.Ordinal);
Assert.Contains("Link=\"Assets\\AppIcon.ico\"", project, StringComparison.Ordinal);
foreach (var targetSize in new[] { 16, 24, 32, 48, 256 })
{
Assert.Contains(
$"Square44x44Logo.targetsize-{targetSize}_altform-unplated.png",
project,
StringComparison.Ordinal);
}
Assert.DoesNotContain("AppIconMaster.png", project, StringComparison.Ordinal);
Assert.Contains(
"Path.Combine(AppContext.BaseDirectory, \"Assets\", \"AppIcon.ico\")",
window,
StringComparison.Ordinal);
Assert.Contains("appWindow.SetIcon(iconPath)", window, StringComparison.Ordinal);
Assert.Contains("Square150x150Logo=\"Assets\\Square150x150Logo.png\"",
manifest,
StringComparison.Ordinal);
Assert.Contains("Square44x44Logo=\"Assets\\Square44x44Logo.png\"",
manifest,
StringComparison.Ordinal);
Assert.Contains("Wide310x150Logo=\"Assets\\Wide310x150Logo.png\"",
manifest,
StringComparison.Ordinal);
Assert.Contains("<uap:SplashScreen Image=\"Assets\\SplashScreen.png\" />",
manifest,
StringComparison.Ordinal);
}
private static string FindRepositoryRoot()
{
var directory = new DirectoryInfo(AppContext.BaseDirectory);
while (directory is not null)
{
if (File.Exists(Path.Combine(directory.FullName, "MBN_STOCK_WEBVIEW.sln")))
{
return directory.FullName;
}
directory = directory.Parent;
}
throw new DirectoryNotFoundException("Repository root could not be located.");
}
}