1418 lines
40 KiB
C++
1418 lines
40 KiB
C++
// ==========================================================================
|
|
// Class Implementation : COXWorkspaceState
|
|
// ==========================================================================
|
|
|
|
// Source file : OXWorkspaceState.cpp
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#if (_MFC_VER < 0x0420)
|
|
// This file uses classes that were introduced in MFC Version 4.2
|
|
// These classes are now officially documented by Microsoft, but did not exist in previous versions
|
|
// Therefore this file will be completely excluded for older versions of MFC
|
|
#pragma message("Warning : OXWorkspaceState.cpp not included because MFC Version < 4.2")
|
|
#else
|
|
// The entire file
|
|
|
|
// need this file for CControlBarInfo class
|
|
#include <afxpriv.h> // MFC extensions for help constants
|
|
|
|
|
|
#include "OXWorkspaceState.h"
|
|
#include "OXSplitterColRowState.h"
|
|
#include "OXSizeCtrlBar.h"
|
|
#include "OXSizeDockBar.h"
|
|
#include "UTB64Bit.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
const int COXWorkspaceState::m_nSerializeSchemaVersion = 1;
|
|
|
|
IMPLEMENT_SERIAL(COXWorkspaceState, CObject, COXWorkspaceState::m_nSerializeSchemaVersion | VERSIONABLE_SCHEMA)
|
|
#define new DEBUG_NEW
|
|
|
|
static const TCHAR szSoftware[] = _T("Software");
|
|
static const TCHAR szWorkspaceState[] = _T("WorkspaceState");
|
|
static const TCHAR szWorkspaceStateDefaultValue[] = _T("Main");
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Definition of static members
|
|
const int COXWorkspaceState::m_nMagicNumber = 0x1234FEDC;
|
|
|
|
// Data members -------------------------------------------------------------
|
|
// protected:
|
|
// CSize m_screenSize;
|
|
// --- The size of the entire video screen in pixels (computed during runtilme)
|
|
|
|
// BOOL m_bSaveMainWndProps;
|
|
// --- WHether the properties of the main window should be saved and restored
|
|
|
|
// WINDOWPLACEMENT m_mainWndPlacement;
|
|
// --- The placement of the main window
|
|
|
|
// BOOL m_bSaveBarProps;
|
|
// ---- Whether the properties of the control bars should be saved and restored
|
|
|
|
// CDockState* m_pDockState;
|
|
// --- The state of the control bars
|
|
|
|
// BOOL m_bSaveChildFrames;
|
|
// ---- Whether the properties of child frame windows should be saved and restored
|
|
|
|
// BOOL m_bSaveSplitterPanes;
|
|
// ---- Whether the properties of splitter panes should be saved and restored
|
|
|
|
// CObArray* m_pChildFrameStates;
|
|
// --- The properties of the child frame windows
|
|
|
|
// int m_nSerializeSchemaVersionLoad;
|
|
// --- The schema version number that is read from archive
|
|
|
|
// private:
|
|
|
|
// Member functions ---------------------------------------------------------
|
|
// public:
|
|
|
|
COXWorkspaceState::COXWorkspaceState()
|
|
:
|
|
m_pDockState(NULL),
|
|
m_pChildFrameStates(NULL),
|
|
m_pSplitterPanes(NULL)
|
|
{
|
|
Initialize();
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
BOOL COXWorkspaceState::IsMainWindowIncluded() const
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
return m_bSaveMainWndProps;
|
|
}
|
|
|
|
BOOL COXWorkspaceState::IsBarPropertyIncluded() const
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
return m_bSaveBarProps;
|
|
}
|
|
|
|
BOOL COXWorkspaceState::IsChildFrameIncluded() const
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
return m_bSaveChildFrames;
|
|
}
|
|
|
|
BOOL COXWorkspaceState::IsSplitterPaneIncluded() const
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
return m_bSaveSplitterPanes;
|
|
}
|
|
|
|
void COXWorkspaceState::IncludeMainWindow(BOOL bInclude /* = TRUE */)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
m_bSaveMainWndProps = bInclude;
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
void COXWorkspaceState::IncludeBarProperty(BOOL bInclude /* = TRUE */)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
m_bSaveBarProps = bInclude;
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
void COXWorkspaceState::IncludeChildFrame(BOOL bInclude /* = TRUE */)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
m_bSaveChildFrames = bInclude;
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
void COXWorkspaceState::IncludeSplitterPane(BOOL bInclude /* = TRUE */)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
m_bSaveSplitterPanes = bInclude;
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
BOOL COXWorkspaceState::ComputeProperties()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
CWnd* pMainWnd = NULL;
|
|
CFrameWnd* pMainFrame = NULL;
|
|
|
|
// Get the main window and the main frame
|
|
pMainWnd = AfxGetMainWnd();
|
|
if (pMainWnd != NULL)
|
|
pMainFrame = pMainWnd->GetTopLevelFrame();
|
|
|
|
// Get the position of the main window
|
|
::ZeroMemory(&m_mainWndPlacement, sizeof(WINDOWPLACEMENT));
|
|
if (m_bSaveMainWndProps && (pMainWnd != NULL))
|
|
{
|
|
m_mainWndPlacement.length = sizeof(WINDOWPLACEMENT);
|
|
VERIFY(pMainWnd->GetWindowPlacement(&m_mainWndPlacement));
|
|
}
|
|
|
|
// Get the current state of the control bars
|
|
if (m_bSaveBarProps && (pMainFrame != NULL))
|
|
{
|
|
pMainFrame->GetDockState(*m_pDockState);
|
|
ComputeDockingWindowsState(m_pDockState->m_arrBarInfo);
|
|
}
|
|
|
|
EmptySplitterPanes(m_pSplitterPanes);
|
|
if (m_bSaveSplitterPanes)
|
|
ComputeSplitterPanes(pMainFrame);
|
|
|
|
EmptyChildFrames(m_pChildFrameStates);
|
|
if (m_bSaveChildFrames)
|
|
ComputeChildFrameState();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COXWorkspaceState::ApplyProperties() const
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
CWnd* pMainWnd = NULL;
|
|
CFrameWnd* pMainFrame = NULL;
|
|
|
|
// Get the main window and the main frame
|
|
pMainWnd = AfxGetMainWnd();
|
|
if (pMainWnd != NULL)
|
|
pMainFrame = pMainWnd->GetTopLevelFrame();
|
|
|
|
BOOL bIsLocked=FALSE;
|
|
// Set the position of the main window
|
|
TRY
|
|
{
|
|
if (m_bSaveMainWndProps && (pMainWnd != NULL))
|
|
{
|
|
WINDOWPLACEMENT mainWndPlacementCopy;
|
|
::CopyMemory(&mainWndPlacementCopy, &m_mainWndPlacement,
|
|
sizeof(WINDOWPLACEMENT));
|
|
int nCmdShow=mainWndPlacementCopy.showCmd;
|
|
// Check whether the last state of the main window was minimized
|
|
if(nCmdShow==SW_SHOWMINIMIZED)
|
|
{
|
|
// ... Remove the minimize state and set the restore state
|
|
nCmdShow=SW_SHOWNORMAL;
|
|
}
|
|
if(!pMainWnd->IsWindowVisible())
|
|
mainWndPlacementCopy.showCmd=SW_HIDE;
|
|
VERIFY(pMainWnd->SetWindowPlacement(&mainWndPlacementCopy));
|
|
CWinApp* pApp=AfxGetApp();
|
|
if(pApp!=NULL)
|
|
pApp->m_nCmdShow=nCmdShow;
|
|
}
|
|
|
|
// Set the current state of of the control bars
|
|
// (Even though the main window has its update locked,
|
|
// toolbars will be shown directly because they are not childs of the mainframe)
|
|
if (m_bSaveBarProps && (pMainFrame != NULL))
|
|
{
|
|
////////
|
|
// remove TBSTYLE_FLAT style out of CToolBar
|
|
CObArray arrFlatBars;
|
|
int i=0;
|
|
for (i=0; i<m_pDockState->m_arrBarInfo.GetSize(); i++)
|
|
{
|
|
CControlBarInfo* pInfo=(CControlBarInfo*)m_pDockState->m_arrBarInfo[i];
|
|
ASSERT(pInfo!=NULL);
|
|
pInfo->m_pBar=pMainFrame->GetControlBar(pInfo->m_nBarID);
|
|
if (pInfo->m_pBar!=NULL)
|
|
{
|
|
if(pInfo->m_pBar->IsKindOf(RUNTIME_CLASS(CToolBar)) &&
|
|
pInfo->m_pBar->GetStyle()&TBSTYLE_FLAT)
|
|
{
|
|
arrFlatBars.Add((CObject*)pInfo->m_pBar);
|
|
pInfo->m_pBar->ModifyStyle(TBSTYLE_FLAT,0);
|
|
}
|
|
|
|
COXSizeControlBar* pSzControlBar = DYNAMIC_DOWNCAST(COXSizeControlBar, pInfo->m_pBar);
|
|
if (pSzControlBar != NULL)
|
|
{
|
|
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
////////
|
|
|
|
pMainFrame->SetDockState(*m_pDockState);
|
|
ApplyDockingWindowsState(m_pDockState->m_arrBarInfo);
|
|
|
|
// Refresh all floating windows
|
|
for (i = 0; i < m_pDockState->m_arrBarInfo.GetSize(); i++)
|
|
{
|
|
CControlBarInfo* pInfo=(CControlBarInfo*)m_pDockState->m_arrBarInfo[i];
|
|
ASSERT(pInfo!=NULL);
|
|
pInfo->m_pBar=pMainFrame->GetControlBar(pInfo->m_nBarID);
|
|
if (pInfo->m_pBar != NULL && pInfo->m_pBar->IsFloating())
|
|
{
|
|
CRect rect;
|
|
pInfo->m_pBar->GetParentFrame()->GetWindowRect(rect);
|
|
rect.bottom += 1;
|
|
pInfo->m_pBar->GetParentFrame()->MoveWindow(rect);
|
|
}
|
|
}
|
|
|
|
////////
|
|
// set TBSTYLE_FLAT style for CToolBar
|
|
for (i=0; i<arrFlatBars.GetSize(); i++)
|
|
{
|
|
((CToolBar*)arrFlatBars.GetAt(i))->ModifyStyle(0,TBSTYLE_FLAT);
|
|
}
|
|
////////
|
|
}
|
|
|
|
if (m_bSaveSplitterPanes)
|
|
ApplySplitterPanes(pMainFrame);
|
|
|
|
// Set the current state of the frame windows
|
|
if (m_bSaveChildFrames)
|
|
ApplyChildFrameState();
|
|
}
|
|
CATCH_ALL(px)
|
|
{
|
|
TRACE0("COXWorkspaceState::ApplyProperties : Catching exception, re-throwing\n");
|
|
|
|
// Re-enable main window
|
|
if (pMainWnd != NULL && bIsLocked)
|
|
pMainWnd->UnlockWindowUpdate();
|
|
|
|
// Throw the exception again
|
|
THROW_LAST();
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void COXWorkspaceState::Serialize(CArchive& ar)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// Check the version
|
|
// (If version == -1, the version is unknown, this occurs when Serialize() is called directly)
|
|
if (ar.IsLoading())
|
|
{
|
|
m_nSerializeSchemaVersionLoad = (int)ar.GetObjectSchema();
|
|
if (m_nSerializeSchemaVersion < m_nSerializeSchemaVersionLoad)
|
|
{
|
|
TRACE1("COXWorkspaceState::Serialize : Unexpected schema version : %i, throwing CArchiveException\n",
|
|
m_nSerializeSchemaVersionLoad);
|
|
AfxThrowArchiveException(CArchiveException::badSchema);
|
|
}
|
|
}
|
|
|
|
// Call base class implementation
|
|
CObject::Serialize(ar);
|
|
|
|
// Serialize magic number and version number so that when Serialize
|
|
// is called directly versioning can still be used
|
|
if (ar.IsStoring())
|
|
{
|
|
ar << m_nMagicNumber;
|
|
ar << m_nSerializeSchemaVersion;
|
|
}
|
|
else
|
|
{
|
|
int nInternalMagicNumber = -1;
|
|
int nInternalVersion = -1;
|
|
|
|
ar >> nInternalMagicNumber;
|
|
if (nInternalMagicNumber != m_nMagicNumber)
|
|
{
|
|
TRACE1("COXWorkspaceState::Serialize : Unexpected magic number : 0x%X, throwing CArchiveException\n",
|
|
nInternalMagicNumber);
|
|
AfxThrowArchiveException(CArchiveException::badSchema);
|
|
}
|
|
|
|
ar >> nInternalVersion;
|
|
if (m_nSerializeSchemaVersion < nInternalVersion)
|
|
{
|
|
TRACE1("COXWorkspaceState::Serialize : Unexpected version number : %i, throwing CArchiveException\n",
|
|
nInternalVersion);
|
|
AfxThrowArchiveException(CArchiveException::badSchema);
|
|
}
|
|
|
|
// ... Internal version number take priority over MFC
|
|
m_nSerializeSchemaVersionLoad = nInternalVersion;
|
|
}
|
|
|
|
// Serialize all data
|
|
if (ar.IsStoring())
|
|
StoreProperties(ar);
|
|
else
|
|
LoadProperties(ar);
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
BOOL COXWorkspaceState::StoreToFile(LPCTSTR pszPath,
|
|
BOOL bSaveOpenDocs /* = TRUE */,
|
|
BOOL bComputeProperties /* = TRUE */,
|
|
BOOL bCloseApplication /* = TRUE */)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// ... When storing : first let all the documents save themselves
|
|
// Because this may change their name
|
|
if(bSaveOpenDocs)
|
|
{
|
|
AfxGetApp()->SaveAllModified();
|
|
|
|
// if this function has been called when application is about to be closed
|
|
// we don't want it to call SaveAllModified() function on the files that
|
|
// user didn't want to save. in order to do that we have to go through
|
|
// all application's document and clear modified flag
|
|
if(bCloseApplication && AfxGetApp()->m_pDocManager!=NULL)
|
|
{
|
|
POSITION pos=AfxGetApp()->m_pDocManager->GetFirstDocTemplatePosition();
|
|
while(pos!=NULL)
|
|
{
|
|
CDocTemplate* pTemplate=
|
|
AfxGetApp()->m_pDocManager->GetNextDocTemplate(pos);
|
|
ASSERT_KINDOF(CDocTemplate,pTemplate);
|
|
POSITION posDoc=pTemplate->GetFirstDocPosition();
|
|
while(posDoc!=NULL)
|
|
{
|
|
CDocument* pDoc=pTemplate->GetNextDoc(posDoc);
|
|
pDoc->SetModifiedFlag(FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ... When storing first establish the values off all properties
|
|
if (bComputeProperties)
|
|
ComputeProperties();
|
|
|
|
BOOL bSuccess = TRUE;
|
|
TRY
|
|
{
|
|
StoreLoadFile(pszPath, TRUE);
|
|
}
|
|
CATCH_ALL(px)
|
|
{
|
|
#ifdef _DEBUG
|
|
const int nMaxErrorMsgLength = 1024;
|
|
CString sErrorMsg;
|
|
px->GetErrorMessage(sErrorMsg.GetBuffer(nMaxErrorMsgLength), nMaxErrorMsgLength);
|
|
sErrorMsg.ReleaseBuffer();
|
|
TRACE1("COXWorkspaceState::StoreToFile : Catching CException (%s)\n", sErrorMsg);
|
|
#endif // _DEBUG
|
|
|
|
bSuccess = FALSE;
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
ASSERT_VALID(this);
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL COXWorkspaceState::LoadFromFile(LPCTSTR pszPath, BOOL bApplyProperties /* = TRUE */)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
BOOL bSuccess = TRUE;
|
|
TRY
|
|
{
|
|
StoreLoadFile(pszPath, FALSE);
|
|
}
|
|
CATCH_ALL(px)
|
|
{
|
|
#ifdef _DEBUG
|
|
const int nMaxErrorMsgLength = 1024;
|
|
CString sErrorMsg;
|
|
px->GetErrorMessage(sErrorMsg.GetBuffer(nMaxErrorMsgLength), nMaxErrorMsgLength);
|
|
sErrorMsg.ReleaseBuffer();
|
|
TRACE1("COXWorkspaceState::LoadFromFile : Catching CException (%s)\n", sErrorMsg);
|
|
#endif // _DEBUG
|
|
|
|
bSuccess = FALSE;
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
|
|
// ... When loading apply the just read properties
|
|
if (bApplyProperties && bSuccess)
|
|
ApplyProperties();
|
|
|
|
ASSERT_VALID(this);
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL COXWorkspaceState::StoreToRegistry(LPCTSTR pszValueName /* = NULL */,
|
|
LPCTSTR pszCompany /* = NULL */,
|
|
LPCTSTR pszApplication /* = NULL*/ ,
|
|
HKEY hKeyRoot /* = HKEY_CURRENT_USER */,
|
|
BOOL bSaveOpenDocs /* = TRUE */,
|
|
BOOL bComputeProperties /* = TRUE */,
|
|
BOOL bCloseApplication /* = TRUE */)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// ... When storing : first let all the documents save themselves
|
|
// Because this may change their name
|
|
if (bSaveOpenDocs)
|
|
{
|
|
AfxGetApp()->SaveAllModified();
|
|
|
|
// if this function has been called when application is about to be closed
|
|
// we don't want it to call SaveAllModified() function on the files that
|
|
// user didn't want to save. in order to do that we have to go through
|
|
// all application's document and clear modified flag
|
|
if(bCloseApplication && AfxGetApp()->m_pDocManager!=NULL)
|
|
{
|
|
POSITION pos=AfxGetApp()->m_pDocManager->GetFirstDocTemplatePosition();
|
|
while(pos!=NULL)
|
|
{
|
|
CDocTemplate* pTemplate=
|
|
AfxGetApp()->m_pDocManager->GetNextDocTemplate(pos);
|
|
ASSERT_KINDOF(CDocTemplate,pTemplate);
|
|
POSITION posDoc=pTemplate->GetFirstDocPosition();
|
|
while(posDoc!=NULL)
|
|
{
|
|
CDocument* pDoc=pTemplate->GetNextDoc(posDoc);
|
|
pDoc->SetModifiedFlag(FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ... When storing first establish the values off all properties
|
|
if (bComputeProperties)
|
|
ComputeProperties();
|
|
|
|
CString sValueName(pszValueName);
|
|
CString sCompany(pszCompany);
|
|
CString sApplication(pszApplication);
|
|
CString sContents;
|
|
|
|
if (sValueName.IsEmpty())
|
|
sValueName = szWorkspaceStateDefaultValue;
|
|
|
|
if (sCompany.IsEmpty())
|
|
sCompany = AfxGetApp()->m_pszRegistryKey;
|
|
if (sCompany.IsEmpty())
|
|
{
|
|
TRACE0("COXWorkspaceState::StoreToRegistry : No valid company name is provided, failing\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (sApplication.IsEmpty())
|
|
sApplication = AfxGetApp()->m_pszProfileName;
|
|
|
|
// Get the contents from the list
|
|
CByteArray binaryState;
|
|
|
|
BOOL bSuccess = GetBinaryWorkspaceState(&binaryState);
|
|
if (bSuccess)
|
|
bSuccess = StoreLoadRegistry(TRUE, sValueName, sCompany, sApplication, hKeyRoot, &binaryState);
|
|
|
|
#ifdef _DEBUG
|
|
if (!bSuccess)
|
|
TRACE0("COXWorkspaceState::StoreToRegistry : Failed to store to registry\n");
|
|
#endif // _DEBUG
|
|
|
|
ASSERT_VALID(this);
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL COXWorkspaceState::LoadFromRegistry(LPCTSTR pszValueName /* = NULL */,
|
|
LPCTSTR pszCompany /* = NULL */, LPCTSTR pszApplication /* = NULL*/ ,
|
|
HKEY hKeyRoot /* = HKEY_CURRENT_USER */, BOOL bApplyProperties /* = TRUE */)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
CString sValueName(pszValueName);
|
|
CString sCompany(pszCompany);
|
|
CString sApplication(pszApplication);
|
|
CString sContents;
|
|
|
|
if (sValueName.IsEmpty())
|
|
sValueName = szWorkspaceStateDefaultValue;
|
|
|
|
if (sCompany.IsEmpty())
|
|
sCompany = AfxGetApp()->m_pszRegistryKey;
|
|
if (sCompany.IsEmpty())
|
|
{
|
|
TRACE0("COXWorkspaceState::LoadFromRegistry : No valid company name is provided, failing\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (sApplication.IsEmpty())
|
|
sApplication = AfxGetApp()->m_pszProfileName;
|
|
|
|
// Get the contents from the list
|
|
CByteArray binaryState;
|
|
|
|
BOOL bSuccess = StoreLoadRegistry(FALSE, sValueName, sCompany, sApplication, hKeyRoot, &binaryState);
|
|
if (bSuccess)
|
|
bSuccess = SetBinaryWorkspaceState(&binaryState);
|
|
|
|
// ... When loading apply the just read properties
|
|
if (bApplyProperties && bSuccess)
|
|
ApplyProperties();
|
|
|
|
#ifdef _DEBUG
|
|
if (!bSuccess)
|
|
TRACE0("COXWorkspaceState::LoadFromRegistry : Failed to load from registry\n");
|
|
#endif // _DEBUG
|
|
|
|
ASSERT_VALID(this);
|
|
return bSuccess;
|
|
}
|
|
|
|
|
|
#ifdef _DEBUG
|
|
void COXWorkspaceState::AssertValid() const
|
|
{
|
|
CObject::AssertValid();
|
|
|
|
// The pointer object must always be valid and may never be NULL
|
|
ASSERT_VALID(m_pDockState);
|
|
ASSERT_VALID(m_pChildFrameStates);
|
|
ASSERT_VALID(m_pSplitterPanes);
|
|
}
|
|
|
|
void COXWorkspaceState::Dump(CDumpContext& dc) const
|
|
{
|
|
CObject::Dump(dc);
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
COXWorkspaceState::~COXWorkspaceState()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// Empty all lists
|
|
EmptyChildFrames(m_pChildFrameStates);
|
|
EmptySplitterPanes(m_pSplitterPanes);
|
|
|
|
// Delete dynamically created members
|
|
delete m_pDockState;
|
|
m_pDockState = NULL;
|
|
delete m_pChildFrameStates;
|
|
m_pChildFrameStates = NULL;
|
|
delete m_pSplitterPanes;
|
|
m_pSplitterPanes = NULL;
|
|
}
|
|
|
|
// protected:
|
|
void COXWorkspaceState::Initialize()
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Initialized the data members of this object
|
|
{
|
|
m_screenSize.cx = ::GetSystemMetrics(SM_CXSCREEN);
|
|
m_screenSize.cy = ::GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
m_bSaveMainWndProps = TRUE;
|
|
::ZeroMemory(&m_mainWndPlacement, sizeof(WINDOWPLACEMENT));
|
|
|
|
m_bSaveBarProps = TRUE;
|
|
if (m_pDockState == NULL)
|
|
m_pDockState = new CDockState();
|
|
m_pDockState->Clear();
|
|
|
|
if (m_pChildFrameStates == NULL)
|
|
m_pChildFrameStates = new CObArray();
|
|
m_bSaveChildFrames = TRUE;
|
|
m_bSaveSplitterPanes = TRUE;
|
|
EmptyChildFrames(m_pChildFrameStates);
|
|
|
|
m_bSaveSplitterPanes = TRUE;
|
|
if (m_pSplitterPanes == NULL)
|
|
m_pSplitterPanes = new CObArray();
|
|
EmptySplitterPanes(m_pSplitterPanes);
|
|
|
|
m_nSerializeSchemaVersionLoad = -1;
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
BOOL COXWorkspaceState::ComputeChildFrameState()
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : Whether it succeeded or not
|
|
// --- Effect : Computes all the states of the child frame windows and adds them
|
|
// to an internal collection
|
|
{
|
|
// Iterate all views
|
|
POSITION MDIChildWndPos = NULL;
|
|
CFrameWnd* pFrameWnd = NULL;
|
|
|
|
BOOL bAllSucceeded = TRUE;
|
|
|
|
MDIChildWndPos = GetFirstMDIChildWndPosition();
|
|
while(MDIChildWndPos != NULL)
|
|
{
|
|
pFrameWnd = GetNextMDIChildWnd(MDIChildWndPos);
|
|
ASSERT(pFrameWnd != NULL);
|
|
|
|
COXChildFrameState* pChildFrameState = new COXChildFrameState;
|
|
pChildFrameState->IncludeSplitterPane(m_bSaveSplitterPanes);
|
|
if (pChildFrameState->ComputeProperties(pFrameWnd))
|
|
m_pChildFrameStates->Add(pChildFrameState);
|
|
else
|
|
{
|
|
TRACE0("COXWorkspaceState::ComputeChildFrameState : Failed to compute properties\n");
|
|
bAllSucceeded = FALSE;
|
|
delete pChildFrameState;
|
|
}
|
|
}
|
|
|
|
return bAllSucceeded;
|
|
}
|
|
|
|
BOOL COXWorkspaceState::ApplyChildFrameState() const
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : Whether it succeeded or not
|
|
// --- Effect : Applies all the states of the child frame windows that are in the
|
|
// internal collection
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
BOOL bAllSucceeded = TRUE;
|
|
|
|
// Delegate the apply to all the child frame states in our list
|
|
// Iterate the child frame sates in backward direction, this way
|
|
// the last handles child will become the active one
|
|
int nChildFrameIndex = 0;
|
|
COXChildFrameState* pChildFrameState = NULL;
|
|
for (nChildFrameIndex = PtrToInt(m_pChildFrameStates->GetSize() - 1); 0 <= nChildFrameIndex ; nChildFrameIndex--)
|
|
{
|
|
pChildFrameState = DYNAMIC_DOWNCAST(COXChildFrameState, m_pChildFrameStates->GetAt(nChildFrameIndex));
|
|
if (pChildFrameState != NULL)
|
|
if (!pChildFrameState->ApplyProperties())
|
|
{
|
|
TRACE0("COXChildFrameState::ApplyChildFrameState : Failed to apply properties\n");
|
|
bAllSucceeded = FALSE;
|
|
}
|
|
}
|
|
|
|
ASSERT_VALID(this);
|
|
return bAllSucceeded;
|
|
}
|
|
|
|
void COXWorkspaceState::StoreProperties(CArchive& ar)
|
|
// --- In : ar : Archive used in serialization
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Stores the properties of this object to archive
|
|
// This action may throw an exception on failure
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(ar.IsStoring());
|
|
|
|
// Some sanity checks
|
|
ASSERT((m_bSaveMainWndProps == FALSE) || (m_bSaveMainWndProps == TRUE));
|
|
ASSERT((m_bSaveBarProps == FALSE) || (m_bSaveBarProps == TRUE));
|
|
ASSERT((m_bSaveChildFrames == FALSE) || (m_bSaveChildFrames == TRUE));
|
|
ASSERT((m_bSaveSplitterPanes == FALSE) || (m_bSaveSplitterPanes == TRUE));
|
|
|
|
// ... General
|
|
ar << m_screenSize;
|
|
|
|
// ... Main window
|
|
ar << m_bSaveMainWndProps;
|
|
ar << m_mainWndPlacement.flags;
|
|
ar << m_mainWndPlacement.showCmd;
|
|
ar << m_mainWndPlacement.ptMinPosition;
|
|
ar << m_mainWndPlacement.ptMaxPosition;
|
|
ar << m_mainWndPlacement.rcNormalPosition;
|
|
|
|
// ... Bars
|
|
ar << m_bSaveBarProps;
|
|
ar << m_pDockState;
|
|
|
|
// ... Child frames
|
|
ar << m_bSaveChildFrames;
|
|
ar << m_bSaveSplitterPanes;
|
|
ar << m_pChildFrameStates;
|
|
|
|
m_mapBarID2TabIdx.Serialize(ar);
|
|
|
|
// ... Splitter panes
|
|
ar << m_bSaveSplitterPanes;
|
|
ar << m_pSplitterPanes;
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
void COXWorkspaceState::LoadProperties(CArchive& ar)
|
|
// --- In : ar : Archive used in serialization
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : loads the properties of this object from archive
|
|
// This action may throw an exception on failure
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(ar.IsLoading());
|
|
|
|
// ... General
|
|
ar >> m_screenSize;
|
|
|
|
// ... Main window
|
|
ar >> m_bSaveMainWndProps;
|
|
ar >> m_mainWndPlacement.flags;
|
|
ar >> m_mainWndPlacement.showCmd;
|
|
ar >> m_mainWndPlacement.ptMinPosition;
|
|
ar >> m_mainWndPlacement.ptMaxPosition;
|
|
ar >> m_mainWndPlacement.rcNormalPosition;
|
|
|
|
// ... Bars
|
|
CDockState* pOldDockState = NULL;
|
|
ar >> m_bSaveBarProps;
|
|
pOldDockState = m_pDockState;
|
|
ar >> m_pDockState;
|
|
delete pOldDockState;
|
|
|
|
// ... Child frames
|
|
ar >> m_bSaveChildFrames;
|
|
ar >> m_bSaveSplitterPanes;
|
|
CObArray* pOldChildFrameStates = NULL;
|
|
pOldChildFrameStates = m_pChildFrameStates;
|
|
ar >> m_pChildFrameStates;
|
|
EmptyChildFrames(pOldChildFrameStates);
|
|
delete pOldChildFrameStates;
|
|
|
|
m_mapBarID2TabIdx.RemoveAll();
|
|
m_mapBarID2TabIdx.Serialize(ar);
|
|
|
|
// ... Splitter panes
|
|
ar >> m_bSaveSplitterPanes;
|
|
CObArray* pOldSplitterPanes= NULL;
|
|
pOldSplitterPanes = m_pSplitterPanes;
|
|
ar >> m_pSplitterPanes;
|
|
EmptySplitterPanes(pOldSplitterPanes);
|
|
delete pOldSplitterPanes;
|
|
|
|
// Some sanity checks
|
|
ASSERT((m_bSaveMainWndProps == FALSE) || (m_bSaveMainWndProps == TRUE));
|
|
ASSERT((m_bSaveBarProps == FALSE) || (m_bSaveBarProps == TRUE));
|
|
ASSERT((m_bSaveChildFrames == FALSE) || (m_bSaveChildFrames == TRUE));
|
|
ASSERT((m_bSaveSplitterPanes == FALSE) || (m_bSaveSplitterPanes == TRUE));
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
void COXWorkspaceState::StoreLoadFile(LPCTSTR pszPath, BOOL bStoring)
|
|
// --- In : pszPath : The file path to use
|
|
// bStoring : Whether the properties should be stored or loaded
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Stores or loads the properties of this object by using a file
|
|
// This action may throw an exception on failure
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// Open the file
|
|
CFile file;
|
|
CFileException* pxFile = NULL;
|
|
UINT nOpenFlags = 0;
|
|
|
|
if (bStoring)
|
|
nOpenFlags = CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive;
|
|
else
|
|
nOpenFlags = CFile::modeRead | CFile::shareDenyWrite;
|
|
pxFile = new CFileException;
|
|
if (!file.Open(pszPath, nOpenFlags, pxFile))
|
|
THROW(pxFile);
|
|
else
|
|
pxFile->Delete();
|
|
|
|
// Wrap a CArchive around it
|
|
CArchive ar(&file, bStoring ? CArchive::store : CArchive::load);
|
|
|
|
// Serialize the properties
|
|
Serialize(ar);
|
|
|
|
// Clean everything up
|
|
ar.Close();
|
|
file.Close();
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
|
|
BOOL COXWorkspaceState::SetBinaryWorkspaceState(CByteArray* pBinaryState)
|
|
// --- In : pBinaryState : Valid CByteArray object
|
|
// --- Out :
|
|
// --- Returns : Whether it succeeded or not
|
|
// --- Effect : Serializes a binary represntation to this object (load)
|
|
{
|
|
ASSERT(pBinaryState != NULL);
|
|
ASSERT_VALID(this);
|
|
|
|
BOOL bSuccess = TRUE;
|
|
TRY
|
|
{
|
|
// Use a memory file to serialize the data in memory
|
|
CMemFile memFile;
|
|
|
|
// Copy CByteArray to a memFile
|
|
BYTE* pBinData = NULL;
|
|
int nDataSize = 0;
|
|
|
|
nDataSize = PtrToInt(pBinaryState->GetSize());
|
|
pBinData = pBinaryState->GetData();
|
|
ASSERT((nDataSize == 0) || AfxIsValidAddress(pBinData, nDataSize, FALSE));
|
|
memFile.Write(pBinData, nDataSize);
|
|
memFile.Seek(0, CFile::begin);
|
|
|
|
// ... Wrap a CArchive around it
|
|
CArchive ar(&memFile, CArchive::load);
|
|
// ... Serialize the properties
|
|
Serialize(ar);
|
|
|
|
// Clean everything up
|
|
ar.Close();
|
|
memFile.Close();
|
|
}
|
|
CATCH_ALL(px)
|
|
{
|
|
#ifdef _DEBUG
|
|
const int nMaxErrorMsgLength = 1024;
|
|
CString sErrorMsg;
|
|
px->GetErrorMessage(sErrorMsg.GetBuffer(nMaxErrorMsgLength), nMaxErrorMsgLength);
|
|
sErrorMsg.ReleaseBuffer();
|
|
TRACE1("COXWorkspaceState::SetBinaryWorkspaceState : Catching CException (%s)\n", sErrorMsg);
|
|
#endif // _DEBUG
|
|
|
|
bSuccess = FALSE;
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
ASSERT_VALID(this);
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL COXWorkspaceState::GetBinaryWorkspaceState(CByteArray* pBinaryState)
|
|
// --- In : pBinaryState : Valid CByteArray object
|
|
// --- Out :
|
|
// --- Returns : Whether it succeeded or not
|
|
// --- Effect : Serializes this object to a binary represntation (store)
|
|
{
|
|
ASSERT(pBinaryState != NULL);
|
|
ASSERT_VALID(this);
|
|
|
|
BOOL bSuccess = TRUE;
|
|
TRY
|
|
{
|
|
// Use a memory file to serialize the data in memory
|
|
CMemFile memFile;
|
|
|
|
// ... Wrap a CArchive around it
|
|
CArchive ar(&memFile, CArchive::store);
|
|
// ... Serialize the properties
|
|
Serialize(ar);
|
|
// ... Flush and close
|
|
ar.Close();
|
|
|
|
// Copy memfile contents to CByteArray
|
|
BYTE* pBinData = NULL;
|
|
BYTE* pMemData = NULL;
|
|
int nDataSize = 0;
|
|
|
|
nDataSize = (int) memFile.GetLength();
|
|
pBinaryState->SetSize(nDataSize);
|
|
pBinData = pBinaryState->GetData();
|
|
ASSERT(AfxIsValidAddress(pBinData, nDataSize, TRUE));
|
|
pMemData = memFile.Detach();
|
|
ASSERT(AfxIsValidAddress(pMemData, nDataSize, FALSE));
|
|
::CopyMemory(pBinData, pMemData, nDataSize);
|
|
|
|
// Clean everything up
|
|
memFile.Close();
|
|
free(pMemData);
|
|
}
|
|
CATCH_ALL(px)
|
|
{
|
|
#ifdef _DEBUG
|
|
const int nMaxErrorMsgLength = 1024;
|
|
CString sErrorMsg;
|
|
px->GetErrorMessage(sErrorMsg.GetBuffer(nMaxErrorMsgLength), nMaxErrorMsgLength);
|
|
sErrorMsg.ReleaseBuffer();
|
|
TRACE1("COXWorkspaceState::GetBinaryWorkspaceState : Catching CException (%s)\n", sErrorMsg);
|
|
#endif // _DEBUG
|
|
|
|
bSuccess = FALSE;
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
ASSERT_VALID(this);
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL COXWorkspaceState::StoreLoadRegistry(BOOL bStoring, LPCTSTR pszValueName,
|
|
LPCTSTR pszCompany, LPCTSTR pszApplication, HKEY hKeyRoot, CByteArray* pBinaryState)
|
|
// --- In : bStoring : Whether the value should be stored or loaded
|
|
// pszValueName The name of the value to set.
|
|
// (A default name will be used when this is NULL)
|
|
// pszCompany : The name of the subkey with which a value is associated.
|
|
// If the parameter is NULL, AfxGetApp()->m_pszRegistryKey is used
|
|
// (use AfxGetApp()->SetRegistryKey() to set this to your company name)
|
|
// pszApplication : Name of this application
|
|
// If the paramater is NULL, AfxGetApp()->m_pszProfileName is used
|
|
// hKeyRoot : An open key in the registry or any of the following predefined handle values:
|
|
// HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS
|
|
// bSaveOpenDocs : Whether open document that have been changed should be
|
|
// saved first (unnamed docs will then receive a name)
|
|
// bComputeProperties : Whether the current workspace should be recomputed
|
|
// (Same as ComputeProperties())
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Stores or loads the properties of this object using the registry
|
|
{
|
|
ASSERT(hKeyRoot != NULL);
|
|
ASSERT((pszCompany != NULL) && (*pszCompany != _T('\0')));
|
|
ASSERT((pszApplication != NULL) && (*pszApplication != _T('\0')));
|
|
ASSERT((pszValueName != NULL) && (*pszValueName != _T('\0')));
|
|
ASSERT(pBinaryState != NULL);
|
|
|
|
REGSAM samDesired = 0;
|
|
if (bStoring)
|
|
samDesired = KEY_WRITE | KEY_READ;
|
|
else
|
|
samDesired = KEY_READ;
|
|
|
|
// Open key for hKeyRoot\<szSoftware>\<pszCompany>\<pszApplication>\<szWorkspaceState>
|
|
HKEY hSoftwareKey = NULL;
|
|
HKEY hCompanyKey = NULL;
|
|
HKEY hApplicationKey = NULL;
|
|
HKEY hWorkspaceKey = NULL;
|
|
if (::RegOpenKeyEx(hKeyRoot, szSoftware, 0, samDesired,
|
|
&hSoftwareKey) == ERROR_SUCCESS)
|
|
{
|
|
DWORD dw;
|
|
if (::RegCreateKeyEx(hSoftwareKey, pszCompany, 0, REG_NONE,
|
|
REG_OPTION_NON_VOLATILE, samDesired, NULL, &hCompanyKey, &dw) == ERROR_SUCCESS)
|
|
{
|
|
if (::RegCreateKeyEx(hCompanyKey, pszApplication, 0, REG_NONE,
|
|
REG_OPTION_NON_VOLATILE, samDesired, NULL, &hApplicationKey, &dw) == ERROR_SUCCESS)
|
|
{
|
|
::RegCreateKeyEx(hApplicationKey, szWorkspaceState, 0, REG_NONE,
|
|
REG_OPTION_NON_VOLATILE, samDesired, NULL, &hWorkspaceKey, &dw);
|
|
}
|
|
}
|
|
}
|
|
if (hSoftwareKey != NULL)
|
|
::RegCloseKey(hSoftwareKey);
|
|
if (hCompanyKey != NULL)
|
|
::RegCloseKey(hCompanyKey);
|
|
if (hApplicationKey != NULL)
|
|
::RegCloseKey(hApplicationKey);
|
|
|
|
if (hWorkspaceKey == NULL)
|
|
{
|
|
TRACE0("COXWorkspaceState::StoreLoadRegistry : Failed to open workspace key, failing\n");
|
|
if (!bStoring)
|
|
pBinaryState->RemoveAll();
|
|
return FALSE;
|
|
}
|
|
|
|
LONG nResult = 0;
|
|
if (bStoring)
|
|
{
|
|
// Store the value
|
|
nResult = ::RegSetValueEx(hWorkspaceKey, pszValueName, NULL, REG_BINARY,
|
|
(LPBYTE)pBinaryState->GetData(), PtrToLong(pBinaryState->GetSize()));
|
|
}
|
|
else
|
|
{
|
|
// Load the value
|
|
DWORD dwType, dwCount;
|
|
nResult = ::RegQueryValueEx(hWorkspaceKey, (LPTSTR)pszValueName, NULL, &dwType,
|
|
NULL, &dwCount);
|
|
if (nResult == ERROR_SUCCESS)
|
|
{
|
|
// ... Workspace must be save in binary format
|
|
ASSERT(dwType == REG_BINARY);
|
|
pBinaryState->SetSize(dwCount);
|
|
nResult = ::RegQueryValueEx(hWorkspaceKey, (LPTSTR)pszValueName, NULL, &dwType,
|
|
(LPBYTE)pBinaryState->GetData(), &dwCount);
|
|
ASSERT(dwType == REG_BINARY);
|
|
}
|
|
}
|
|
::RegCloseKey(hWorkspaceKey);
|
|
|
|
if (nResult != ERROR_SUCCESS)
|
|
{
|
|
TRACE1("COXWorkspaceState::StoreLoadRegistry : Failed to access workspace value (%s), failing\n",
|
|
pszValueName);
|
|
if (!bStoring)
|
|
pBinaryState->RemoveAll();
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void COXWorkspaceState::EmptyChildFrames(CObArray* pChildFrameStates)
|
|
// --- In : pChildFrameStates: Collection to use
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Clears the collection by deleting all its members and
|
|
// clearing the collection itself
|
|
{
|
|
ASSERT_VALID(pChildFrameStates);
|
|
|
|
int nChildFrameIndex = 0;
|
|
CObject* pChildFrameState = NULL;
|
|
for (nChildFrameIndex = 0; nChildFrameIndex < pChildFrameStates->GetSize(); nChildFrameIndex++)
|
|
{
|
|
pChildFrameState = pChildFrameStates->GetAt(nChildFrameIndex);
|
|
delete pChildFrameState;
|
|
pChildFrameStates->SetAt(nChildFrameIndex, NULL);
|
|
}
|
|
pChildFrameStates->RemoveAll();
|
|
}
|
|
|
|
POSITION COXWorkspaceState::GetFirstMDIChildWndPosition()
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : The first position of the child windows
|
|
// (NULL if the end has been reached)
|
|
// --- Effect : Used to iterate all the MDI child windows
|
|
{
|
|
CMDIFrameWnd* pMainMDIFrameWnd = DYNAMIC_DOWNCAST(CMDIFrameWnd, AfxGetMainWnd());
|
|
if (pMainMDIFrameWnd == NULL)
|
|
{
|
|
TRACE0("COXWorkspaceState::GetFirstMDIChildWndPosition : Unable to get the main frame window\n");
|
|
return NULL;
|
|
}
|
|
|
|
HWND hChildWnd = ::GetWindow(pMainMDIFrameWnd->m_hWndMDIClient, GW_CHILD);
|
|
CWnd* pChildWnd = CWnd::FromHandlePermanent(hChildWnd);
|
|
CMDIChildWnd* pMDIChildWnd = DYNAMIC_DOWNCAST(CMDIChildWnd, pChildWnd);
|
|
if ((pMDIChildWnd != NULL) && (pMDIChildWnd->GetWindow(GW_OWNER) == NULL))
|
|
return (POSITION)hChildWnd;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
CMDIChildWnd* COXWorkspaceState::GetNextMDIChildWnd(POSITION& pos)
|
|
// --- In : pos : The current position in the iteration
|
|
// --- Out : The next position in the iteration (NULL if the end has been reached)
|
|
// --- Returns : The current child frame window
|
|
// --- Effect : Used to iterate all the MDI child windows
|
|
{
|
|
CMDIChildWnd* pPrevMDIChildWnd = DYNAMIC_DOWNCAST(CMDIChildWnd,
|
|
CWnd::FromHandlePermanent((HWND)pos));
|
|
ASSERT(pPrevMDIChildWnd != NULL);
|
|
|
|
HWND hChildWnd = ::GetWindow(pPrevMDIChildWnd->GetSafeHwnd(), GW_HWNDNEXT);
|
|
CWnd* pChildWnd = CWnd::FromHandlePermanent(hChildWnd);
|
|
CMDIChildWnd* pMDIChildWnd = DYNAMIC_DOWNCAST(CMDIChildWnd, pChildWnd);
|
|
if ((pMDIChildWnd != NULL) && (pMDIChildWnd->GetWindow(GW_OWNER) == NULL))
|
|
pos = (POSITION)hChildWnd;
|
|
else
|
|
pos = NULL;
|
|
|
|
return pPrevMDIChildWnd;
|
|
}
|
|
|
|
BOOL COXWorkspaceState::ComputeSplitterPanes(CFrameWnd* pFrameWnd)
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : Whether it succeeded or not
|
|
// --- Effect : Computes all the states of the splitter panes and adds them
|
|
// to an internal collection
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// Check for a CSplitterWnd child window
|
|
CSplitterWnd* pSplitterWnd = GetSplitterWindow(pFrameWnd);
|
|
if (pSplitterWnd == NULL)
|
|
// ... No splitter window found : nothing to do
|
|
return TRUE;
|
|
|
|
BOOL bAllSucceeded = TRUE;
|
|
int nRowColIndex = 0;
|
|
|
|
// Calculate the row properties
|
|
for (nRowColIndex = 0; nRowColIndex < pSplitterWnd->GetRowCount(); nRowColIndex++)
|
|
{
|
|
COXSplitterColRowState* pSplitterColRowState = new COXSplitterColRowState;
|
|
if (pSplitterColRowState->ComputeProperties(pSplitterWnd, nRowColIndex, TRUE))
|
|
m_pSplitterPanes->Add(pSplitterColRowState);
|
|
else
|
|
{
|
|
TRACE0("COXChildFrameState::ComputeSplitterPanes : Failed to compute properties (row)\n");
|
|
bAllSucceeded = FALSE;
|
|
delete pSplitterColRowState;
|
|
}
|
|
}
|
|
|
|
// Calculate the column properties
|
|
for (nRowColIndex = 0; nRowColIndex < pSplitterWnd->GetColumnCount(); nRowColIndex++)
|
|
{
|
|
COXSplitterColRowState* pSplitterColRowState = new COXSplitterColRowState;
|
|
if (pSplitterColRowState->ComputeProperties(pSplitterWnd, nRowColIndex, FALSE))
|
|
m_pSplitterPanes->Add(pSplitterColRowState);
|
|
else
|
|
{
|
|
TRACE0("COXChildFrameState::ComputeSplitterPanes : Failed to compute properties (column)\n");
|
|
bAllSucceeded = FALSE;
|
|
delete pSplitterColRowState;
|
|
}
|
|
}
|
|
|
|
ASSERT_VALID(this);
|
|
return bAllSucceeded;
|
|
}
|
|
|
|
BOOL COXWorkspaceState::ApplySplitterPanes(CFrameWnd* pFrameWnd) const
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : Whether it succeeded or not
|
|
// --- Effect : Applies all the states of the splitter panes that are in the
|
|
// internal collection
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// Check for a CSplitterWnd child window
|
|
CSplitterWnd* pSplitterWnd = GetSplitterWindow(pFrameWnd);
|
|
if (pSplitterWnd == NULL)
|
|
// ... No splitter window found : nothing to do
|
|
return TRUE;
|
|
|
|
BOOL bAllSucceeded = TRUE;
|
|
int nSplitterColRowStateIndex = 0;
|
|
COXSplitterColRowState* pSplitterColRowState = NULL;
|
|
for(nSplitterColRowStateIndex = 0;
|
|
nSplitterColRowStateIndex < m_pSplitterPanes->GetSize();
|
|
nSplitterColRowStateIndex++)
|
|
{
|
|
pSplitterColRowState = DYNAMIC_DOWNCAST(COXSplitterColRowState,
|
|
m_pSplitterPanes->GetAt(nSplitterColRowStateIndex));
|
|
if (pSplitterColRowState != NULL)
|
|
{
|
|
if (!pSplitterColRowState->ApplyProperties(pSplitterWnd))
|
|
{
|
|
TRACE0("COXChildFrameState::ApplySplitterPanes : Failed to apply properties\n");
|
|
bAllSucceeded = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Make the changes visible
|
|
pSplitterWnd->RecalcLayout();
|
|
|
|
ASSERT_VALID(this);
|
|
return bAllSucceeded;
|
|
}
|
|
|
|
void COXWorkspaceState::EmptySplitterPanes(CObArray* pSplitterPanes)
|
|
// --- In : pSplitterPanes: Collection to use
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Clears the collection by deleting all its members and
|
|
// clearing the collection itself
|
|
{
|
|
ASSERT_VALID(pSplitterPanes);
|
|
|
|
int nSplitterColRowStateIndex = 0;
|
|
CObject* pSplitterColRowState = NULL;
|
|
for (nSplitterColRowStateIndex = 0; nSplitterColRowStateIndex < pSplitterPanes->GetSize(); nSplitterColRowStateIndex++)
|
|
{
|
|
pSplitterColRowState = pSplitterPanes->GetAt(nSplitterColRowStateIndex);
|
|
delete pSplitterColRowState;
|
|
pSplitterPanes->SetAt(nSplitterColRowStateIndex, NULL);
|
|
}
|
|
pSplitterPanes->RemoveAll();
|
|
}
|
|
|
|
CSplitterWnd* COXWorkspaceState::GetSplitterWindow(CFrameWnd* pFrameWnd)
|
|
// --- In : pFrameWnd : The MDI child frame to use
|
|
// --- Out :
|
|
// --- Returns : The splitter window of the specified frame or NULL otherwise
|
|
// --- Effect : When spliiter windows are nested, only the top level window is used
|
|
{
|
|
if (pFrameWnd == NULL)
|
|
return NULL;
|
|
|
|
// Search all children for a CSplitterWnd derived object
|
|
HWND hChildWnd = NULL;
|
|
CWnd* pChildWnd = NULL;
|
|
CSplitterWnd* pSplitterWnd = NULL;
|
|
|
|
hChildWnd = ::GetWindow(pFrameWnd->GetSafeHwnd(), GW_CHILD);
|
|
pChildWnd = CWnd::FromHandlePermanent(hChildWnd);
|
|
pSplitterWnd = DYNAMIC_DOWNCAST(CSplitterWnd, pChildWnd);
|
|
while ((hChildWnd != NULL) && (pSplitterWnd == NULL))
|
|
{
|
|
hChildWnd = ::GetWindow(hChildWnd, GW_HWNDNEXT);
|
|
pChildWnd = CWnd::FromHandlePermanent(hChildWnd);
|
|
pSplitterWnd = DYNAMIC_DOWNCAST(CSplitterWnd, pChildWnd);
|
|
}
|
|
|
|
return pSplitterWnd;
|
|
}
|
|
|
|
void COXWorkspaceState::ComputeDockingWindowsState(CPtrArray& aryBarInfo)
|
|
{
|
|
// Get the main window and the main frame
|
|
CFrameWnd* pMainFrame = NULL;
|
|
CWnd* pMainWnd = AfxGetMainWnd();
|
|
if (pMainWnd != NULL)
|
|
pMainFrame = pMainWnd->GetTopLevelFrame();
|
|
|
|
// Loop through all control bars and populate the m_mapBarID2TabIdx map
|
|
m_mapBarID2TabIdx.RemoveAll();
|
|
int iSize = PtrToInt(aryBarInfo.GetSize());
|
|
for (int i = 0; i < iSize; i++)
|
|
{
|
|
CControlBarInfo* pInfo = (CControlBarInfo*) aryBarInfo[i];
|
|
ASSERT(pInfo != NULL);
|
|
pInfo->m_pBar = pMainFrame->GetControlBar(pInfo->m_nBarID);
|
|
if (pInfo->m_pBar != NULL)
|
|
{
|
|
COXSizeControlBar* pSzBar = DYNAMIC_DOWNCAST(COXSizeControlBar, pInfo->m_pBar);
|
|
if (pSzBar != NULL)
|
|
{
|
|
// Get the tab index
|
|
COXSizeDockBar* pSzDockBar = (COXSizeDockBar*) pSzBar->m_pDockBar;
|
|
if (pSzDockBar != NULL && ::IsWindow(pSzDockBar->m_wndDockTabCtrl))
|
|
{
|
|
OXDOCKTABPOSITION oxdtp;
|
|
oxdtp.nControlBarID = pInfo->m_nBarID;
|
|
oxdtp.nDockBarID = pSzDockBar->GetDlgCtrlID();
|
|
oxdtp.iTabIndex = pSzDockBar->m_wndDockTabCtrl.FindTab(pSzBar);
|
|
if (oxdtp.iTabIndex == pSzDockBar->m_wndDockTabCtrl.GetCurSel())
|
|
oxdtp.bSelected = TRUE;
|
|
else
|
|
oxdtp.bSelected = FALSE;
|
|
|
|
m_mapBarID2TabIdx.SetAt(pInfo->m_nBarID, oxdtp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void COXWorkspaceState::ApplyDockingWindowsState(CPtrArray& aryBarInfo) const
|
|
{
|
|
// Get the main window and the main frame
|
|
CFrameWnd* pMainFrame = NULL;
|
|
CWnd* pMainWnd = AfxGetMainWnd();
|
|
if (pMainWnd != NULL)
|
|
pMainFrame = pMainWnd->GetTopLevelFrame();
|
|
|
|
// Loop through all control bars and add then to their appropriate tab
|
|
int iSize = PtrToInt(aryBarInfo.GetSize());
|
|
for (int i = 0; i < iSize; i++)
|
|
{
|
|
CControlBarInfo* pInfo = (CControlBarInfo*) aryBarInfo[i];
|
|
ASSERT(pInfo != NULL);
|
|
pInfo->m_pBar = pMainFrame->GetControlBar(pInfo->m_nBarID);
|
|
if (pInfo->m_pBar != NULL)
|
|
{
|
|
COXSizeControlBar* pSzBar = DYNAMIC_DOWNCAST(COXSizeControlBar, pInfo->m_pBar);
|
|
if (pSzBar != NULL)
|
|
{
|
|
// Lookup this bar in m_mapBarID2TabIdx
|
|
OXDOCKTABPOSITION oxdtp;
|
|
BOOL bFound = m_mapBarID2TabIdx.Lookup(pInfo->m_nBarID, oxdtp);
|
|
|
|
if (bFound && oxdtp.iTabIndex != -1)
|
|
{
|
|
// Add this bar to its tab control
|
|
DWORD arDockPos[4] = {AFX_IDW_DOCKBAR_LEFT, AFX_IDW_DOCKBAR_RIGHT,
|
|
AFX_IDW_DOCKBAR_TOP, AFX_IDW_DOCKBAR_BOTTOM};
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
COXSizeDockBar* pDockBar = DYNAMIC_DOWNCAST(COXSizeDockBar,
|
|
pMainFrame->GetControlBar(arDockPos[i]));
|
|
if (pDockBar != NULL && oxdtp.nDockBarID == arDockPos[i])
|
|
{
|
|
// This is the one
|
|
int iIndex = pDockBar->m_wndDockTabCtrl.FindTab(pSzBar);
|
|
if (iIndex == -1)
|
|
{
|
|
// Remove if tabbed to another dockbar
|
|
/*
|
|
COXSizeDockBar* pOtherDockBar = DYNAMIC_DOWNCAST(COXSizeDockBar, pSzBar->m_pDockBar);
|
|
if (pOtherDockBar != pDockBar)
|
|
{
|
|
}
|
|
*/
|
|
pDockBar->m_wndDockTabCtrl.InsertTab(pSzBar, oxdtp.iTabIndex, TRUE);
|
|
|
|
|
|
|
|
}
|
|
/*
|
|
if (oxdtp.bSelected)
|
|
{
|
|
pDockBar->m_wndDockTabCtrl.SetCurSel(oxdtp.iTabIndex);
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Remove this from its tab control
|
|
|
|
// Check the left, top, right and bottom dock bars
|
|
DWORD arDockPos[4] = {AFX_IDW_DOCKBAR_LEFT, AFX_IDW_DOCKBAR_RIGHT,
|
|
AFX_IDW_DOCKBAR_TOP, AFX_IDW_DOCKBAR_BOTTOM};
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
COXSizeDockBar* pDockBar = DYNAMIC_DOWNCAST(COXSizeDockBar,
|
|
pMainFrame->GetControlBar(arDockPos[i]));
|
|
if (pDockBar != NULL)
|
|
{
|
|
int iIndex = pDockBar->m_wndDockTabCtrl.FindTab(pSzBar);
|
|
if (iIndex != -1)
|
|
pDockBar->m_wndDockTabCtrl.RemoveTab(pSzBar);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// private:
|
|
|
|
#endif // _MFC_VER
|
|
// ==========================================================================
|