1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2012 - 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.
21 #include "BrowseFolder.h"
24 BOOL
CBrowseFolder::m_bCheck
= FALSE
;
25 BOOL
CBrowseFolder::m_bCheck2
= FALSE
;
26 WNDPROC
CBrowseFolder::CBProc
= NULL
;
27 HWND
CBrowseFolder::checkbox
= NULL
;
28 HWND
CBrowseFolder::checkbox2
= NULL
;
29 HWND
CBrowseFolder::ListView
= NULL
;
30 TCHAR
CBrowseFolder::m_CheckText
[200];
31 TCHAR
CBrowseFolder::m_CheckText2
[200];
32 CString
CBrowseFolder::m_sDefaultPath
;
33 bool CBrowseFolder::m_DisableCheckbox2WhenCheckbox1IsChecked
= false;
36 CBrowseFolder::CBrowseFolder(void)
40 memset(m_displayName
, 0, sizeof(m_displayName
));
41 memset(m_title
, 0, sizeof(m_title
));
42 memset(m_CheckText
, 0, sizeof(m_CheckText
));
45 CBrowseFolder::~CBrowseFolder(void)
50 CBrowseFolder::retVal
CBrowseFolder::Show(HWND parent
, LPTSTR path
, size_t pathlen
, LPCTSTR szDefaultPath
/* = NULL */)
56 sDefault
= szDefaultPath
;
57 CBrowseFolder::retVal ret
= Show(parent
, temp
, sDefault
);
58 _tcscpy_s(path
, pathlen
, temp
);
61 CBrowseFolder::retVal
CBrowseFolder::Show(HWND parent
, CString
& path
, const CString
& sDefaultPath
/* = CString() */)
63 retVal ret
= OK
; //assume OK
64 m_sDefaultPath
= sDefaultPath
;
65 if (m_sDefaultPath
.IsEmpty() && !path
.IsEmpty())
67 // if the result path already contains a path, use that as the default path
68 m_sDefaultPath
= path
;
70 LPITEMIDLIST itemIDList
;
72 BROWSEINFO browseInfo
;
74 browseInfo
.hwndOwner
= parent
;
75 browseInfo
.pidlRoot
= m_root
;
76 browseInfo
.pszDisplayName
= m_displayName
;
77 browseInfo
.lpszTitle
= m_title
;
78 browseInfo
.ulFlags
= m_style
;
79 browseInfo
.lpfn
= NULL
;
80 browseInfo
.lParam
= (LPARAM
)this;
82 if ((_tcslen(m_CheckText
) > 0)||(!m_sDefaultPath
.IsEmpty()))
84 browseInfo
.lpfn
= BrowseCallBackProc
;
87 itemIDList
= SHBrowseForFolder(&browseInfo
);
89 //is the dialog canceled?
95 if (!SHGetPathFromIDList(itemIDList
, path
.GetBuffer(MAX_PATH
))) // MAX_PATH ok. Explorer can't handle paths longer than MAX_PATH.
100 LPMALLOC shellMalloc
;
103 hr
= SHGetMalloc(&shellMalloc
);
108 shellMalloc
->Free(itemIDList
);
110 shellMalloc
->Release();
116 void CBrowseFolder::SetInfo(LPCTSTR title
)
121 _tcscpy_s(m_title
, 200, title
);
124 void CBrowseFolder::SetCheckBoxText(LPCTSTR checktext
)
129 _tcscpy_s(m_CheckText
, 200, checktext
);
132 void CBrowseFolder::SetCheckBoxText2(LPCTSTR checktext
)
137 _tcscpy_s(m_CheckText2
, 200, checktext
);
140 void CBrowseFolder::SetFont(HWND hwnd
,LPTSTR FontName
,int FontSize
)
147 GetObject(GetWindowFont(hwnd
),sizeof(lf
),&lf
);
148 lf
.lfWeight
= FW_REGULAR
;
149 lf
.lfHeight
= (LONG
)FontSize
;
150 StringCchCopy( lf
.lfFaceName
, _countof(lf
.lfFaceName
), FontName
);
151 hf
=CreateFontIndirect(&lf
);
152 SetBkMode(hdc
,OPAQUE
);
153 SendMessage(hwnd
,WM_SETFONT
,(WPARAM
)hf
,TRUE
);
158 int CBrowseFolder::BrowseCallBackProc(HWND hwnd
, UINT uMsg
, LPARAM lParam
, LPARAM
/*lpData*/)
160 RECT ListViewRect
,Dialog
;
161 //Initialization callback message
162 if (uMsg
== BFFM_INITIALIZED
)
164 if (_tcslen(m_CheckText
) > 0)
166 bool bSecondCheckbox
= (_tcslen(m_CheckText2
)!=0);
167 //Rectangles for getting the positions
168 checkbox
= CreateWindowEx( 0,
171 WS_CHILD
|WS_VISIBLE
|WS_CLIPCHILDREN
|BS_AUTOCHECKBOX
,
177 if (checkbox
== NULL
)
182 //Rectangles for getting the positions
183 checkbox2
= CreateWindowEx( 0,
186 WS_CHILD
|WS_VISIBLE
|WS_CLIPCHILDREN
|BS_AUTOCHECKBOX
,
192 if (checkbox2
== NULL
)
196 ListView
= FindWindowEx(hwnd
,NULL
,_T("SysTreeView32"),NULL
);
197 if (ListView
== NULL
)
198 ListView
= FindWindowEx(hwnd
,NULL
,_T("SHBrowseForFolder ShellNameSpace Control"),NULL
);
200 if (ListView
== NULL
)
203 //Gets the dimensions of the windows
204 GetWindowRect(hwnd
,&Dialog
);
205 GetWindowRect(ListView
,&ListViewRect
);
207 pt
.x
= ListViewRect
.left
;
208 pt
.y
= ListViewRect
.top
;
209 ScreenToClient(hwnd
, &pt
);
210 ListViewRect
.top
= pt
.y
;
211 ListViewRect
.left
= pt
.x
;
212 pt
.x
= ListViewRect
.right
;
213 pt
.y
= ListViewRect
.bottom
;
214 ScreenToClient(hwnd
, &pt
);
215 ListViewRect
.bottom
= pt
.y
;
216 ListViewRect
.right
= pt
.x
;
217 //Sets the list view controls dimensions
218 SetWindowPos(ListView
,0,ListViewRect
.left
,
219 bSecondCheckbox
? ListViewRect
.top
+40 : ListViewRect
.top
+20,
220 (ListViewRect
.right
-ListViewRect
.left
),
221 bSecondCheckbox
? (ListViewRect
.bottom
- ListViewRect
.top
)-40 : (ListViewRect
.bottom
- ListViewRect
.top
)-20,
223 //Sets the window positions of checkbox and dialog controls
224 SetWindowPos(checkbox
,HWND_BOTTOM
,ListViewRect
.left
,
226 (ListViewRect
.right
-ListViewRect
.left
),
231 SetWindowPos(checkbox2
,HWND_BOTTOM
,ListViewRect
.left
,
233 (ListViewRect
.right
-ListViewRect
.left
),
237 HWND label
= FindWindowEx(hwnd
, NULL
, _T("STATIC"), NULL
);
240 HFONT hFont
= (HFONT
)::SendMessage(label
, WM_GETFONT
, 0, 0);
242 GetObject(hFont
, sizeof(lf
), &lf
);
243 HFONT hf2
= CreateFontIndirect(&lf
);
244 ::SendMessage(checkbox
, WM_SETFONT
, (WPARAM
)hf2
, TRUE
);
246 ::SendMessage(checkbox2
, WM_SETFONT
, (WPARAM
)hf2
, TRUE
);
250 //Sets the fonts of static controls
251 SetFont(checkbox
,_T("MS Sans Serif"),12);
253 SetFont(checkbox2
,_T("MS Sans Serif"),12);
256 // Subclass the checkbox control.
257 CBProc
= (WNDPROC
) SetWindowLongPtr(checkbox
,GWLP_WNDPROC
, (LONG_PTR
) CheckBoxSubclassProc
);
258 //Sets the checkbox to checked position
259 SendMessage(checkbox
,BM_SETCHECK
,(WPARAM
)m_bCheck
,0);
262 CBProc
= (WNDPROC
) SetWindowLongPtr(checkbox2
,GWLP_WNDPROC
, (LONG_PTR
) CheckBoxSubclassProc2
);
263 SendMessage(checkbox2
,BM_SETCHECK
,(WPARAM
)m_bCheck
,0);
265 // send a resize message to the resized list view control. Otherwise it won't show
266 // up properly until the user resizes the window!
267 SendMessage(ListView
, WM_SIZE
, SIZE_RESTORED
, MAKELONG(ListViewRect
.right
-ListViewRect
.left
, bSecondCheckbox
? (ListViewRect
.bottom
- ListViewRect
.top
)-40 : (ListViewRect
.bottom
- ListViewRect
.top
)-20));
270 // now set the default directory
271 SendMessage(hwnd
, BFFM_SETSELECTION
, TRUE
, (LPARAM
)(LPCTSTR
)m_sDefaultPath
);
273 if (uMsg
== BFFM_SELCHANGED
)
275 // Set the status window to the currently selected path.
276 TCHAR szDir
[MAX_PATH
];
277 if (SHGetPathFromIDList((LPITEMIDLIST
)lParam
, szDir
))
279 SendMessage(hwnd
,BFFM_SETSTATUSTEXT
, 0, (LPARAM
)szDir
);
286 LRESULT
CBrowseFolder::CheckBoxSubclassProc(HWND hwnd
,UINT uMsg
,WPARAM wParam
,LPARAM lParam
)
288 if (uMsg
== WM_LBUTTONUP
)
290 m_bCheck
= (SendMessage(hwnd
,BM_GETCHECK
,0,0)==BST_UNCHECKED
);
291 if (m_bCheck
&& m_DisableCheckbox2WhenCheckbox1IsChecked
)
293 ::EnableWindow(checkbox2
, !m_bCheck
);
296 ::EnableWindow(checkbox2
, true);
299 return CallWindowProc(CBProc
, hwnd
, uMsg
,
303 LRESULT
CBrowseFolder::CheckBoxSubclassProc2(HWND hwnd
,UINT uMsg
,WPARAM wParam
,LPARAM lParam
)
305 if (uMsg
== WM_LBUTTONUP
)
307 m_bCheck2
= (SendMessage(hwnd
,BM_GETCHECK
,0,0)==BST_UNCHECKED
);
310 return CallWindowProc(CBProc
, hwnd
, uMsg
,