// cdxCDynamicWndEx.cpp: implementation of the cdxCDynamicWndEx class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "cdxCDynamicWndEx.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
/////////////////////////////////////////////////////////////////////////////
// Some static variables (taken from cdxCDynamicControlsManager)
/////////////////////////////////////////////////////////////////////////////
#define REGVAL_NOSTATE -1
#define REGVAL_VISIBLE 1
#define REGVAL_HIDDEN 0
#define REGVAL_MAXIMIZED 1
#define REGVAL_ICONIC 0
#define REGVAL_INVALID 0
#define REGVAL_VALID 1
/*
* registry value names
* (for StoreWindowPosition()/RestoreWindowPosition())
*/
static LPCTSTR lpszRegVal_Left = _T("Left"),
lpszRegVal_Right = _T("Right"),
lpszRegVal_Top = _T("Top"),
lpszRegVal_Bottom = _T("Bottom"),
lpszRegVal_Visible = _T("Visibility"),
lpszRegVal_State = _T("State"),
lpszRegVal_Valid = _T("(valid)");
LPCTSTR cdxCDynamicWndEx::M_lpszAutoPosProfileSection = _T("WindowPositions");
/////////////////////////////////////////////////////////////////////////////
// cdxCDynamicWndEx
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// cdxCDynamicWndEx stretches windows
/////////////////////////////////////////////////////////////////////////////
static inline CString _makeFullProfile(LPCTSTR lpszBase, const CString & str)
{
CString s = lpszBase;
if(s.GetLength() && (s[s.GetLength()-1] != _T('\\')))
s += _T('\\');
s += str;
return s;
}
void cdxCDynamicWndEx::OnInitialized()
{
ASSERT(IsWindow());
if(!m_strAutoPos.IsEmpty())
{
if(!RestoreWindowPosition(_makeFullProfile(M_lpszAutoPosProfileSection,m_strAutoPos),rflg_all))
{
Window()->CenterWindow();
StretchWindow(0);
}
}
}
void cdxCDynamicWndEx::OnDestroying()
{
if(!m_strAutoPos.IsEmpty() && IsWindow())
StoreWindowPosition(_makeFullProfile(M_lpszAutoPosProfileSection,m_strAutoPos));
}
/////////////////////////////////////////////////////////////////////////////
// cdxCDynamicWndEx stretches windows
/////////////////////////////////////////////////////////////////////////////
/*
* stretches the window by szDelta (i.e. if szDelta is 100, the window is enlarged by 100 pixels)
* stretching means that the center point of the window remains
*
* returns false if the window would be smaller than (1,1)
*
* NOTE: this function does NOT care of the min/max dimensions of a window
* Use MoveWindow() if you need to take care of it.
*
* STATIC
*/
bool cdxCDynamicWndEx::StretchWindow(const CSize & szDelta)
{
if(!IsWindow())
{
ASSERT(false);
return false;
}
CWnd *pWnd = Window();
WINDOWPLACEMENT wpl;
pWnd->GetWindowPlacement(&wpl);
wpl.rcNormalPosition.left -= szDelta.cx / 2;
wpl.rcNormalPosition.right += (szDelta.cx + 1) / 2;
wpl.rcNormalPosition.top -= szDelta.cy / 2;
wpl.rcNormalPosition.bottom += (szDelta.cy + 1) / 2;
// wpl.flags = SW_SHOWNA|SW_SHOWNOACTIVATE;
if((wpl.rcNormalPosition.left >= wpl.rcNormalPosition.right) ||
(wpl.rcNormalPosition.top >= wpl.rcNormalPosition.bottom))
return false;
VERIFY( pWnd->SetWindowPos(NULL,
wpl.rcNormalPosition.left,
wpl.rcNormalPosition.top,
wpl.rcNormalPosition.right - wpl.rcNormalPosition.left,
wpl.rcNormalPosition.bottom - wpl.rcNormalPosition.top,
SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER) );
return true;
}
/*
* stretch window by a percent value
* the algorithm calculates the new size for both dimensions by:
*
* newWid = oldWid + (oldWid * iAddPcnt) / 100
*
* NOTE: iAddPcnt may even be nagtive, but it MUST be greater than -100.
* NOTE: this function does NOT care of the min/max dimensions of a window
*
* The function will return false if the new size would be empty.
*/
bool cdxCDynamicWndEx::StretchWindow(int iAddPcnt)
{
if(!IsWindow())
{
ASSERT(false);
return false;
}
CSize szDelta = GetCurrentClientSize() + GetBorderSize();
szDelta.cx = (szDelta.cx * iAddPcnt) / 100;
szDelta.cy = (szDelta.cy * iAddPcnt) / 100;
return StretchWindow(szDelta);
}
/////////////////////////////////////////////////////////////////////////////
// cdxCDynamicWndEx registry positioning
/////////////////////////////////////////////////////////////////////////////
/*
* stores a window's position and visiblity to the registry.
* return false if any error occured
*/
bool cdxCDynamicWndEx::StoreWindowPosition(LPCTSTR lpszProfile)
{
if(!IsWindow() || !lpszProfile || !*lpszProfile)
{
ASSERT(false);
return false;
}
CWnd *pWnd = Window();
WINDOWPLACEMENT wpl;
VERIFY( pWnd->GetWindowPlacement(&wpl) );
BOOL bVisible = pWnd->IsWindowVisible();
int iState = REGVAL_NOSTATE;
if(pWnd->IsIconic())
iState = REGVAL_ICONIC;
else
if(pWnd->IsZoomed())
iState = REGVAL_MAXIMIZED;
CWinApp *app = AfxGetApp();
if(!app->m_pszRegistryKey || !*app->m_pszRegistryKey)
{
TRACE(_T("*** NOTE[cdxCDynamicWndEx::StoreWindowPosition()]: To properly store and restore a window's position, please call CWinApp::SetRegistryKey() in you app's InitInstance() !\n"));
return false;
}
return app->WriteProfileInt(lpszProfile, lpszRegVal_Valid, REGVAL_INVALID) && // invalidate first
app->WriteProfileInt(lpszProfile, lpszRegVal_Left, wpl.rcNormalPosition.left) &&
app->WriteProfileInt(lpszProfile, lpszRegVal_Right, wpl.rcNormalPosition.right) &&
app->WriteProfileInt(lpszProfile, lpszRegVal_Top, wpl.rcNormalPosition.top) &&
app->WriteProfileInt(lpszProfile, lpszRegVal_Bottom, wpl.rcNormalPosition.bottom) &&
app->WriteProfileInt(lpszProfile, lpszRegVal_Visible, bVisible ? REGVAL_VISIBLE : REGVAL_HIDDEN) &&
app->WriteProfileInt(lpszProfile, lpszRegVal_State, iState) &&
app->WriteProfileInt(lpszProfile, lpszRegVal_Valid, REGVAL_VALID); // validate position
}
/*
* load the registry data stored by StoreWindowPosition()
* returns true if data have been found in the registry
*/
bool cdxCDynamicWndEx::RestoreWindowPosition(LPCTSTR lpszProfile, UINT restoreFlags)
{
if(!IsWindow() || !lpszProfile || !*lpszProfile)
{
ASSERT(false);
return false;
}
CWnd *pWnd = Window();
CWinApp *app = AfxGetApp();
if(!app->m_pszRegistryKey || !*app->m_pszRegistryKey)
{
TRACE(_T("*** NOTE[cdxCDynamicWndEx::RestoreWindowPosition()]: To properly store and restore a window's position, please call CWinApp::SetRegistryKey() in you app's InitInstance() !\n"));
return false;
}
//
// first, we check whether the position had been saved successful any time before
//
if( app->GetProfileInt(lpszProfile,lpszRegVal_Valid,REGVAL_INVALID) != REGVAL_VALID )
return false;
//
// get old position
//
WINDOWPLACEMENT wpl;
VERIFY( pWnd->GetWindowPlacement(&wpl) );
//
// read registry
//
int iState = app->GetProfileInt(lpszProfile, lpszRegVal_State, REGVAL_NOSTATE);
//
// get window's previous normal position
//
wpl.rcNormalPosition.left = app->GetProfileInt(lpszProfile, lpszRegVal_Left, wpl.rcNormalPosition.left);
wpl.rcNormalPosition.right = app->GetProfileInt(lpszProfile, lpszRegVal_Right, wpl.rcNormalPosition.right);
wpl.rcNormalPosition.top = app->GetProfileInt(lpszProfile, lpszRegVal_Top, wpl.rcNormalPosition.top);
wpl.rcNormalPosition.bottom = app->GetProfileInt(lpszProfile, lpszRegVal_Bottom, wpl.rcNormalPosition.bottom);
if(wpl.rcNormalPosition.left > wpl.rcNormalPosition.right)
{
long l = wpl.rcNormalPosition.right;
wpl.rcNormalPosition.right = wpl.rcNormalPosition.left;
wpl.rcNormalPosition.left = l;
}
if(wpl.rcNormalPosition.top > wpl.rcNormalPosition.bottom)
{
long l = wpl.rcNormalPosition.bottom;
wpl.rcNormalPosition.bottom = wpl.rcNormalPosition.top;
wpl.rcNormalPosition.top = l;
}
//
// get restore stuff
//
UINT showCmd = SW_SHOWNA;
if(restoreFlags & rflg_state)
{
if(iState == REGVAL_MAXIMIZED)
showCmd = SW_MAXIMIZE;
else
if(iState == REGVAL_ICONIC)
showCmd = SW_MINIMIZE;
}
//
// use MoveWindow() which takes care of WM_GETMINMAXINFO
//
pWnd->MoveWindow( wpl.rcNormalPosition.left,wpl.rcNormalPosition.top,
wpl.rcNormalPosition.right - wpl.rcNormalPosition.left,
wpl.rcNormalPosition.bottom - wpl.rcNormalPosition.top,
showCmd == SW_SHOWNA);
if(showCmd != SW_SHOWNA)
{
// read updated position
VERIFY( pWnd->GetWindowPlacement(&wpl) );
wpl.showCmd = showCmd;
pWnd->SetWindowPlacement(&wpl);
}
//
// get visiblity
//
if(restoreFlags & rflg_visibility)
{
int i = app->GetProfileInt(lpszProfile, lpszRegVal_Visible, REGVAL_NOSTATE);
if(i == REGVAL_VISIBLE)
pWnd->ShowWindow(SW_SHOW);
else
if(i == REGVAL_HIDDEN)
pWnd->ShowWindow(SW_HIDE);
}
return true;
}