Correctly deallocate buffer
[TortoiseGit.git] / src / Utils / MiscUI / StandAloneDlg.h
blob3499ee9aec4cd3cf8606dc20dcc2134401a35ce2
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #pragma once
21 #include "ResizableDialog.h"
23 #pragma comment(lib, "htmlhelp.lib")
25 /**
26 * \ingroup TortoiseProc
28 * A template which can be used as the base-class of dialogs which form the main dialog
29 * of a 'dialog-style application'
30 * Just provides the boiler-plate code for dealing with application icons
32 * \remark Replace all references to CDialog or CResizableDialog in your dialog class with
33 * either CResizableStandAloneDialog, CStandAloneDialog or CStateStandAloneDialog, as appropriate
35 template <typename BaseType> class CStandAloneDialogTmpl : public BaseType
37 protected:
38 CStandAloneDialogTmpl(UINT nIDTemplate, CWnd* pParentWnd = NULL) : BaseType(nIDTemplate, pParentWnd)
40 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
42 virtual BOOL OnInitDialog()
44 BaseType::OnInitDialog();
46 // Set the icon for this dialog. The framework does this automatically
47 // when the application's main window is not a dialog
48 SetIcon(m_hIcon, TRUE); // Set big icon
49 SetIcon(m_hIcon, FALSE); // Set small icon
51 return FALSE;
54 virtual BOOL PreTranslateMessage(MSG* pMsg)
56 if (pMsg->message == WM_KEYDOWN)
58 int nVirtKey = (int) pMsg->wParam;
60 if (nVirtKey == 'A' && (GetKeyState(VK_CONTROL) & 0x8000 ) )
62 TCHAR buffer[129];
63 ::GetClassName(pMsg->hwnd, buffer,128);
65 if(_tcsnicmp(buffer,_T("EDIT"),128) == 0)
67 ::PostMessage(pMsg->hwnd,EM_SETSEL,0,-1);
68 return TRUE;
72 return BaseType::PreTranslateMessage(pMsg);
74 afx_msg void OnPaint()
76 if (IsIconic())
78 CPaintDC dc(this); // device context for painting
80 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
82 // Center icon in client rectangle
83 int cxIcon = GetSystemMetrics(SM_CXICON);
84 int cyIcon = GetSystemMetrics(SM_CYICON);
85 CRect rect;
86 GetClientRect(&rect);
87 int x = (rect.Width() - cxIcon + 1) / 2;
88 int y = (rect.Height() - cyIcon + 1) / 2;
90 // Draw the icon
91 dc.DrawIcon(x, y, m_hIcon);
93 else
95 BaseType::OnPaint();
98 /**
99 * Wrapper around the CWnd::EnableWindow() method, but
100 * makes sure that a control that has the focus is not disabled
101 * before the focus is passed on to the next control.
103 BOOL DialogEnableWindow(UINT nID, BOOL bEnable)
105 CWnd * pwndDlgItem = GetDlgItem(nID);
106 if (pwndDlgItem == NULL)
107 return FALSE;
108 if (bEnable)
109 return pwndDlgItem->EnableWindow(bEnable);
110 if (GetFocus() == pwndDlgItem)
112 SendMessage(WM_NEXTDLGCTL, 0, FALSE);
114 return pwndDlgItem->EnableWindow(bEnable);
118 * Adjusts the size of a checkbox or radio button control.
119 * Since we always make the size of those bigger than 'necessary'
120 * for making sure that translated strings can fit in those too,
121 * this method can reduce the size of those controls again to only
122 * fit the text.
124 RECT AdjustControlSize(UINT nID)
126 CWnd * pwndDlgItem = GetDlgItem(nID);
127 // adjust the size of the control to fit its content
128 CString sControlText;
129 pwndDlgItem->GetWindowText(sControlText);
130 // next step: find the rectangle the control text needs to
131 // be displayed
133 CDC * pDC = pwndDlgItem->GetWindowDC();
134 RECT controlrect;
135 RECT controlrectorig;
136 pwndDlgItem->GetWindowRect(&controlrect);
137 ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT)&controlrect, 2);
138 controlrectorig = controlrect;
139 if (pDC)
141 CFont * font = pwndDlgItem->GetFont();
142 CFont * pOldFont = pDC->SelectObject(font);
143 if (pDC->DrawText(sControlText, -1, &controlrect, DT_WORDBREAK | DT_EDITCONTROL | DT_EXPANDTABS | DT_LEFT | DT_CALCRECT))
145 // now we have the rectangle the control really needs
146 if ((controlrectorig.right - controlrectorig.left) > (controlrect.right - controlrect.left))
148 // we're dealing with radio buttons and check boxes,
149 // which means we have to add a little space for the checkbox
150 // the value of 3 pixels added here is necessary in case certain visual styles have
151 // been disabled. Without this, the width is calculated too short.
152 const int checkWidth = GetSystemMetrics(SM_CXMENUCHECK) + 2*GetSystemMetrics(SM_CXEDGE) + 3;
153 controlrectorig.right = controlrectorig.left + (controlrect.right - controlrect.left) + checkWidth;
154 pwndDlgItem->MoveWindow(&controlrectorig);
157 pDC->SelectObject(pOldFont);
158 ReleaseDC(pDC);
160 return controlrectorig;
164 * Adjusts the size of a static control.
165 * \param rc the position of the control where this control shall
166 * be positioned next to on its right side.
167 * \param spacing number of pixels to add to rc.right
169 RECT AdjustStaticSize(UINT nID, RECT rc, long spacing)
171 CWnd * pwndDlgItem = GetDlgItem(nID);
172 // adjust the size of the control to fit its content
173 CString sControlText;
174 pwndDlgItem->GetWindowText(sControlText);
175 // next step: find the rectangle the control text needs to
176 // be displayed
178 CDC * pDC = pwndDlgItem->GetWindowDC();
179 RECT controlrect;
180 RECT controlrectorig;
181 pwndDlgItem->GetWindowRect(&controlrect);
182 ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT)&controlrect, 2);
183 controlrect.right += 200; // in case the control needs to be bigger than it currently is (e.g., due to translations)
184 controlrectorig = controlrect;
186 long height = controlrectorig.bottom-controlrectorig.top;
187 long width = controlrectorig.right-controlrectorig.left;
188 controlrectorig.left = rc.right + spacing;
189 controlrectorig.right = controlrectorig.left + width;
190 controlrectorig.bottom = rc.bottom;
191 controlrectorig.top = controlrectorig.bottom - height;
193 if (pDC)
195 CFont * font = pwndDlgItem->GetFont();
196 CFont * pOldFont = pDC->SelectObject(font);
197 if (pDC->DrawText(sControlText, -1, &controlrect, DT_WORDBREAK | DT_EDITCONTROL | DT_EXPANDTABS | DT_LEFT | DT_CALCRECT))
199 // now we have the rectangle the control really needs
200 controlrectorig.right = controlrectorig.left + (controlrect.right - controlrect.left);
201 pwndDlgItem->MoveWindow(&controlrectorig);
203 pDC->SelectObject(pOldFont);
204 ReleaseDC(pDC);
206 return controlrectorig;
210 * Display a balloon with close button, anchored at a given edit control on this dialog.
212 void ShowEditBalloon(UINT nIdControl, UINT nIdText, UINT nIdTitle, int nIcon = TTI_WARNING)
214 CString text(MAKEINTRESOURCE(nIdText));
215 CString title(MAKEINTRESOURCE(nIdTitle));
216 ShowEditBalloon(nIdControl, text, title, nIcon);
218 void ShowEditBalloon(UINT nIdControl, const CString& text, const CString& title, int nIcon = TTI_WARNING)
220 EDITBALLOONTIP bt;
221 bt.cbStruct = sizeof(bt);
222 bt.pszText = text;
223 bt.pszTitle = title;
224 bt.ttiIcon = nIcon;
225 SendDlgItemMessage(nIdControl, EM_SHOWBALLOONTIP, 0, (LPARAM)&bt);
229 * Refreshes the cursor by forcing a WM_SETCURSOR message.
231 void RefreshCursor()
233 POINT pt;
234 GetCursorPos(&pt);
235 SetCursorPos(pt.x, pt.y);
237 private:
238 HCURSOR OnQueryDragIcon()
240 return static_cast<HCURSOR>(m_hIcon);
243 virtual void HtmlHelp(DWORD_PTR dwData, UINT nCmd = 0x000F)
245 CWinApp* pApp = AfxGetApp();
246 ASSERT_VALID(pApp);
247 ASSERT(pApp->m_pszHelpFilePath != NULL);
248 // to call HtmlHelp the m_fUseHtmlHelp must be set in
249 // the application's constructor
250 ASSERT(pApp->m_eHelpType == afxHTMLHelp);
252 CWaitCursor wait;
254 PrepareForHelp();
255 // run the HTML Help engine
256 if (!::HtmlHelp(m_hWnd, pApp->m_pszHelpFilePath, nCmd, dwData))
258 AfxMessageBox(AFX_IDP_FAILED_TO_LAUNCH_HELP);
263 HICON m_hIcon;
266 class CStateDialog : public CDialog, public CResizableWndState
268 public:
269 CStateDialog()
270 : m_bEnableSaveRestore(false)
271 , m_bRectOnly(false)
273 CStateDialog(UINT /*nIDTemplate*/, CWnd* /*pParentWnd = NULL*/)
274 : m_bEnableSaveRestore(false)
275 , m_bRectOnly(false)
277 CStateDialog(LPCTSTR /*lpszTemplateName*/, CWnd* /*pParentWnd = NULL*/)
278 : m_bEnableSaveRestore(false)
279 , m_bRectOnly(false)
281 virtual ~CStateDialog();
283 private:
284 // flags
285 bool m_bEnableSaveRestore;
286 bool m_bRectOnly;
288 // internal status
289 CString m_sSection; // section name (identifies a parent window)
291 protected:
292 // section to use in app's profile
293 void EnableSaveRestore(LPCTSTR pszSection, bool bRectOnly = FALSE)
295 m_sSection = pszSection;
297 m_bEnableSaveRestore = true;
298 m_bRectOnly = bRectOnly;
300 // restore immediately
301 LoadWindowRect(pszSection, bRectOnly);
304 virtual CWnd* GetResizableWnd() const
306 // make the layout know its parent window
307 return CWnd::FromHandle(m_hWnd);
310 afx_msg void OnDestroy()
312 if (m_bEnableSaveRestore)
313 SaveWindowRect(m_sSection, m_bRectOnly);
314 CDialog::OnDestroy();
317 DECLARE_MESSAGE_MAP()
321 class CResizableStandAloneDialog : public CStandAloneDialogTmpl<CResizableDialog>
323 public:
324 CResizableStandAloneDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL);
326 private:
327 DECLARE_DYNAMIC(CResizableStandAloneDialog)
329 protected:
330 afx_msg void OnSizing(UINT fwSide, LPRECT pRect);
331 afx_msg void OnMoving(UINT fwSide, LPRECT pRect);
332 afx_msg void OnNcMButtonUp(UINT nHitTest, CPoint point);
333 afx_msg void OnNcRButtonUp(UINT nHitTest, CPoint point);
335 DECLARE_MESSAGE_MAP()
337 private:
338 bool m_bVertical;
339 bool m_bHorizontal;
340 CRect m_rcOrgWindowRect;
343 typedef CStandAloneDialogTmpl<CDialog> CStandAloneDialog;
344 typedef CStandAloneDialogTmpl<CStateDialog> CStateStandAloneDialog;