/libusbK/src/inf-wizard2/src/ResizableSheetEx.cpp
C++ | 611 lines | 428 code | 97 blank | 86 comment | 58 complexity | 399e4d8041a4678821fd9588fedb11e7 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, LGPL-2.0
- // ResizableSheetEx.cpp : implementation file
- //
- /////////////////////////////////////////////////////////////////////////////
- //
- // This file is part of ResizableLib
- // http://sourceforge.net/projects/resizablelib
- //
- // Copyright (C) 2000-2004 by Paolo Messina
- // http://www.geocities.com/ppescher - mailto:ppescher@hotmail.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 "ResizableSheetEx.h"
- #include "Resource.h"
-
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // CResizableSheetEx
-
- IMPLEMENT_DYNAMIC(CResizableSheetEx, CPropertySheetEx)
-
- inline void CResizableSheetEx::PrivateConstruct()
- {
- m_bEnableSaveRestore = FALSE;
- m_bSavePage = FALSE;
- m_dwGripTempState = 1;
- m_bLayoutDone = FALSE;
-
- m_psh.dwFlags |= PSH_NOCONTEXTHELP;
- m_psh.dwFlags &= ~(PSH_HASHELP);
- }
-
- inline BOOL CResizableSheetEx::IsWizard() const
- {
- return (m_psh.dwFlags & PSH_WIZARD);
- }
-
- inline BOOL CResizableSheetEx::IsWizard97() const
- {
- return (m_psh.dwFlags & (PSH_IE4WIZARD97 | PSH_IE5WIZARD97));
- }
-
- CResizableSheetEx::CResizableSheetEx()
- {
- PrivateConstruct();
- }
-
- CResizableSheetEx::CResizableSheetEx(UINT nIDCaption, CWnd* pParentWnd,
- UINT iSelectPage, HBITMAP hbmWatermark, HPALETTE hpalWatermark,
- HBITMAP hbmHeader)
- : CPropertySheetEx(nIDCaption, pParentWnd, iSelectPage,
- hbmWatermark, hpalWatermark, hbmHeader)
- {
- PrivateConstruct();
- }
-
- CResizableSheetEx::CResizableSheetEx(LPCTSTR pszCaption, CWnd* pParentWnd,
- UINT iSelectPage, HBITMAP hbmWatermark, HPALETTE hpalWatermark,
- HBITMAP hbmHeader)
- : CPropertySheetEx(pszCaption, pParentWnd, iSelectPage,
- hbmWatermark, hpalWatermark, hbmHeader)
- {
- PrivateConstruct();
- }
-
-
- CResizableSheetEx::~CResizableSheetEx()
- {
- }
-
- BEGIN_MESSAGE_MAP(CResizableSheetEx, CPropertySheetEx)
- //{{AFX_MSG_MAP(CResizableSheetEx)
- ON_WM_GETMINMAXINFO()
- ON_WM_SIZE()
- ON_WM_DESTROY()
- ON_WM_ERASEBKGND()
- ON_WM_NCCREATE()
- //}}AFX_MSG_MAP
- ON_NOTIFY_REFLECT_EX(PSN_SETACTIVE, OnPageChanging)
- ON_REGISTERED_MESSAGE(WMU_RESIZESUPPORT, OnResizeSupport)
- ON_BN_CLICKED(ID_WIZDONATE, OnBtnCLickWizDonate)
- END_MESSAGE_MAP()
-
- VOID CResizableSheetEx::OnBtnCLickWizDonate()
- {
- ShellExecute(NULL, NULL, _T("http://sourceforge.net/donate/index.php?group_id=78138"), NULL, NULL, SW_SHOWNORMAL);
- }
-
-
-
- void CResizableSheetEx::DoDataExchange(CDataExchange* pDX)
- {
- CPropertySheetEx::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CPageInstall)
- // NOTE: the ClassWizard will add DDX and DDV calls here
- //}}AFX_DATA_MAP
- DDX_Control(pDX, ID_WIZBACK, m_BtnNavBack);
- DDX_Control(pDX, ID_WIZNEXT, m_BtnNavNext);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CResizableSheetEx message handlers
-
- BOOL CResizableSheetEx::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (!CPropertySheetEx::OnNcCreate(lpCreateStruct))
- return FALSE;
-
- // child dialogs don't want resizable border or size grip,
- // nor they can handle the min/max size constraints
- BOOL bChild = lpCreateStruct->style & WS_CHILD;
-
- // create and init the size-grip
- if (!CreateSizeGrip(!bChild))
- return FALSE;
-
- MakeResizable(lpCreateStruct);
-
- return TRUE;
- }
-
- BOOL CResizableSheetEx::OnInitDialog()
- {
- BOOL bResult = CPropertySheetEx::OnInitDialog();
- // set the initial size as the min track size
- CRect rc;
- GetWindowRect(&rc);
- SetMinTrackSize(rc.Size());
-
- // initialize layout
- PresetLayout();
- m_bLayoutDone = TRUE;
-
- return bResult;
- }
-
- LRESULT CResizableSheetEx::OnResizeSupport(WPARAM wParam, LPARAM lParam)
- {
- switch (wParam)
- {
- case RSZSUP_SHEETPAGEEXHACK:
- {
- // a window object must be still associated to the page handle
- // but MFC subclassing has been turned off to allow the system
- // to subclass it first, so we can catch all the messages
- CWnd* pWnd = CWnd::FromHandlePermanent((HWND)lParam);
- if (pWnd == NULL)
- return 0;
-
- // suclass the window again and refresh page and sheet
- pWnd->SubclassWindow(pWnd->Detach());
- RefreshLayout();
- pWnd->SendMessage(WM_SIZE);
- Invalidate();
- UnlockWindowUpdate();
-
- if (pWnd->IsWindowVisible())
- {
- // send lost PSN_SETACTIVE notification message
- CPropertyPage* pPage = DYNAMIC_DOWNCAST(CPropertyPage, pWnd);
- if (pPage != NULL)
- SetActivePage(pPage);
- }
- }
- break;
-
- default:
- return FALSE;
- }
- return TRUE;
- }
-
- void CResizableSheetEx::OnDestroy()
- {
- if (m_bEnableSaveRestore)
- {
- SaveWindowRect(m_sSection, m_bRectOnly);
- if (m_bSavePage)
- SavePage(m_sSection);
- }
-
- RemoveAllAnchors();
-
- CPropertySheetEx::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
- };
- const int _propButtonsCount = sizeof(_propButtons) / sizeof(UINT);
-
- // horizontal line in wizard mode
- #define ID_WIZLINE ID_WIZFINISH+1
- #define ID_WIZLINEHDR ID_WIZFINISH+2
-
- void CResizableSheetEx::PresetLayout()
- {
- if (IsWizard() || IsWizard97()) // wizard mode
- {
- // hide tab control
- GetTabControl()->ShowWindow(SW_HIDE);
-
- AddAnchor(ID_WIZLINE, BOTTOM_LEFT, BOTTOM_RIGHT);
-
- if (IsWizard97()) // add header line for wizard97 dialogs
- AddAnchor(ID_WIZLINEHDR, TOP_LEFT, TOP_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)
- m_nCallbackID = AddAnchorCallback();
-
- // use *total* parent size to have correct margins
- CRect rectPage, rectSheet;
- GetTotalClientRect(&rectSheet);
-
- GetActivePage()->GetWindowRect(&rectPage);
- ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectPage, 2);
-
- // 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 < _propButtonsCount; i++)
- {
- CButton* dlgBtn = reinterpret_cast<CButton*>(GetDlgItem(_propButtons[i]));
- if (dlgBtn != NULL)
- {
- CRect rcBtn;
- CString sBtn;
-
- dlgBtn->GetWindowRect(rcBtn);
- ScreenToClient(rcBtn);
-
- HBITMAP hBmp = NULL;
- switch(_propButtons[i])
- {
- case ID_WIZBACK:
- dlgBtn->SetWindowPos(NULL, rcBtn.left - 16, rcBtn.top - 8, rcBtn.Width(), rcBtn.Height() + 4, SWP_NOZORDER | SWP_NOREDRAW);
- sBtn.LoadString(IDS_BACK);
- //sBtn.Insert(0, _T(" "));
- dlgBtn->SetWindowText(sBtn);
- m_BtnNavBack.SubclassDlgItem(_propButtons[i], this);
- m_BtnNavBack.SetIcon(IDI_ICON_NAV_BACK);
-
- rcBtn.right = rcBtn.Width() * 2 + 10;
- rcBtn.left = 5;
- rcBtn.top -= 10;
- rcBtn.bottom -= 3;
-
- m_BtnDonate.Create(_T("Help keep us strong!"), WS_CHILD | WS_VISIBLE | WS_GROUP, rcBtn, this, ID_WIZDONATE);
- m_BtnDonate.SetIcon(IDI_ICON_DONATE);
- m_BtnDonate.SetAlign(CButtonST::ST_ALIGN_HORIZ);
- m_BtnDonate.SetDisplayStyle(CButtonST::DISP_FLAT);
- m_BtnDonate.SetFont(GetFont(), FALSE);
-
- AddAnchor(ID_WIZDONATE, BOTTOM_LEFT);
- AddAnchor(_propButtons[i], BOTTOM_RIGHT);
- break;
- case ID_WIZNEXT:
- dlgBtn->SetWindowPos(NULL, rcBtn.left - 14, rcBtn.top - 8, rcBtn.Width(), rcBtn.Height() + 4, SWP_NOZORDER | SWP_NOREDRAW);
- sBtn.LoadString(IDS_NEXT);
- //sBtn.Append(_T(" "));
- dlgBtn->SetWindowText(sBtn);
- m_BtnNavNext.SubclassDlgItem(_propButtons[i], this);
- m_BtnNavNext.SetIcon(IDI_ICON_NAV_NEXT);
- m_BtnNavNext.SetAlign(CButtonST::ST_ALIGN_HORIZ_RIGHT);
- AddAnchor(_propButtons[i], BOTTOM_RIGHT);
- break;
- case IDCANCEL:
- dlgBtn->SetWindowPos(NULL, rcBtn.left - 14, rcBtn.top - 8, rcBtn.Width(), rcBtn.Height() + 4, SWP_NOZORDER | SWP_NOREDRAW);
- sBtn.LoadString(IDS_CANCEL);
- //sBtn.Append(_T(" "));
- dlgBtn->SetWindowText(sBtn);
- m_BtnNavCancel.SubclassDlgItem(_propButtons[i], this);
- m_BtnNavCancel.SetIcon(IDI_ICON_NAV_CANCEL);
- m_BtnNavCancel.SetAlign(CButtonST::ST_ALIGN_HORIZ_RIGHT);
- AddAnchor(_propButtons[i], BOTTOM_RIGHT);
- break;
- case ID_WIZFINISH:
- dlgBtn->SetWindowPos(NULL, rcBtn.left - 14, rcBtn.top - 8, rcBtn.Width(), rcBtn.Height() + 4, SWP_NOZORDER | SWP_NOREDRAW);
- sBtn.LoadString(IDS_FINISH);
- //sBtn.Append(_T(" "));
- dlgBtn->SetWindowText(sBtn);
- m_BtnNavFinish.SubclassDlgItem(_propButtons[i], this);
- m_BtnNavFinish.SetIcon(IDI_ICON_NAV_FINISH);
- m_BtnNavFinish.SetAlign(CButtonST::ST_ALIGN_HORIZ_RIGHT);
- AddAnchor(_propButtons[i], BOTTOM_RIGHT);
- break;
- }
- }
- }
- }
-
- BOOL CResizableSheetEx::ArrangeLayoutCallback(LAYOUTINFO& layout) const
- {
- if (layout.nCallbackID != m_nCallbackID) // we only added 1 callback
- return CResizableLayout::ArrangeLayoutCallback(layout);
-
- // set layout info for active page
- layout.hWnd = (HWND)::SendMessage(GetSafeHwnd(), PSM_GETCURRENTPAGEHWND, 0, 0);
- if (!::IsWindow(layout.hWnd))
- return FALSE;
-
- // set margins
- if (IsWizard()) // wizard mode
- {
- // use pre-calculated margins
- layout.marginTopLeft = m_sizePageTL;
- layout.marginBottomRight = m_sizePageBR;
- }
- else if (IsWizard97()) // wizard 97
- {
- // use pre-calculated margins
- layout.marginTopLeft = m_sizePageTL;
- layout.marginBottomRight = m_sizePageBR;
-
- if (!(GetActivePage()->m_psp.dwFlags & PSP_HIDEHEADER))
- {
- // add header vertical offset
- CRect rectLine, rectSheet;
- GetTotalClientRect(&rectSheet);
- GetAnchorPosition(ID_WIZLINEHDR, rectSheet, rectLine);
-
- layout.marginTopLeft.cy = rectLine.bottom;
- }
- }
- else // tab mode
- {
- CTabCtrl* pTab = GetTabControl();
- ASSERT(pTab != NULL);
-
- // get tab position after resizing and calc page rect
- CRect rectPage, rectSheet;
- GetTotalClientRect(&rectSheet);
-
- if (!GetAnchorPosition(pTab->m_hWnd, rectSheet, rectPage))
- return FALSE; // no page yet
-
- // temporarily resize the tab control to calc page size
- CRect rectSave;
- pTab->GetWindowRect(rectSave);
- ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectSave, 2);
- pTab->SetRedraw(FALSE);
- pTab->MoveWindow(rectPage, FALSE);
- pTab->AdjustRect(FALSE, &rectPage);
- pTab->MoveWindow(rectSave, FALSE);
- pTab->SetRedraw(TRUE);
-
- // set margins
- layout.marginTopLeft = rectPage.TopLeft() - rectSheet.TopLeft();
- layout.marginBottomRight = rectPage.BottomRight() - rectSheet.BottomRight();
- }
-
- // set anchor types
- layout.anchorTopLeft = TOP_LEFT;
- layout.anchorBottomRight = BOTTOM_RIGHT;
-
- // use this layout info
- return TRUE;
- }
-
- void CResizableSheetEx::OnSize(UINT nType, int cx, int cy)
- {
- CWnd::OnSize(nType, cx, cy);
-
- if (nType == SIZE_MAXHIDE || nType == SIZE_MAXSHOW)
- return; // arrangement not needed
-
- if (nType == SIZE_MAXIMIZED)
- HideSizeGrip(&m_dwGripTempState);
- else
- ShowSizeGrip(&m_dwGripTempState);
-
- // update grip and layout
- UpdateSizeGrip();
- ArrangeLayout();
-
- if (IsWizard97())
- {
- // refresh header area
- CRect rect;
- GetHeaderRect(rect);
- InvalidateRect(rect, FALSE);
- }
- }
-
- BOOL CResizableSheetEx::OnPageChanging(NMHDR* /*pNotifyStruct*/, LRESULT* /*pResult*/)
- {
- // update new wizard page
- // active page changes after this notification
- PostMessage(WM_SIZE);
-
- return FALSE; // continue routing
- }
-
- BOOL CResizableSheetEx::OnEraseBkgnd(CDC* pDC)
- {
- if (ClipChildren(pDC, FALSE))
- {
- // when clipping, remove header from clipping area
- if (IsWizard97())
- {
- // clip header area out
- CRect rect;
- GetHeaderRect(rect);
- pDC->ExcludeClipRect(rect);
- }
- }
-
- BOOL bRet = CPropertySheetEx::OnEraseBkgnd(pDC);
-
- ClipChildren(pDC, TRUE);
-
- return bRet;
- }
-
- BOOL CResizableSheetEx::CalcSizeExtra(HWND /*hWndChild*/, CSize sizeChild, CSize& sizeExtra)
- {
- CTabCtrl* pTab = GetTabControl();
- if (!pTab)
- return FALSE;
-
- // get margins of tabcontrol
- CRect rectMargins;
- if (!GetAnchorMargins(pTab->m_hWnd, sizeChild, rectMargins))
- return FALSE;
-
- // get margin caused by tabcontrol
- CRect rectTabMargins(0, 0, 0, 0);
-
- // get tab position after resizing and calc page rect
- CRect rectPage, rectSheet;
- GetTotalClientRect(&rectSheet);
-
- if (!GetAnchorPosition(pTab->m_hWnd, rectSheet, rectPage))
- return FALSE; // no page yet
-
- // temporarily resize the tab control to calc page size
- CRect rectSave;
- pTab->GetWindowRect(rectSave);
- ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectSave, 2);
- pTab->SetRedraw(FALSE);
- pTab->MoveWindow(rectPage, FALSE);
- pTab->AdjustRect(TRUE, &rectTabMargins);
- pTab->MoveWindow(rectSave, FALSE);
- pTab->SetRedraw(TRUE);
-
- // add non-client size
- ::AdjustWindowRectEx(&rectTabMargins, GetStyle(), !(GetStyle() & WS_CHILD) &&
- ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle());
-
- // compute extra size
- sizeExtra = rectMargins.TopLeft() + rectMargins.BottomRight() +
- rectTabMargins.Size();
- return TRUE;
- }
-
- void CResizableSheetEx::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
- {
- MinMaxInfo(lpMMI);
-
- CTabCtrl* pTab = GetTabControl();
- if (!pTab)
- return;
-
- int nCount = GetPageCount();
- for (int idx = 0; idx < nCount; ++idx)
- {
- if (IsWizard()) // wizard mode
- {
- // use pre-calculated margins
- CRect rectExtra(-CPoint(m_sizePageTL), -CPoint(m_sizePageBR));
- // add non-client size
- ::AdjustWindowRectEx(&rectExtra, GetStyle(), !(GetStyle() & WS_CHILD) &&
- ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle());
- ChainMinMaxInfo(lpMMI, *GetPage(idx), rectExtra.Size());
- }
- else if (IsWizard97()) // wizard 97
- {
- // use pre-calculated margins
- CRect rectExtra(-CPoint(m_sizePageTL), -CPoint(m_sizePageBR));
-
- if (!(GetPage(idx)->m_psp.dwFlags & PSP_HIDEHEADER))
- {
- // add header vertical offset
- CRect rectLine, rectSheet;
- GetTotalClientRect(&rectSheet);
- GetAnchorPosition(ID_WIZLINEHDR, rectSheet, rectLine);
-
- rectExtra.top = -rectLine.bottom;
- }
- // add non-client size
- ::AdjustWindowRectEx(&rectExtra, GetStyle(), !(GetStyle() & WS_CHILD) &&
- ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle());
- ChainMinMaxInfo(lpMMI, *GetPage(idx), rectExtra.Size());
- }
- else // tab mode
- {
- ChainMinMaxInfoCB(lpMMI, *GetPage(idx));
- }
- }
- }
-
- // protected members
-
- void CResizableSheetEx::GetHeaderRect(LPRECT lpRect)
- {
- CWnd* pWizLineHdr = GetDlgItem(ID_WIZLINEHDR);
- if (pWizLineHdr != NULL && pWizLineHdr->IsWindowVisible())
- {
- pWizLineHdr->GetWindowRect(lpRect);
- ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)lpRect, 2);
- LONG bottom = lpRect->top;
- GetClientRect(lpRect);
- lpRect->bottom = bottom;
- }
- else
- ::SetRectEmpty(lpRect);
- }
-
- int CResizableSheetEx::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);
- ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectWnd, 2);
- 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 CResizableSheetEx::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly, BOOL bWithPage)
- {
- m_sSection = pszSection;
- m_bSavePage = bWithPage;
-
- m_bEnableSaveRestore = TRUE;
- m_bRectOnly = bRectOnly;
-
- // restore immediately
- LoadWindowRect(pszSection, bRectOnly);
- if (bWithPage)
- {
- LoadPage(pszSection);
- ArrangeLayout(); // needs refresh
- }
- }
-
- void CResizableSheetEx::RefreshLayout()
- {
- SendMessage(WM_SIZE);
- }
-
- LRESULT CResizableSheetEx::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
- {
- if (message != WM_NCCALCSIZE || wParam == 0 || !m_bLayoutDone)
- return CPropertySheetEx::WindowProc(message, wParam, lParam);
-
- // specifying valid rects needs controls already anchored
- LRESULT lResult = 0;
- HandleNcCalcSize(FALSE, (LPNCCALCSIZE_PARAMS)lParam, lResult);
- lResult = CPropertySheetEx::WindowProc(message, wParam, lParam);
- HandleNcCalcSize(TRUE, (LPNCCALCSIZE_PARAMS)lParam, lResult);
- return lResult;
- }