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.

465 lines
13 KiB

  1. /*
  2. * comdlg32 - Common Dialog settings
  3. *
  4. * NOTE! That it is safe to use Shlwapi here because all platforms that
  5. * support the new common dialogs come with IE5 installed.
  6. */
  7. #include "tweakui.h"
  8. #define COMDLG32_KL(nm) \
  9. KL const c_kl##nm = { &g_hkCUSMWCV, TEXT("Policies\\comdlg32"), TEXT(#nm) }
  10. COMDLG32_KL(NoBackButton);
  11. COMDLG32_KL(NoFileMru);
  12. COMDLG32_KL(NoPlacesBar);
  13. #define REGSTR_PATH_PLACESBAR TEXT("Policies\\comdlg32\\PlacesBar")
  14. #define MAX_PLACES 5
  15. const static DWORD CODESEG rgdwHelp[] = {
  16. IDC_SHOWBACK, IDH_CDBACKBUTTON,
  17. IDC_FILEMRU, IDH_CDFILEMRU,
  18. IDC_PLACESGROUP, IDH_CDPLACESBAR,
  19. IDC_PLACESDEF, IDH_CDPLACESBAR,
  20. IDC_PLACESHIDE, IDH_CDPLACESBAR,
  21. IDC_PLACESCUSTOM, IDH_CDPLACESBAR,
  22. IDC_PLACE0+0, IDH_CDPLACESBAR,
  23. IDC_PLACE0+1, IDH_CDPLACESBAR,
  24. IDC_PLACE0+2, IDH_CDPLACESBAR,
  25. IDC_PLACE0+3, IDH_CDPLACESBAR,
  26. IDC_PLACE0+4, IDH_CDPLACESBAR,
  27. 0, 0,
  28. };
  29. /*****************************************************************************
  30. *
  31. * Comdlg32_GetPlacePidl
  32. *
  33. *****************************************************************************/
  34. LPITEMIDLIST
  35. Comdlg32_GetPlacePidl(int i)
  36. {
  37. PIDL pidl = NULL;
  38. HKEY hkPlaces;
  39. if (_RegOpenKey(g_hkCUSMWCV, REGSTR_PATH_PLACESBAR, &hkPlaces) == ERROR_SUCCESS) {
  40. TCHAR szPlaceN[8];
  41. wsprintf(szPlaceN, TEXT("Place%d"), i);
  42. DWORD dwType;
  43. union {
  44. TCHAR szPath[MAX_PATH];
  45. DWORD dwCsidl;
  46. } u;
  47. DWORD cbData = sizeof(u);
  48. DWORD dwRc = SHQueryValueEx(hkPlaces, szPlaceN, NULL, &dwType,
  49. &u, &cbData);
  50. if (dwRc == ERROR_SUCCESS) {
  51. switch (dwType) {
  52. case REG_DWORD:
  53. SHGetSpecialFolderLocation(NULL, u.dwCsidl, &pidl);
  54. break;
  55. case REG_SZ:
  56. pidl = pidlSimpleFromPath(u.szPath);
  57. break;
  58. }
  59. }
  60. RegCloseKey(hkPlaces);
  61. }
  62. return pidl;
  63. }
  64. /*****************************************************************************
  65. *
  66. * c_rgcsidlPlace - an array of csidls that are good candidates for "Places"
  67. *
  68. *****************************************************************************/
  69. const int c_rgcsidlPlace[] = {
  70. -1, /* CSIDL_NONE */
  71. #ifdef IDS_CWD
  72. -2, /* CSIDL_CWD */
  73. #endif
  74. CSIDL_DESKTOP,
  75. CSIDL_FAVORITES,
  76. CSIDL_PERSONAL,
  77. CSIDL_MYMUSIC,
  78. CSIDL_MYVIDEO,
  79. CSIDL_DRIVES,
  80. CSIDL_NETWORK,
  81. CSIDL_HISTORY,
  82. CSIDL_MYPICTURES,
  83. };
  84. /*****************************************************************************
  85. *
  86. * CPlace - Wangle the "place" combobox
  87. *
  88. *****************************************************************************/
  89. class CPlace {
  90. public:
  91. CPlace(HWND hwnd, HKEY hkPlaces, int iPlace);
  92. void Apply(HKEY hkPlaces);
  93. private:
  94. HWND _hwnd;
  95. int _iPlace;
  96. DWORD _dwType; // REG_DWORD (_csidl) or REG_SZ (_szPath)
  97. union {
  98. TCHAR _szPath[MAX_PATH];
  99. int _csidl;
  100. } _u;
  101. TCHAR _szValue[8]; /* place name value */
  102. };
  103. /*****************************************************************************
  104. *
  105. * CPlace::CPlace (constructor)
  106. *
  107. * The reference data for each combo item is a csidl (integer).
  108. *
  109. *****************************************************************************/
  110. CPlace::CPlace(HWND hwnd, HKEY hkPlaces, int iPlace) :
  111. _hwnd(hwnd), _iPlace(iPlace)
  112. {
  113. PIDL pidlPlace = NULL;
  114. PIDL pidl;
  115. wsprintf(_szValue, TEXT("Place%d"), _iPlace);
  116. DWORD dwRc = ERROR_INVALID_FUNCTION; /* anything that isn't ERROR_SUCCESS */
  117. if (hkPlaces) {
  118. DWORD cbData = sizeof(_u);
  119. dwRc = SHQueryValueEx(hkPlaces, _szValue, NULL, &_dwType, &_u, &cbData);
  120. #ifdef IDS_CWD
  121. if (dwRc == ERROR_SUCCESS && _dwType == REG_SZ && _u._szPath[0] == TEXT('\0')) {
  122. _dwType = REG_DWORD;
  123. _u._csidl = -2;
  124. }
  125. #endif
  126. }
  127. /* Sigh - SHQueryValueEx trashes its inputs on failure */
  128. if (dwRc != ERROR_SUCCESS) {
  129. _dwType = REG_DWORD;
  130. _u._csidl = -1; /* Default to <none> */
  131. }
  132. for (int i = 0; i < cA(c_rgcsidlPlace); i++) {
  133. int csidl = c_rgcsidlPlace[i];
  134. pidl = NULL;
  135. if (csidl < 0 || SUCCEEDED(SHGetSpecialFolderLocation(NULL, csidl, &pidl))) {
  136. TCHAR tszName[MAX_PATH];
  137. UINT ids;
  138. switch (csidl) {
  139. case -1: ids = IDS_NONE; break;
  140. #ifdef IDS_CWD
  141. case -2: ids = IDS_CWD; break;
  142. #endif
  143. default: ids = csidl + IDS_FOLDER_BASE; break;
  144. }
  145. LoadString(hinstCur, ids, tszName, cA(tszName));
  146. int iCombo = ComboBox_AddString(_hwnd, tszName);
  147. if (iCombo >= 0) {
  148. ComboBox_SetItemData(_hwnd, iCombo, csidl);
  149. if (_dwType == REG_DWORD && _u._csidl == csidl) {
  150. ComboBox_SetCurSel(_hwnd, iCombo);
  151. }
  152. }
  153. Ole_Free(pidl);
  154. }
  155. }
  156. if (ComboBox_GetCurSel(_hwnd) == -1) {
  157. switch (_dwType) {
  158. case REG_SZ:
  159. ComboBox_SetText(_hwnd, _u._szPath);
  160. break;
  161. case REG_DWORD:
  162. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, _u._csidl, &pidl))) {
  163. SHFILEINFO sfi;
  164. if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME | SHGFI_PIDL)) {
  165. ComboBox_SetText(_hwnd, sfi.szDisplayName);
  166. }
  167. Ole_Free(pidl);
  168. }
  169. break;
  170. }
  171. }
  172. }
  173. /*****************************************************************************
  174. *
  175. * CPlace::Apply
  176. *
  177. *****************************************************************************/
  178. void CPlace::Apply(HKEY hkPlaces)
  179. {
  180. int iSel = ComboBox_GetCurSel(_hwnd);
  181. /* If the selection is -1, see if it matches any of the predefined items */
  182. if (iSel == -1) {
  183. ComboBox_GetText(_hwnd, _u._szPath, cA(_u._szPath));
  184. /* Special case: Blank string equals "<none>" */
  185. if (_u._szPath[0] == TEXT('\0')) {
  186. LoadString(hinstCur, IDS_NONE, _u._szPath, cA(_u._szPath));
  187. }
  188. iSel = ComboBox_GetCount(_hwnd);
  189. while (--iSel >= 0) {
  190. TCHAR szSpecial[MAX_PATH];
  191. ComboBox_GetLBText(_hwnd, iSel, szSpecial);
  192. if (lstrcmpi(szSpecial, _u._szPath) == 0) break;
  193. }
  194. }
  195. if (iSel >= 0) {
  196. int csidl = (int)ComboBox_GetItemData(_hwnd, iSel);
  197. switch (csidl) {
  198. case -1: RegDeleteValue(hkPlaces, _szValue); break;
  199. #ifdef IDS_CWD
  200. case -2: SHRegSetPath(hkPlaces, NULL, _szValue, TEXT("."), 0); break;
  201. #endif
  202. default: RegSetValueEx(hkPlaces, _szValue, NULL, REG_DWORD, (LPCBYTE)&csidl, sizeof(csidl)); break;
  203. }
  204. } else {
  205. /* text is a path, we hope */
  206. SHRegSetPath(hkPlaces, NULL, _szValue, _u._szPath, 0);
  207. }
  208. }
  209. /*****************************************************************************
  210. *
  211. * Comdlg32_SetDirty
  212. *
  213. * Make a control dirty.
  214. *
  215. *****************************************************************************/
  216. #define Comdlg32_SetDirty Common_SetDirty
  217. /*****************************************************************************
  218. *
  219. * Comdlg32_EnableDisableItems
  220. *
  221. * If "Custom places bar" is set, then enable the combos.
  222. * If any combo is set to "Custom location", then enable the Change button.
  223. *
  224. *****************************************************************************/
  225. void
  226. Comdlg32_EnableDisableItems(HWND hdlg)
  227. {
  228. BOOL bEnableCombo = IsDlgButtonChecked(hdlg, IDC_PLACESCUSTOM);
  229. for (int i = 0; i < MAX_PLACES; i++)
  230. {
  231. EnableDlgItem(hdlg, IDC_PLACE0+i, bEnableCombo);
  232. }
  233. }
  234. /*****************************************************************************
  235. *
  236. * Comdlg32_OnCommand
  237. *
  238. * Ooh, we got a command.
  239. *
  240. *****************************************************************************/
  241. BOOL PASCAL
  242. Comdlg32_OnCommand(HWND hdlg, int id, UINT codeNotify)
  243. {
  244. switch (id) {
  245. case IDC_SHOWBACK:
  246. case IDC_FILEMRU:
  247. if (codeNotify == BN_CLICKED) Comdlg32_SetDirty(hdlg);
  248. break;
  249. case IDC_PLACESDEF:
  250. case IDC_PLACESHIDE:
  251. case IDC_PLACESCUSTOM:
  252. if (codeNotify == BN_CLICKED) {
  253. Comdlg32_SetDirty(hdlg);
  254. Comdlg32_EnableDisableItems(hdlg);
  255. }
  256. break;
  257. case IDC_PLACE0+0:
  258. case IDC_PLACE0+1:
  259. case IDC_PLACE0+2:
  260. case IDC_PLACE0+3:
  261. case IDC_PLACE0+4:
  262. if (codeNotify == CBN_SELCHANGE ||
  263. codeNotify == CBN_EDITCHANGE) {
  264. Comdlg32_SetDirty(hdlg);
  265. }
  266. break;
  267. }
  268. return 0;
  269. }
  270. /*****************************************************************************
  271. *
  272. * Comdlg32_OnInitDialog
  273. *
  274. * Initialize the listview with the current restrictions.
  275. *
  276. *****************************************************************************/
  277. BOOL PASCAL
  278. Comdlg32_OnInitDialog(HWND hdlg)
  279. {
  280. CheckDlgButton(hdlg, IDC_SHOWBACK, !GetDwordPkl(&c_klNoBackButton, 0));
  281. CheckDlgButton(hdlg, IDC_FILEMRU, !GetDwordPkl(&c_klNoFileMru, 0));
  282. HKEY hkPlaces = NULL;
  283. _RegOpenKey(g_hkCUSMWCV, REGSTR_PATH_PLACESBAR, &hkPlaces);
  284. UINT idc;
  285. if (GetDwordPkl(&c_klNoPlacesBar, 0)) {
  286. idc = IDC_PLACESHIDE;
  287. } else if (hkPlaces) {
  288. idc = IDC_PLACESCUSTOM;
  289. } else {
  290. idc = IDC_PLACESDEF;
  291. }
  292. CheckRadioButton(hdlg, IDC_PLACESDEF, IDC_PLACESCUSTOM, idc);
  293. for (int i = 0; i < MAX_PLACES; i++) {
  294. HWND hwndCombo = GetDlgItem(hdlg, IDC_PLACE0+i);
  295. CPlace *pplace = new CPlace(hwndCombo, hkPlaces, i);
  296. if (pplace) {
  297. SetWindowLongPtr(hwndCombo, GWLP_USERDATA, (LPARAM)pplace);
  298. }
  299. }
  300. if (hkPlaces) {
  301. RegCloseKey(hkPlaces);
  302. }
  303. Comdlg32_EnableDisableItems(hdlg);
  304. return 1;
  305. }
  306. /*****************************************************************************
  307. *
  308. * Comdlg32_Apply
  309. *
  310. *****************************************************************************/
  311. void PASCAL
  312. Comdlg32_Apply(HWND hdlg)
  313. {
  314. SetDwordPkl2(&c_klNoBackButton, !IsDlgButtonChecked(hdlg, IDC_SHOWBACK));
  315. SetDwordPkl2(&c_klNoFileMru, !IsDlgButtonChecked(hdlg, IDC_FILEMRU));
  316. if (IsDlgButtonChecked(hdlg, IDC_PLACESHIDE)) {
  317. SetDwordPkl2(&c_klNoPlacesBar, 1);
  318. } else if (IsDlgButtonChecked(hdlg, IDC_PLACESDEF)) {
  319. DelPkl(&c_klNoPlacesBar);
  320. RegDeleteTree(g_hkCUSMWCV, REGSTR_PATH_PLACESBAR);
  321. } else {
  322. DelPkl(&c_klNoPlacesBar);
  323. HKEY hkPlaces;
  324. if (_RegCreateKey(g_hkCUSMWCV, REGSTR_PATH_PLACESBAR, &hkPlaces) == ERROR_SUCCESS) {
  325. for (int i = 0; i < MAX_PLACES; i++) {
  326. HWND hwndCombo = GetDlgItem(hdlg, IDC_PLACE0+i);
  327. CPlace *pplace = (CPlace *)GetWindowLongPtr(hwndCombo, GWLP_USERDATA);
  328. if (pplace) {
  329. pplace->Apply(hkPlaces);
  330. }
  331. }
  332. RegCloseKey(hkPlaces);
  333. }
  334. }
  335. }
  336. /*****************************************************************************
  337. *
  338. * Comdlg32_OnNotify
  339. *
  340. * Ooh, we got a notification.
  341. *
  342. *****************************************************************************/
  343. BOOL PASCAL
  344. Comdlg32_OnNotify(HWND hdlg, NMHDR FAR *pnm)
  345. {
  346. switch (pnm->code) {
  347. case PSN_APPLY:
  348. Comdlg32_Apply(hdlg);
  349. break;
  350. }
  351. return 0;
  352. }
  353. /*****************************************************************************
  354. *
  355. * Comdlg32_OnDestroy
  356. *
  357. *****************************************************************************/
  358. void
  359. Comdlg32_OnDestroy(HWND hdlg)
  360. {
  361. for (int i = 0; i < MAX_PLACES; i++) {
  362. HWND hwndCombo = GetDlgItem(hdlg, IDC_PLACE0+i);
  363. CPlace *pplace = (CPlace *)GetWindowLongPtr(hwndCombo, GWLP_USERDATA);
  364. delete pplace;
  365. }
  366. }
  367. /*****************************************************************************
  368. *
  369. * Our window procedure.
  370. *
  371. *****************************************************************************/
  372. INT_PTR EXPORT
  373. Comdlg32_DlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam)
  374. {
  375. switch (wm) {
  376. case WM_INITDIALOG: return Comdlg32_OnInitDialog(hdlg);
  377. case WM_COMMAND:
  378. return Comdlg32_OnCommand(hdlg,
  379. (int)GET_WM_COMMAND_ID(wParam, lParam),
  380. (UINT)GET_WM_COMMAND_CMD(wParam, lParam));
  381. case WM_NOTIFY:
  382. return Comdlg32_OnNotify(hdlg, (NMHDR FAR *)lParam);
  383. case WM_DESTROY:
  384. Comdlg32_OnDestroy(hdlg);
  385. break;
  386. case WM_HELP: Common_OnHelp(lParam, &rgdwHelp[0]); break;
  387. case WM_CONTEXTMENU: Common_OnContextMenu(wParam, &rgdwHelp[0]); break;
  388. default: return 0; /* Unhandled */
  389. }
  390. return 1; /* Handled */
  391. }