PathDialog.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. //////////////////////////////////////////////////////////////////////////
  2. //PathDialog.h file
  3. //
  4. //Written by Nguyen Tan Hung <[email protected]>
  5. //////////////////////////////////////////////////////////////////////////
  6. #include "stdafx.h"
  7. #include "PathDialog.h"
  8. #include <io.h>
  9. #ifdef _DEBUG
  10. #define new DEBUG_NEW
  11. #undef THIS_FILE
  12. static char THIS_FILE[] = __FILE__;
  13. #endif
  14. #define IDC_FOLDERTREE 0x3741
  15. #define IDC_TITLE 0x3742
  16. #define IDC_STATUSTEXT 0x3743
  17. #define IDC_NEW_EDIT_PATH 0x3744
  18. // Class CDlgWnd
  19. BEGIN_MESSAGE_MAP(CPathDialogSub, CWnd)
  20. ON_BN_CLICKED(IDOK, OnOK)
  21. ON_EN_CHANGE(IDC_NEW_EDIT_PATH, OnChangeEditPath)
  22. END_MESSAGE_MAP()
  23. void CPathDialogSub::OnOK()
  24. {
  25. ::GetWindowText(::GetDlgItem(m_hWnd, IDC_NEW_EDIT_PATH),
  26. m_pPathDialog->m_szPathName, MAX_PATH);
  27. if(CPathDialog::MakeSurePathExists(m_pPathDialog->m_szPathName)==0)
  28. {
  29. m_pPathDialog->m_bGetSuccess=TRUE;
  30. ::EndDialog(m_pPathDialog->m_hWnd, IDOK);
  31. }
  32. else
  33. {
  34. ::SetFocus(::GetDlgItem(m_hWnd, IDC_NEW_EDIT_PATH));
  35. }
  36. }
  37. void CPathDialogSub::OnChangeEditPath()
  38. {
  39. ::GetWindowText(::GetDlgItem(m_hWnd, IDC_NEW_EDIT_PATH),
  40. m_pPathDialog->m_szPathName, MAX_PATH);
  41. BOOL bEnableOKButton = (_tcslen(m_pPathDialog->m_szPathName)>0);
  42. SendMessage(BFFM_ENABLEOK, 0, bEnableOKButton);
  43. }
  44. /////////////////////////////////////////////////////////////////////////////
  45. // CPathDialog dialog
  46. CPathDialog::CPathDialog(LPCTSTR lpszCaption,
  47. LPCTSTR lpszTitle,
  48. LPCTSTR lpszInitialPath,
  49. CWnd* pParent)
  50. {
  51. m_hWnd=NULL;
  52. m_PathDialogSub.m_pPathDialog= this;
  53. m_bParentDisabled = FALSE;
  54. // Get the true parent of the dialog
  55. m_pParentWnd = CWnd::GetSafeOwner(pParent);
  56. m_lpszCaption = lpszCaption;
  57. m_lpszInitialPath = lpszInitialPath;
  58. memset(&m_bi, 0, sizeof(BROWSEINFO) );
  59. m_bi.hwndOwner = (m_pParentWnd==NULL)?NULL:m_pParentWnd->GetSafeHwnd();
  60. m_bi.pszDisplayName = 0;
  61. m_bi.pidlRoot = 0;
  62. m_bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;
  63. m_bi.lpfn = BrowseCallbackProc;
  64. m_bi.lpszTitle = lpszTitle;
  65. }
  66. /////////////////////////////////////////////////////////////////////////////
  67. // CPathDialog message handlers
  68. CString CPathDialog::GetPathName()
  69. {
  70. return CString(m_szPathName);
  71. }
  72. int CALLBACK CPathDialog::BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam, LPARAM pData)
  73. {
  74. CPathDialog* pDlg = (CPathDialog*)pData;
  75. switch(uMsg)
  76. {
  77. case BFFM_INITIALIZED:
  78. {
  79. RECT rc;
  80. HWND hEdit;
  81. HFONT hFont;
  82. pDlg->m_hWnd = hwnd;
  83. if(pDlg->m_lpszCaption!=NULL)
  84. {
  85. ::SetWindowText(hwnd, pDlg->m_lpszCaption);
  86. }
  87. VERIFY(pDlg->m_PathDialogSub.SubclassWindow(hwnd));
  88. ::ShowWindow(::GetDlgItem(hwnd, IDC_STATUSTEXT), SW_HIDE);
  89. ::GetWindowRect(::GetDlgItem(hwnd, IDC_FOLDERTREE), &rc);
  90. rc.bottom = rc.top - 4;
  91. rc.top = rc.bottom - 23;
  92. ::ScreenToClient(hwnd, (LPPOINT)&rc);
  93. ::ScreenToClient(hwnd, ((LPPOINT)&rc)+1);
  94. hEdit = ::CreateWindowEx(WS_EX_CLIENTEDGE, _T("EDIT"), _T(""),
  95. WS_CHILD|WS_TABSTOP|WS_VISIBLE|ES_AUTOHSCROLL,
  96. rc.left, rc.top,
  97. rc.right-rc.left, rc.bottom-rc.top,
  98. hwnd, NULL, NULL, NULL);
  99. ::SetWindowLong(hEdit, GWL_ID, IDC_NEW_EDIT_PATH);
  100. ::ShowWindow(hEdit, SW_SHOW);
  101. hFont = (HFONT)::SendMessage(hwnd, WM_GETFONT, 0, 0);
  102. ::SendMessage(hEdit, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
  103. LPCTSTR lpszPath = pDlg->m_lpszInitialPath;
  104. TCHAR szTemp[MAX_PATH];
  105. if(lpszPath==NULL)
  106. {
  107. ::GetCurrentDirectory(MAX_PATH, szTemp );
  108. lpszPath = szTemp;
  109. }
  110. // WParam is TRUE since you are passing a path.
  111. // It would be FALSE if you were passing a pidl.
  112. ::SendMessage(hwnd,BFFM_SETSELECTION,TRUE,
  113. (LPARAM)lpszPath);
  114. break;
  115. }
  116. case BFFM_SELCHANGED:
  117. {
  118. char szSelection[MAX_PATH];
  119. if(!::SHGetPathFromIDList((LPITEMIDLIST)lParam, szSelection) ||
  120. (szSelection[1] !=':' && szSelection[1] != '\\'))
  121. {
  122. szSelection[0] = '\0';
  123. ::SendMessage(hwnd, BFFM_ENABLEOK, 0, FALSE);
  124. }
  125. else
  126. {
  127. ::SendMessage(hwnd, BFFM_ENABLEOK, 0, TRUE);
  128. }
  129. ::SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szSelection);
  130. ::SetWindowText(::GetDlgItem(hwnd, IDC_NEW_EDIT_PATH), szSelection);
  131. break;
  132. }
  133. default:
  134. break;
  135. }
  136. return 0;
  137. }
  138. int CPathDialog::DoModal()
  139. {
  140. /////////////////////////////////////////////////////////
  141. TCHAR szPathTemp[MAX_PATH];
  142. m_bi.lpfn = BrowseCallbackProc; // address of callback function
  143. m_bi.lParam = (LPARAM)this; // pass address of object to callback function
  144. m_bi.pszDisplayName = szPathTemp;
  145. LPITEMIDLIST pidl;
  146. LPMALLOC pMalloc;
  147. int iResult=-1;
  148. if(SUCCEEDED(SHGetMalloc(&pMalloc)))
  149. {
  150. m_bGetSuccess = FALSE;
  151. pidl = SHBrowseForFolder(&m_bi);
  152. if (pidl!=NULL)
  153. {
  154. #if defined(_WIN64) && defined(__INTEL_COMPILER)
  155. # pragma warning ( disable : 167)
  156. #endif
  157. // In C++:
  158. pMalloc->Free(pidl);
  159. //In C:
  160. //pMalloc->lpVtbl->Free(pMalloc,pidl);
  161. //pMalloc->lpVtbl->Release(pMalloc);
  162. }
  163. if(m_bGetSuccess)
  164. {
  165. iResult = IDOK;
  166. }
  167. pMalloc->Release();
  168. }
  169. if(m_bParentDisabled && (m_pParentWnd!=NULL))
  170. {
  171. m_pParentWnd->EnableWindow(TRUE);
  172. }
  173. m_bParentDisabled=FALSE;
  174. return iResult;
  175. }
  176. BOOL CPathDialog::IsFileNameValid(LPCTSTR lpFileName)
  177. {
  178. return TRUE;
  179. }
  180. const TCHAR c_FolderDoesNotExist[] = _T(
  181. "The folder:\n\n"
  182. "%s\n\n"
  183. "does not exist. Do you want the folder to be created?");
  184. const TCHAR c_szErrInvalidPath[] = _T(
  185. "The folder:"
  186. "\n\n"
  187. "%s\n\n"
  188. "is invalid. Please reenter.");
  189. const TCHAR c_szErrCreatePath[] = _T(
  190. "The folder:"
  191. "\n\n"
  192. "%s"
  193. "\n\ncan not be created. Please double check.");
  194. //return -1: user break;
  195. //return 0: no error
  196. //return 1: lpPath is invalid
  197. //return 2: can not create lpPath
  198. int CPathDialog::MakeSurePathExists(LPCTSTR lpPath)
  199. {
  200. CString strMsg;
  201. int iRet;
  202. try
  203. {
  204. //validate path
  205. iRet=Touch(lpPath, TRUE);
  206. if(iRet!=0)
  207. {
  208. throw iRet;
  209. }
  210. if(_taccess(lpPath, 0)==0)
  211. {
  212. return (int)0;
  213. }
  214. strMsg.Format(c_FolderDoesNotExist, lpPath);
  215. if(AfxMessageBox(strMsg, MB_YESNO|MB_ICONQUESTION) != IDYES)
  216. {
  217. return (int)-1;
  218. }
  219. //create path
  220. iRet=Touch(lpPath, FALSE);
  221. if(iRet!=0)
  222. {
  223. throw iRet;
  224. }
  225. return 0;
  226. }
  227. catch(int nErrCode)
  228. {
  229. switch(nErrCode)
  230. {
  231. case 1:
  232. strMsg.Format(c_szErrInvalidPath, lpPath);
  233. break;
  234. case 2:
  235. default:
  236. strMsg.Format(c_szErrCreatePath, lpPath);
  237. break;
  238. }
  239. AfxMessageBox(strMsg, MB_OK|MB_ICONEXCLAMATION);
  240. }
  241. return iRet;
  242. }
  243. //return 0: no error
  244. //return 1: lpPath is invalid
  245. //return 2: lpPath can not be created(bValidate==FALSE)
  246. int CPathDialog::Touch(LPCTSTR lpPath, BOOL bValidate)
  247. {
  248. if(lpPath==NULL)
  249. {
  250. return 1;
  251. }
  252. TCHAR szPath[MAX_PATH];
  253. _tcscpy(szPath, lpPath);
  254. size_t nLen = _tcslen(szPath);
  255. int i;
  256. if(nLen==3)
  257. {
  258. if(!bValidate)
  259. {
  260. if(_access(szPath, 0)!=0)
  261. {
  262. return 2;
  263. }
  264. }
  265. return 0;
  266. }
  267. i = 3;
  268. BOOL bLastOne=TRUE;
  269. LPTSTR lpCurrentName;
  270. while(szPath[i]!=0)
  271. {
  272. lpCurrentName = &szPath[i];
  273. while( (szPath[i]!=0) && (szPath[i]!=_T('\\')) )
  274. {
  275. i++;
  276. }
  277. bLastOne =(szPath[i]==0);
  278. szPath[i] = 0;
  279. if(!bValidate)
  280. {
  281. CreateDirectory(szPath, NULL);
  282. if(_taccess(szPath, 0)!=0)
  283. {
  284. return 2;
  285. }
  286. }
  287. if(bLastOne)
  288. {
  289. break; //it's done
  290. }
  291. else
  292. {
  293. szPath[i] = _T('\\');
  294. }
  295. i++;
  296. }
  297. return (bLastOne?0:1);
  298. }
  299. //return 0: ok
  300. //return 1: error
  301. int CPathDialog::ConcatPath(LPTSTR lpRoot, LPCTSTR lpMorePath)
  302. {
  303. if(lpRoot==NULL)
  304. {
  305. return 1;
  306. }
  307. size_t nLen = _tcslen(lpRoot);
  308. if(nLen<3)
  309. {
  310. return 1;
  311. }
  312. if(lpMorePath==NULL)
  313. {
  314. return 0;
  315. }
  316. if(nLen==3)
  317. {
  318. _tcscat(lpRoot, lpMorePath);
  319. return 0;
  320. }
  321. _tcscat(lpRoot, _T("\\"));
  322. _tcscat(lpRoot, lpMorePath);
  323. return 0;
  324. }