diff --git a/app/Main.cpp b/app/Main.cpp index b74b9a6..9e7d2e5 100644 --- a/app/Main.cpp +++ b/app/Main.cpp @@ -133,6 +133,7 @@ static const UINT gFindReplaceID = RegisterWindowMessage(FINDMSGSTRING); BEGIN_MESSAGE_MAP(MainWindow, CFrameWnd) ON_WM_CREATE() + ON_WM_CLOSE() ON_MESSAGE(WMU_LATE_INIT, OnLateInit) //ON_MESSAGE(WMU_CLOSE_MAIN_DIALOG, OnCloseMainDialog) ON_WM_SIZE() @@ -306,6 +307,12 @@ MainWindow::~MainWindow() LOGI("MainWindow destructor complete"); } +void MainWindow::OnClose() +{ + SaveWinPlacement(); + CFrameWnd::OnClose(); +} + BOOL MainWindow::PreCreateWindow(CREATESTRUCT& cs) { BOOL res = CFrameWnd::PreCreateWindow(cs); @@ -563,6 +570,8 @@ int MainWindow::OnCreate(LPCREATESTRUCT lpcs) fStatusBar.SetPaneText(kProgressPane, L""); + RestoreWinPlacement(); + return 0; } @@ -1889,6 +1898,82 @@ void MainWindow::EventPause(int duration) * =================================== */ +static const WCHAR kMainWinSection[] = L"mainwin"; +static const WCHAR kMainWin_Left[] = L"left"; +static const WCHAR kMainWin_Top[] = L"top"; +static const WCHAR kMainWin_Right[] = L"right"; +static const WCHAR kMainWin_Bottom[] = L"bottom"; +static const WCHAR kMainWin_Cmd[] = L"cmd"; + +void MainWindow::SaveWinPlacement() +{ + // Capture the current window position. At the point where the destructor + // fires, too much has been shut down, so we need to do it here. + WINDOWPLACEMENT wndpl; + wndpl.length = sizeof(wndpl); + if (!GetWindowPlacement(&wndpl)) { + LOGW("Unable to get window placement"); + return; + } + + LOGD("Window is at ltrb=%ld,%ld %ldx%ld showCmd=%d", + wndpl.rcNormalPosition.left, + wndpl.rcNormalPosition.top, + wndpl.rcNormalPosition.right - wndpl.rcNormalPosition.left, + wndpl.rcNormalPosition.bottom - wndpl.rcNormalPosition.top, + wndpl.showCmd); + gMyApp.WriteProfileInt(kMainWinSection, + kMainWin_Left, wndpl.rcNormalPosition.left); + gMyApp.WriteProfileInt(kMainWinSection, + kMainWin_Top, wndpl.rcNormalPosition.top); + gMyApp.WriteProfileInt(kMainWinSection, + kMainWin_Right, wndpl.rcNormalPosition.right); + gMyApp.WriteProfileInt(kMainWinSection, + kMainWin_Bottom, wndpl.rcNormalPosition.bottom); + gMyApp.WriteProfileInt(kMainWinSection, + kMainWin_Cmd, wndpl.showCmd); +} + +void MainWindow::RestoreWinPlacement() +{ + RECT normPos; + normPos.left = gMyApp.GetProfileInt(kMainWinSection, kMainWin_Left, -1); + normPos.top = gMyApp.GetProfileInt(kMainWinSection, kMainWin_Top, -1); + normPos.right = gMyApp.GetProfileInt(kMainWinSection, kMainWin_Right, -1); + normPos.bottom = gMyApp.GetProfileInt(kMainWinSection, kMainWin_Bottom, -1); + int cmd = gMyApp.GetProfileInt(kMainWinSection, kMainWin_Cmd, -1); + + if (normPos.left < 0 || normPos.top < 0 || normPos.right < 0 || + normPos.bottom < 0 || cmd < 0) { + LOGI("Previous window placement not found."); + return; + } + + POINT nopt; + nopt.x = nopt.y = -1; + + // We need to set the placement for "normal", and then deal with + // maximized windows by having the MyApp ShowWindow() call pass the + // appropriate command. If we pass the correct normal rect here with + // the "maximized" command, we end up with a non-maximized window of + // maximum size. (If done correctly, you can maximize, quit, restart, + // and un-maximize back to the original size.) + WINDOWPLACEMENT wndpl; + wndpl.length = sizeof(wndpl); + wndpl.flags = 0; + wndpl.showCmd = SW_SHOWNORMAL; + wndpl.ptMinPosition = nopt; + wndpl.ptMaxPosition = nopt; + wndpl.rcNormalPosition = normPos; + + LOGD("Restoring previous placement, cmd=%d", wndpl.showCmd); + SetWindowPlacement(&wndpl); + + // Stomp on MyApp's show command. We don't want to start minimized, + // so switch to "normal" if that's set. + gMyApp.m_nCmdShow = (cmd == SW_SHOWMINIMIZED ? SW_SHOWNORMAL : cmd); +} + void MainWindow::DrawEmptyClientArea(CDC* pDC, const CRect& clientRect) { CBrush brush; diff --git a/app/Main.h b/app/Main.h index 3dd9e72..9351d01 100644 --- a/app/Main.h +++ b/app/Main.h @@ -54,7 +54,7 @@ public: /* * Override the pre-create function to tweak the window style. */ - BOOL PreCreateWindow(CREATESTRUCT& cs) override; + virtual BOOL PreCreateWindow(CREATESTRUCT& cs) override; /* * Override GetClientRect so we can factor in the status and tool bars. @@ -268,6 +268,7 @@ private: // Command handlers afx_msg int OnCreate(LPCREATESTRUCT lpcs); + afx_msg void OnClose(); afx_msg LONG OnLateInit(UINT, LONG); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnGetMinMaxInfo(MINMAXINFO* pMMI); @@ -489,6 +490,14 @@ private: */ void DrawEmptyClientArea(CDC* pDC, const CRect& clientRect); + /* + * Save/restore main window placement. The restore function will move + * the window if the previous placement is no longer visible (e.g. a + * secondary monitor was removed). + */ + void SaveWinPlacement(); + void RestoreWinPlacement(); + /* * Extract a record to the temp folder and open it with a new instance of * CiderPress. We might want to extract disk images as 2MG files to take diff --git a/app/MyApp.cpp b/app/MyApp.cpp index 87dac70..b7425bf 100644 --- a/app/MyApp.cpp +++ b/app/MyApp.cpp @@ -64,6 +64,16 @@ MyApp::~MyApp(void) BOOL MyApp::InitInstance(void) { + // This causes functions like SetProfileInt to use the registry rather + // than a .INI file. The registry key is "usually the name of a company". + // (Must do this before creating main window so we can restore the + // previous window position.) +#ifdef CAN_UPDATE_FILE_ASSOC + SetRegistryKey(fRegistry.GetAppRegistryKey()); +#else + SetRegistryKey(L"faddenSoft"); +#endif + // Create the main window. m_pMainWnd = new MainWindow; m_pMainWnd->ShowWindow(m_nCmdShow); @@ -92,14 +102,6 @@ BOOL MyApp::InitInstance(void) LogModuleLocation(L"riched32.dll"); LogModuleLocation(L"msftedit.dll"); - // This causes functions like SetProfileInt to use the registry rather - // than a .INI file. The registry key is "usually the name of a company". -#ifdef CAN_UPDATE_FILE_ASSOC - SetRegistryKey(fRegistry.GetAppRegistryKey()); -#else - SetRegistryKey(L"faddenSoft"); -#endif - //LOGI("Registry key is '%ls'", m_pszRegistryKey); //LOGI("Profile name is '%ls'", m_pszProfileName); LOGI("Short command line is '%ls'", m_lpCmdLine);