diff --git a/src/core/types.h b/src/core/types.h index b3fcbfd..3cbd585 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -126,6 +126,10 @@ struct AppState std::deque recentFiles; BackgroundSettings background; std::wstring customIconPath; + int windowX = CW_USEDEFAULT; + int windowY = CW_USEDEFAULT; + int windowWidth = 640; + int windowHeight = 480; }; typedef BOOL(WINAPI *fnAllowDarkModeForWindow)(HWND hWnd, BOOL allow); diff --git a/src/main.cpp b/src/main.cpp index 376aa4b..0f6c911 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -499,6 +499,21 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) g_state.closing = false; return 0; case WM_DESTROY: + // Save window position and size before destroying + { + WINDOWPLACEMENT wp = {}; + wp.length = sizeof(WINDOWPLACEMENT); + if (GetWindowPlacement(hwnd, &wp)) + { + // Always save the normal position, even if maximized or minimized + RECT rect = wp.rcNormalPosition; + g_state.windowX = rect.left; + g_state.windowY = rect.top; + g_state.windowWidth = rect.right - rect.left; + g_state.windowHeight = rect.bottom - rect.top; + } + SaveWindowSettings(); + } if (g_state.hFont) { DeleteObject(g_state.hFont); @@ -556,6 +571,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int nCmdSh } LoadFontSettings(); + LoadWindowSettings(); WNDCLASSEXW wc = {}; wc.cbSize = sizeof(wc); @@ -578,7 +594,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int nCmdSh const auto &lang = GetLangStrings(); std::wstring initialTitle = lang.untitled + L" - " + lang.appName; g_hwndMain = CreateWindowExW(0, L"NotepadClass", initialTitle.c_str(), - WS_OVERLAPPEDWINDOW | WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, + WS_OVERLAPPEDWINDOW | WS_MAXIMIZEBOX, g_state.windowX, g_state.windowY, g_state.windowWidth, g_state.windowHeight, nullptr, nullptr, hInstance, nullptr); g_hAccel = LoadAcceleratorsW(hInstance, MAKEINTRESOURCEW(IDR_ACCEL)); ShowWindow(g_hwndMain, nCmdShow); diff --git a/src/modules/settings.cpp b/src/modules/settings.cpp index 3d43bb0..c969c55 100644 --- a/src/modules/settings.cpp +++ b/src/modules/settings.cpp @@ -10,7 +10,7 @@ ███ ███ ▀ Settings management for persisting user preferences via Windows Registry. - Handles font name and font size storage and retrieval. + Handles font settings, always on top, window size and position storage and retrieval. */ #include "settings.h" @@ -25,6 +25,10 @@ #define FONT_ITALIC_VALUE L"FontItalic" #define FONT_UNDERLINE_VALUE L"FontUnderline" #define ALWAYS_ON_TOP_VALUE L"AlwaysOnTop" +#define WINDOW_X_VALUE L"WindowX" +#define WINDOW_Y_VALUE L"WindowY" +#define WINDOW_WIDTH_VALUE L"WindowWidth" +#define WINDOW_HEIGHT_VALUE L"WindowHeight" #define MIN_FONT_SIZE 8 #define MAX_FONT_SIZE 72 @@ -119,3 +123,88 @@ void SaveFontSettings() RegCloseKey(hKey); } } + +void LoadWindowSettings() +{ + HKEY hKey; + if (RegOpenKeyExW(HKEY_CURRENT_USER, SETTINGS_KEY, 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + DWORD x = 0; + DWORD size = sizeof(x); + if (RegQueryValueExW(hKey, WINDOW_X_VALUE, nullptr, nullptr, reinterpret_cast(&x), &size) == ERROR_SUCCESS) + { + // Cast DWORD to int - on Windows, this preserves negative coordinates correctly + g_state.windowX = static_cast(x); + } + + DWORD y = 0; + size = sizeof(y); + if (RegQueryValueExW(hKey, WINDOW_Y_VALUE, nullptr, nullptr, reinterpret_cast(&y), &size) == ERROR_SUCCESS) + { + // Cast DWORD to int - on Windows, this preserves negative coordinates correctly + g_state.windowY = static_cast(y); + } + + DWORD width = 0; + size = sizeof(width); + if (RegQueryValueExW(hKey, WINDOW_WIDTH_VALUE, nullptr, nullptr, reinterpret_cast(&width), &size) == ERROR_SUCCESS) + { + if (width > 0) + { + g_state.windowWidth = static_cast(width); + } + } + + DWORD height = 0; + size = sizeof(height); + if (RegQueryValueExW(hKey, WINDOW_HEIGHT_VALUE, nullptr, nullptr, reinterpret_cast(&height), &size) == ERROR_SUCCESS) + { + if (height > 0) + { + g_state.windowHeight = static_cast(height); + } + } + + RegCloseKey(hKey); + } + + // Validate that the window position is visible on at least one monitor + RECT rc = {g_state.windowX, g_state.windowY, g_state.windowX + g_state.windowWidth, g_state.windowY + g_state.windowHeight}; + HMONITOR hMonitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONULL); + if (!hMonitor) + { + // Window would be off-screen, reset to default + g_state.windowX = CW_USEDEFAULT; + g_state.windowY = CW_USEDEFAULT; + } +} + +void SaveWindowSettings() +{ + HKEY hKey; + if (RegCreateKeyExW(HKEY_CURRENT_USER, SETTINGS_KEY, 0, nullptr, 0, KEY_WRITE, nullptr, &hKey, nullptr) == ERROR_SUCCESS) + { + // Store coordinates as REG_DWORD - static_cast preserves bit pattern for negative values + DWORD x = static_cast(g_state.windowX); + RegSetValueExW(hKey, WINDOW_X_VALUE, 0, REG_DWORD, + reinterpret_cast(&x), + sizeof(x)); + + DWORD y = static_cast(g_state.windowY); + RegSetValueExW(hKey, WINDOW_Y_VALUE, 0, REG_DWORD, + reinterpret_cast(&y), + sizeof(y)); + + DWORD width = static_cast(g_state.windowWidth); + RegSetValueExW(hKey, WINDOW_WIDTH_VALUE, 0, REG_DWORD, + reinterpret_cast(&width), + sizeof(width)); + + DWORD height = static_cast(g_state.windowHeight); + RegSetValueExW(hKey, WINDOW_HEIGHT_VALUE, 0, REG_DWORD, + reinterpret_cast(&height), + sizeof(height)); + + RegCloseKey(hKey); + } +} diff --git a/src/modules/settings.h b/src/modules/settings.h index ab7bec9..6efbefc 100644 --- a/src/modules/settings.h +++ b/src/modules/settings.h @@ -17,3 +17,5 @@ void LoadFontSettings(); void SaveFontSettings(); +void LoadWindowSettings(); +void SaveWindowSettings();