Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

769 lines
18 KiB

  1. //
  2. // FileChooser.cpp
  3. //
  4. #include "stdafx.h"
  5. #include "common.h"
  6. #include "FileChooser.h"
  7. #include <Shlwapi.h>
  8. #include <shellapi.h>
  9. #include <ShlObj.h>
  10. #include <CommDlg.h>
  11. #ifdef _DEBUG
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15. const TCHAR QuotMark = _T('\"');
  16. const TCHAR AllExt[] = _T(".*");
  17. //---------------------
  18. BOOL
  19. CFileChooser::Init(CWindow * pParent, DWORD dwStyle, UINT idEdit, UINT idButton)
  20. {
  21. ASSERT(NULL != pParent);
  22. ASSERT(NULL != pParent->GetDlgItem(idEdit));
  23. ASSERT(NULL != pParent->GetDlgItem(idButton));
  24. m_pParent = pParent;
  25. SetStyle(dwStyle);
  26. VERIFY(m_edit.SubclassWindow(pParent->GetDlgItem(idEdit)));
  27. if (StyleBitSet(FC_AUTOCOMPLETION))
  28. {
  29. SHAutoComplete(pParent->GetDlgItem(idEdit), SHACF_FILESYSTEM);
  30. }
  31. VERIFY(m_button.SubclassWindow(pParent->GetDlgItem(idButton)));
  32. return FALSE;
  33. }
  34. // External SetPath
  35. void
  36. CFileChooser::SetPath(const CString& path)
  37. {
  38. m_strPath = path;
  39. if (OpenForRead() && StyleBitSet(FC_PREPARE_DEFAULT))
  40. CreateDefaultPathForRead();
  41. SetPathToEdit(m_strPath);
  42. m_bEditDirty = FALSE;
  43. }
  44. BOOL
  45. CFileChooser::HasEditFocus()
  46. {
  47. return GetFocus() == m_edit.m_hWnd;
  48. }
  49. void
  50. CFileChooser::SetPathToEdit(LPCTSTR path)
  51. {
  52. if (HasEditFocus())
  53. {
  54. m_edit.SetWindowText(path);
  55. }
  56. else
  57. {
  58. SetCompactedPath(path);
  59. }
  60. }
  61. void
  62. CFileChooser::CreateDefaultPathForRead()
  63. {
  64. if (!PathFileExists(m_strPath))
  65. {
  66. // try to find first file with the first extension
  67. // from the extensions list
  68. BOOL bDefaultSet = FALSE;
  69. BOOL bPathEmpty = m_strPath.IsEmpty();
  70. TCHAR find_str[MAX_PATH];
  71. WIN32_FIND_DATA find_data;
  72. if (bPathEmpty)
  73. {
  74. GetCurrentDirectory(MAX_PATH, find_str);
  75. m_strPath = find_str;
  76. }
  77. else
  78. {
  79. StrCpy(find_str, m_strPath);
  80. if (!PathIsDirectory(find_str))
  81. {
  82. PathRemoveFileSpec(find_str);
  83. }
  84. }
  85. PathAppend(find_str, _T("*"));
  86. std::list<CFilterEntry>::iterator it;
  87. for (it = m_ext.begin(); it != m_ext.end(); it++)
  88. {
  89. CString ext = (*it).m_ext;
  90. PathAddExtension(find_str, ext);
  91. HANDLE hFind = FindFirstFile(find_str, &find_data);
  92. if ( hFind != INVALID_HANDLE_VALUE
  93. && (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0
  94. )
  95. {
  96. if (!bPathEmpty)
  97. {
  98. TCHAR buf[MAX_PATH];
  99. StrCpy(buf, m_strPath);
  100. PathRemoveFileSpec(buf);
  101. m_strPath = buf;
  102. }
  103. m_strPath += find_data.cFileName;
  104. FindClose(hFind);
  105. bDefaultSet = TRUE;
  106. break;
  107. }
  108. }
  109. if (!bDefaultSet && StyleBitSet(FC_WILDCARD_DEFAULT))
  110. {
  111. // if nothing found, just attach *.ext to the path
  112. // find_str was prepared before as xxx\*.
  113. m_strPath = find_str;
  114. if (!m_ext.empty())
  115. {
  116. m_strPath += m_ext.front().m_ext;
  117. }
  118. else
  119. {
  120. m_strPath += _T("*");
  121. }
  122. }
  123. }
  124. }
  125. BOOL
  126. CFileChooser::IsValidChar(UINT nChar, BOOL bExcludeWildcards)
  127. {
  128. switch (PathGetCharType((TCHAR)nChar))
  129. {
  130. case GCT_INVALID:
  131. return FALSE;
  132. case GCT_WILD:
  133. return !bExcludeWildcards;
  134. case GCT_LFNCHAR:
  135. case GCT_SEPARATOR:
  136. case GCT_SHORTCHAR:
  137. break;
  138. }
  139. return TRUE;
  140. }
  141. BOOL
  142. CFileChooser::IsValidPath(LPCTSTR path)
  143. {
  144. UINT len = lstrlen(path);
  145. BOOL bRes = TRUE;
  146. for (UINT i = 0; i < len; i++)
  147. {
  148. TCHAR c = path[i];
  149. if (!IsValidChar(c))
  150. {
  151. bRes = FALSE;
  152. break;
  153. }
  154. }
  155. return bRes;
  156. }
  157. // Character filtering routine for the edit control.
  158. // Returns TRUE if character should be passed to the CEdit
  159. //
  160. LRESULT
  161. CFileChooser::OnEditChar(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  162. {
  163. UINT nChar = wParam;
  164. UINT nRepCount = (UINT)lParam & 0xFFFF;
  165. UINT nFlags = (UINT)((lParam & 0xFFFF0000) >> 16);
  166. bHandled = TRUE;
  167. if (IsValidChar(nChar))
  168. {
  169. bHandled = FALSE;
  170. }
  171. else
  172. {
  173. switch (nChar)
  174. {
  175. case VK_DELETE:
  176. case VK_BACK:
  177. case _T('/'):
  178. bHandled = FALSE;
  179. break;
  180. case _T('"'):
  181. bHandled = !StyleBitSet(FC_COMMANDLINE);
  182. break;
  183. }
  184. }
  185. m_bEditDirty = !bHandled;
  186. return 0;
  187. }
  188. // Text was pasted to edit control
  189. void
  190. CFileChooser::OnPaste()
  191. {
  192. TCHAR buf[MAX_PATH];
  193. int len = m_edit.GetWindowText(buf, MAX_PATH);
  194. for (int i = 0; i < len || IsValidChar(buf[i]); i++)
  195. ;
  196. if (i < len)
  197. {
  198. m_edit.SendMessage(EM_SETSEL, i, len - 1);
  199. m_bTextValid = FALSE;
  200. m_bEditDirty = FALSE;
  201. }
  202. else
  203. {
  204. m_strPath = buf;
  205. SetPathToEdit(buf);
  206. m_bEditDirty = TRUE;
  207. }
  208. }
  209. void
  210. CFileChooser::OnEditChange()
  211. {
  212. if (!m_bInternalChange)
  213. {
  214. m_bEditDirty = TRUE;
  215. }
  216. }
  217. LRESULT
  218. CFileChooser::OnEditSetFocus(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  219. {
  220. m_bInternalChange = TRUE;
  221. m_edit.SetWindowText(m_strPath);
  222. m_bInternalChange = FALSE;
  223. bHandled = FALSE;
  224. return 0;
  225. }
  226. LRESULT
  227. CFileChooser::OnEditKillFocus(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  228. {
  229. // update internal string buffer with path
  230. TCHAR buf[MAX_PATH];
  231. ZeroMemory(buf, MAX_PATH);
  232. if (m_bEditDirty)
  233. {
  234. m_edit.GetWindowText(buf, MAX_PATH);
  235. m_strPath = buf;
  236. }
  237. m_bInternalChange = TRUE;
  238. SetCompactedPath(m_strPath);
  239. m_bInternalChange = FALSE;
  240. m_bEditDirty = FALSE;
  241. bHandled = FALSE;
  242. return 0;
  243. }
  244. LRESULT
  245. CFileChooser::OnSetBrowseState(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  246. {
  247. // We are producing dialog on the way back
  248. if (!wParam)
  249. {
  250. OnBrowseBtn();
  251. }
  252. bHandled = FALSE;
  253. return 0;
  254. }
  255. void
  256. CFileChooser::SetCompactedPath(LPCTSTR path)
  257. {
  258. // compact path before writing to edit
  259. CRect rc;
  260. m_edit.GetClientRect(&rc);
  261. HDC dc = m_edit.GetDC();
  262. TCHAR buf[MAX_PATH] = {0};
  263. StrCpy(buf, path);
  264. PathMakePretty(buf);
  265. PathCompactPath(dc, buf, rc.Width());
  266. m_edit.ReleaseDC(dc);
  267. m_edit.SetWindowText(buf);
  268. }
  269. DWORD
  270. CFileChooser::GetFileName(CString& strFile)
  271. {
  272. DWORD dwRes = FC_SUCCESS;
  273. TCHAR str[MAX_PATH];
  274. BOOL expanded = FALSE;
  275. if ( !m_bTextValid
  276. || FC_SUCCESS != ExtractPath(str)
  277. || !IsValidPath(str)
  278. )
  279. return FC_TEXT_IS_INVALID;
  280. if (StyleBitSet(FC_PATH_CHECK))
  281. {
  282. if (OpenForRead())
  283. {
  284. TCHAR str_exp[MAX_PATH];
  285. lstrcpy(str_exp, str);
  286. DoEnvironmentSubst(str_exp, MAX_PATH);
  287. expanded = lstrcmpi(str, str_exp) != 0;
  288. if (!PathFileExists(str_exp) && !PathIsDirectory(str_exp))
  289. {
  290. BOOL bFound = FALSE;
  291. if (StyleBitSet(FC_CHECK_FILENAME_ONLY))
  292. {
  293. // try with default extension(s) if it is just filename
  294. // without any extensions
  295. LPTSTR p = PathFindExtension(str_exp);
  296. if (p != NULL && *p == 0)
  297. {
  298. CString strExt, strTest = str_exp;
  299. std::list<CFilterEntry>::iterator it;
  300. for (it = m_ext.begin(); it != m_ext.end(); it++)
  301. {
  302. strExt = (*it).m_ext;
  303. if (PathFileExists(strTest + strExt))
  304. {
  305. StrCat(str, strExt);
  306. bFound = TRUE;
  307. break;
  308. }
  309. }
  310. }
  311. }
  312. if (!bFound)
  313. dwRes = FC_FILE_DOES_NOT_EXIST;
  314. }
  315. else if (PathIsDirectory(str_exp))
  316. {
  317. if (!StyleBitSet(FC_DIRECTORY_ONLY))
  318. {
  319. PathAddBackslash(str);
  320. dwRes = FC_FILENAME_IS_DIRECTORY;
  321. }
  322. }
  323. else if (StyleBitSet(FC_DIRECTORY_ONLY))
  324. {
  325. if (PathFileExists(str_exp))
  326. dwRes = FC_FILENAME_IS_FILE;
  327. }
  328. }
  329. else if (StyleBitSet(FC_FORWRITE))
  330. {
  331. // TODO: make sure we have write access to this path
  332. }
  333. }
  334. if (dwRes == FC_SUCCESS)
  335. {
  336. if (StyleBitSet(FC_COMMANDLINE) || expanded)
  337. {
  338. // We are returning whole command line, get it again
  339. GetText(str);
  340. }
  341. strFile = str;
  342. }
  343. return dwRes;
  344. }
  345. BOOL
  346. CFileChooser::BrowseForFile(CString& strPath, CString& strFile)
  347. {
  348. BOOL bRes = FALSE;
  349. OPENFILENAME ofn;
  350. TCHAR buf[MAX_PATH];
  351. ZeroMemory(&ofn, sizeof(OPENFILENAME));
  352. StrCpy(buf, strFile);
  353. ofn.lStructSize = sizeof(OPENFILENAME);
  354. // We are not using template
  355. ofn.hInstance = NULL;
  356. ofn.Flags |= m_ofn_Flags;
  357. ofn.Flags |= OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
  358. if (OpenForRead())
  359. ofn.Flags |= OFN_FILEMUSTEXIST;
  360. else
  361. ofn.Flags |= (OFN_NOREADONLYRETURN | OFN_NOTESTFILECREATE | OFN_HIDEREADONLY);
  362. #if (_WIN32_WINNT >= 0x0500)
  363. ofn.FlagsEx &= ~(OFN_EX_NOPLACESBAR);
  364. #endif
  365. // Create filter using our extensions list
  366. CString strFilter, strDefExt;
  367. CreateFilter(strFilter, strDefExt);
  368. ofn.lpstrDefExt = strDefExt;
  369. ofn.lpstrFile = buf;
  370. ofn.nMaxFile = MAX_PATH;
  371. ofn.lpstrInitialDir = strPath.IsEmpty() ? NULL : (LPCTSTR)strPath;
  372. ofn.lpstrFilter = strFilter;
  373. ofn.nFilterIndex = GetFilterIndex(strFile);
  374. // We better set the owner, or this dialog will be visible on task bar
  375. ofn.hwndOwner = m_pParent->m_hWnd;
  376. ofn.lpstrTitle = m_strTitle;
  377. if (StyleBitSet(FC_HIDEREADONLY))
  378. ofn.Flags |= OFN_HIDEREADONLY;
  379. if (!StyleBitSet(FC_FORWRITE))
  380. bRes = GetOpenFileName(&ofn);
  381. else
  382. bRes = GetSaveFileName(&ofn);
  383. if (bRes)
  384. {
  385. m_bDoReplaceFile = TRUE;
  386. }
  387. else
  388. {
  389. #ifdef _DEBUG
  390. DWORD dwError;
  391. ASSERT(0 == (dwError = CommDlgExtendedError()));
  392. #endif
  393. }
  394. strFile = buf;
  395. return bRes;
  396. }
  397. static int CALLBACK
  398. FileChooserCallback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
  399. {
  400. CFileChooser * pThis = (CFileChooser *)lpData;
  401. ASSERT(pThis != NULL);
  402. return pThis->BrowseForFolderCallback(hwnd, uMsg, lParam);
  403. }
  404. int CFileChooser::BrowseForFolderCallback(HWND hwnd, UINT uMsg, LPARAM lParam)
  405. {
  406. switch (uMsg)
  407. {
  408. case BFFM_INITIALIZED:
  409. ASSERT(m_pPathTemp != NULL);
  410. if (::PathIsNetworkPath(m_pPathTemp))
  411. return 0;
  412. while (!::PathIsDirectory(m_pPathTemp))
  413. {
  414. if (0 == ::PathRemoveFileSpec(m_pPathTemp) && !::PathIsRoot(m_pPathTemp))
  415. {
  416. return 0;
  417. }
  418. DWORD attr = GetFileAttributes(m_pPathTemp);
  419. if (StyleBitSet(FC_FORWRITE) && (attr & FILE_ATTRIBUTE_READONLY) == 0)
  420. break;
  421. }
  422. ::SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)m_pPathTemp);
  423. break;
  424. case BFFM_SELCHANGED:
  425. {
  426. LPITEMIDLIST pidl = (LPITEMIDLIST)lParam;
  427. TCHAR path[MAX_PATH];
  428. if (SHGetPathFromIDList(pidl, path))
  429. {
  430. ::SendMessage(hwnd, BFFM_ENABLEOK, 0, !PathIsNetworkPath(path));
  431. }
  432. }
  433. break;
  434. case BFFM_VALIDATEFAILED:
  435. break;
  436. }
  437. return 0;
  438. }
  439. BOOL
  440. CFileChooser::BrowseForFolder(CString& strPath)
  441. {
  442. LPITEMIDLIST pidl = NULL;
  443. HRESULT hr;
  444. BOOL bRes = FALSE;
  445. if (SUCCEEDED(hr = CoInitialize(NULL)))
  446. {
  447. if (SUCCEEDED(SHGetFolderLocation(NULL, CSIDL_DRIVES, NULL, 0, &pidl)))
  448. {
  449. LPITEMIDLIST pidList = NULL;
  450. BROWSEINFO bi;
  451. TCHAR buf[MAX_PATH];
  452. ZeroMemory(&bi, sizeof(bi));
  453. int drive = PathGetDriveNumber(strPath);
  454. if (GetDriveType(PathBuildRoot(buf, drive)) == DRIVE_FIXED)
  455. {
  456. StrCpy(buf, strPath);
  457. }
  458. else
  459. {
  460. buf[0] = 0;
  461. }
  462. bi.hwndOwner = m_pParent->m_hWnd;
  463. bi.pidlRoot = pidl;
  464. bi.pszDisplayName = m_pPathTemp = buf;
  465. bi.lpszTitle = m_strTitle;
  466. bi.ulFlags |= BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS/* | BIF_EDITBOX*/;
  467. bi.lpfn = FileChooserCallback;
  468. bi.lParam = (LPARAM)this;
  469. pidList = SHBrowseForFolder(&bi);
  470. if ( pidList != NULL
  471. && SHGetPathFromIDList(pidList, buf)
  472. )
  473. {
  474. strPath = buf;
  475. bRes = TRUE;
  476. }
  477. IMalloc * pMalloc;
  478. VERIFY(SUCCEEDED(SHGetMalloc(&pMalloc)));
  479. if (pidl != NULL)
  480. pMalloc->Free(pidl);
  481. pMalloc->Release();
  482. }
  483. CoUninitialize();
  484. }
  485. return bRes;
  486. }
  487. void
  488. CFileChooser::AddExtension(HINSTANCE hInst, UINT idText, UINT idExt)
  489. {
  490. CString text, ext;
  491. if (text.LoadString(hInst, idText) && ext.LoadString(hInst, idExt))
  492. {
  493. AddExtension(text, ext);
  494. }
  495. }
  496. void
  497. CFileChooser::AddExtension(LPCTSTR text, LPCTSTR ext)
  498. {
  499. ASSERT(ext != NULL && *ext == _T('.'));
  500. CFilterEntry entry(text, ext);
  501. m_ext.push_back(entry);
  502. }
  503. const TCHAR cDelimiter = _T('\n');
  504. void
  505. CFileChooser::CreateFilter(CString& strFilter, CString& strDefExt)
  506. {
  507. strFilter.Empty();
  508. strDefExt.Empty();
  509. BOOL bExtDone = FALSE;
  510. std::list<CFilterEntry>::iterator it;
  511. for (it = m_ext.begin(); it != m_ext.end(); it++)
  512. {
  513. CFilterEntry entry = (*it);
  514. strFilter += entry.m_text;
  515. if (m_dwStyle & FC_WILDCARD_DESC)
  516. {
  517. strFilter += _T(" (*");
  518. strFilter += entry.m_ext;
  519. strFilter += _T(")");
  520. }
  521. strFilter += cDelimiter;
  522. strFilter += _T('*');
  523. strFilter += entry.m_ext;
  524. strFilter += cDelimiter;
  525. if (!bExtDone)
  526. {
  527. LPCTSTR pExt = entry.m_ext;
  528. strDefExt =
  529. *pExt == _T('.') ? pExt + 1 : pExt;
  530. bExtDone = TRUE;
  531. }
  532. }
  533. if (!strFilter.IsEmpty())
  534. {
  535. strFilter += cDelimiter;
  536. for (int i = 0; i < strFilter.GetLength(); i++)
  537. {
  538. if (strFilter[i] == cDelimiter)
  539. strFilter.SetAt(i, 0);
  540. }
  541. }
  542. }
  543. int
  544. CFileChooser::GetFilterIndex(const CString& fileName)
  545. {
  546. LPTSTR p = PathFindExtension(fileName);
  547. if (p == NULL)
  548. p = (LPTSTR)AllExt;
  549. std::list<CFilterEntry>::iterator it;
  550. int idx = 1;
  551. for (it = m_ext.begin(); it != m_ext.end(); it++, idx++)
  552. {
  553. if (StrCmpI((*it).m_ext, p) == 0)
  554. return idx;
  555. }
  556. return 0;
  557. }
  558. void
  559. CFileChooser::GetText(LPTSTR buf)
  560. {
  561. ASSERT(buf != NULL);
  562. if (m_bEditDirty)
  563. {
  564. m_edit.GetWindowText(buf, MAX_PATH);
  565. }
  566. else
  567. {
  568. StrCpy(buf, m_strPath);
  569. }
  570. }
  571. int
  572. CFileChooser::ExtractPath(LPTSTR path)
  573. {
  574. ASSERT(path != NULL);
  575. int rc = FC_SUCCESS;
  576. TCHAR buf[MAX_PATH] = {0};
  577. LPTSTR start = buf;
  578. GetText(buf);
  579. if (StyleBitSet(FC_COMMANDLINE))
  580. {
  581. if (*buf == QuotMark)
  582. {
  583. LPTSTR end = StrChr(++start, QuotMark);
  584. if (end == NULL)
  585. {
  586. // Wrong format, closing quotation mark is not set
  587. rc = FC_NO_CLOSING_QUOTE;
  588. // Return part of the path up to first space
  589. PathRemoveArgs(buf);
  590. }
  591. else
  592. {
  593. ++end;
  594. *end = 0;
  595. PathUnquoteSpaces(buf);
  596. start = buf;
  597. }
  598. }
  599. else
  600. {
  601. PathRemoveArgs(buf);
  602. }
  603. }
  604. StrCpy(path, start);
  605. return rc;
  606. }
  607. int
  608. CFileChooser::ExtractArgs(LPTSTR buf)
  609. {
  610. ASSERT(buf != NULL);
  611. int rc = FC_SUCCESS;
  612. GetText(buf);
  613. LPTSTR p = PathGetArgs(buf);
  614. if (p != NULL)
  615. {
  616. StrCpy(buf, p);
  617. }
  618. else
  619. {
  620. *buf = 0;
  621. }
  622. return rc;
  623. }
  624. void
  625. CFileChooser::OnBrowseBtn()
  626. {
  627. BOOL bRes = FALSE;
  628. if (m_bDialogActive)
  629. return;
  630. m_bDialogActive = TRUE;
  631. TCHAR path[MAX_PATH] = {0};
  632. TCHAR args[MAX_PATH] = {0};
  633. int rc = ExtractPath(path);
  634. if (StyleBitSet(FC_COMMANDLINE))
  635. {
  636. ExtractArgs(args);
  637. }
  638. CString strFile, strBuffer;
  639. // m_strPath = path;
  640. strBuffer = path;
  641. if (StyleBitSet(FC_FORWRITE))
  642. {
  643. if (!PathIsDirectory(path))
  644. {
  645. if (PathRemoveFileSpec(path))
  646. {
  647. // check if path part of filename exists
  648. if (PathIsDirectory(path))
  649. {
  650. // we will use non-path part of spec as a filename
  651. strFile = PathFindFileName(strBuffer);
  652. }
  653. else
  654. {
  655. // it is wrong path, use default one
  656. // TODO: actually I need to take from filespec all existent
  657. // chunks of path and filename, for example c:\aa\bb\cc\dd.txt,
  658. // if c:\aa\bb exists, then strPath should be set to c:\aa\bb,
  659. // and strFile to dd.txt
  660. path[0] = 0;
  661. }
  662. }
  663. else
  664. {
  665. // it is filename only
  666. strFile = strBuffer;
  667. path[0] = 0;
  668. }
  669. }
  670. }
  671. else
  672. {
  673. if (!PathIsDirectory(path))
  674. {
  675. strFile = PathFindFileName(path);
  676. PathRemoveFileSpec(path);
  677. }
  678. }
  679. CString strPath(path);
  680. if (StyleBitSet(FC_DIRECTORY_ONLY))
  681. {
  682. bRes = BrowseForFolder(strPath);
  683. if (bRes)
  684. {
  685. StrCpy(path, strPath);
  686. }
  687. }
  688. else
  689. {
  690. bRes = BrowseForFile(strPath, strFile);
  691. if (bRes)
  692. {
  693. StrCpy(path, strFile);
  694. }
  695. }
  696. if (bRes)
  697. {
  698. if (StyleBitSet(FC_COMMANDLINE))
  699. {
  700. PathQuoteSpaces(path);
  701. m_strPath = path;
  702. if (*args != 0)
  703. {
  704. m_strPath += _T(' ');
  705. m_strPath += args;
  706. }
  707. }
  708. else
  709. m_strPath = path;
  710. SetPathToEdit(m_strPath);
  711. m_bEditDirty = FALSE;
  712. ::SendMessage(GetParent(), WM_COMMAND, (WPARAM)EN_CHANGE, (LPARAM)m_edit.m_hWnd);
  713. }
  714. m_bDialogActive = FALSE;
  715. }