1 // TortoiseSVN - a Windows shell extension for easy version control
\r
3 // Copyright (C) 2003-2008 - TortoiseSVN
\r
5 // This program is free software; you can redistribute it and/or
\r
6 // modify it under the terms of the GNU General Public License
\r
7 // as published by the Free Software Foundation; either version 2
\r
8 // of the License, or (at your option) any later version.
\r
10 // This program is distributed in the hope that it will be useful,
\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 // GNU General Public License for more details.
\r
15 // You should have received a copy of the GNU General Public License
\r
16 // along with this program; if not, write to the Free Software Foundation,
\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
21 #include "ResizableDialog.h"
\r
22 #include "Balloon.h"
\r
24 #pragma comment(lib, "htmlhelp.lib")
\r
27 * \ingroup TortoiseProc
\r
29 * A template which can be used as the base-class of dialogs which form the main dialog
\r
30 * of a 'dialog-style application'
\r
31 * Just provides the boiler-plate code for dealing with application icons
\r
33 * \remark Replace all references to CDialog or CResizableDialog in your dialog class with
\r
34 * either CResizableStandAloneDialog, CStandAloneDialog or CStateStandAloneDialog, as appropriate
\r
36 template <typename BaseType> class CStandAloneDialogTmpl : public BaseType
\r
39 CStandAloneDialogTmpl(UINT nIDTemplate, CWnd* pParentWnd = NULL) : BaseType(nIDTemplate, pParentWnd)
\r
41 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
\r
43 virtual BOOL OnInitDialog()
\r
45 BaseType::OnInitDialog();
\r
47 // Set the icon for this dialog. The framework does this automatically
\r
48 // when the application's main window is not a dialog
\r
49 SetIcon(m_hIcon, TRUE); // Set big icon
\r
50 SetIcon(m_hIcon, FALSE); // Set small icon
\r
55 afx_msg void OnPaint()
\r
59 CPaintDC dc(this); // device context for painting
\r
61 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
\r
63 // Center icon in client rectangle
\r
64 int cxIcon = GetSystemMetrics(SM_CXICON);
\r
65 int cyIcon = GetSystemMetrics(SM_CYICON);
\r
67 GetClientRect(&rect);
\r
68 int x = (rect.Width() - cxIcon + 1) / 2;
\r
69 int y = (rect.Height() - cyIcon + 1) / 2;
\r
72 dc.DrawIcon(x, y, m_hIcon);
\r
76 BaseType::OnPaint();
\r
80 * Wrapper around the CWnd::EnableWindow() method, but
\r
81 * makes sure that a control that has the focus is not disabled
\r
82 * before the focus is passed on to the next control.
\r
84 BOOL DialogEnableWindow(UINT nID, BOOL bEnable)
\r
86 CWnd * pwndDlgItem = GetDlgItem(nID);
\r
87 if (pwndDlgItem == NULL)
\r
90 return pwndDlgItem->EnableWindow(bEnable);
\r
91 if (GetFocus() == pwndDlgItem)
\r
93 SendMessage(WM_NEXTDLGCTL, 0, FALSE);
\r
95 return pwndDlgItem->EnableWindow(bEnable);
\r
99 * Adjusts the size of a checkbox or radio button control.
\r
100 * Since we always make the size of those bigger than 'necessary'
\r
101 * for making sure that translated strings can fit in those too,
\r
102 * this method can reduce the size of those controls again to only
\r
105 void AdjustControlSize(UINT nID)
\r
107 CWnd * pwndDlgItem = GetDlgItem(nID);
\r
108 // adjust the size of the control to fit its content
\r
109 CString sControlText;
\r
110 pwndDlgItem->GetWindowText(sControlText);
\r
111 // next step: find the rectangle the control text needs to
\r
114 CDC * pDC = pwndDlgItem->GetWindowDC();
\r
116 RECT controlrectorig;
\r
117 pwndDlgItem->GetWindowRect(&controlrect);
\r
118 ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT)&controlrect, 2);
\r
119 controlrectorig = controlrect;
\r
122 CFont * font = pwndDlgItem->GetFont();
\r
123 CFont * pOldFont = pDC->SelectObject(font);
\r
124 if (pDC->DrawText(sControlText, -1, &controlrect, DT_WORDBREAK | DT_EDITCONTROL | DT_EXPANDTABS | DT_LEFT | DT_CALCRECT))
\r
126 // now we have the rectangle the control really needs
\r
127 if ((controlrectorig.right - controlrectorig.left) > (controlrect.right - controlrect.left))
\r
129 // we're dealing with radio buttons and check boxes,
\r
130 // which means we have to add a little space for the checkbox
\r
131 controlrectorig.right = controlrectorig.left + (controlrect.right - controlrect.left) + 20;
\r
132 pwndDlgItem->MoveWindow(&controlrectorig);
\r
135 pDC->SelectObject(pOldFont);
\r
141 * Display a balloon with close button, anchored at a given control on this dialog.
\r
143 void ShowBalloon(UINT nIdControl, UINT nIdText, LPCTSTR szIcon = IDI_EXCLAMATION)
\r
145 CBalloon::ShowBalloon(this, CBalloon::GetCtrlCentre(this, nIdControl), nIdText, TRUE, szIcon);
\r
149 * Refreshes the cursor by forcing a WM_SETCURSOR message.
\r
151 void RefreshCursor()
\r
155 SetCursorPos(pt.x, pt.y);
\r
158 HCURSOR OnQueryDragIcon()
\r
160 return static_cast<HCURSOR>(m_hIcon);
\r
163 virtual void HtmlHelp(DWORD_PTR dwData, UINT nCmd = 0x000F)
\r
165 CWinApp* pApp = AfxGetApp();
\r
166 ASSERT_VALID(pApp);
\r
167 ASSERT(pApp->m_pszHelpFilePath != NULL);
\r
168 // to call HtmlHelp the m_fUseHtmlHelp must be set in
\r
169 // the application's constructor
\r
170 ASSERT(pApp->m_eHelpType == afxHTMLHelp);
\r
175 // run the HTML Help engine
\r
176 if (!::HtmlHelp(m_hWnd, pApp->m_pszHelpFilePath, nCmd, dwData))
\r
178 AfxMessageBox(AFX_IDP_FAILED_TO_LAUNCH_HELP);
\r
186 class CStateDialog : public CDialog, public CResizableWndState
\r
189 CStateDialog() {m_bEnableSaveRestore = false;}
\r
190 CStateDialog(UINT /*nIDTemplate*/, CWnd* /*pParentWnd = NULL*/) {m_bEnableSaveRestore = false;}
\r
191 CStateDialog(LPCTSTR /*lpszTemplateName*/, CWnd* /*pParentWnd = NULL*/) {m_bEnableSaveRestore = false;}
\r
192 virtual ~CStateDialog();
\r
196 bool m_bEnableSaveRestore;
\r
200 CString m_sSection; // section name (identifies a parent window)
\r
203 // section to use in app's profile
\r
204 void EnableSaveRestore(LPCTSTR pszSection, bool bRectOnly = FALSE)
\r
206 m_sSection = pszSection;
\r
208 m_bEnableSaveRestore = true;
\r
209 m_bRectOnly = bRectOnly;
\r
211 // restore immediately
\r
212 LoadWindowRect(pszSection, bRectOnly);
\r
215 virtual CWnd* GetResizableWnd() const
\r
217 // make the layout know its parent window
\r
218 return CWnd::FromHandle(m_hWnd);
\r
221 afx_msg void OnDestroy()
\r
223 if (m_bEnableSaveRestore)
\r
224 SaveWindowRect(m_sSection, m_bRectOnly);
\r
225 CDialog::OnDestroy();
\r
228 DECLARE_MESSAGE_MAP()
\r
232 class CResizableStandAloneDialog : public CStandAloneDialogTmpl<CResizableDialog>
\r
235 CResizableStandAloneDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL);
\r
238 DECLARE_DYNAMIC(CResizableStandAloneDialog)
\r
241 afx_msg void OnSizing(UINT fwSide, LPRECT pRect);
\r
242 afx_msg void OnMoving(UINT fwSide, LPRECT pRect);
\r
243 afx_msg void OnNcMButtonUp(UINT nHitTest, CPoint point);
\r
244 afx_msg void OnNcRButtonUp(UINT nHitTest, CPoint point);
\r
246 DECLARE_MESSAGE_MAP()
\r
250 bool m_bHorizontal;
\r
251 CRect m_rcOrgWindowRect;
\r
254 typedef CStandAloneDialogTmpl<CDialog> CStandAloneDialog;
\r
255 typedef CStandAloneDialogTmpl<CStateDialog> CStateStandAloneDialog;
\r