Support unrar64.dll
[xy_vsfilter.git] / src / ui / ResizableLib / ResizableSheet.cpp
blob95ac673a0cb449e66afec8e467afe0024fd2c863
1 // ResizableSheet.cpp : implementation file
2 //
3 /////////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2000-2002 by Paolo Messina
6 // (http://www.geocities.com/ppescher - ppescher@yahoo.com)
7 //
8 // The contents of this file are subject to the Artistic License (the "License").
9 // You may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at:
11 // http://www.opensource.org/licenses/artistic-license.html
13 // If you find this code useful, credits would be nice!
15 /////////////////////////////////////////////////////////////////////////////
17 #include "stdafx.h"
18 #include "ResizableSheet.h"
20 #ifdef _DEBUG
21 #define new DEBUG_NEW
22 #undef THIS_FILE
23 static char THIS_FILE[] = __FILE__;
24 #endif
26 /////////////////////////////////////////////////////////////////////////////
27 // CResizableSheet
29 IMPLEMENT_DYNAMIC(CResizableSheet, CPropertySheet)
31 inline void CResizableSheet::PrivateConstruct()
33 m_bEnableSaveRestore = FALSE;
34 m_bSavePage = FALSE;
35 m_dwGripTempState = 1;
39 CResizableSheet::CResizableSheet()
41 PrivateConstruct();
44 CResizableSheet::CResizableSheet(UINT nIDCaption, CWnd *pParentWnd, UINT iSelectPage)
45 : CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
47 PrivateConstruct();
50 CResizableSheet::CResizableSheet(LPCTSTR pszCaption, CWnd *pParentWnd, UINT iSelectPage)
51 : CPropertySheet(pszCaption, pParentWnd, iSelectPage)
53 PrivateConstruct();
56 CResizableSheet::~CResizableSheet()
60 BEGIN_MESSAGE_MAP(CResizableSheet, CPropertySheet)
61 //{{AFX_MSG_MAP(CResizableSheet)
62 ON_WM_GETMINMAXINFO()
63 ON_WM_SIZE()
64 ON_WM_DESTROY()
65 ON_WM_CREATE()
66 ON_WM_ERASEBKGND()
67 //}}AFX_MSG_MAP
68 ON_NOTIFY_REFLECT_EX(PSN_SETACTIVE, OnPageChanging)
69 END_MESSAGE_MAP()
71 /////////////////////////////////////////////////////////////////////////////
72 // CResizableSheet message handlers
74 int CResizableSheet::OnCreate(LPCREATESTRUCT lpCreateStruct)
76 if (CPropertySheet::OnCreate(lpCreateStruct) == -1)
77 return -1;
79 // keep client area
80 CRect rect;
81 GetClientRect(&rect);
82 // set resizable style
83 ModifyStyle(DS_MODALFRAME, WS_POPUP | WS_THICKFRAME);
84 // adjust size to reflect new style
85 ::AdjustWindowRectEx(&rect, GetStyle(),
86 ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle());
87 SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(), SWP_FRAMECHANGED|
88 SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREPOSITION);
90 // create and init the size-grip
91 if (!CreateSizeGrip())
92 return -1;
94 return 0;
97 BOOL CResizableSheet::OnInitDialog()
99 BOOL bResult = CPropertySheet::OnInitDialog();
101 // set the initial size as the min track size
102 CRect rc;
103 GetWindowRect(&rc);
104 SetMinTrackSize(rc.Size());
106 // initialize layout
107 PresetLayout();
109 // prevent flickering
110 GetTabControl()->ModifyStyle(0, WS_CLIPSIBLINGS);
112 return bResult;
115 void CResizableSheet::OnDestroy()
117 if (m_bEnableSaveRestore)
119 SaveWindowRect(m_sSection, m_bRectOnly);
120 SavePage();
123 RemoveAllAnchors();
125 CPropertySheet::OnDestroy();
128 // maps an index to a button ID and vice-versa
129 static UINT _propButtons[] =
131 IDOK, IDCANCEL, ID_APPLY_NOW, IDHELP,
132 ID_WIZBACK, ID_WIZNEXT, ID_WIZFINISH
134 const int _propButtonsCount = sizeof(_propButtons)/sizeof(UINT);
136 // horizontal line in wizard mode
137 #define ID_WIZLINE ID_WIZFINISH+1
139 void CResizableSheet::PresetLayout()
141 if (IsWizard()) // wizard mode
143 // hide tab control
144 GetTabControl()->ShowWindow(SW_HIDE);
146 AddAnchor(ID_WIZLINE, BOTTOM_LEFT, BOTTOM_RIGHT);
148 else // tab mode
150 AddAnchor(AFX_IDC_TAB_CONTROL, TOP_LEFT, BOTTOM_RIGHT);
153 // add a callback for active page (which can change at run-time)
154 AddAnchorCallback(1);
156 // use *total* parent size to have correct margins
157 CRect rectPage, rectSheet;
158 GetTotalClientRect(&rectSheet);
160 GetActivePage()->GetWindowRect(&rectPage);
161 ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectPage, 2);
163 // pre-calculate margins
164 m_sizePageTL = rectPage.TopLeft() - rectSheet.TopLeft();
165 m_sizePageBR = rectPage.BottomRight() - rectSheet.BottomRight();
167 // add all possible buttons, if they exist
168 for (int i = 0; i < _propButtonsCount; i++)
170 if (NULL != GetDlgItem(_propButtons[i]))
171 AddAnchor(_propButtons[i], BOTTOM_RIGHT);
175 BOOL CResizableSheet::ArrangeLayoutCallback(LayoutInfo &layout)
177 if (layout.nCallbackID != 1) // we only added 1 callback
178 return CResizableLayout::ArrangeLayoutCallback(layout);
180 // set layout info for active page
181 layout.hWnd = (HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 0, 0);
182 if (!::IsWindow(layout.hWnd))
183 return FALSE;
185 // set margins
186 if (IsWizard()) // wizard mode
188 // use pre-calculated margins
189 layout.sizeMarginTL = m_sizePageTL;
190 layout.sizeMarginBR = m_sizePageBR;
192 else // tab mode
194 CTabCtrl* pTab = GetTabControl();
195 ASSERT(pTab != NULL);
197 // get tab position after resizing and calc page rect
198 CRect rectPage, rectSheet;
199 GetTotalClientRect(&rectSheet);
201 VERIFY(GetAnchorPosition(pTab->m_hWnd, rectSheet, rectPage));
202 pTab->AdjustRect(FALSE, &rectPage);
204 // set margins
205 layout.sizeMarginTL = rectPage.TopLeft() - rectSheet.TopLeft();
206 layout.sizeMarginBR = rectPage.BottomRight() - rectSheet.BottomRight();
209 // set anchor types
210 layout.sizeTypeTL = TOP_LEFT;
211 layout.sizeTypeBR = BOTTOM_RIGHT;
213 // use this layout info
214 return TRUE;
217 void CResizableSheet::OnSize(UINT nType, int cx, int cy)
219 CWnd::OnSize(nType, cx, cy);
221 if (nType == SIZE_MAXHIDE || nType == SIZE_MAXSHOW)
222 return; // arrangement not needed
224 if (nType == SIZE_MAXIMIZED)
225 HideSizeGrip(&m_dwGripTempState);
226 else
227 ShowSizeGrip(&m_dwGripTempState);
229 // update grip and layout
230 UpdateSizeGrip();
231 ArrangeLayout();
234 BOOL CResizableSheet::OnPageChanging(NMHDR* /*pNotifyStruct*/, LRESULT* /*pResult*/)
236 // update new wizard page
237 // active page changes after this notification
238 PostMessage(WM_SIZE);
240 return FALSE; // continue routing
243 BOOL CResizableSheet::OnEraseBkgnd(CDC* pDC)
245 // Windows XP doesn't like clipping regions ...try this!
246 EraseBackground(pDC);
247 return TRUE;
249 /* ClipChildren(pDC); // old-method (for safety)
251 return CPropertySheet::OnEraseBkgnd(pDC);
255 void CResizableSheet::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
257 MinMaxInfo(lpMMI);
260 // protected members
262 int CResizableSheet::GetMinWidth()
264 CWnd* pWnd = NULL;
265 CRect rectWnd, rectSheet;
266 GetTotalClientRect(&rectSheet);
268 int max = 0, min = rectSheet.Width();
269 // search for leftmost and rightmost button margins
270 for (int i = 0; i < 7; i++)
272 pWnd = GetDlgItem(_propButtons[i]);
273 // exclude not present or hidden buttons
274 if (pWnd == NULL || !(pWnd->GetStyle() & WS_VISIBLE))
275 continue;
277 // left position is relative to the right border
278 // of the parent window (negative value)
279 pWnd->GetWindowRect(&rectWnd);
280 ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectWnd, 2);
281 int left = rectSheet.right - rectWnd.left;
282 int right = rectSheet.right - rectWnd.right;
284 if (left > max)
285 max = left;
286 if (right < min)
287 min = right;
290 // sizing border width
291 int border = GetSystemMetrics(SM_CXSIZEFRAME);
293 // compute total width
294 return max + min + 2*border;
298 // NOTE: this must be called after all the other settings
299 // to have the window and its controls displayed properly
300 void CResizableSheet::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly, BOOL bWithPage)
302 m_sSection = pszSection;
303 m_bSavePage = bWithPage;
305 m_bEnableSaveRestore = TRUE;
306 m_bRectOnly = bRectOnly;
308 // restore immediately
309 LoadWindowRect(pszSection, bRectOnly);
310 LoadPage();
313 // private memebers
315 // used to save/restore active page
316 // either in the registry or a private .INI file
317 // depending on your application settings
319 #define ACTIVEPAGE _T("ActivePage")
321 void CResizableSheet::SavePage()
323 if (!m_bSavePage)
324 return;
326 // saves active page index, zero (the first) if problems
327 // cannot use GetActivePage, because it always fails
329 CTabCtrl *pTab = GetTabControl();
330 int page = 0;
332 if (pTab != NULL)
333 page = pTab->GetCurSel();
334 if (page < 0)
335 page = 0;
337 AfxGetApp()->WriteProfileInt(m_sSection, ACTIVEPAGE, page);
340 void CResizableSheet::LoadPage()
342 // restore active page, zero (the first) if not found
343 int page = AfxGetApp()->GetProfileInt(m_sSection, ACTIVEPAGE, 0);
345 if (m_bSavePage)
347 SetActivePage(page);
348 ArrangeLayout(); // needs refresh
352 void CResizableSheet::RefreshLayout()
354 SendMessage(WM_SIZE);