Improve readability of version string
[TortoiseGit.git] / src / Utils / MiscUI / StandAloneDlg.h
blobf35d494bf8509e2be920837681889e3bbd85d7a3
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2015 - 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"
22 #include "TaskbarUUID.h"
23 #include "Tooltip.h"
25 #pragma comment(lib, "htmlhelp.lib")
27 #define DIALOG_BLOCKHORIZONTAL 1
28 #define DIALOG_BLOCKVERTICAL 2
30 /**
31 * \ingroup TortoiseProc
33 * A template which can be used as the base-class of dialogs which form the main dialog
34 * of a 'dialog-style application'
35 * Just provides the boiler-plate code for dealing with application icons
37 * \remark Replace all references to CDialog or CResizableDialog in your dialog class with
38 * either CResizableStandAloneDialog, CStandAloneDialog or CStateStandAloneDialog, as appropriate
40 template <typename BaseType> class CStandAloneDialogTmpl : public BaseType
42 protected:
43 CStandAloneDialogTmpl(UINT nIDTemplate, CWnd* pParentWnd = nullptr) : BaseType(nIDTemplate, pParentWnd)
45 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
46 m_nResizeBlock = 0;
47 m_height = 0;
48 m_width = 0;
50 virtual BOOL OnInitDialog()
52 BaseType::OnInitDialog();
54 // Set the icon for this dialog. The framework does this automatically
55 // when the application's main window is not a dialog
56 SetIcon(m_hIcon, TRUE); // Set big icon
57 SetIcon(m_hIcon, FALSE); // Set small icon
59 RECT rect;
60 GetWindowRect(&rect);
61 m_height = rect.bottom - rect.top;
62 m_width = rect.right - rect.left;
63 EnableToolTips();
64 m_tooltips.Create(this);
66 return FALSE;
69 virtual BOOL PreTranslateMessage(MSG* pMsg)
71 m_tooltips.RelayEvent(pMsg, this);
72 if (pMsg->message == WM_KEYDOWN)
74 int nVirtKey = (int) pMsg->wParam;
76 if (nVirtKey == 'A' && (GetKeyState(VK_CONTROL) & 0x8000 ) )
78 TCHAR buffer[129];
79 ::GetClassName(pMsg->hwnd, buffer,128);
81 if(_tcsnicmp(buffer,_T("EDIT"),128) == 0)
83 ::PostMessage(pMsg->hwnd,EM_SETSEL,0,-1);
84 return TRUE;
88 return BaseType::PreTranslateMessage(pMsg);
90 afx_msg void OnPaint()
92 if (IsIconic())
94 CPaintDC dc(this); // device context for painting
96 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
98 // Center icon in client rectangle
99 int cxIcon = GetSystemMetrics(SM_CXICON);
100 int cyIcon = GetSystemMetrics(SM_CYICON);
101 CRect rect;
102 GetClientRect(&rect);
103 int x = (rect.Width() - cxIcon + 1) / 2;
104 int y = (rect.Height() - cyIcon + 1) / 2;
106 // Draw the icon
107 dc.DrawIcon(x, y, m_hIcon);
109 else
111 BaseType::OnPaint();
115 * Wrapper around the CWnd::EnableWindow() method, but
116 * makes sure that a control that has the focus is not disabled
117 * before the focus is passed on to the next control.
119 BOOL DialogEnableWindow(UINT nID, BOOL bEnable)
121 CWnd * pwndDlgItem = GetDlgItem(nID);
122 if (!pwndDlgItem)
123 return FALSE;
124 if (bEnable)
125 return pwndDlgItem->EnableWindow(bEnable);
126 if (GetFocus() == pwndDlgItem)
128 SendMessage(WM_NEXTDLGCTL, 0, FALSE);
130 return pwndDlgItem->EnableWindow(bEnable);
134 * Adjusts the size of a checkbox or radio button control.
135 * Since we always make the size of those bigger than 'necessary'
136 * for making sure that translated strings can fit in those too,
137 * this method can reduce the size of those controls again to only
138 * fit the text.
140 RECT AdjustControlSize(UINT nID)
142 CWnd * pwndDlgItem = GetDlgItem(nID);
143 // adjust the size of the control to fit its content
144 CString sControlText;
145 pwndDlgItem->GetWindowText(sControlText);
146 // next step: find the rectangle the control text needs to
147 // be displayed
149 CDC * pDC = pwndDlgItem->GetWindowDC();
150 RECT controlrect;
151 RECT controlrectorig;
152 pwndDlgItem->GetWindowRect(&controlrect);
153 ::MapWindowPoints(nullptr, GetSafeHwnd(), (LPPOINT)&controlrect, 2);
154 controlrectorig = controlrect;
155 if (pDC)
157 CFont * font = pwndDlgItem->GetFont();
158 CFont * pOldFont = pDC->SelectObject(font);
159 if (pDC->DrawText(sControlText, -1, &controlrect, DT_WORDBREAK | DT_EDITCONTROL | DT_EXPANDTABS | DT_LEFT | DT_CALCRECT))
161 // now we have the rectangle the control really needs
162 if ((controlrectorig.right - controlrectorig.left) > (controlrect.right - controlrect.left))
164 // we're dealing with radio buttons and check boxes,
165 // which means we have to add a little space for the checkbox
166 // the value of 3 pixels added here is necessary in case certain visual styles have
167 // been disabled. Without this, the width is calculated too short.
168 const int checkWidth = GetSystemMetrics(SM_CXMENUCHECK) + 2*GetSystemMetrics(SM_CXEDGE) + 3;
169 controlrectorig.right = controlrectorig.left + (controlrect.right - controlrect.left) + checkWidth;
170 pwndDlgItem->MoveWindow(&controlrectorig);
173 pDC->SelectObject(pOldFont);
174 ReleaseDC(pDC);
176 return controlrectorig;
180 * Adjusts the size of a static control.
181 * \param nID control ID
182 * \param rc the position of the control where this control shall
183 * be positioned next to on its right side.
184 * \param spacing number of pixels to add to rc.right
186 RECT AdjustStaticSize(UINT nID, RECT rc, long spacing)
188 CWnd * pwndDlgItem = GetDlgItem(nID);
189 // adjust the size of the control to fit its content
190 CString sControlText;
191 pwndDlgItem->GetWindowText(sControlText);
192 // next step: find the rectangle the control text needs to
193 // be displayed
195 CDC * pDC = pwndDlgItem->GetWindowDC();
196 RECT controlrect;
197 RECT controlrectorig;
198 pwndDlgItem->GetWindowRect(&controlrect);
199 ::MapWindowPoints(nullptr, GetSafeHwnd(), (LPPOINT)&controlrect, 2);
200 controlrect.right += 200; // in case the control needs to be bigger than it currently is (e.g., due to translations)
201 controlrectorig = controlrect;
203 long height = controlrectorig.bottom-controlrectorig.top;
204 long width = controlrectorig.right-controlrectorig.left;
205 controlrectorig.left = rc.right + spacing;
206 controlrectorig.right = controlrectorig.left + width;
207 controlrectorig.bottom = rc.bottom;
208 controlrectorig.top = controlrectorig.bottom - height;
210 if (pDC)
212 CFont * font = pwndDlgItem->GetFont();
213 CFont * pOldFont = pDC->SelectObject(font);
214 if (pDC->DrawText(sControlText, -1, &controlrect, DT_WORDBREAK | DT_EDITCONTROL | DT_EXPANDTABS | DT_LEFT | DT_CALCRECT))
216 // now we have the rectangle the control really needs
217 controlrectorig.right = controlrectorig.left + (controlrect.right - controlrect.left);
218 pwndDlgItem->MoveWindow(&controlrectorig);
220 pDC->SelectObject(pOldFont);
221 ReleaseDC(pDC);
223 return controlrectorig;
227 * Display a balloon with close button, anchored at a given edit control on this dialog.
229 void ShowEditBalloon(UINT nIdControl, UINT nIdText, UINT nIdTitle, int nIcon = TTI_WARNING)
231 CString text(MAKEINTRESOURCE(nIdText));
232 CString title(MAKEINTRESOURCE(nIdTitle));
233 ShowEditBalloon(nIdControl, text, title, nIcon);
235 void ShowEditBalloon(UINT nIdControl, const CString& text, const CString& title, int nIcon = TTI_WARNING)
237 EDITBALLOONTIP bt;
238 bt.cbStruct = sizeof(bt);
239 bt.pszText = text;
240 bt.pszTitle = title;
241 bt.ttiIcon = nIcon;
242 SendDlgItemMessage(nIdControl, EM_SHOWBALLOONTIP, 0, (LPARAM)&bt);
246 * Refreshes the cursor by forcing a WM_SETCURSOR message.
248 void RefreshCursor()
250 POINT pt;
251 GetCursorPos(&pt);
252 SetCursorPos(pt.x, pt.y);
255 void BlockResize(int block)
257 m_nResizeBlock = block;
260 void EnableSaveRestore(LPCTSTR pszSection, bool bRectOnly = FALSE)
262 // call the base method with the bHorzResize and bVertResize parameters
263 // figured out from the resize block flags.
264 BaseType::EnableSaveRestore(pszSection, bRectOnly, (m_nResizeBlock & DIALOG_BLOCKHORIZONTAL) == 0, (m_nResizeBlock & DIALOG_BLOCKVERTICAL) == 0);
267 protected:
268 CToolTips m_tooltips;
269 int m_nResizeBlock;
270 long m_width;
271 long m_height;
273 DECLARE_MESSAGE_MAP()
275 private:
276 HCURSOR OnQueryDragIcon()
278 return static_cast<HCURSOR>(m_hIcon);
280 protected:
281 virtual void HtmlHelp(DWORD_PTR dwData, UINT nCmd = 0x000F)
283 CWinApp* pApp = AfxGetApp();
284 ASSERT_VALID(pApp);
285 ASSERT(pApp->m_pszHelpFilePath);
286 // to call HtmlHelp the m_fUseHtmlHelp must be set in
287 // the application's constructor
288 ASSERT(pApp->m_eHelpType == afxHTMLHelp);
290 CWaitCursor wait;
292 PrepareForHelp();
293 // run the HTML Help engine
294 if (!::HtmlHelp(m_hWnd, pApp->m_pszHelpFilePath, nCmd, dwData))
296 AfxMessageBox(AFX_IDP_FAILED_TO_LAUNCH_HELP);
299 private:
300 afx_msg LRESULT OnTaskbarButtonCreated(WPARAM /*wParam*/, LPARAM /*lParam*/)
302 SetUUIDOverlayIcon(m_hWnd);
303 return 0;
306 HICON m_hIcon;
309 class CStateDialog : public CDialog, public CResizableWndState
311 public:
312 CStateDialog()
313 : CDialog()
314 , m_bEnableSaveRestore(false)
315 , m_bRectOnly(false)
317 CStateDialog(UINT nIDTemplate, CWnd* pParentWnd = nullptr)
318 : CDialog(nIDTemplate, pParentWnd)
319 , m_bEnableSaveRestore(false)
320 , m_bRectOnly(false)
322 CStateDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd = nullptr)
323 : CDialog(lpszTemplateName, pParentWnd)
324 , m_bEnableSaveRestore(false)
325 , m_bRectOnly(false)
327 virtual ~CStateDialog() {};
329 private:
330 // flags
331 bool m_bEnableSaveRestore;
332 bool m_bRectOnly;
334 // internal status
335 CString m_sSection; // section name (identifies a parent window)
337 protected:
338 // overloaded method, but since this dialog class is for non-resizable dialogs,
339 // the bHorzResize and bVertResize params are ignored and passed as false
340 // to the base method.
341 void EnableSaveRestore(LPCTSTR pszSection, bool bRectOnly = FALSE, BOOL bHorzResize = TRUE, BOOL bVertResize = TRUE)
343 UNREFERENCED_PARAMETER(bHorzResize);
344 UNREFERENCED_PARAMETER(bVertResize);
345 m_sSection = pszSection;
347 m_bEnableSaveRestore = true;
348 m_bRectOnly = bRectOnly;
350 // restore immediately
351 LoadWindowRect(pszSection, bRectOnly, false, false);
354 virtual CWnd* GetResizableWnd() const
356 // make the layout know its parent window
357 return CWnd::FromHandle(m_hWnd);
360 afx_msg void OnDestroy()
362 if (m_bEnableSaveRestore)
363 SaveWindowRect(m_sSection, m_bRectOnly);
364 CDialog::OnDestroy();
367 DECLARE_MESSAGE_MAP()
370 class CResizableStandAloneDialog : public CStandAloneDialogTmpl<CResizableDialog>
372 public:
373 CResizableStandAloneDialog(UINT nIDTemplate, CWnd* pParentWnd = nullptr);
375 private:
376 DECLARE_DYNAMIC(CResizableStandAloneDialog)
378 protected:
379 afx_msg void OnSizing(UINT fwSide, LPRECT pRect);
380 afx_msg void OnMoving(UINT fwSide, LPRECT pRect);
381 afx_msg void OnNcMButtonUp(UINT nHitTest, CPoint point);
382 afx_msg void OnNcRButtonUp(UINT nHitTest, CPoint point);
383 afx_msg LRESULT OnNcHitTest(CPoint point);
385 DECLARE_MESSAGE_MAP()
387 private:
388 bool m_bVertical;
389 bool m_bHorizontal;
390 CRect m_rcOrgWindowRect;
393 class CStandAloneDialog : public CStandAloneDialogTmpl<CDialog>
395 public:
396 CStandAloneDialog(UINT nIDTemplate, CWnd* pParentWnd = nullptr);
397 protected:
398 DECLARE_MESSAGE_MAP()
399 private:
400 DECLARE_DYNAMIC(CStandAloneDialog)
403 class CStateStandAloneDialog : public CStandAloneDialogTmpl<CStateDialog>
405 public:
406 CStateStandAloneDialog(UINT nIDTemplate, CWnd* pParentWnd = nullptr);
407 protected:
408 DECLARE_MESSAGE_MAP()
409 private:
410 DECLARE_DYNAMIC(CStateStandAloneDialog)