123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- // ResizableSheet.cpp : implementation file
- //
- /////////////////////////////////////////////////////////////////////////////
- //
- // Copyright (C) 2000-2001 by Paolo Messina
- // (http://www.geocities.com/ppescher - ppescher@yahoo.com)
- //
- // The contents of this file are subject to the Artistic License (the "License").
- // You may not use this file except in compliance with the License.
- // You may obtain a copy of the License at:
- // http://www.opensource.org/licenses/artistic-license.html
- //
- // If you find this code useful, credits would be nice!
- //
- /////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "ResizableSheet.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CResizableSheet
- IMPLEMENT_DYNAMIC(CResizableSheet, CPropertySheet)
- inline void CResizableSheet::Construct()
- {
- m_bInitDone = FALSE;
- m_bEnableSaveRestore = FALSE;
- m_bSavePage = FALSE;
- }
- CResizableSheet::CResizableSheet()
- {
- Construct();
- }
- CResizableSheet::CResizableSheet(UINT nIDCaption, CWnd *pParentWnd, UINT iSelectPage)
- : CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
- {
- Construct();
- }
- CResizableSheet::CResizableSheet(LPCTSTR pszCaption, CWnd *pParentWnd, UINT iSelectPage)
- : CPropertySheet(pszCaption, pParentWnd, iSelectPage)
- {
- Construct();
- }
- CResizableSheet::~CResizableSheet()
- {
- }
- BEGIN_MESSAGE_MAP(CResizableSheet, CPropertySheet)
- //{{AFX_MSG_MAP(CResizableSheet)
- ON_WM_GETMINMAXINFO()
- ON_WM_SIZE()
- ON_WM_DESTROY()
- ON_WM_CREATE()
- ON_WM_ERASEBKGND()
- //}}AFX_MSG_MAP
- ON_NOTIFY_REFLECT_EX(PSN_SETACTIVE, OnPageChanging)
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CResizableSheet message handlers
- int CResizableSheet::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (CPropertySheet::OnCreate(lpCreateStruct) == -1)
- return -1;
-
- // keep client area
- CRect rect;
- GetClientRect(&rect);
- // set resizable style
- ModifyStyle(DS_MODALFRAME, WS_POPUP | WS_THICKFRAME);
- // adjust size to reflect new style
- ::AdjustWindowRectEx(&rect, GetStyle(),
- ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle());
- SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(), SWP_FRAMECHANGED|
- SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREPOSITION);
- if (!InitGrip())
- return -1;
- return 0;
- }
- BOOL CResizableSheet::OnInitDialog()
- {
- BOOL bResult = CPropertySheet::OnInitDialog();
-
- // set the initial size as the min track size
- CRect rc;
- GetWindowRect(&rc);
- SetMinTrackSize(rc.Size());
- // init
- UpdateGripPos();
- PresetLayout();
- // prevent flickering
- GetTabControl()->ModifyStyle(0, WS_CLIPSIBLINGS);
- m_bInitDone = TRUE;
- return bResult;
- }
- void CResizableSheet::OnDestroy()
- {
- if (m_bEnableSaveRestore)
- {
- SaveWindowRect(m_sSection, m_bRectOnly);
- SavePage();
- }
- RemoveAllAnchors();
- CPropertySheet::OnDestroy();
- }
- // maps an index to a button ID and vice-versa
- static UINT _propButtons[] =
- {
- IDOK, IDCANCEL, ID_APPLY_NOW, IDHELP,
- ID_WIZBACK, ID_WIZNEXT, ID_WIZFINISH
- };
- // horizontal line in wizard mode
- #define ID_WIZLINE ID_WIZFINISH+1
- void CResizableSheet::PresetLayout()
- {
- if (IsWizard()) // wizard mode
- {
- // hide tab control
- GetTabControl()->ShowWindow(SW_HIDE);
- AddAnchor(ID_WIZLINE, BOTTOM_LEFT, BOTTOM_RIGHT);
- }
- else // tab mode
- {
- AddAnchor(AFX_IDC_TAB_CONTROL, TOP_LEFT, BOTTOM_RIGHT);
- }
- // add a callback for active page (which can change at run-time)
- AddAnchorCallback(1);
- // use *total* parent size to have correct margins
- CRect rectPage, rectSheet;
- GetTotalClientRect(&rectSheet);
- GetActivePage()->GetWindowRect(&rectPage);
- ScreenToClient(&rectPage);
- // pre-calculate margins
- m_sizePageTL = rectPage.TopLeft() - rectSheet.TopLeft();
- m_sizePageBR = rectPage.BottomRight() - rectSheet.BottomRight();
- // add all possible buttons, if they exist
- for (int i = 0; i < 7; i++)
- {
- if (NULL != GetDlgItem(_propButtons[i]))
- AddAnchor(_propButtons[i], BOTTOM_RIGHT);
- }
- }
- BOOL CResizableSheet::ArrangeLayoutCallback(LayoutInfo &layout)
- {
- if (layout.nCallbackID != 1) // we only added 1 callback
- return CResizableLayout::ArrangeLayoutCallback(layout);
- // set layout info for active page
- layout.hWnd = GetActivePage()->GetSafeHwnd();
- // set margins
- if (IsWizard()) // wizard mode
- {
- // use pre-calculated margins
- layout.sizeMarginTL = m_sizePageTL;
- layout.sizeMarginBR = m_sizePageBR;
- }
- else // tab mode
- {
- CRect rectPage, rectSheet;
- GetTotalClientRect(&rectSheet);
- CTabCtrl* pTab = GetTabControl();
- pTab->GetWindowRect(&rectPage);
- pTab->AdjustRect(FALSE, &rectPage);
- ScreenToClient(&rectPage);
- // use tab control
- layout.sizeMarginTL = rectPage.TopLeft() - rectSheet.TopLeft();
- layout.sizeMarginBR = rectPage.BottomRight() - rectSheet.BottomRight();
- }
- // set anchor types
- layout.sizeTypeTL = TOP_LEFT;
- layout.sizeTypeBR = BOTTOM_RIGHT;
- // use this layout info
- return TRUE;
- }
- void CResizableSheet::OnSize(UINT nType, int cx, int cy)
- {
- CWnd::OnSize(nType, cx, cy);
-
- if (nType == SIZE_MAXHIDE || nType == SIZE_MAXSHOW)
- return; // arrangement not needed
- if (m_bInitDone)
- {
- // update size-grip
- UpdateGripPos();
- ArrangeLayout();
- }
- }
- BOOL CResizableSheet::OnPageChanging(NMHDR* /*pNotifyStruct*/, LRESULT* /*pResult*/)
- {
- // update new wizard page
- // active page changes after this notification
- PostMessage(WM_SIZE);
- return FALSE; // continue routing
- }
- BOOL CResizableSheet::OnEraseBkgnd(CDC* pDC)
- {
- ClipChildren(pDC);
- return CPropertySheet::OnEraseBkgnd(pDC);
- }
- void CResizableSheet::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
- {
- if (!m_bInitDone)
- return;
- MinMaxInfo(lpMMI);
- }
- // protected members
- int CResizableSheet::GetMinWidth()
- {
- CWnd* pWnd = NULL;
- CRect rectWnd, rectSheet;
- GetTotalClientRect(&rectSheet);
- int max = 0, min = rectSheet.Width();
- // search for leftmost and rightmost button margins
- for (int i = 0; i < 7; i++)
- {
- pWnd = GetDlgItem(_propButtons[i]);
- // exclude not present or hidden buttons
- if (pWnd == NULL || !(pWnd->GetStyle() & WS_VISIBLE))
- continue;
- // left position is relative to the right border
- // of the parent window (negative value)
- pWnd->GetWindowRect(&rectWnd);
- ScreenToClient(&rectWnd);
- int left = rectSheet.right - rectWnd.left;
- int right = rectSheet.right - rectWnd.right;
- if (left > max)
- max = left;
- if (right < min)
- min = right;
- }
- // sizing border width
- int border = GetSystemMetrics(SM_CXSIZEFRAME);
-
- // compute total width
- return max + min + 2*border;
- }
- // NOTE: this must be called after all the other settings
- // to have the window and its controls displayed properly
- void CResizableSheet::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly, BOOL bWithPage)
- {
- m_sSection = pszSection;
- m_bSavePage = bWithPage;
- m_bEnableSaveRestore = TRUE;
- m_bRectOnly = bRectOnly;
- // restore immediately
- LoadWindowRect(pszSection, bRectOnly);
- LoadPage();
- }
- // private memebers
- // used to save/restore active page
- // either in the registry or a private .INI file
- // depending on your application settings
- #define ACTIVEPAGE _T("ActivePage")
- void CResizableSheet::SavePage()
- {
- if (!m_bSavePage)
- return;
- // saves active page index, zero (the first) if problems
- // cannot use GetActivePage, because it always fails
- CTabCtrl *pTab = GetTabControl();
- int page = 0;
- if (pTab != NULL)
- page = pTab->GetCurSel();
- if (page < 0)
- page = 0;
- AfxGetApp()->WriteProfileInt(m_sSection, ACTIVEPAGE, page);
- }
- void CResizableSheet::LoadPage()
- {
- // restore active page, zero (the first) if not found
- int page = AfxGetApp()->GetProfileInt(m_sSection, ACTIVEPAGE, 0);
-
- if (m_bSavePage)
- {
- SetActivePage(page);
- ArrangeLayout(); // needs refresh
- }
- }
|