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.

931 lines
24 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: N C U I . C P P
  7. //
  8. // Contents: Common user interface routines.
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 24 Mar 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.h>
  16. #pragma hdrstop
  17. #include "ncerror.h"
  18. #include "ncstring.h"
  19. #include "ncui.h"
  20. #include "ncperms.h"
  21. #include "netconp.h"
  22. //+---------------------------------------------------------------------------
  23. //
  24. // Function: EnableOrDisableDialogControls
  25. //
  26. // Purpose: Enable or disable a group of controls all at once.
  27. //
  28. // Arguments:
  29. // hDlg [in] Window handle of parent dialog.
  30. // ccid [in] Count of elements in array pointed to by acid.
  31. // acid [in] Array of control ids.
  32. // fEnable [in] TRUE to enable controls, FALSE to disable.
  33. //
  34. // Returns: nothing
  35. //
  36. // Author: shaunco 24 Mar 1997
  37. //
  38. // Notes: Don't forget to declare your array as 'static const'.
  39. //
  40. NOTHROW
  41. VOID
  42. EnableOrDisableDialogControls (
  43. IN HWND hDlg,
  44. IN INT ccid,
  45. IN const INT* acid,
  46. IN BOOL fEnable)
  47. {
  48. Assert (IsWindow (hDlg));
  49. Assert (FImplies (ccid, acid));
  50. while (ccid--)
  51. {
  52. EnableWindow (GetDlgItem (hDlg, *acid++), fEnable);
  53. }
  54. }
  55. //+---------------------------------------------------------------------------
  56. //
  57. // Function: FMapRadioButtonToValue
  58. //
  59. // Purpose: Maps the current state of a set of radio buttons to a DWORD
  60. // value based on a mapping table.
  61. //
  62. // Arguments:
  63. // hDlg [in] Window handle of parent dialog.
  64. // crbm [in] Count of elements in array pointed to by arbm.
  65. // arbm [in] Array of elements that map a radio button control id to
  66. // its associated value.
  67. // pdwValue [out] The returned value.
  68. //
  69. // Returns: TRUE if a radio button was set and the value returned.
  70. // FALSE otherwise.
  71. //
  72. // Author: shaunco 24 Mar 1997
  73. //
  74. // Notes: Don't forget to declare your array as 'static const'.
  75. //
  76. NOTHROW
  77. BOOL
  78. FMapRadioButtonToValue (
  79. IN HWND hDlg,
  80. IN INT crbm,
  81. IN const RADIO_BUTTON_MAP* arbm,
  82. OUT DWORD* pdwValue)
  83. {
  84. Assert (IsWindow (hDlg));
  85. Assert (FImplies (crbm, arbm));
  86. Assert (pdwValue);
  87. while (crbm--)
  88. {
  89. // If it is set, return the corresponding value.
  90. if (BST_CHECKED & IsDlgButtonChecked (hDlg, arbm->cid))
  91. {
  92. *pdwValue = arbm->dwValue;
  93. return TRUE;
  94. }
  95. arbm++;
  96. }
  97. *pdwValue = 0;
  98. return FALSE;
  99. }
  100. //+---------------------------------------------------------------------------
  101. //
  102. // Function: FMapValueToRadioButton
  103. //
  104. // Purpose: Set the state of a set of radio buttons based on the value of
  105. // of a DWORD and a mapping table.
  106. //
  107. // Arguments:
  108. // hDlg [in] Window handle of parent dialog.
  109. // crbm [in] Count of elements in array pointed to by arbm.
  110. // arbm [in] Array of elements that map a radio button control id to
  111. // its associated value.
  112. // dwValue [in] value which gets mapped to set the appropriate radio
  113. // button.
  114. //
  115. // Returns: TRUE if dwValue was found in the map. FALSE otherwise.
  116. //
  117. // Author: shaunco 24 Mar 1997
  118. //
  119. // Notes: Don't forget to declare your array as 'static const'.
  120. //
  121. NOTHROW
  122. BOOL
  123. FMapValueToRadioButton (
  124. IN HWND hDlg,
  125. IN INT crbm,
  126. IN const RADIO_BUTTON_MAP* arbm,
  127. IN DWORD dwValue,
  128. IN INT* pncid)
  129. {
  130. Assert (IsWindow (hDlg));
  131. Assert (FImplies (crbm, arbm));
  132. while (crbm--)
  133. {
  134. if (dwValue == arbm->dwValue)
  135. {
  136. // Set the radio button.
  137. CheckDlgButton (hDlg, arbm->cid, BST_CHECKED);
  138. // Return the control id if requested.
  139. if (pncid)
  140. {
  141. *pncid = arbm->cid;
  142. }
  143. return TRUE;
  144. }
  145. arbm++;
  146. }
  147. return FALSE;
  148. }
  149. //+---------------------------------------------------------------------------
  150. //
  151. // Function: GetIntegerFormat
  152. //
  153. // Purpose: Uses GetNumberFormat to format an integer number.
  154. //
  155. // Arguments:
  156. // Locale [in] See Win32 API description of GetNumberFormat.
  157. // pszValue [in]
  158. // pszFormattedValue [out]
  159. // cchFormattedValue [in]
  160. //
  161. // Returns: return value from GetNumberFormat
  162. //
  163. // Author: shaunco 4 May 1998
  164. //
  165. // Notes:
  166. //
  167. INT
  168. GetIntegerFormat (
  169. IN LCID Locale,
  170. IN PCWSTR pszValue,
  171. OUT PWSTR pszFormattedValue,
  172. IN INT cchFormattedValue)
  173. {
  174. // Format the number for the user's locale and preferences.
  175. //
  176. WCHAR szGrouping [16];
  177. GetLocaleInfo (Locale, LOCALE_SGROUPING,
  178. szGrouping, celems(szGrouping));
  179. WCHAR szDecimalSep [16];
  180. GetLocaleInfo (Locale, LOCALE_SDECIMAL,
  181. szDecimalSep, celems(szDecimalSep));
  182. WCHAR szThousandSep [16];
  183. GetLocaleInfo (Locale, LOCALE_STHOUSAND,
  184. szThousandSep, celems(szThousandSep));
  185. NUMBERFMT nf;
  186. ZeroMemory (&nf, sizeof(nf));
  187. nf.Grouping = wcstoul (szGrouping, NULL, 10);
  188. nf.lpDecimalSep = szDecimalSep;
  189. nf.lpThousandSep = szThousandSep;
  190. return GetNumberFormat (
  191. Locale,
  192. 0,
  193. pszValue,
  194. &nf,
  195. pszFormattedValue,
  196. cchFormattedValue);
  197. }
  198. INT
  199. Format32bitInteger (
  200. IN UINT32 unValue,
  201. IN BOOL fSigned,
  202. OUT PWSTR pszFormattedValue,
  203. IN INT cchFormattedValue)
  204. {
  205. // Convert the number to a string.
  206. //
  207. WCHAR szValue [33];
  208. *szValue = 0;
  209. if (fSigned)
  210. {
  211. _itow ((INT)unValue, szValue, 10);
  212. }
  213. else
  214. {
  215. _ultow (unValue, szValue, 10);
  216. }
  217. // Format the number according to user locale settings.
  218. //
  219. INT cch = GetIntegerFormat (
  220. LOCALE_USER_DEFAULT,
  221. szValue,
  222. pszFormattedValue,
  223. cchFormattedValue);
  224. if (!cch)
  225. {
  226. TraceHr(ttidError, FAL, HrFromLastWin32Error(), FALSE,
  227. "GetIntegerFormat failed in Format32bitInteger");
  228. lstrcpynW (pszFormattedValue, szValue, cchFormattedValue);
  229. cch = lstrlenW (pszFormattedValue);
  230. }
  231. return cch;
  232. }
  233. INT
  234. Format64bitInteger (
  235. IN UINT64 ulValue,
  236. IN BOOL fSigned,
  237. OUT PWSTR pszFormattedValue,
  238. IN INT cchFormattedValue)
  239. {
  240. // Convert the number to a string.
  241. //
  242. WCHAR szValue [32];
  243. *szValue = 0;
  244. if (fSigned)
  245. {
  246. _i64tow ((INT64)ulValue, szValue, 10);
  247. }
  248. else
  249. {
  250. _ui64tow (ulValue, szValue, 10);
  251. }
  252. // Format the number according to user locale settings.
  253. //
  254. INT cch = GetIntegerFormat (
  255. LOCALE_USER_DEFAULT,
  256. szValue,
  257. pszFormattedValue,
  258. cchFormattedValue);
  259. if (!cch)
  260. {
  261. TraceHr(ttidError, FAL, HrFromLastWin32Error(), FALSE,
  262. "GetIntegerFormat failed in Format64bitInteger");
  263. lstrcpynW (pszFormattedValue, szValue, cchFormattedValue);
  264. cch = lstrlenW (pszFormattedValue);
  265. }
  266. return cch;
  267. }
  268. BOOL
  269. SetDlgItemFormatted32bitInteger (
  270. IN HWND hDlg,
  271. IN INT nIdDlgItem,
  272. IN UINT32 unValue,
  273. IN BOOL fSigned)
  274. {
  275. // Format the number according to user locale settings.
  276. //
  277. WCHAR szFormattedValue[64];
  278. Format32bitInteger(
  279. unValue,
  280. fSigned,
  281. szFormattedValue,
  282. celems(szFormattedValue));
  283. // Display the number.
  284. //
  285. return SetDlgItemText (hDlg, nIdDlgItem, szFormattedValue);
  286. }
  287. BOOL
  288. SetDlgItemFormatted64bitInteger (
  289. IN HWND hDlg,
  290. IN INT nIdDlgItem,
  291. IN UINT64 ulValue,
  292. IN BOOL fSigned)
  293. {
  294. // Format the number according to user locale settings.
  295. //
  296. WCHAR szFormattedValue[64];
  297. Format64bitInteger(
  298. ulValue,
  299. fSigned,
  300. szFormattedValue,
  301. celems(szFormattedValue));
  302. // Display the number.
  303. //
  304. return SetDlgItemText (hDlg, nIdDlgItem, szFormattedValue);
  305. }
  306. //+---------------------------------------------------------------------------
  307. //
  308. // Function: HrNcQueryUserForRebootEx
  309. //
  310. // Purpose: Query the user to reboot. If he/she chooses yes, a reboot
  311. // is initiated.
  312. //
  313. // Arguments:
  314. // hwndParent [in] Parent window handle.
  315. // pszCaption [in] Caption text.
  316. // pszText [in] Message text.
  317. // dwFlags [in] Control flags (QUFR_PROMPT | QUFR_REBOOT)
  318. //
  319. // Returns: S_OK if a reboot was requested, S_FALSE if the user
  320. // didn't want to, or an error code otherwise.
  321. //
  322. // Author: danielwe 29 Oct 1997
  323. //
  324. // Notes:
  325. //
  326. HRESULT
  327. HrNcQueryUserForRebootEx (
  328. IN HWND hwndParent,
  329. IN PCWSTR pszCaption,
  330. IN PCWSTR pszText,
  331. IN DWORD dwFlags)
  332. {
  333. HRESULT hr = S_FALSE;
  334. INT nRet = IDYES;
  335. if (dwFlags & QUFR_PROMPT)
  336. {
  337. nRet = MessageBox (hwndParent, pszText, pszCaption,
  338. MB_YESNO | MB_ICONEXCLAMATION);
  339. }
  340. if (nRet == IDYES)
  341. {
  342. if (dwFlags & QUFR_REBOOT)
  343. {
  344. TOKEN_PRIVILEGES* ptpOld;
  345. hr = HrEnableAllPrivileges (&ptpOld);
  346. if (S_OK == hr)
  347. {
  348. if (!ExitWindowsEx (EWX_REBOOT, 10))
  349. {
  350. hr = HrFromLastWin32Error();
  351. }
  352. MemFree (ptpOld);
  353. }
  354. }
  355. else
  356. {
  357. hr = S_OK;
  358. }
  359. }
  360. TraceError("HrNcQueryUserForRebootEx", (hr == S_FALSE) ? S_OK : hr);
  361. return hr;
  362. }
  363. //+---------------------------------------------------------------------------
  364. //
  365. // Function: HrNcQueryUserForReboot
  366. //
  367. // Purpose: Query the user to reboot. If he/she chooses yes, a reboot
  368. // is initiated.
  369. //
  370. // Arguments:
  371. // hinst [in] Module instance with string ids.
  372. // hwndParent [in] Parent window handle.
  373. // unIdCaption [in] String id of caption text.
  374. // unIdText [in] String id of message text.
  375. // dwFlags [in] Control flags (QUFR_PROMPT | QUFR_REBOOT)
  376. //
  377. // Returns: S_OK if a reboot is initiated, S_FALSE if the user
  378. // didn't want to, or an error code otherwise.
  379. //
  380. // Author: shaunco 2 Jan 1998
  381. //
  382. // Notes:
  383. //
  384. HRESULT
  385. HrNcQueryUserForReboot (
  386. IN HINSTANCE hinst,
  387. IN HWND hwndParent,
  388. IN UINT unIdCaption,
  389. IN UINT unIdText,
  390. IN DWORD dwFlags)
  391. {
  392. PCWSTR pszCaption = SzLoadString (hinst, unIdCaption);
  393. PCWSTR pszText = SzLoadString (hinst, unIdText);
  394. HRESULT hr = HrNcQueryUserForRebootEx (hwndParent, pszCaption,
  395. pszText, dwFlags);
  396. TraceError("HrNcQueryUserForReboot", (hr == S_FALSE) ? S_OK : hr);
  397. return hr;
  398. }
  399. //+---------------------------------------------------------------------------
  400. //
  401. // Function: HrShell_NotifyIcon
  402. //
  403. // Purpose: HRESULT returning wrapper for Shell_NotifyIcon.
  404. //
  405. // Arguments:
  406. // dwMessage [in]
  407. // pData [in]
  408. //
  409. // Returns: S_OK or an error code.
  410. //
  411. // Author: shaunco 11 Nov 1998
  412. //
  413. // Notes:
  414. //
  415. HRESULT
  416. HrShell_NotifyIcon (
  417. IN DWORD dwMessage,
  418. IN PNOTIFYICONDATA pData)
  419. {
  420. HRESULT hr = E_FAIL; // First time through, this will succeed
  421. BOOL fr = FALSE;
  422. BOOL fRetriedAlready = FALSE;
  423. BOOL fAttemptRetry = FALSE;
  424. INT iRetries = 0;
  425. // Attempt the first time, and attempt again after an attempted correction
  426. //
  427. while ((hr == E_FAIL) || fAttemptRetry)
  428. {
  429. if (fAttemptRetry)
  430. fRetriedAlready = TRUE;
  431. fr = Shell_NotifyIcon(dwMessage, pData);
  432. if (!fr)
  433. {
  434. if (dwMessage == NIM_ADD && !fRetriedAlready)
  435. {
  436. NOTIFYICONDATA nidDelete;
  437. ZeroMemory (&nidDelete, sizeof(nidDelete));
  438. nidDelete.cbSize = sizeof(NOTIFYICONDATA);
  439. nidDelete.hWnd = pData->hWnd;
  440. nidDelete.uID = pData->uID;
  441. Shell_NotifyIcon(NIM_DELETE, &nidDelete);
  442. fAttemptRetry = TRUE;
  443. hr = E_FAIL;
  444. }
  445. else
  446. {
  447. // We should not attempt [a|another] retry
  448. //
  449. fAttemptRetry = FALSE;
  450. hr = S_FALSE;
  451. }
  452. }
  453. else
  454. {
  455. fAttemptRetry = FALSE;
  456. hr = S_OK;
  457. }
  458. }
  459. // At this point, if hr == S_FALSE, it means that we tried to retry, and even that failed
  460. // We need to convert this to E_FAIL so we still return what we did before
  461. //
  462. if (S_FALSE == hr)
  463. {
  464. hr = E_FAIL;
  465. }
  466. // If we successfully swapped an icon, we should assert and figure out why that
  467. // went wrong.
  468. //
  469. if ((S_OK == hr) && fRetriedAlready)
  470. {
  471. TraceTag(ttidShellFolder, "We should debug this. We worked around a duplicate icon by removing "
  472. "the old one and putting the new one in place");
  473. }
  474. TraceError("HrShell_NotifyIcon", hr);
  475. return hr;
  476. }
  477. //+---------------------------------------------------------------------------
  478. //
  479. // Function: LresFromHr
  480. //
  481. // Purpose: Translates an HRESULT into a valid LRESULT to be returned by
  482. // a dialog handler function.
  483. //
  484. // Arguments:
  485. // hr [in] HRESULT to be translated.
  486. //
  487. // Returns: LRESULT
  488. //
  489. // Author: danielwe 24 Mar 1997
  490. //
  491. // Notes:
  492. //
  493. LRESULT
  494. LresFromHr (
  495. IN HRESULT hr)
  496. {
  497. AssertSz (((LRESULT)hr) != PSNRET_INVALID, "Don't pass PSNRET_INVALID to "
  498. "LresFromHr! Use equivalent NETCFG_E_* value instead!");
  499. AssertSz (((LRESULT)hr) != PSNRET_INVALID_NOCHANGEPAGE, "Don't pass "
  500. "PSNRET_INVALID_NOCHANGEPAGE to "
  501. "LresFromHr! Use equivalent NETCFG_E_* value instead!");
  502. if (NETCFG_E_PSNRET_INVALID == hr)
  503. {
  504. return PSNRET_INVALID;
  505. }
  506. if (NETCFG_E_PSNRET_INVALID_NCPAGE == hr)
  507. {
  508. return PSNRET_INVALID_NOCHANGEPAGE;
  509. }
  510. return (SUCCEEDED(hr)) ? PSNRET_NOERROR : (LRESULT)hr;
  511. }
  512. //+---------------------------------------------------------------------------
  513. //
  514. // Function: NcMsgBox
  515. //
  516. // Purpose: Displays a message box using resource strings and replaceable
  517. // parameters.
  518. //
  519. // Arguments:
  520. // hinst [in] hinstance for resource strings
  521. // hwnd [in] parent window handle
  522. // unIdCaption [in] resource id of caption string
  523. // unIdFormat [in] resource id of text string (with %1, %2, etc.)
  524. // unStyle [in] standard message box styles
  525. // ... [in] replaceable parameters (optional)
  526. // (these must be PCWSTRs as that is all
  527. // FormatMessage handles.)
  528. //
  529. // Returns: the return value of MessageBox()
  530. //
  531. // Author: shaunco 24 Mar 1997
  532. //
  533. // Notes: FormatMessage is used to do the parameter substitution.
  534. //
  535. INT
  536. WINAPIV
  537. NcMsgBox (
  538. IN HINSTANCE hinst,
  539. IN HWND hwnd,
  540. IN UINT unIdCaption,
  541. IN UINT unIdFormat,
  542. IN UINT unStyle,
  543. IN ...)
  544. {
  545. PCWSTR pszCaption = SzLoadString (hinst, unIdCaption);
  546. PCWSTR pszFormat = SzLoadString (hinst, unIdFormat);
  547. PWSTR pszText = NULL;
  548. va_list val;
  549. va_start (val, unStyle);
  550. FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  551. pszFormat, 0, 0, (PWSTR)&pszText, 0, &val);
  552. va_end (val);
  553. INT nRet = MessageBox (hwnd, pszText, pszCaption, unStyle);
  554. LocalFree (pszText);
  555. return nRet;
  556. }
  557. //+---------------------------------------------------------------------------
  558. //
  559. // Function: NcMsgBoxWithVarCaption
  560. //
  561. // Purpose: Same as NcMsgBox, but allows a string parameter to be used
  562. // for the caption.
  563. //
  564. // Arguments:
  565. // hinst [in] hinstance for resource strings
  566. // hwnd [in] parent window handle
  567. // unIdCaption [in] resource id of caption string
  568. // pszCaptionParam [in] string parameter to use for caption
  569. // unIdFormat [in] resource id of text string (with %1, %2, etc.)
  570. // unStyle [in] standard message box styles
  571. // ... [in] replaceable parameters (optional)
  572. // (these must be PCWSTRs as that is all
  573. // FormatMessage handles.)
  574. //
  575. // Returns: the return value of MessageBox()
  576. //
  577. // Author: danielwe 29 Oct 1997
  578. //
  579. // Notes: FormatMessage is used to do the parameter substitution.
  580. //
  581. INT
  582. WINAPIV
  583. NcMsgBoxWithVarCaption (
  584. HINSTANCE hinst,
  585. HWND hwnd,
  586. UINT unIdCaption,
  587. PCWSTR pszCaptionParam,
  588. UINT unIdFormat,
  589. UINT unStyle,
  590. ...)
  591. {
  592. PCWSTR pszCaption = SzLoadString (hinst, unIdCaption);
  593. PCWSTR pszFormat = SzLoadString (hinst, unIdFormat);
  594. PWSTR pszNewCaption = NULL;
  595. DwFormatStringWithLocalAlloc (pszCaption, &pszNewCaption, pszCaptionParam);
  596. PWSTR pszText = NULL;
  597. va_list val;
  598. va_start (val, unStyle);
  599. FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  600. pszFormat, 0, 0, (PWSTR)&pszText, 0, &val);
  601. va_end (val);
  602. INT nRet = MessageBox (hwnd, pszText, pszNewCaption, unStyle);
  603. LocalFree (pszText);
  604. LocalFree (pszNewCaption);
  605. return nRet;
  606. }
  607. //+---------------------------------------------------------------------------
  608. //
  609. // Function: NcMsgBoxWithWin32ErrorText
  610. //
  611. // Purpose: Displays a message box using a Win32 error code, resource
  612. // strings and replaceable parameters.
  613. // The output text is a combination of the user's format
  614. // string (with parameter's replaced) and the Win32 error
  615. // text as returned from FormatMessage. These two strings
  616. // are combined using the IDS_TEXT_WITH_WIN32_ERROR resource.
  617. //
  618. // Arguments:
  619. // dwError [in] Win32 error code
  620. // hinst [in] Module instance where string resources live.
  621. // hwnd [in] parent window handle
  622. // unIdCaption [in] resource id of caption string
  623. // unIdCombineFormat [in] resource id of format string to combine
  624. // error text with unIdFormat text.
  625. // unIdFormat [in] resource id of text string (with %1, %2, etc.)
  626. // unStyle [in] standard message box styles
  627. // ... [in] replaceable parameters (optional)
  628. // (these must be PCWSTRs as that is all
  629. // FormatMessage handles.)
  630. //
  631. // Returns: the return value of MessageBox()
  632. //
  633. // Author: shaunco 3 May 1997
  634. //
  635. // Notes: FormatMessage is used to do the parameter substitution.
  636. //
  637. NOTHROW
  638. INT
  639. WINAPIV
  640. NcMsgBoxWithWin32ErrorText (
  641. IN DWORD dwError,
  642. IN HINSTANCE hinst,
  643. IN HWND hwnd,
  644. IN UINT unIdCaption,
  645. IN UINT unIdCombineFormat,
  646. IN UINT unIdFormat,
  647. IN UINT unStyle,
  648. IN ...)
  649. {
  650. // Get the user's text with parameter's replaced.
  651. //
  652. PCWSTR pszFormat = SzLoadString (hinst, unIdFormat);
  653. PWSTR pszText;
  654. va_list val;
  655. va_start (val, unStyle);
  656. FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  657. pszFormat, 0, 0, (PWSTR)&pszText, 0, &val);
  658. va_end(val);
  659. // Get the error text for the Win32 error.
  660. //
  661. PWSTR pszError;
  662. FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  663. NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  664. (PWSTR)&pszError, 0, NULL);
  665. // Combine the user's text with the error text using IDS_TEXT_WITH_WIN32_ERROR.
  666. //
  667. PCWSTR pszTextWithErrorFmt = SzLoadString (hinst, unIdCombineFormat);
  668. PWSTR pszTextWithError;
  669. DwFormatStringWithLocalAlloc (pszTextWithErrorFmt, &pszTextWithError,
  670. pszText, pszError);
  671. PCWSTR pszCaption = SzLoadString (hinst, unIdCaption);
  672. INT nRet = MessageBox (hwnd, pszTextWithError, pszCaption, unStyle);
  673. LocalFree (pszTextWithError);
  674. LocalFree (pszError);
  675. LocalFree (pszText);
  676. return nRet;
  677. }
  678. //+---------------------------------------------------------------------------
  679. //
  680. // Function: SendDlgItemsMessage
  681. //
  682. // Purpose: Send a group of dialog items the same message.
  683. //
  684. // Arguments:
  685. // hDlg [in] Window handle of parent dialog.
  686. // ccid [in] Count of elements in array pointed to by acid.
  687. // acid [in] Array of control ids.
  688. // unMsg [in] Message to send
  689. // wParam [in] First message parameter
  690. // lParam [in] Second message parameter
  691. //
  692. // Returns: nothing
  693. //
  694. // Author: shaunco 11 Jun 1997
  695. //
  696. // Notes:
  697. //
  698. VOID
  699. SendDlgItemsMessage (
  700. IN HWND hDlg,
  701. IN INT ccid,
  702. IN const INT* acid,
  703. IN UINT unMsg,
  704. IN WPARAM wParam,
  705. IN LPARAM lParam)
  706. {
  707. Assert (IsWindow (hDlg));
  708. Assert (FImplies (ccid, acid));
  709. while (ccid--)
  710. {
  711. Assert (IsWindow (GetDlgItem (hDlg, *acid)));
  712. SendDlgItemMessage (hDlg, *acid++, unMsg, wParam, lParam);
  713. }
  714. }
  715. //
  716. // Function: SetDefaultButton
  717. //
  718. // Purpose: Set the new default pushbutton on a dialog
  719. //
  720. // Params: hdlg [in] - Dialog HWND
  721. // iddef [in] - Id of new default pushbutton
  722. //
  723. // Returns: nothing
  724. //
  725. VOID
  726. SetDefaultButton(
  727. IN HWND hdlg,
  728. IN INT iddef)
  729. {
  730. HWND hwnd;
  731. DWORD dwData;
  732. Assert(hdlg);
  733. dwData = SendMessage (hdlg, DM_GETDEFID, 0, 0L);
  734. if ((HIWORD(dwData) == DC_HASDEFID) && LOWORD(dwData))
  735. {
  736. hwnd = GetDlgItem (hdlg, (INT)LOWORD(dwData));
  737. if ((LOWORD(dwData) != iddef) && (hwnd))
  738. {
  739. SendMessage (hwnd, BM_SETSTYLE, (WPARAM)BS_PUSHBUTTON, TRUE);
  740. }
  741. }
  742. SendMessage (hdlg, DM_SETDEFID,(WPARAM)iddef, 0L);
  743. if (iddef)
  744. {
  745. hwnd = GetDlgItem (hdlg, iddef);
  746. Assert(hwnd);
  747. SendMessage (hwnd, BM_SETSTYLE, (WPARAM)BS_DEFPUSHBUTTON, TRUE);
  748. }
  749. }
  750. static const CONTEXTIDMAP c_adwContextIdMap[] =
  751. {
  752. { IDOK, IDH_OK, IDH_OK },
  753. { IDCANCEL, IDH_CANCEL, IDH_CANCEL },
  754. { 0, 0, 0 }, // end marker
  755. };
  756. //+---------------------------------------------------------------------------
  757. //
  758. // Function: DwContextIdFromIdc
  759. //
  760. // Purpose: Converts the given control ID to a context help ID
  761. //
  762. // Arguments:
  763. // idControl [in] Control ID to convert
  764. //
  765. // Returns: Context help ID for that control (mapping comes from help
  766. // authors)
  767. //
  768. // Author: danielwe 27 May 1998
  769. //
  770. // Notes:
  771. //
  772. DWORD DwContextIdFromIdc(
  773. PCCONTEXTIDMAP lpContextIdMap,
  774. BOOL bJpn,
  775. INT idControl)
  776. {
  777. DWORD idw;
  778. Assert(lpContextIdMap);
  779. for (idw = 0; lpContextIdMap[idw].idControl; idw++)
  780. {
  781. if (idControl == lpContextIdMap[idw].idControl)
  782. {
  783. if (!bJpn)
  784. {
  785. return lpContextIdMap[idw].dwContextId;
  786. }
  787. else
  788. {
  789. return lpContextIdMap[idw].dwContextIdJapan;
  790. }
  791. }
  792. }
  793. // Not found, just return 0
  794. return 0;
  795. }
  796. //+---------------------------------------------------------------------------
  797. //
  798. // Function: OnHelpGeneric
  799. //
  800. // Purpose: Handles help generically
  801. //
  802. // Arguments:
  803. // hwnd [in] HWND of parent window
  804. // lParam [in] lParam of the WM_HELP message
  805. //
  806. // Returns: Nothing
  807. //
  808. // Author: danielwe 27 May 1998
  809. // anbrad 18 May 1999 moved to common. common control id's added.
  810. //
  811. // Notes:
  812. //
  813. VOID OnHelpGeneric(
  814. HWND hwnd,
  815. LPHELPINFO lphi,
  816. PCCONTEXTIDMAP pContextMap,
  817. BOOL bJpn,
  818. PCWSTR pszHelpFile)
  819. {
  820. static const TCHAR c_szWindowsHelpFile[] = TEXT("windows.hlp");
  821. Assert(lphi);
  822. if (lphi->iContextType == HELPINFO_WINDOW)
  823. {
  824. switch(lphi->iCtrlId)
  825. {
  826. case -1: // IDC_STATIC
  827. break;
  828. case IDOK:
  829. case IDCANCEL:
  830. case IDABORT:
  831. case IDRETRY:
  832. case IDIGNORE:
  833. case IDYES:
  834. case IDNO:
  835. case IDCLOSE:
  836. case IDHELP:
  837. WinHelp(hwnd, c_szWindowsHelpFile, HELP_CONTEXTPOPUP,
  838. DwContextIdFromIdc(c_adwContextIdMap, bJpn, lphi->iCtrlId));
  839. break;
  840. default:
  841. WinHelp(hwnd, pszHelpFile, HELP_CONTEXTPOPUP,
  842. DwContextIdFromIdc(pContextMap, bJpn, lphi->iCtrlId));
  843. }
  844. }
  845. }