Allow to move item past last item
[TortoiseGit.git] / src / Utils / MiscUI / CommonDialogFunctions.h
blob7f7aa16c8b0f51a980f8db4de3ca6709d6274e1a
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2015-2016 - TortoiseGit
4 // Copyright (C) 2003-2015 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #pragma once
22 template <typename BaseType> class CommonDialogFunctions
24 public:
25 CommonDialogFunctions(BaseType* ctrl)
26 : m_ctrl(ctrl)
29 private:
30 BaseType* m_ctrl;
32 public:
33 /**
34 * Adjusts the size of a checkbox or radio button control.
35 * Since we always make the size of those bigger than 'necessary'
36 * for making sure that translated strings can fit in those too,
37 * this method can reduce the size of those controls again to only
38 * fit the text.
40 RECT AdjustControlSize(UINT nID, bool ischeck = true)
42 CWnd* pwndDlgItem = m_ctrl->GetDlgItem(nID);
43 if (!pwndDlgItem)
44 return { 0 };
45 // adjust the size of the control to fit its content
46 CString sControlText;
47 pwndDlgItem->GetWindowText(sControlText);
48 // next step: find the rectangle the control text needs to
49 // be displayed
51 CDC* pDC = pwndDlgItem->GetWindowDC();
52 RECT controlrect;
53 RECT controlrectorig;
54 pwndDlgItem->GetWindowRect(&controlrect);
55 ::MapWindowPoints(nullptr, m_ctrl->GetSafeHwnd(), (LPPOINT)&controlrect, 2);
56 controlrectorig = controlrect;
57 if (pDC)
59 CFont* font = pwndDlgItem->GetFont();
60 CFont* pOldFont = pDC->SelectObject(font);
61 if (pDC->DrawText(sControlText, -1, &controlrect, DT_WORDBREAK | DT_EDITCONTROL | DT_EXPANDTABS | DT_LEFT | DT_CALCRECT))
63 // now we have the rectangle the control really needs
64 if ((controlrectorig.right - controlrectorig.left) > (controlrect.right - controlrect.left))
66 // we're dealing with radio buttons and check boxes,
67 // which means we have to add a little space for the checkbox
68 // the value of 3 pixels added here is necessary in case certain visual styles have
69 // been disabled. Without this, the width is calculated too short.
70 const int checkWidth = GetSystemMetrics(SM_CXMENUCHECK) + 2 * GetSystemMetrics(SM_CXEDGE) + 3;
71 controlrectorig.right = controlrectorig.left + (controlrect.right - controlrect.left) + (ischeck ? checkWidth : 0);
72 pwndDlgItem->MoveWindow(&controlrectorig);
75 pDC->SelectObject(pOldFont);
76 m_ctrl->ReleaseDC(pDC);
78 return controlrectorig;
81 /**
82 * Adjusts the size of a static control.
83 * \param nID control ID
84 * \param rc the position of the control where this control shall
85 * be positioned next to on its right side.
86 * \param spacing number of pixels to add to rc.right
88 RECT AdjustStaticSize(UINT nID, RECT rc, long spacing)
90 CWnd* pwndDlgItem = m_ctrl->GetDlgItem(nID);
91 // adjust the size of the control to fit its content
92 CString sControlText;
93 pwndDlgItem->GetWindowText(sControlText);
94 // next step: find the rectangle the control text needs to
95 // be displayed
97 CDC* pDC = pwndDlgItem->GetWindowDC();
98 RECT controlrect;
99 RECT controlrectorig;
100 pwndDlgItem->GetWindowRect(&controlrect);
101 ::MapWindowPoints(nullptr, m_ctrl->GetSafeHwnd(), (LPPOINT)&controlrect, 2);
102 controlrect.right += 200; // in case the control needs to be bigger than it currently is (e.g., due to translations)
103 controlrectorig = controlrect;
105 long height = controlrectorig.bottom - controlrectorig.top;
106 long width = controlrectorig.right - controlrectorig.left;
107 controlrectorig.left = rc.right + spacing;
108 controlrectorig.right = controlrectorig.left + width;
109 controlrectorig.bottom = rc.bottom;
110 controlrectorig.top = controlrectorig.bottom - height;
112 if (pDC)
114 CFont* font = pwndDlgItem->GetFont();
115 CFont* pOldFont = pDC->SelectObject(font);
116 if (pDC->DrawText(sControlText, -1, &controlrect, DT_WORDBREAK | DT_EDITCONTROL | DT_EXPANDTABS | DT_LEFT | DT_CALCRECT))
118 // now we have the rectangle the control really needs
119 controlrectorig.right = controlrectorig.left + (controlrect.right - controlrect.left);
120 pwndDlgItem->MoveWindow(&controlrectorig);
122 pDC->SelectObject(pOldFont);
123 m_ctrl->ReleaseDC(pDC);
125 return controlrectorig;
129 * Display a balloon with close button, anchored at a given edit control on this dialog.
131 void ShowEditBalloon(UINT nIdControl, UINT nIdText, UINT nIdTitle, int nIcon = TTI_WARNING)
133 CString text(MAKEINTRESOURCE(nIdText));
134 CString title(MAKEINTRESOURCE(nIdTitle));
135 ShowEditBalloon(nIdControl, text, title, nIcon);
137 void ShowEditBalloon(UINT nIdControl, const CString& text, const CString& title, int nIcon = TTI_WARNING)
139 EDITBALLOONTIP bt;
140 bt.cbStruct = sizeof(bt);
141 bt.pszText = text;
142 bt.pszTitle = title;
143 bt.ttiIcon = nIcon;
144 m_ctrl->SendDlgItemMessage(nIdControl, EM_SHOWBALLOONTIP, 0, (LPARAM)&bt);