| 193 | } |
| 194 | |
| 195 | DWORD WINAPI SplashScreen::ThreadProc(void* param) |
| 196 | { |
| 197 | State* st = (State*)param; |
| 198 | auto& s = st->s; |
| 199 | |
| 200 | // Your app is PerMonitorV2. Make this UI thread PerMonitorV2 as well. |
| 201 | auto oldCtx = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); |
| 202 | |
| 203 | CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); |
| 204 | |
| 205 | // Register window class (per-process; safe to call multiple times with same name) |
| 206 | const wchar_t* kClassName = L"SplashScreenWindowClass_PMv2"; |
| 207 | |
| 208 | WNDCLASSW wc = {}; |
| 209 | wc.lpfnWndProc = &SplashScreen::WndProc; |
| 210 | wc.hInstance = s.hInstance; |
| 211 | wc.lpszClassName = kClassName; |
| 212 | wc.hCursor = LoadCursor(nullptr, IDC_ARROW); |
| 213 | RegisterClassW(&wc); |
| 214 | |
| 215 | // Create window: borderless, no taskbar button, optionally topmost. |
| 216 | HWND hwnd = CreateWindowExW( |
| 217 | WS_EX_TOOLWINDOW | WS_EX_LAYERED, |
| 218 | kClassName, |
| 219 | L"", |
| 220 | WS_POPUP, |
| 221 | 0, 0, 1, 1, |
| 222 | nullptr, nullptr, s.hInstance, |
| 223 | st); |
| 224 | |
| 225 | s.hwnd.store(hwnd, std::memory_order_release); |
| 226 | |
| 227 | // Load image |
| 228 | std::vector<uint8_t> bgra; |
| 229 | UINT w = 0; |
| 230 | UINT h = 0; |
| 231 | |
| 232 | bool ok = LoadPngWic_BGRA32(s.pngPath.c_str(), bgra, w, h); |
| 233 | if (ok) |
| 234 | { |
| 235 | // Premultiply for UpdateLayeredWindow (even if mostly opaque, this is fine). |
| 236 | PremultiplyIfNeeded(bgra); |
| 237 | |
| 238 | ShowWindow(hwnd, SW_SHOWNORMAL); |
| 239 | SetForegroundWindow(hwnd); |
| 240 | UpdateWindow(hwnd); |
| 241 | |
| 242 | SetLayeredWindowBitmap(hwnd, bgra.data(), w, h); |
| 243 | } |
| 244 | else |
| 245 | { |
| 246 | // If image fails, don't show an empty window. |
| 247 | ShowWindow(hwnd, SW_HIDE); |
| 248 | } |
| 249 | |
| 250 | if (s.readyEvent) |
| 251 | { |
| 252 | SetEvent(s.readyEvent); |
nothing calls this directly
no test coverage detected