Extract file menu binding and Win32 splash helper

This commit is contained in:
2026-06-16 11:10:31 +02:00
parent 8afeb087b8
commit d135835787
8 changed files with 369 additions and 232 deletions

View File

@@ -0,0 +1,124 @@
#include "pch.h"
#include "platform_windows/windows_splash.h"
#include "app.h"
#include "image.h"
#include "log.h"
#include "version.h"
#include "../resource.h"
#include <chrono>
#include <shellscalingapi.h>
#include <string>
#include <stop_token>
extern HRESULT(*GetDpiForMonitor_fn)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);
namespace {
constexpr UINT kSplashCloseMessage = WM_USER + 1;
HBITMAP image_to_hbitmap(const Image& img)
{
BITMAPINFOHEADER bmih;
memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
bmih.biWidth = img.width;
bmih.biHeight = img.height;
bmih.biBitCount = 32;
bmih.biCompression = BI_RGB;
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biPlanes = 1;
BITMAPINFO* bmi = (BITMAPINFO*)&bmih;
return CreateDIBitmap(GetDC(NULL), &bmih, CBM_INIT, img.data(), bmi, DIB_RGB_COLORS);
}
LRESULT CALLBACK splash_proc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_INITDIALOG:
{
auto monitor = MonitorFromWindow(0, MONITOR_DEFAULTTOPRIMARY);
auto x = unsigned{ 96 };
auto y = unsigned{ 96 };
if (GetDpiForMonitor_fn)
GetDpiForMonitor_fn(monitor, MDT_EFFECTIVE_DPI, &x, &y);
float z = (float)x / 96.f;
static char base_path[MAX_PATH];
GetCurrentDirectoryA(MAX_PATH, base_path);
std::string path = std::string(base_path) + "\\data\\splash.jpg";
Image img;
img.load_file(path);
img.flip();
auto hbitmap = image_to_hbitmap(img.resize(512 * z, 200 * z));
SendMessage(GetDlgItem(hWndDlg, IDC_STATIC_IMAGE), STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbitmap);
SetDlgItemText(hWndDlg, IDC_STATIC_VERSION, g_version_number_w);
RECT r;
GetClientRect(hWndDlg, &r);
MoveWindow(GetDlgItem(hWndDlg, IDC_STATIC_IMAGE), 0, 0, 512 * z, 200 * z, TRUE);
SetWindowPos(hWndDlg, HWND_TOP, 0, 0, 512 * z, 200 * z, SWP_NOMOVE);
HWND hWndVersion = GetDlgItem(hWndDlg, IDC_STATIC_VERSION);
RECT rv;
GetClientRect(hWndVersion, &rv);
MoveWindow(hWndVersion, 0, 200 * z - (rv.bottom - rv.top), r.right - r.left, rv.bottom - rv.top, TRUE);
return TRUE;
}
case kSplashCloseMessage:
PostQuitMessage(0);
return TRUE;
}
return DefWindowProc(hWndDlg, Msg, wParam, lParam);
}
}
namespace pp::platform::windows {
SplashScreen::SplashScreen(HINSTANCE hInst)
: hInst_(hInst)
, thread_([this](std::stop_token) { thread_main(); })
{
}
SplashScreen::~SplashScreen()
{
dismiss();
}
void SplashScreen::dismiss()
{
if (HWND dialog = dialog_.load(std::memory_order_acquire))
SendMessage(dialog, kSplashCloseMessage, 0, 0);
if (thread_.joinable())
thread_.join();
}
void SplashScreen::thread_main()
{
BT_SetTerminate();
HWND dialog = CreateDialog(hInst_, MAKEINTRESOURCE(IDD_SPLASH), NULL, reinterpret_cast<DLGPROC>(splash_proc));
dialog_.store(dialog, std::memory_order_release);
if (!dialog)
return;
MSG msg;
while (GetMessage(&msg, 0, 0, 0) > 0)
{
if (IsDialogMessage(dialog, &msg))
{
DispatchMessage(&msg);
TranslateMessage(&msg);
}
}
if (HWND dialog = dialog_.exchange(nullptr))
DestroyWindow(dialog);
}
}

View File

@@ -0,0 +1,30 @@
#pragma once
#include <windows.h>
#include <atomic>
#include <thread>
namespace pp::platform::windows {
class SplashScreen final
{
public:
explicit SplashScreen(HINSTANCE hInst);
~SplashScreen();
SplashScreen(const SplashScreen&) = delete;
SplashScreen& operator=(const SplashScreen&) = delete;
SplashScreen(SplashScreen&&) = delete;
SplashScreen& operator=(SplashScreen&&) = delete;
void dismiss();
private:
void thread_main();
HINSTANCE hInst_{};
std::atomic<HWND> dialog_{};
std::jthread thread_;
};
}