The EX15A program illustrates the use of a persistent frame window class, CPersistentFrame. Figure 15-1 shows the contents of the files Persist.h and Persist.cpp, which are included in the EX15A project on the companion CD-ROM. In this example, you'll insert the new frame class into an AppWizard-generated SDI application. EX15A is a "do-nothing" application, but you can insert the persistent frame class into any of your own SDI "do-something" applications.
PERSIST.H
// Persist.h #ifndef _INSIDE_VISUAL_CPP_PERSISTENT_FRAME #define _INSIDE_VISUAL_CPP_PERSISTENT_FRAME class CPersistentFrame : public CFrameWnd { // remembers where it was on the desktop DECLARE_DYNAMIC(CPersistentFrame) private: static const CRect s_rectDefault; static const char s_profileHeading[]; static const char s_profileRect[]; static const char s_profileIcon[]; static const char s_profileMax[]; static const char s_profileTool[]; static const char s_profileStatus[]; BOOL m_bFirstTime; protected: // Create from serialization only CPersistentFrame(); ~CPersistentFrame(); //{{AFX_VIRTUAL(CPersistentFrame) public: virtual void ActivateFrame(int nCmdShow = -1); protected: //}}AFX_VIRTUAL //{{AFX_MSG(CPersistentFrame) afx_msg void OnDestroy(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; #endif // _INSIDE_VISUAL_CPP_PERSISTENT_FRAME PERSIST.CPP
// Persist.cpp Persistent frame class for SDI apps #include "stdafx.h" #include "persist.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif /////////////////////////////////////////////////////////////// // CPersistentFrame const CRect CPersistentFrame::s_rectDefault(10, 10, 500, 400); // static const char CPersistentFrame::s_profileHeading[] = "Window size"; const char CPersistentFrame::s_profileRect[] = "Rect"; const char CPersistentFrame::s_profileIcon[] = "icon"; const char CPersistentFrame::s_profileMax[] = "max"; const char CPersistentFrame::s_profileTool[] = "tool"; const char CPersistentFrame::s_profileStatus[] = "status"; IMPLEMENT_DYNAMIC(CPersistentFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CPersistentFrame, CFrameWnd) //{{AFX_MSG_MAP(CPersistentFrame) ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() /////////////////////////////////////////////////////////////// CPersistentFrame::CPersistentFrame(){ m_bFirstTime = TRUE; } /////////////////////////////////////////////////////////////// CPersistentFrame::~CPersistentFrame() { } /////////////////////////////////////////////////////////////// void CPersistentFrame::OnDestroy() { CString strText; BOOL bIconic, bMaximized; WINDOWPLACEMENT wndpl; wndpl.length = sizeof(WINDOWPLACEMENT); // gets current window position and // iconized/maximized status BOOL bRet = GetWindowPlacement(&wndpl); if (wndpl.showCmd == SW_SHOWNORMAL) { bIconic = FALSE; bMaximized = FALSE; } else if (wndpl.showCmd == SW_SHOWMAXIMIZED) { bIconic = FALSE; bMaximized = TRUE; } else if (wndpl.showCmd == SW_SHOWMINIMIZED) { bIconic = TRUE; if (wndpl.flags) { bMaximized = TRUE; } else { bMaximized = FALSE; } } strText.Format("%04d %04d %04d %04d", wndpl.rcNormalPosition.left, wndpl.rcNormalPosition.top, wndpl.rcNormalPosition.right, wndpl.rcNormalPosition.bottom); AfxGetApp()->WriteProfileString(s_profileHeading, s_profileRect, strText); AfxGetApp()->WriteProfileInt(s_profileHeading, s_profileIcon, bIconic); AfxGetApp()->WriteProfileInt(s_profileHeading, s_profileMax, bMaximized); SaveBarState(AfxGetApp()->m_pszProfileName); CFrameWnd::OnDestroy(); } /////////////////////////////////////////////////////////////// void CPersistentFrame::ActivateFrame(int nCmdShow) { CString strText; BOOL bIconic, bMaximized; UINT flags; WINDOWPLACEMENT wndpl; CRect rect; if (m_bFirstTime) { m_bFirstTime = FALSE; strText = AfxGetApp()->GetProfileString(s_profileHeading, s_profileRect); if (!strText.IsEmpty()) { rect.left = atoi((const char*) strText); rect.top = atoi((const char*) strText + 5); rect.right = atoi((const char*) strText + 10); rect.bottom = atoi((const char*) strText + 15); } else { rect = s_rectDefault; } bIconic = AfxGetApp()->GetProfileInt(s_profileHeading, s_profileIcon, 0); bMaximized = AfxGetApp()->GetProfileInt(s_profileHeading, s_profileMax, 0); if (bIconic) { nCmdShow = SW_SHOWMINNOACTIVE; if (bMaximized) { flags = WPF_RESTORETOMAXIMIZED; } else { flags = WPF_SETMINPOSITION; } } else { if (bMaximized) { nCmdShow = SW_SHOWMAXIMIZED; flags = WPF_RESTORETOMAXIMIZED; } else { nCmdShow = SW_NORMAL; flags = WPF_SETMINPOSITION; } } wndpl.length = sizeof(WINDOWPLACEMENT); wndpl.showCmd = nCmdShow; wndpl.flags = flags; wndpl.ptMinPosition = CPoint(0, 0); wndpl.ptMaxPosition = CPoint(-::GetSystemMetrics(SM_CXBORDER), -::GetSystemMetrics(SM_CYBORDER)); wndpl.rcNormalPosition = rect; LoadBarState(AfxGetApp()->m_pszProfileName); // sets window's position and minimized/maximized status BOOL bRet = SetWindowPlacement(&wndpl); } CFrameWnd::ActivateFrame(nCmdShow); } |
Here are the steps for building the EX15A example program.
class CMainFrame : public CFrameWnd
to
class CMainFrame : public CPersistentFrame
Also, add the line
#include "persist.h"
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
with the line
SetRegistryKey("Programming Visual C++");
Then click OK to regenerate the CLW file. Notice that CPersistentFrame is now integrated into ClassWizard. You'll now be able to map messages and override virtual functions in the CPersistentFrame class.
Notice the relationship between the Registry key and the SetRegistryKey function parameter, "Programming Visual C++." If you supply an empty string as the SetRegistryKey parameter, the program name (ex15a, in this case) is positioned directly below the Software key.