Source code of Windows XP (NT5)
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.

621 lines
17 KiB

  1. /*++
  2. Microsoft Windows
  3. Copyright (C) Microsoft Corporation, 1981 - 2000
  4. Module Name:
  5. pathslct.cxx
  6. Abstract:
  7. This module contains the methods and message handlers for the dialog
  8. that is used to select the redirection destination. This dialog is
  9. used as a child dialog by both the basic and the advanced settings.
  10. Author:
  11. Rahul Thombre (RahulTh) 3/1/2000
  12. Revision History:
  13. 3/1/2000 RahulTh Created this module.
  14. --*/
  15. #include "precomp.hxx"
  16. BEGIN_MESSAGE_MAP (CEditNoVars, CEdit)
  17. ON_WM_CHAR()
  18. END_MESSAGE_MAP()
  19. //+--------------------------------------------------------------------------
  20. //
  21. // Member: CEditNoVars::OnChar
  22. //
  23. // Synopsis: Customized edit control behavior. Prevents users from
  24. // entering variables.
  25. //
  26. // Arguments: see MFC documentation
  27. //
  28. // Returns: nothing
  29. //
  30. // History: 3/2/2000 RahulTh created
  31. //
  32. // Notes:
  33. //
  34. //---------------------------------------------------------------------------
  35. void CEditNoVars::OnChar (UINT nChar, UINT nRepCnt, UINT nFlags)
  36. {
  37. // Ignore the * symbol. Do not allow users to type it in.
  38. if ('*' != nChar)
  39. {
  40. CEdit::OnChar (nChar, nRepCnt, nFlags);
  41. }
  42. else
  43. {
  44. // Indicate to the user that % is not permitted in the path.
  45. ::MessageBeep (-1);
  46. }
  47. }
  48. // Mapping between control IDs and Help IDs for the path chooser
  49. const DWORD g_aHelpIDMap_IDD_PATHCHOOSER[] =
  50. {
  51. IDC_DESTTYPE, IDH_DESTTYPE,
  52. IDC_ROOT_DESC, IDH_DISABLEHELP,
  53. IDC_ROOT_PATH, IDH_ROOT_PATH,
  54. IDC_BROWSE, IDH_BROWSE,
  55. IDC_SAMPLE_PATH, IDH_DISABLEHELP,
  56. 0, 0
  57. };
  58. CPathChooser::CPathChooser(CWnd* pParent /*=NULL*/)
  59. : CDialog(CPathChooser::IDD, pParent), m_pParent (pParent)
  60. {
  61. //{{AFX_DATA_INIT(CPathChooser)
  62. // NOTE: the ClassWizard will add member initialization here
  63. //}}AFX_DATA_INIT
  64. m_iCurrType = 0;
  65. }
  66. void CPathChooser::GetRoot (CString & szRoot)
  67. {
  68. m_rootPath.GetWindowText (szRoot);
  69. szRoot.TrimLeft();
  70. szRoot.TrimRight();
  71. szRoot.TrimRight(L'\\');
  72. // When redirecting to the root of a drive, redirect to X:\ rather than X:
  73. if (2 == szRoot.GetLength() && L':' == ((LPCTSTR)szRoot)[1])
  74. szRoot += L'\\';
  75. }
  76. UINT CPathChooser::GetType (void)
  77. {
  78. return m_iCurrType + m_iTypeStart;
  79. }
  80. void
  81. CPathChooser::Instantiate (IN UINT cookie,
  82. IN CWnd * pParent,
  83. IN CWnd * pwndInsertAt,
  84. IN const CRedirPath * pRedirPath,
  85. IN UINT nFlags // = SWP_HIDEWINDOW
  86. )
  87. {
  88. RECT rc;
  89. RECT rc_ctrl;
  90. //
  91. // Now initialize the member variables.
  92. // Note: it is important to set the parent before the making the call to
  93. // Create so that CPathChooser's OnInitDialog is able to set the right
  94. // parent. Otherwise, the window positioning won't work as expected.
  95. //
  96. m_pParent = pParent;
  97. m_cookie = cookie;
  98. m_pRedirPath = pRedirPath;
  99. // First create the modeless window.
  100. this->Create (IDD, pParent);
  101. //
  102. // Set a limit on the number of characters that can be entered into
  103. // into the edit control
  104. //
  105. m_rootPath.SetLimitText (TARGETPATHLIMIT);
  106. // Now adjust the dimensions and place the window that the right location.
  107. pwndInsertAt->ShowWindow (SW_HIDE);
  108. pwndInsertAt->GetWindowRect (&rc);
  109. pParent->ScreenToClient (&rc);
  110. this->SetWindowPos (pwndInsertAt,
  111. rc.left,
  112. rc.top,
  113. rc.right - rc.left,
  114. rc.bottom - rc.top,
  115. nFlags
  116. );
  117. //
  118. // Now resize and move the controls within this dialog to fit the new size
  119. // Widen the dest. type combo box.
  120. //
  121. m_destType.GetClientRect (&rc_ctrl);
  122. m_destType.SetWindowPos (NULL,
  123. -1,
  124. -1,
  125. rc.right - rc.left,
  126. rc_ctrl.bottom,
  127. SWP_NOZORDER | SWP_NOMOVE
  128. );
  129. //
  130. // Widen the edit control -- set the height to be the same as the
  131. // combo box above
  132. //
  133. m_rootPath.SetWindowPos (NULL,
  134. -1,
  135. -1,
  136. rc.right - rc.left,
  137. rc_ctrl.bottom,
  138. SWP_NOZORDER | SWP_NOMOVE
  139. );
  140. //
  141. // Move the browse button so that it is aligned with the right
  142. // edge of the edit control
  143. //
  144. m_rootPath.GetWindowRect (&rc);
  145. this->ScreenToClient (&rc);
  146. m_browse.GetWindowRect (&rc_ctrl);
  147. this->ScreenToClient (&rc_ctrl);
  148. m_browse.SetWindowPos (NULL,
  149. rc_ctrl.left + rc.right - rc_ctrl.right,
  150. rc_ctrl.top,
  151. -1,
  152. -1,
  153. SWP_NOZORDER | SWP_NOSIZE
  154. );
  155. //
  156. // Change the height and width of the static control used to display
  157. // example per user paths so that it is as wide as the dialog and is
  158. // aligned with the bottom of the control
  159. //
  160. this->GetClientRect (&rc);
  161. m_peruserPathDesc.GetWindowRect (&rc_ctrl);
  162. this->ScreenToClient (&rc_ctrl);
  163. m_iPathDescWidth = rc.right;
  164. m_peruserPathDesc.SetWindowPos (NULL,
  165. -1,
  166. -1,
  167. m_iPathDescWidth,
  168. rc.bottom - rc_ctrl.top,
  169. SWP_NOZORDER | SWP_NOMOVE
  170. );
  171. // Load the values into the controls
  172. PopulateControls ();
  173. }
  174. // Populates the controls based on the values passed into the dialog
  175. void
  176. CPathChooser::PopulateControls (void)
  177. {
  178. AFX_MANAGE_STATE (AfxGetStaticModuleState());
  179. LONG i;
  180. CString szText;
  181. m_iCurrType = 0;
  182. switch (m_cookie)
  183. {
  184. case IDS_MYDOCS:
  185. m_iTypeStart = IDS_MYDOCS_DESTTYPE_START;
  186. break;
  187. case IDS_STARTMENU:
  188. m_iTypeStart = IDS_SMENU_DESTTYPE_START;
  189. break;
  190. default:
  191. m_iTypeStart = IDS_DESTTYPE_START;
  192. break;
  193. }
  194. // Now populate the destination type combo box based on the settings
  195. for (i = m_iTypeStart; i < IDS_DESTTYPE_END; i++)
  196. {
  197. szText.LoadString (i);
  198. m_destType.AddString ((LPCTSTR) szText);
  199. }
  200. // Put data in the controls.
  201. if (m_pRedirPath->IsPathValid())
  202. {
  203. m_iCurrType = m_pRedirPath->GetType() - m_iTypeStart;
  204. m_pRedirPath->GetPrefix (szText);
  205. m_rootPath.SetWindowText (szText);
  206. m_rootPath.SetModify (TRUE);
  207. }
  208. else
  209. {
  210. //
  211. // Use the first choice for all but the MyDocs folder.
  212. // because the first choice for MyDocs is the HOMEDIR option
  213. // and we want to encourage users to specify the path through
  214. // group policy rather than use the HOMEDIR path set on the user
  215. // object
  216. //
  217. if (IDS_MYDOCS == m_cookie)
  218. m_iCurrType = IDS_PERUSER_PATH - m_iTypeStart;
  219. else
  220. m_iCurrType = 0;
  221. m_rootPath.SetWindowText (L"");
  222. m_rootPath.SetModify (TRUE);
  223. }
  224. // Set the current type
  225. m_destType.SetCurSel (m_iCurrType);
  226. // Make sure that some of the controls are hidden if required
  227. ShowControls ();
  228. //
  229. // Notify the parent that the path has been tweaked so that it can
  230. // update any controls that on it that might depend on the contents of
  231. // this dialog
  232. //
  233. TweakPathNotify ();
  234. }
  235. void CPathChooser::DoDataExchange(CDataExchange* pDX)
  236. {
  237. CDialog::DoDataExchange(pDX);
  238. //{{AFX_DATA_MAP(CPathChooser)
  239. DDX_Control(pDX, IDC_DESTTYPE, m_destType);
  240. DDX_Control(pDX, IDC_ROOT_DESC, m_rootDesc);
  241. DDX_Control(pDX, IDC_ROOT_PATH, m_rootPath);
  242. DDX_Control(pDX, IDC_SAMPLE_PATH, m_peruserPathDesc);
  243. DDX_Control(pDX, IDC_BROWSE, m_browse);
  244. //}}AFX_DATA_MAP
  245. }
  246. BEGIN_MESSAGE_MAP(CPathChooser, CDialog)
  247. //{{AFX_MSG_MAP(CPathChooser)
  248. ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
  249. ON_CBN_SELCHANGE (IDC_DESTTYPE, OnDestTypeChange)
  250. ON_EN_CHANGE (IDC_ROOT_PATH, OnChangeRoot)
  251. ON_EN_KILLFOCUS (IDC_ROOT_PATH, OnRootKillFocus)
  252. ON_MESSAGE (WM_HELP, OnHelp)
  253. ON_MESSAGE (WM_CONTEXTMENU, OnContextMenu)
  254. //}}AFX_MSG_MAP
  255. END_MESSAGE_MAP()
  256. /////////////////////////////////////////////////////////////////////////////
  257. // CPathChooser message handlers
  258. BOOL CPathChooser::OnInitDialog()
  259. {
  260. CDialog::OnInitDialog();
  261. //
  262. // Always hide by default. Actual visible state will be determined
  263. // later in the instantiate method.
  264. //
  265. this->ShowWindow (SW_HIDE);
  266. this->SetParent (m_pParent);
  267. // Subclass the edit control to modify behavior
  268. m_rootPath.SubclassDlgItem (IDC_ROOT_PATH, this);
  269. return TRUE; // return TRUE unless you set the focus to a control
  270. // EXCEPTION: OCX Property Pages should return FALSE
  271. }
  272. void CPathChooser::OnCancel()
  273. {
  274. DestroyWindow ();
  275. }
  276. void CPathChooser::OnBrowse()
  277. {
  278. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  279. BROWSEINFO browseInfo;
  280. CString szInstructions;
  281. TCHAR pszSelectedFolder[MAX_PATH];
  282. LPITEMIDLIST lpItemIDList;
  283. LPMALLOC pMalloc;
  284. CError error(this);
  285. DWORD dwError;
  286. CString szSelectedPath;
  287. CString szUNC;
  288. szSelectedPath.Empty();
  289. szInstructions.LoadString (IDS_FOLDERBROWSE_DESC);
  290. browseInfo.hwndOwner = m_hWnd;
  291. browseInfo.pidlRoot = NULL;
  292. browseInfo.pszDisplayName = pszSelectedFolder;
  293. browseInfo.lpszTitle = (LPCTSTR)szInstructions;
  294. browseInfo.ulFlags = BIF_RETURNONLYFSDIRS;
  295. browseInfo.lpfn = BrowseCallbackProc;
  296. browseInfo.lParam = (LPARAM) (&szSelectedPath);
  297. if (NULL != (lpItemIDList = SHBrowseForFolder (&browseInfo)))
  298. {
  299. //try to get the path from the item id list
  300. dwError = GetUNCPath (szSelectedPath, szUNC);
  301. if (NO_ERROR != dwError) //then do the best you can
  302. szUNC = szSelectedPath;
  303. if (TARGETPATHLIMIT < szUNC.GetLength())
  304. error.ShowMessage (IDS_PATHTOOLONG_ERROR, TARGETPATHLIMIT);
  305. else
  306. {
  307. m_rootPath.SetWindowText (szUNC);
  308. m_rootPath.SetModify(TRUE);
  309. // Notify the parent that the path has been modified
  310. TweakPathNotify();
  311. }
  312. SHGetMalloc(&pMalloc);
  313. pMalloc->Free (lpItemIDList);
  314. pMalloc->Release();
  315. }
  316. }
  317. void CPathChooser::OnDestTypeChange (void)
  318. {
  319. int Sel;
  320. Sel = m_destType.GetCurSel();
  321. if (Sel == m_iCurrType)
  322. return; // The choice has not changed
  323. // Update the current choice.
  324. m_iCurrType = Sel;
  325. ShowControls();
  326. // Notify the parent of the change
  327. TweakPathNotify ();
  328. }
  329. void CPathChooser::ShowControls (void)
  330. {
  331. int nCmdShow;
  332. switch (m_iCurrType + m_iTypeStart)
  333. {
  334. case IDS_SPECIFIC_PATH:
  335. case IDS_PERUSER_PATH:
  336. nCmdShow = SW_SHOW;
  337. break;
  338. case IDS_USERPROFILE_PATH:
  339. case IDS_HOMEDIR_PATH:
  340. nCmdShow = SW_HIDE;
  341. break;
  342. }
  343. m_browse.ShowWindow (nCmdShow);
  344. m_rootPath.ShowWindow (nCmdShow);
  345. m_rootDesc.ShowWindow (nCmdShow);
  346. }
  347. void CPathChooser::OnChangeRoot()
  348. {
  349. // Notify the parent that the path has changed.
  350. TweakPathNotify ();
  351. }
  352. void CPathChooser::OnRootKillFocus()
  353. {
  354. CString szUNC;
  355. CString szCurr;
  356. m_rootPath.GetWindowText (szCurr);
  357. szCurr.TrimLeft();
  358. szCurr.TrimRight();
  359. szCurr.TrimRight(L'\\');
  360. if (szCurr.IsEmpty() || PathIsUNC ((LPCTSTR)szCurr))
  361. {
  362. return;
  363. }
  364. if (NO_ERROR == GetUNCPath (szCurr, szUNC))
  365. {
  366. if (TARGETPATHLIMIT < szUNC.GetLength())
  367. return;
  368. }
  369. else
  370. {
  371. szUNC = szCurr;
  372. }
  373. //
  374. // if the path is of the form X: change it to X:\ (so that
  375. // the redirection at the client does not run into problems
  376. //
  377. if (2 == szUNC.GetLength() && L':' == ((LPCTSTR)szUNC)[1])
  378. szUNC += L'\\';
  379. m_rootPath.SetWindowText (szUNC);
  380. }
  381. LONG CPathChooser::OnHelp (WPARAM wParam, LPARAM lParam)
  382. {
  383. LONG lResult = 0;
  384. CString szHelpFile;
  385. szHelpFile.LoadString(IDS_HELP_FILE);
  386. ::WinHelp((HWND)(((LPHELPINFO)lParam)->hItemHandle),
  387. (LPCTSTR) szHelpFile,
  388. HELP_WM_HELP,
  389. (ULONG_PTR)(LPTSTR)g_aHelpIDMap_IDD_PATHCHOOSER);
  390. return lResult;
  391. }
  392. LONG CPathChooser::OnContextMenu (WPARAM wParam, LPARAM lParam)
  393. {
  394. AFX_MANAGE_STATE (AfxGetStaticModuleState());
  395. LONG lResult = 0;
  396. CString szHelpFile;
  397. szHelpFile.LoadString(IDS_HELP_FILE);
  398. ::WinHelp((HWND)wParam,
  399. (LPCTSTR)szHelpFile,
  400. HELP_CONTEXTMENU,
  401. (ULONG_PTR)(LPVOID)g_aHelpIDMap_IDD_PATHCHOOSER);
  402. return lResult;
  403. }
  404. //+--------------------------------------------------------------------------
  405. //
  406. // Member: CPathChooser::TweakPathNotify
  407. //
  408. // Synopsis: Notifies the parent that the path has been tweaked.
  409. //
  410. // Arguments:
  411. //
  412. // Returns:
  413. //
  414. // History: 3/3/2000 RahulTh created
  415. //
  416. // Notes:
  417. //
  418. //---------------------------------------------------------------------------
  419. void
  420. CPathChooser::TweakPathNotify (void)
  421. {
  422. LPARAM lParam;
  423. WPARAM wParam;
  424. CString szRootPath;
  425. WCHAR szCompactPath[MAX_PATH];
  426. static CString szUser = TEXT("");
  427. static CString szPathDesc = TEXT("");
  428. lParam = (LPARAM) (m_iCurrType + m_iTypeStart);
  429. if (-1 == m_iCurrType)
  430. {
  431. wParam = (WPARAM) FALSE;
  432. }
  433. else
  434. {
  435. switch (m_iCurrType + m_iTypeStart)
  436. {
  437. case IDS_PERUSER_PATH:
  438. if (IDS_STARTMENU == m_cookie)
  439. {
  440. wParam = (WPARAM) FALSE;
  441. }
  442. else
  443. {
  444. m_rootPath.GetWindowText (szRootPath);
  445. szRootPath.TrimLeft();
  446. szRootPath.TrimRight();
  447. szRootPath.TrimRight (L'\\');
  448. if (szRootPath.IsEmpty() ||
  449. ! IsValidPrefix (IDS_PERUSER_PATH, (LPCTSTR) szRootPath))
  450. {
  451. wParam = (WPARAM) FALSE;
  452. m_peruserPathDesc.ShowWindow (SW_HIDE);
  453. }
  454. else
  455. {
  456. wParam = (WPARAM) TRUE;
  457. if (szUser.IsEmpty())
  458. szUser.LoadString (IDS_SAMPLE_USER);
  459. if (szPathDesc.IsEmpty())
  460. szPathDesc.LoadString (IDS_SAMPLE_PATHDESC);
  461. CString szTmp;
  462. CString szPath;
  463. BOOL bShowPath;
  464. // Check if the path has changed
  465. if (m_pRedirPath->IsPathDifferent (IDS_PERUSER_PATH, szRootPath))
  466. {
  467. CRedirPath displayPath (m_cookie);
  468. displayPath.GenerateSuffix (szTmp, m_cookie, IDS_PERUSER_PATH);
  469. bShowPath = displayPath.Load (IDS_PERUSER_PATH, szRootPath, szTmp);
  470. if (bShowPath)
  471. {
  472. bShowPath = displayPath.GeneratePath (szPath, szUser);
  473. }
  474. }
  475. else
  476. {
  477. bShowPath = m_pRedirPath->GeneratePath (szPath, szUser);
  478. }
  479. if (bShowPath)
  480. bShowPath = (MAX_PATH > szPath.GetLength());
  481. if (bShowPath)
  482. {
  483. lstrcpy (szCompactPath, (LPCTSTR) szPath);
  484. bShowPath = PathCompactPath (NULL, szCompactPath, m_iPathDescWidth);
  485. if (bShowPath)
  486. szTmp.Format (szPathDesc, szUser, szCompactPath);
  487. }
  488. if (bShowPath)
  489. {
  490. m_peruserPathDesc.SetWindowText (szTmp);
  491. m_peruserPathDesc.ShowWindow (SW_SHOW);
  492. }
  493. else
  494. {
  495. m_peruserPathDesc.ShowWindow (SW_HIDE);
  496. }
  497. }
  498. }
  499. break;
  500. case IDS_SPECIFIC_PATH:
  501. m_peruserPathDesc.ShowWindow (SW_HIDE);
  502. m_rootPath.GetWindowText(szRootPath);
  503. szRootPath.TrimLeft();
  504. szRootPath.TrimRight();
  505. szRootPath.TrimRight ('\\');
  506. if (! IsValidPrefix (IDS_SPECIFIC_PATH, (LPCTSTR) szRootPath))
  507. wParam = (WPARAM) FALSE;
  508. else
  509. wParam = (WPARAM) TRUE;
  510. break;
  511. case IDS_HOMEDIR_PATH:
  512. {
  513. CString szTmp;
  514. szTmp.LoadString (IDS_HOMEDIR_WARNING);
  515. m_peruserPathDesc.SetWindowText (szTmp);
  516. m_peruserPathDesc.ShowWindow (SW_SHOW);
  517. wParam = (WPARAM) (m_cookie == IDS_MYDOCS ? TRUE : FALSE);
  518. break;
  519. }
  520. case IDS_USERPROFILE_PATH:
  521. m_peruserPathDesc.ShowWindow (SW_HIDE);
  522. wParam = (WPARAM) TRUE;
  523. break;
  524. default:
  525. m_peruserPathDesc.ShowWindow (SW_HIDE);
  526. wParam = (WPARAM) FALSE;
  527. break;
  528. }
  529. }
  530. m_pParent->SendMessage (WM_PATH_TWEAKED, wParam, lParam);
  531. }