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.

677 lines
16 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-1998 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // AtlUtil.cpp
  7. //
  8. // Abstract:
  9. // Implementation of helper functions for use in an ATL project.
  10. //
  11. // Author:
  12. // David Potter (davidp) December 11, 1997
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "AtlUtil.h"
  20. #include "resource.h"
  21. /////////////////////////////////////////////////////////////////////////////
  22. //++
  23. //
  24. // DDX_GetText
  25. //
  26. // Routine Description:
  27. // Get a text value from a control on a dialog.
  28. //
  29. // Arguments:
  30. // hwndDlg [IN] Dialog window handle.
  31. // nIDC [IN] ID of control to get value from.
  32. // rstrValue [IN OUT] String in which to return value.
  33. //
  34. // Return Value:
  35. // TRUE Value retrieved successfully.
  36. // FALSE Error retrieving value.
  37. //
  38. //--
  39. /////////////////////////////////////////////////////////////////////////////
  40. BOOL DDX_GetText(
  41. IN HWND hwndDlg,
  42. IN int nIDC,
  43. IN OUT CString & rstrValue
  44. )
  45. {
  46. ATLASSERT( hwndDlg != NULL );
  47. //
  48. // Get the handle for the control.
  49. //
  50. HWND hwndCtrl = GetDlgItem( hwndDlg, nIDC );
  51. ATLASSERT( hwndCtrl != NULL );
  52. //
  53. // Get the text from the control.
  54. //
  55. int cch = GetWindowTextLength( hwndCtrl );
  56. if ( cch == 0 )
  57. {
  58. rstrValue = _T("");
  59. } // if: edit control is empty
  60. else
  61. {
  62. LPTSTR pszValue = rstrValue.GetBuffer( cch + 1 );
  63. ATLASSERT( pszValue != NULL );
  64. int cchRet = GetWindowText( hwndCtrl, pszValue, cch + 1 );
  65. ATLASSERT( cchRet > 0 );
  66. rstrValue.ReleaseBuffer();
  67. } // else: length of text retrieved
  68. return TRUE;
  69. } //*** DDX_GetText()
  70. /////////////////////////////////////////////////////////////////////////////
  71. //++
  72. //
  73. // DDX_SetText
  74. //
  75. // Routine Description:
  76. // Set a text value into a control on a dialog.
  77. //
  78. // Arguments:
  79. // hwndDlg [IN] Dialog window handle.
  80. // nIDC [IN] ID of control to set value to.
  81. // rstrValue [IN] String to set into the dialog.
  82. //
  83. // Return Value:
  84. // TRUE Value set successfully.
  85. // FALSE Error setting value.
  86. //
  87. //--
  88. /////////////////////////////////////////////////////////////////////////////
  89. BOOL DDX_SetText(
  90. IN HWND hwndDlg,
  91. IN int nIDC,
  92. IN const CString & rstrValue
  93. )
  94. {
  95. ATLASSERT( hwndDlg != NULL );
  96. //
  97. // Set the text into the control.
  98. //
  99. BOOL bSuccess = SetDlgItemText( hwndDlg, nIDC, rstrValue );
  100. ATLASSERT( bSuccess );
  101. return bSuccess;
  102. } //*** DDX_SetText()
  103. /////////////////////////////////////////////////////////////////////////////
  104. //++
  105. //
  106. // DDX_SetComboBoxText
  107. //
  108. // Routine Description:
  109. // Set a text value into a control on a dialog.
  110. //
  111. // Arguments:
  112. // hwndDlg [IN] Dialog window handle.
  113. // nIDC [IN] ID of control to set value to.
  114. // rstrValue [IN] String to set into the dialog.
  115. // bRequired [IN] TRUE = text must already exist in the combobox.
  116. //
  117. // Return Value:
  118. // TRUE Value set successfully.
  119. // FALSE Error setting value.
  120. //
  121. //--
  122. /////////////////////////////////////////////////////////////////////////////
  123. BOOL DDX_SetComboBoxText(
  124. IN HWND hwndDlg,
  125. IN int nIDC,
  126. IN const CString & rstrValue,
  127. IN BOOL bRequired
  128. )
  129. {
  130. ATLASSERT( hwndDlg != NULL );
  131. BOOL bSuccess = TRUE;
  132. //
  133. // Get the handle for the control.
  134. //
  135. HWND hwndCtrl = GetDlgItem( hwndDlg, nIDC );
  136. ATLASSERT( hwndCtrl != NULL );
  137. #if DBG
  138. TCHAR szWindowClass[256];
  139. ::GetClassName( hwndCtrl, szWindowClass, (sizeof( szWindowClass ) / sizeof( TCHAR )) - 1 );
  140. ATLASSERT( lstrcmp( szWindowClass, _T("ComboBox") ) == 0 );
  141. #endif // DBG
  142. int idx = (int) SendMessage( hwndCtrl, CB_FINDSTRINGEXACT, -1, (LPARAM)(LPCTSTR) rstrValue );
  143. if ( idx != CB_ERR )
  144. {
  145. SendMessage( hwndCtrl, CB_SETCURSEL, idx, 0 );
  146. } // if: message sent successfully
  147. else
  148. {
  149. if ( bRequired )
  150. {
  151. ATLASSERT( idx != CB_ERR );
  152. } // if: string was supposed to be present already
  153. bSuccess = FALSE;
  154. } // else if: error sending message
  155. return bSuccess;
  156. } //*** DDX_SetComboBoxText()
  157. /////////////////////////////////////////////////////////////////////////////
  158. //++
  159. //
  160. // DDX_GetNumber
  161. //
  162. // Routine Description:
  163. // Get a numeric value from a control on a dialog.
  164. //
  165. // Arguments:
  166. // hwndDlg [IN] Dialog window handle.
  167. // nIDC [IN] ID of control to get value from.
  168. // rnValue [IN OUT] Number in which to return value.
  169. // nMin [IN] Minimum value.
  170. // nMax [IN] Maximum value.
  171. // bSigned [IN] TRUE = value is signed, FALSE = value is unsigned
  172. //
  173. // Return Value:
  174. // TRUE Value retrieved successfully.
  175. // FALSE Error retrieving value.
  176. //
  177. //--
  178. /////////////////////////////////////////////////////////////////////////////
  179. BOOL DDX_GetNumber(
  180. IN HWND hwndDlg,
  181. IN int nIDC,
  182. IN OUT ULONG & rnValue,
  183. IN ULONG nMin,
  184. IN ULONG nMax,
  185. IN BOOL bSigned
  186. )
  187. {
  188. ATLASSERT( hwndDlg != NULL );
  189. BOOL bSuccess = TRUE;
  190. BOOL bTranslated;
  191. ULONG nValue;
  192. //
  193. // Get the handle for the control.
  194. //
  195. HWND hwndCtrl = GetDlgItem( hwndDlg, nIDC );
  196. ATLASSERT( hwndCtrl != NULL );
  197. //
  198. // Get the number from the control.
  199. //
  200. nValue = GetDlgItemInt( hwndDlg, nIDC, &bTranslated, bSigned );
  201. //
  202. // If the retrival failed, it is a signed number, and the minimum
  203. // value is the smallest negative value possible, check the string itself.
  204. //
  205. if ( ! bTranslated && bSigned && (nMin == 0x80000000) )
  206. {
  207. UINT cch;
  208. TCHAR szNumber[20];
  209. //
  210. // See if it is the smallest negative number.
  211. //
  212. cch = GetWindowText( hwndCtrl, szNumber, sizeof( szNumber ) / sizeof(TCHAR ) );
  213. if ( (cch != 0) && (lstrcmp( szNumber, _T("-2147483648") ) == 0) )
  214. {
  215. nValue = 0x80000000;
  216. bTranslated = TRUE;
  217. } // if: text retrieved successfully and is highest negative number
  218. } // if: error translating number and getting signed number
  219. //
  220. // If the retrieval failed or the specified number is
  221. // out of range, display an error.
  222. //
  223. if ( ! bTranslated
  224. || (bSigned && (((LONG) nValue < (LONG) nMin) || ((LONG) nValue > (LONG) nMax)))
  225. || (! bSigned && ((nValue < nMin) || (nValue > nMax)))
  226. )
  227. {
  228. TCHAR szMin[32];
  229. TCHAR szMax[32];
  230. CString strPrompt;
  231. bSuccess = FALSE;
  232. if ( bSigned )
  233. {
  234. wsprintf( szMin, _T("%d%"), nMin );
  235. wsprintf( szMax, _T("%d%"), nMax );
  236. } // if: signed number
  237. else
  238. {
  239. wsprintf( szMin, _T("%u%"), nMin );
  240. wsprintf( szMax, _T("%u%"), nMax );
  241. } // else: unsigned number
  242. strPrompt.FormatMessage( IDP_PARSE_INT_RANGE, szMin, szMax );
  243. AppMessageBox( hwndDlg, strPrompt, MB_ICONEXCLAMATION );
  244. SetFocus( hwndCtrl );
  245. } // if: invalid string
  246. else
  247. {
  248. rnValue = nValue;
  249. } // else: valid string
  250. return bSuccess;
  251. } //*** DDX_GetNumber()
  252. /////////////////////////////////////////////////////////////////////////////
  253. //++
  254. //
  255. // DDX_GetNumber
  256. //
  257. // Routine Description:
  258. // Set a numeric value into a control on a dialog.
  259. //
  260. // Arguments:
  261. // hwndDlg [IN] Dialog window handle.
  262. // nIDC [IN] ID of control to get value from.
  263. // nValue [IN] Number value to set into the control.
  264. // nMin [IN] Minimum value.
  265. // nMax [IN] Maximum value.
  266. // bSigned [IN] TRUE = value is signed, FALSE = value is unsigned
  267. //
  268. // Return Value:
  269. // TRUE Value retrieved successfully.
  270. // FALSE Error retrieving value.
  271. //
  272. //--
  273. /////////////////////////////////////////////////////////////////////////////
  274. BOOL DDX_SetNumber(
  275. IN HWND hwndDlg,
  276. IN int nIDC,
  277. IN ULONG nValue,
  278. IN ULONG nMin,
  279. IN ULONG nMax,
  280. IN BOOL bSigned
  281. )
  282. {
  283. ATLASSERT( hwndDlg != NULL );
  284. CString strMinValue;
  285. CString strMaxValue;
  286. UINT cchMax;
  287. //
  288. // Get the handle for the control.
  289. //
  290. HWND hwndCtrl = GetDlgItem( hwndDlg, nIDC );
  291. ATLASSERT( hwndCtrl != NULL );
  292. //
  293. // Set the maximum number of characters that can be entered.
  294. //
  295. if ( bSigned )
  296. {
  297. strMinValue.Format( _T("%d"), nMin );
  298. strMaxValue.Format( _T("%d"), nMax );
  299. } // if: signed value
  300. else
  301. {
  302. strMinValue.Format( _T("%u"), nMin );
  303. strMaxValue.Format( _T("%u"), nMax );
  304. } // else: unsigned value
  305. cchMax = max( strMinValue.GetLength(), strMaxValue.GetLength() );
  306. SendMessage( hwndCtrl, EM_LIMITTEXT, cchMax, 0 );
  307. // Set the value into the control.
  308. BOOL bSuccess = SetDlgItemInt( hwndDlg, nIDC, nValue, bSigned );
  309. ATLASSERT( bSuccess );
  310. return bSuccess;
  311. } //*** DDX_SetNumber()
  312. /////////////////////////////////////////////////////////////////////////////
  313. //++
  314. //
  315. // DDV_RequiredText
  316. //
  317. // Routine Description:
  318. // Validate that the dialog string is present.
  319. //
  320. // Arguments:
  321. // hwndDlg [IN] Dialog window handle.
  322. // nIDC [IN] Control ID.
  323. // nIDCLabel [IN] Label control ID.
  324. // rstrValue [IN] Value to set or get.
  325. //
  326. // Return Value:
  327. // TRUE Required value is present.
  328. // FALSE Required value is not present.
  329. //
  330. //--
  331. /////////////////////////////////////////////////////////////////////////////
  332. BOOL DDV_RequiredText(
  333. IN HWND hwndDlg,
  334. IN int nIDC,
  335. IN int nIDCLabel,
  336. IN const CString & rstrValue
  337. )
  338. {
  339. ATLASSERT( hwndDlg != NULL );
  340. BOOL bSuccess = TRUE;
  341. BOOL bIsBlank;
  342. //
  343. // Get the handle for the control.
  344. //
  345. HWND hwndCtrl = GetDlgItem( hwndDlg, nIDC );
  346. ATLASSERT( hwndCtrl != NULL );
  347. //
  348. // Get the window class name.
  349. //
  350. TCHAR szWindowClass[256];
  351. GetClassName( hwndCtrl, szWindowClass, (sizeof( szWindowClass ) / sizeof( TCHAR )) - 1 );
  352. //
  353. // If this is the IP Address control, send a special message to
  354. // determine if it is empty or not.
  355. //
  356. if ( lstrcmp( szWindowClass, WC_IPADDRESS ) == 0 )
  357. {
  358. bIsBlank = SendMessage( hwndCtrl, IPM_ISBLANK, 0, 0 );
  359. } // if: IP Address control
  360. else
  361. {
  362. bIsBlank = rstrValue.GetLength() == 0;
  363. } // else: edit control
  364. if ( bIsBlank )
  365. {
  366. TCHAR szLabel[1024];
  367. bSuccess = FALSE;
  368. //
  369. // Get the text of the label.
  370. //
  371. GetDlgItemText( hwndDlg, nIDCLabel, szLabel, sizeof( szLabel ) / sizeof( TCHAR ) );
  372. //
  373. // Remove ampersands (&) and colons (:).
  374. //
  375. CleanupLabel( szLabel );
  376. //
  377. // Format and display a message.
  378. //
  379. CString strPrompt;
  380. strPrompt.FormatMessage( IDS_REQUIRED_FIELD_EMPTY, szLabel );
  381. AppMessageBox( hwndDlg, strPrompt, MB_ICONEXCLAMATION );
  382. //
  383. // Set focus to the control.
  384. HWND hwndCtrl = GetDlgItem( hwndDlg, nIDC );
  385. ATLASSERT( hwndCtrl != NULL );
  386. SetFocus( hwndCtrl );
  387. } // if: field not specified
  388. return bSuccess;
  389. } //*** DDV_RequiredText()
  390. /////////////////////////////////////////////////////////////////////////////
  391. //++
  392. //
  393. // CleanupLabel
  394. //
  395. // Routine Description:
  396. // Prepare a label read from a dialog to be used as a string in a
  397. // message by removing ampersands (&) and colons (:).
  398. //
  399. // Arguments:
  400. // pszLabel [IN OUT] Label to be cleaned up.
  401. //
  402. // Return Value:
  403. // None.
  404. //
  405. //--
  406. /////////////////////////////////////////////////////////////////////////////
  407. void CleanupLabel( IN OUT LPTSTR pszLabel )
  408. {
  409. LPTSTR pIn, pOut;
  410. LANGID langid;
  411. WORD primarylangid;
  412. BOOL bFELanguage;
  413. //
  414. // Get the language ID.
  415. //
  416. langid = GetUserDefaultLangID();
  417. primarylangid = (WORD) PRIMARYLANGID( langid );
  418. bFELanguage = ((primarylangid == LANG_JAPANESE)
  419. || (primarylangid == LANG_CHINESE)
  420. || (primarylangid == LANG_KOREAN));
  421. //
  422. // Copy the name sans '&' and ':' chars
  423. //
  424. pIn = pOut = pszLabel;
  425. do
  426. {
  427. //
  428. // Strip FE accelerators with parentheses. e.g. "foo(&F)" -> "foo"
  429. //
  430. if ( bFELanguage
  431. && (pIn[0] == _T('('))
  432. && (pIn[1] == _T('&'))
  433. && (pIn[2] != _T('\0'))
  434. && (pIn[3] == _T(')')))
  435. {
  436. pIn += 3;
  437. } // if: FE language and parenthesized hotkey present
  438. else if ( (*pIn != _T('&')) && (*pIn != _T(':')) )
  439. {
  440. *pOut++ = *pIn;
  441. } // if: found hotkey
  442. } while ( *pIn++ != _T('\0') ) ;
  443. } //*** CleanupLabel()
  444. /////////////////////////////////////////////////////////////////////////////
  445. //++
  446. //
  447. // DDV_GetCheck
  448. //
  449. // Routine Description:
  450. // Validate that the dialog string is present.
  451. //
  452. // Arguments:
  453. // hwndDlg [IN] Dialog window handle.
  454. // nIDC [IN] Control ID.
  455. // rnValue [OUT] Value to get.
  456. //
  457. // Return Value:
  458. // None.
  459. //
  460. //--
  461. /////////////////////////////////////////////////////////////////////////////
  462. void DDX_GetCheck( IN HWND hwndDlg, IN int nIDC, OUT int & rnValue )
  463. {
  464. ATLASSERT( hwndDlg != NULL );
  465. //
  466. // Get the handle for the control.
  467. //
  468. HWND hWndCtrl = GetDlgItem( hwndDlg, nIDC );
  469. ATLASSERT( hWndCtrl != NULL );
  470. rnValue = (int)::SendMessage( hWndCtrl, BM_GETCHECK, 0, 0L );
  471. ATLASSERT( (rnValue >= 0) && (rnValue <= 2) );
  472. } //*** DDX_GetCheck()
  473. /////////////////////////////////////////////////////////////////////////////
  474. //++
  475. //
  476. // DDX_SetCheck
  477. //
  478. // Routine Description:
  479. // Validate that the dialog string is present.
  480. //
  481. // Arguments:
  482. // hwndDlg [IN] Dialog window handle.
  483. // nIDC [IN] Control ID.
  484. // nValue [IN] Value to set.
  485. //
  486. // Return Value:
  487. // None.
  488. //
  489. //--
  490. /////////////////////////////////////////////////////////////////////////////
  491. void DDX_SetCheck( IN HWND hwndDlg, IN int nIDC, IN int nValue )
  492. {
  493. ATLASSERT( hwndDlg != NULL );
  494. //
  495. // Get the handle for the control.
  496. //
  497. HWND hWndCtrl = GetDlgItem( hwndDlg, nIDC );
  498. ATLASSERT( hWndCtrl != NULL );
  499. ATLASSERT( (nValue >= 0) && (nValue <= 2) );
  500. if ( (nValue < 0) || (nValue > 2) )
  501. {
  502. ATLTRACE( _T("Warning: dialog data checkbox value (%d) out of range.\n"), nValue );
  503. nValue = 0; // default to off
  504. } // if: value is out of range
  505. ::SendMessage( hWndCtrl, BM_SETCHECK, (WPARAM) nValue, 0L );
  506. } //*** DDX_SetCheck()
  507. /////////////////////////////////////////////////////////////////////////////
  508. //++
  509. //
  510. // DDX_GetRadio
  511. //
  512. // Routine Description:
  513. // Validate that the dialog string is present.
  514. //
  515. // Arguments:
  516. // hwndDlg [IN] Dialog window handle.
  517. // nIDC [IN] Control ID of first radio button in a group.
  518. // rnValue [OUT] Value to get.
  519. //
  520. // Return Value:
  521. // None.
  522. //
  523. //--
  524. /////////////////////////////////////////////////////////////////////////////
  525. void DDX_GetRadio( IN HWND hwndDlg, IN int nIDC, IN int & rnValue )
  526. {
  527. ATLASSERT( hwndDlg != NULL );
  528. //
  529. // Get the handle for the control.
  530. //
  531. HWND hWndCtrl = GetDlgItem( hwndDlg, nIDC );
  532. ATLASSERT( hWndCtrl != NULL );
  533. ATLASSERT( ::GetWindowLong( hWndCtrl, GWL_STYLE ) & WS_GROUP );
  534. ATLASSERT( ::SendMessage( hWndCtrl, WM_GETDLGCODE, 0, 0L ) & DLGC_RADIOBUTTON );
  535. rnValue = -1; // value if none found
  536. // walk all children in group
  537. int iButton = 0;
  538. do
  539. {
  540. if ( ::SendMessage( hWndCtrl, WM_GETDLGCODE, 0, 0L ) & DLGC_RADIOBUTTON )
  541. {
  542. // control in group is a radio button
  543. if ( ::SendMessage( hWndCtrl, BM_GETCHECK, 0, 0L ) != 0 )
  544. {
  545. ASSERT( rnValue == -1 ); // only set once
  546. rnValue = iButton;
  547. } // if: button is set
  548. iButton++;
  549. } // if: control is a radio button
  550. else
  551. {
  552. ATLTRACE( _T("Warning: skipping non-radio button in group.\n") );
  553. } // else: control is not a radio button
  554. hWndCtrl = ::GetWindow( hWndCtrl, GW_HWNDNEXT );
  555. } while ( hWndCtrl != NULL &&
  556. !(GetWindowLong( hWndCtrl, GWL_STYLE ) & WS_GROUP) );
  557. } //*** DDX_GetRadio()
  558. /////////////////////////////////////////////////////////////////////////////
  559. //++
  560. //
  561. // DDX_SetRadio
  562. //
  563. // Routine Description:
  564. // Validate that the dialog string is present.
  565. //
  566. // Arguments:
  567. // hwndDlg [IN] Dialog window handle.
  568. // nIDC [IN] Control ID of first radio button in a group.
  569. // nValue [IN] Value to set.
  570. //
  571. // Return Value:
  572. // None.
  573. //
  574. //--
  575. /////////////////////////////////////////////////////////////////////////////
  576. void DDX_SetRadio( IN HWND hwndDlg, IN int nIDC, IN int nValue )
  577. {
  578. ATLASSERT( hwndDlg != NULL );
  579. //
  580. // Get the handle for the control.
  581. //
  582. HWND hWndCtrl = GetDlgItem( hwndDlg, nIDC );
  583. ATLASSERT( hWndCtrl != NULL );
  584. ATLASSERT( ::GetWindowLong( hWndCtrl, GWL_STYLE ) & WS_GROUP );
  585. ATLASSERT( ::SendMessage( hWndCtrl, WM_GETDLGCODE, 0, 0L ) & DLGC_RADIOBUTTON );
  586. // walk all children in group
  587. int iButton = 0;
  588. do
  589. {
  590. if ( ::SendMessage( hWndCtrl, WM_GETDLGCODE, 0, 0L ) & DLGC_RADIOBUTTON )
  591. {
  592. // control in group is a radio button
  593. // select button
  594. ::SendMessage( hWndCtrl, BM_SETCHECK, (iButton == nValue), 0L );
  595. iButton++;
  596. } // if: control is a radio button
  597. else
  598. {
  599. ATLTRACE( _T("Warning: skipping non-radio button in group.\n") );
  600. } // else: control is not a radio button
  601. hWndCtrl = ::GetWindow( hWndCtrl, GW_HWNDNEXT );
  602. } while ( (hWndCtrl != NULL)
  603. && ! (GetWindowLong( hWndCtrl, GWL_STYLE ) & WS_GROUP) );
  604. } //*** DDX_SetRadio()