|
8 | 8 | using Serilog; |
9 | 9 | using Serilog.Events; |
10 | 10 | using Serilog.Sinks.SystemConsole.Themes; |
| 11 | +using System.Drawing; |
11 | 12 | using System.Extensions.Core; |
| 13 | +using System.Reflection; |
12 | 14 | using System.Runtime.InteropServices; |
13 | 15 |
|
14 | 16 | namespace Daybreak.Launch; |
15 | 17 |
|
16 | 18 | public partial class Launcher |
17 | 19 | { |
| 20 | + private const string IconResourceName = "Daybreak.Daybreak.ico"; |
| 21 | + |
18 | 22 | public const string OutputTemplate = "[{Timestamp:yyyy-MM-dd HH:mm:ss}] {Level:u4}: [{EnvironmentName}] [{ThreadId}:{ThreadName}] [{SourceContext}]{NewLine}{Message:lj}{NewLine}{Exception}"; |
19 | 23 |
|
20 | 24 | private static nint OriginalWndProc; |
21 | 25 | private static NativeMethods.WndProcDelegate? WndProcDelegate; |
| 26 | + private static Icon? WindowIcon; |
22 | 27 |
|
23 | 28 | public static void SetupLogging(IServiceCollection services) |
24 | 29 | { |
@@ -130,6 +135,49 @@ private static void SetupBorderless(PhotinoBlazorApp app) |
130 | 135 | 0x0001 | 0x0002 | 0x0004 | 0x0020); // SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED |
131 | 136 | } |
132 | 137 |
|
| 138 | + private static void SetupWindowIcon(PhotinoBlazorApp app) |
| 139 | + { |
| 140 | + var hwnd = app.MainWindow.WindowHandle; |
| 141 | + if (hwnd == IntPtr.Zero) |
| 142 | + { |
| 143 | + return; |
| 144 | + } |
| 145 | + |
| 146 | + var scopedLogger = app.Services.GetRequiredService<ILogger<Launcher>>().CreateScopedLogger(); |
| 147 | + try |
| 148 | + { |
| 149 | + var assembly = Assembly.GetExecutingAssembly(); |
| 150 | + if (assembly.GetManifestResourceInfo(IconResourceName) is not ManifestResourceInfo info) |
| 151 | + { |
| 152 | + scopedLogger.LogWarning("Icon resource '{IconResourceName}' not found in assembly.", IconResourceName); |
| 153 | + return; |
| 154 | + } |
| 155 | + |
| 156 | + var embeddedIconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(IconResourceName); |
| 157 | + if (embeddedIconStream is null) |
| 158 | + { |
| 159 | + scopedLogger.LogWarning("Icon resource '{IconResourceName}' stream is null.", IconResourceName); |
| 160 | + return; |
| 161 | + } |
| 162 | + |
| 163 | + WindowIcon = new Icon(embeddedIconStream); |
| 164 | + var hIcon = WindowIcon.Handle; |
| 165 | + if (hIcon is 0) |
| 166 | + { |
| 167 | + scopedLogger.LogWarning("Failed to get handle for window icon."); |
| 168 | + return; |
| 169 | + } |
| 170 | + |
| 171 | + NativeMethods.SendMessage(hwnd, NativeMethods.WM_SETICON, NativeMethods.ICON_BIG, hIcon); |
| 172 | + NativeMethods.SendMessage(hwnd, NativeMethods.WM_SETICON, NativeMethods.ICON_SMALL, hIcon); |
| 173 | + scopedLogger.LogDebug("Window icon set successfully."); |
| 174 | + } |
| 175 | + catch(Exception ex) |
| 176 | + { |
| 177 | + scopedLogger.LogError(ex, "Failed to set window icon."); |
| 178 | + } |
| 179 | + } |
| 180 | + |
133 | 181 | private static nint WndProc(nint hwnd, uint msg, nint wParam, nint lParam) |
134 | 182 | { |
135 | 183 | if (msg == NativeMethods.WM_NCCALCSIZE && wParam != 0) |
|
0 commit comments