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
20 #include <windowsx.h>
\r
21 #include "BrowseFolder.h"
\r
23 BOOL CBrowseFolder::m_bCheck = FALSE;
\r
24 BOOL CBrowseFolder::m_bCheck2 = FALSE;
\r
25 WNDPROC CBrowseFolder::CBProc = NULL;
\r
26 HWND CBrowseFolder::checkbox = NULL;
\r
27 HWND CBrowseFolder::checkbox2 = NULL;
\r
28 HWND CBrowseFolder::ListView = NULL;
\r
29 TCHAR CBrowseFolder::m_CheckText[200];
\r
30 TCHAR CBrowseFolder::m_CheckText2[200];
\r
31 CString CBrowseFolder::m_sDefaultPath;
\r
32 bool CBrowseFolder::m_DisableCheckbox2WhenCheckbox1IsChecked = false;
\r
35 CBrowseFolder::CBrowseFolder(void)
\r
39 memset(m_displayName, 0, sizeof(m_displayName));
\r
40 memset(m_title, 0, sizeof(m_title));
\r
41 memset(m_CheckText, 0, sizeof(m_CheckText));
\r
44 CBrowseFolder::~CBrowseFolder(void)
\r
49 CBrowseFolder::retVal CBrowseFolder::Show(HWND parent, LPTSTR path, size_t pathlen, LPCTSTR szDefaultPath /* = NULL */)
\r
55 sDefault = szDefaultPath;
\r
56 CBrowseFolder::retVal ret = Show(parent, temp, sDefault);
\r
57 _tcscpy_s(path, pathlen, temp);
\r
60 CBrowseFolder::retVal CBrowseFolder::Show(HWND parent, CString& path, const CString& sDefaultPath /* = CString() */)
\r
62 retVal ret = OK; //assume OK
\r
63 m_sDefaultPath = sDefaultPath;
\r
64 if (m_sDefaultPath.IsEmpty() && !path.IsEmpty())
\r
66 // if the result path already contains a path, use that as the default path
\r
67 m_sDefaultPath = path;
\r
69 LPITEMIDLIST itemIDList;
\r
71 BROWSEINFO browseInfo;
\r
73 browseInfo.hwndOwner = parent;
\r
74 browseInfo.pidlRoot = m_root;
\r
75 browseInfo.pszDisplayName = m_displayName;
\r
76 browseInfo.lpszTitle = m_title;
\r
77 browseInfo.ulFlags = m_style;
\r
78 browseInfo.lpfn = NULL;
\r
79 browseInfo.lParam = (LPARAM)this;
\r
81 if ((_tcslen(m_CheckText) > 0)||(!m_sDefaultPath.IsEmpty()))
\r
83 browseInfo.lpfn = BrowseCallBackProc;
\r
86 itemIDList = SHBrowseForFolder(&browseInfo);
\r
88 //is the dialog canceled?
\r
94 if (!SHGetPathFromIDList(itemIDList, path.GetBuffer(MAX_PATH))) // MAX_PATH ok. Explorer can't handle paths longer than MAX_PATH.
\r
97 path.ReleaseBuffer();
\r
99 LPMALLOC shellMalloc;
\r
102 hr = SHGetMalloc(&shellMalloc);
\r
104 if (SUCCEEDED(hr))
\r
107 shellMalloc->Free(itemIDList);
\r
108 //release interface
\r
109 shellMalloc->Release();
\r
115 void CBrowseFolder::SetInfo(LPCTSTR title)
\r
120 _tcscpy_s(m_title, 200, title);
\r
123 void CBrowseFolder::SetCheckBoxText(LPCTSTR checktext)
\r
128 _tcscpy_s(m_CheckText, 200, checktext);
\r
131 void CBrowseFolder::SetCheckBoxText2(LPCTSTR checktext)
\r
136 _tcscpy_s(m_CheckText2, 200, checktext);
\r
139 void CBrowseFolder::SetFont(HWND hwnd,LPTSTR FontName,int FontSize)
\r
144 HDC hdc=GetDC(hwnd);
\r
146 GetObject(GetWindowFont(hwnd),sizeof(lf),&lf);
\r
147 lf.lfWeight = FW_REGULAR;
\r
148 lf.lfHeight = (LONG)FontSize;
\r
149 lstrcpy( lf.lfFaceName, FontName );
\r
150 hf=CreateFontIndirect(&lf);
\r
151 SetBkMode(hdc,OPAQUE);
\r
152 SendMessage(hwnd,WM_SETFONT,(WPARAM)hf,TRUE);
\r
153 ReleaseDC(hwnd,hdc);
\r
157 int CBrowseFolder::BrowseCallBackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM /*lpData*/)
\r
159 RECT ListViewRect,Dialog;
\r
160 //Initialization callback message
\r
161 if (uMsg == BFFM_INITIALIZED)
\r
163 if (_tcslen(m_CheckText) > 0)
\r
165 bool bSecondCheckbox = (_tcslen(m_CheckText2)!=0);
\r
166 //Rectangles for getting the positions
\r
167 checkbox = CreateWindowEx( 0,
\r
170 WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|BS_AUTOCHECKBOX,
\r
176 if (checkbox == NULL)
\r
179 if (bSecondCheckbox)
\r
181 //Rectangles for getting the positions
\r
182 checkbox2 = CreateWindowEx( 0,
\r
185 WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|BS_AUTOCHECKBOX,
\r
191 if (checkbox2 == NULL)
\r
195 ListView = FindWindowEx(hwnd,NULL,_T("SysTreeView32"),NULL);
\r
196 if (ListView == NULL)
\r
197 ListView = FindWindowEx(hwnd,NULL,_T("SHBrowseForFolder ShellNameSpace Control"),NULL);
\r
199 if (ListView == NULL)
\r
202 //Gets the dimensions of the windows
\r
203 GetWindowRect(hwnd,&Dialog);
\r
204 GetWindowRect(ListView,&ListViewRect);
\r
206 pt.x = ListViewRect.left;
\r
207 pt.y = ListViewRect.top;
\r
208 ScreenToClient(hwnd, &pt);
\r
209 ListViewRect.top = pt.y;
\r
210 ListViewRect.left = pt.x;
\r
211 pt.x = ListViewRect.right;
\r
212 pt.y = ListViewRect.bottom;
\r
213 ScreenToClient(hwnd, &pt);
\r
214 ListViewRect.bottom = pt.y;
\r
215 ListViewRect.right = pt.x;
\r
216 //Sets the list view controls dimensions
\r
217 SetWindowPos(ListView,0,ListViewRect.left,
\r
218 bSecondCheckbox ? ListViewRect.top+40 : ListViewRect.top+20,
\r
219 (ListViewRect.right-ListViewRect.left),
\r
220 bSecondCheckbox ? (ListViewRect.bottom - ListViewRect.top)-40 : (ListViewRect.bottom - ListViewRect.top)-20,
\r
222 //Sets the window positions of checkbox and dialog controls
\r
223 SetWindowPos(checkbox,HWND_BOTTOM,ListViewRect.left,
\r
225 (ListViewRect.right-ListViewRect.left),
\r
228 if (bSecondCheckbox)
\r
230 SetWindowPos(checkbox2,HWND_BOTTOM,ListViewRect.left,
\r
231 ListViewRect.top+20,
\r
232 (ListViewRect.right-ListViewRect.left),
\r
236 HWND label = FindWindowEx(hwnd, NULL, _T("STATIC"), NULL);
\r
239 HFONT hFont = (HFONT)::SendMessage(label, WM_GETFONT, 0, 0);
\r
241 GetObject(hFont, sizeof(lf), &lf);
\r
242 HFONT hf2 = CreateFontIndirect(&lf);
\r
243 ::SendMessage(checkbox, WM_SETFONT, (WPARAM)hf2, TRUE);
\r
244 if (bSecondCheckbox)
\r
245 ::SendMessage(checkbox2, WM_SETFONT, (WPARAM)hf2, TRUE);
\r
249 //Sets the fonts of static controls
\r
250 SetFont(checkbox,_T("MS Sans Serif"),12);
\r
251 if (bSecondCheckbox)
\r
252 SetFont(checkbox2,_T("MS Sans Serif"),12);
\r
255 // Subclass the checkbox control.
\r
256 CBProc = (WNDPROC) SetWindowLongPtr(checkbox,GWLP_WNDPROC, (LONG_PTR) CheckBoxSubclassProc);
\r
257 //Sets the checkbox to checked position
\r
258 SendMessage(checkbox,BM_SETCHECK,(WPARAM)m_bCheck,0);
\r
259 if (bSecondCheckbox)
\r
261 CBProc = (WNDPROC) SetWindowLongPtr(checkbox2,GWLP_WNDPROC, (LONG_PTR) CheckBoxSubclassProc2);
\r
262 SendMessage(checkbox2,BM_SETCHECK,(WPARAM)m_bCheck,0);
\r
264 // send a resize message to the resized list view control. Otherwise it won't show
\r
265 // up properly until the user resizes the window!
\r
266 SendMessage(ListView, WM_SIZE, SIZE_RESTORED, MAKELONG(ListViewRect.right-ListViewRect.left, bSecondCheckbox ? (ListViewRect.bottom - ListViewRect.top)-40 : (ListViewRect.bottom - ListViewRect.top)-20));
\r
269 // now set the default directory
\r
270 SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)(LPCTSTR)m_sDefaultPath);
\r
272 if (uMsg == BFFM_SELCHANGED)
\r
274 // Set the status window to the currently selected path.
\r
275 TCHAR szDir[MAX_PATH];
\r
276 if (SHGetPathFromIDList((LPITEMIDLIST)lParam, szDir))
\r
278 SendMessage(hwnd,BFFM_SETSTATUSTEXT, 0, (LPARAM)szDir);
\r
285 LRESULT CBrowseFolder::CheckBoxSubclassProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
\r
287 if (uMsg == WM_LBUTTONUP)
\r
289 m_bCheck = (SendMessage(hwnd,BM_GETCHECK,0,0)==BST_UNCHECKED);
\r
290 if (m_bCheck && m_DisableCheckbox2WhenCheckbox1IsChecked)
\r
292 ::EnableWindow(checkbox2, !m_bCheck);
\r
295 ::EnableWindow(checkbox2, true);
\r
298 return CallWindowProc(CBProc, hwnd, uMsg,
\r
302 LRESULT CBrowseFolder::CheckBoxSubclassProc2(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
\r
304 if (uMsg == WM_LBUTTONUP)
\r
306 m_bCheck2 = (SendMessage(hwnd,BM_GETCHECK,0,0)==BST_UNCHECKED);
\r
309 return CallWindowProc(CBProc, hwnd, uMsg,
\r