dlgdata.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #include "occimpl.h"
  12. #ifdef AFX_CORE3_SEG
  13. #pragma code_seg(AFX_CORE3_SEG)
  14. #endif
  15. #ifdef _DEBUG
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CDataExchange member functions (contructor is in wincore.cpp for swap tuning)
  21. HWND CDataExchange::PrepareEditCtrl(int nIDC)
  22. {
  23. HWND hWndCtrl = PrepareCtrl(nIDC);
  24. ASSERT(hWndCtrl != NULL);
  25. m_bEditLastControl = TRUE;
  26. return hWndCtrl;
  27. }
  28. HWND CDataExchange::PrepareCtrl(int nIDC)
  29. {
  30. ASSERT(nIDC != 0);
  31. ASSERT(nIDC != -1); // not allowed
  32. HWND hWndCtrl;
  33. m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);
  34. if (hWndCtrl == NULL)
  35. {
  36. TRACE1("Error: no data exchange control with ID 0x%04X.\n", nIDC);
  37. ASSERT(FALSE);
  38. AfxThrowNotSupportedException();
  39. }
  40. m_hWndLastControl = hWndCtrl;
  41. m_bEditLastControl = FALSE; // not an edit item by default
  42. ASSERT(hWndCtrl != NULL); // never return NULL handle
  43. return hWndCtrl;
  44. }
  45. void CDataExchange::Fail()
  46. {
  47. if (!m_bSaveAndValidate)
  48. {
  49. TRACE0("Warning: CDataExchange::Fail called when not validating.\n");
  50. // throw the exception anyway
  51. }
  52. else if (m_hWndLastControl != NULL)
  53. {
  54. // restore focus and selection to offending field
  55. ::SetFocus(m_hWndLastControl);
  56. if (m_bEditLastControl) // select edit item
  57. ::SendMessage(m_hWndLastControl, EM_SETSEL, 0, -1);
  58. }
  59. else
  60. {
  61. TRACE0("Error: fail validation with no control to restore focus to.\n");
  62. // do nothing more
  63. }
  64. AfxThrowUserException();
  65. }
  66. /////////////////////////////////////////////////////////////////////////////
  67. // Notes for implementing dialog data exchange and validation procs:
  68. // * always start with PrepareCtrl or PrepareEditCtrl
  69. // * always start with 'pDX->m_bSaveAndValidate' check
  70. // * pDX->Fail() will throw an exception - so be prepared
  71. // * avoid creating temporary HWNDs for dialog controls - i.e.
  72. // use HWNDs for child elements
  73. // * validation procs should only act if 'm_bSaveAndValidate'
  74. // * use the suffices:
  75. // DDX_ = exchange proc
  76. // DDV_ = validation proc
  77. //
  78. /////////////////////////////////////////////////////////////////////////////
  79. // only supports '%d', '%u', '%sd', '%su', '%ld' and '%lu'
  80. AFX_STATIC BOOL AFXAPI _AfxSimpleScanf(LPCTSTR lpszText,
  81. LPCTSTR lpszFormat, va_list pData)
  82. {
  83. ASSERT(lpszText != NULL);
  84. ASSERT(lpszFormat != NULL);
  85. ASSERT(*lpszFormat == '%');
  86. lpszFormat++; // skip '%'
  87. BOOL bLong = FALSE;
  88. BOOL bShort = FALSE;
  89. if (*lpszFormat == 'l')
  90. {
  91. bLong = TRUE;
  92. lpszFormat++;
  93. }
  94. else if (*lpszFormat == 's')
  95. {
  96. bShort = TRUE;
  97. lpszFormat++;
  98. }
  99. ASSERT(*lpszFormat == 'd' || *lpszFormat == 'u');
  100. ASSERT(lpszFormat[1] == '\0');
  101. while (*lpszText == ' ' || *lpszText == '\t')
  102. lpszText++;
  103. TCHAR chFirst = lpszText[0];
  104. long l, l2;
  105. if (*lpszFormat == 'd')
  106. {
  107. // signed
  108. l = _tcstol(lpszText, (LPTSTR*)&lpszText, 10);
  109. l2 = (int)l;
  110. }
  111. else
  112. {
  113. // unsigned
  114. if (*lpszText == '-')
  115. return FALSE;
  116. l = (long)_tcstoul(lpszText, (LPTSTR*)&lpszText, 10);
  117. l2 = (unsigned int)l;
  118. }
  119. if (l == 0 && chFirst != '0')
  120. return FALSE; // could not convert
  121. while (*lpszText == ' ' || *lpszText == '\t')
  122. lpszText++;
  123. if (*lpszText != '\0')
  124. return FALSE; // not terminated properly
  125. if (bShort)
  126. {
  127. if ((short)l != l)
  128. return FALSE; // too big for short
  129. *va_arg(pData, short*) = (short)l;
  130. }
  131. else
  132. {
  133. ASSERT(sizeof(long) == sizeof(int));
  134. ASSERT(l == l2);
  135. *va_arg(pData, long*) = l;
  136. }
  137. // all ok
  138. return TRUE;
  139. }
  140. AFX_STATIC void AFX_CDECL _Afx_DDX_TextWithFormat(CDataExchange* pDX, int nIDC,
  141. LPCTSTR lpszFormat, UINT nIDPrompt, ...)
  142. // only supports windows output formats - no floating point
  143. {
  144. va_list pData;
  145. va_start(pData, nIDPrompt);
  146. HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
  147. TCHAR szT[32];
  148. if (pDX->m_bSaveAndValidate)
  149. {
  150. // the following works for %d, %u, %ld, %lu
  151. ::GetWindowText(hWndCtrl, szT, _countof(szT));
  152. if (!_AfxSimpleScanf(szT, lpszFormat, pData))
  153. {
  154. AfxMessageBox(nIDPrompt);
  155. pDX->Fail(); // throws exception
  156. }
  157. }
  158. else
  159. {
  160. wvsprintf(szT, lpszFormat, pData);
  161. // does not support floating point numbers - see dlgfloat.cpp
  162. AfxSetWindowText(hWndCtrl, szT);
  163. }
  164. va_end(pData);
  165. }
  166. /////////////////////////////////////////////////////////////////////////////
  167. // Simple formatting to text item
  168. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, BYTE& value)
  169. {
  170. int n = (int)value;
  171. if (pDX->m_bSaveAndValidate)
  172. {
  173. _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%u"), AFX_IDP_PARSE_BYTE, &n);
  174. if (n > 255)
  175. {
  176. AfxMessageBox(AFX_IDP_PARSE_BYTE);
  177. pDX->Fail(); // throws exception
  178. }
  179. value = (BYTE)n;
  180. }
  181. else
  182. _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%u"), AFX_IDP_PARSE_BYTE, n);
  183. }
  184. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, short& value)
  185. {
  186. if (pDX->m_bSaveAndValidate)
  187. _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%sd"), AFX_IDP_PARSE_INT, &value);
  188. else
  189. _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%hd"), AFX_IDP_PARSE_INT, value);
  190. }
  191. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, int& value)
  192. {
  193. if (pDX->m_bSaveAndValidate)
  194. _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%d"), AFX_IDP_PARSE_INT, &value);
  195. else
  196. _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%d"), AFX_IDP_PARSE_INT, value);
  197. }
  198. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, UINT& value)
  199. {
  200. if (pDX->m_bSaveAndValidate)
  201. _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%u"), AFX_IDP_PARSE_UINT, &value);
  202. else
  203. _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%u"), AFX_IDP_PARSE_UINT, value);
  204. }
  205. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, long& value)
  206. {
  207. if (pDX->m_bSaveAndValidate)
  208. _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%ld"), AFX_IDP_PARSE_INT, &value);
  209. else
  210. _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%ld"), AFX_IDP_PARSE_INT, value);
  211. }
  212. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, DWORD& value)
  213. {
  214. if (pDX->m_bSaveAndValidate)
  215. _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%lu"), AFX_IDP_PARSE_UINT, &value);
  216. else
  217. _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%lu"), AFX_IDP_PARSE_UINT, value);
  218. }
  219. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, CString& value)
  220. {
  221. HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
  222. if (pDX->m_bSaveAndValidate)
  223. {
  224. int nLen = ::GetWindowTextLength(hWndCtrl);
  225. ::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1);
  226. value.ReleaseBuffer();
  227. }
  228. else
  229. {
  230. AfxSetWindowText(hWndCtrl, value);
  231. }
  232. }
  233. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, LPTSTR value, int nMaxLen)
  234. {
  235. ASSERT(nMaxLen != 0);
  236. HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
  237. if (pDX->m_bSaveAndValidate)
  238. {
  239. int nLen = ::GetWindowTextLength(hWndCtrl);
  240. int nRetrieved = ::GetWindowText(hWndCtrl, value, nMaxLen);
  241. if (nLen > nRetrieved)
  242. TRACE1("Text in control ID %d is too long. Call DDV_MaxChars()!\n", nIDC);
  243. }
  244. else
  245. {
  246. AfxSetWindowText(hWndCtrl, value);
  247. }
  248. }
  249. /////////////////////////////////////////////////////////////////////////////
  250. // Data exchange for special control
  251. void AFXAPI DDX_Check(CDataExchange* pDX, int nIDC, int& value)
  252. {
  253. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  254. if (pDX->m_bSaveAndValidate)
  255. {
  256. value = (int)::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L);
  257. ASSERT(value >= 0 && value <= 2);
  258. }
  259. else
  260. {
  261. if (value < 0 || value > 2)
  262. {
  263. TRACE1("Warning: dialog data checkbox value (%d) out of range.\n",
  264. value);
  265. value = 0; // default to off
  266. }
  267. ::SendMessage(hWndCtrl, BM_SETCHECK, (WPARAM)value, 0L);
  268. }
  269. }
  270. void AFXAPI DDX_Radio(CDataExchange* pDX, int nIDC, int& value)
  271. // must be first in a group of auto radio buttons
  272. {
  273. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  274. ASSERT(::GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP);
  275. ASSERT(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON);
  276. if (pDX->m_bSaveAndValidate)
  277. value = -1; // value if none found
  278. // walk all children in group
  279. int iButton = 0;
  280. do
  281. {
  282. if (::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON)
  283. {
  284. // control in group is a radio button
  285. if (pDX->m_bSaveAndValidate)
  286. {
  287. if (::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L) != 0)
  288. {
  289. ASSERT(value == -1); // only set once
  290. value = iButton;
  291. }
  292. }
  293. else
  294. {
  295. // select button
  296. ::SendMessage(hWndCtrl, BM_SETCHECK, (iButton == value), 0L);
  297. }
  298. iButton++;
  299. }
  300. else
  301. {
  302. TRACE0("Warning: skipping non-radio button in group.\n");
  303. }
  304. hWndCtrl = ::GetWindow(hWndCtrl, GW_HWNDNEXT);
  305. } while (hWndCtrl != NULL &&
  306. !(GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP));
  307. }
  308. /////////////////////////////////////////////////////////////////////////////
  309. // Listboxes, comboboxes
  310. void AFXAPI DDX_LBString(CDataExchange* pDX, int nIDC, CString& value)
  311. {
  312. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  313. if (pDX->m_bSaveAndValidate)
  314. {
  315. int nIndex = (int)::SendMessage(hWndCtrl, LB_GETCURSEL, 0, 0L);
  316. if (nIndex != -1)
  317. {
  318. int nLen = (int)::SendMessage(hWndCtrl, LB_GETTEXTLEN, nIndex, 0L);
  319. ::SendMessage(hWndCtrl, LB_GETTEXT, nIndex,
  320. (LPARAM)(LPVOID)value.GetBufferSetLength(nLen));
  321. }
  322. else
  323. {
  324. // no selection
  325. value.Empty();
  326. }
  327. value.ReleaseBuffer();
  328. }
  329. else
  330. {
  331. // set current selection based on data string
  332. if (::SendMessage(hWndCtrl, LB_SELECTSTRING, (WPARAM)-1,
  333. (LPARAM)(LPCTSTR)value) == LB_ERR)
  334. {
  335. // no selection match
  336. TRACE0("Warning: no listbox item selected.\n");
  337. }
  338. }
  339. }
  340. void AFXAPI DDX_LBStringExact(CDataExchange* pDX, int nIDC, CString& value)
  341. {
  342. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  343. if (pDX->m_bSaveAndValidate)
  344. {
  345. DDX_LBString(pDX, nIDC, value);
  346. }
  347. else
  348. {
  349. // set current selection based on data string
  350. int i = (int)::SendMessage(hWndCtrl, LB_FINDSTRINGEXACT, (WPARAM)-1,
  351. (LPARAM)(LPCTSTR)value);
  352. if (i < 0)
  353. {
  354. // no selection match
  355. TRACE0("Warning: no listbox item selected.\n");
  356. }
  357. else
  358. {
  359. // select it
  360. SendMessage(hWndCtrl, LB_SETCURSEL, i, 0L);
  361. }
  362. }
  363. }
  364. void AFXAPI DDX_CBString(CDataExchange* pDX, int nIDC, CString& value)
  365. {
  366. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  367. if (pDX->m_bSaveAndValidate)
  368. {
  369. // just get current edit item text (or drop list static)
  370. int nLen = ::GetWindowTextLength(hWndCtrl);
  371. if (nLen > 0)
  372. {
  373. // get known length
  374. ::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1);
  375. }
  376. else
  377. {
  378. // for drop lists GetWindowTextLength does not work - assume
  379. // max of 255 characters
  380. ::GetWindowText(hWndCtrl, value.GetBuffer(255), 255+1);
  381. }
  382. value.ReleaseBuffer();
  383. }
  384. else
  385. {
  386. // set current selection based on model string
  387. if (::SendMessage(hWndCtrl, CB_SELECTSTRING, (WPARAM)-1,
  388. (LPARAM)(LPCTSTR)value) == CB_ERR)
  389. {
  390. // just set the edit text (will be ignored if DROPDOWNLIST)
  391. AfxSetWindowText(hWndCtrl, value);
  392. }
  393. }
  394. }
  395. void AFXAPI DDX_CBStringExact(CDataExchange* pDX, int nIDC, CString& value)
  396. {
  397. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  398. if (pDX->m_bSaveAndValidate)
  399. {
  400. DDX_CBString(pDX, nIDC, value);
  401. }
  402. else
  403. {
  404. // set current selection based on data string
  405. int i = (int)::SendMessage(hWndCtrl, CB_FINDSTRINGEXACT, (WPARAM)-1,
  406. (LPARAM)(LPCTSTR)value);
  407. if (i < 0)
  408. {
  409. // just set the edit text (will be ignored if DROPDOWNLIST)
  410. AfxSetWindowText(hWndCtrl, value);
  411. }
  412. else
  413. {
  414. // select it
  415. SendMessage(hWndCtrl, CB_SETCURSEL, i, 0L);
  416. }
  417. }
  418. }
  419. void AFXAPI DDX_LBIndex(CDataExchange* pDX, int nIDC, int& index)
  420. {
  421. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  422. if (pDX->m_bSaveAndValidate)
  423. index = (int)::SendMessage(hWndCtrl, LB_GETCURSEL, 0, 0L);
  424. else
  425. ::SendMessage(hWndCtrl, LB_SETCURSEL, (WPARAM)index, 0L);
  426. }
  427. void AFXAPI DDX_CBIndex(CDataExchange* pDX, int nIDC, int& index)
  428. {
  429. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  430. if (pDX->m_bSaveAndValidate)
  431. index = (int)::SendMessage(hWndCtrl, CB_GETCURSEL, 0, 0L);
  432. else
  433. ::SendMessage(hWndCtrl, CB_SETCURSEL, (WPARAM)index, 0L);
  434. }
  435. void AFXAPI DDX_Scroll(CDataExchange* pDX, int nIDC, int& value)
  436. {
  437. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  438. if (pDX->m_bSaveAndValidate)
  439. value = GetScrollPos(hWndCtrl, SB_CTL);
  440. else
  441. SetScrollPos(hWndCtrl, SB_CTL, value, TRUE);
  442. }
  443. void AFXAPI DDX_Slider(CDataExchange* pDX, int nIDC, int& value)
  444. {
  445. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  446. if (pDX->m_bSaveAndValidate)
  447. value = (int) ::SendMessage(hWndCtrl, TBM_GETPOS, 0, 0l);
  448. else
  449. ::SendMessage(hWndCtrl, TBM_SETPOS, TRUE, value);
  450. }
  451. /////////////////////////////////////////////////////////////////////////////
  452. // Range Dialog Data Validation
  453. AFX_STATIC void AFXAPI _AfxFailMinMaxWithFormat(CDataExchange* pDX,
  454. long minVal, long maxVal, LPCTSTR lpszFormat, UINT nIDPrompt)
  455. // error string must have '%1' and '%2' strings for min and max values
  456. // wsprintf formatting uses long values (format should be '%ld' or '%lu')
  457. {
  458. ASSERT(lpszFormat != NULL);
  459. if (!pDX->m_bSaveAndValidate)
  460. {
  461. TRACE0("Warning: initial dialog data is out of range.\n");
  462. return; // don't stop now
  463. }
  464. TCHAR szMin[32];
  465. TCHAR szMax[32];
  466. wsprintf(szMin, lpszFormat, minVal);
  467. wsprintf(szMax, lpszFormat, maxVal);
  468. CString prompt;
  469. AfxFormatString2(prompt, nIDPrompt, szMin, szMax);
  470. AfxMessageBox(prompt, MB_ICONEXCLAMATION, nIDPrompt);
  471. prompt.Empty(); // exception prep
  472. pDX->Fail();
  473. }
  474. //NOTE: don't use overloaded function names to avoid type ambiguities
  475. void AFXAPI DDV_MinMaxByte(CDataExchange* pDX, BYTE value, BYTE minVal, BYTE maxVal)
  476. {
  477. ASSERT(minVal <= maxVal);
  478. if (value < minVal || value > maxVal)
  479. _AfxFailMinMaxWithFormat(pDX, (long)minVal, (long)maxVal, _T("%u"),
  480. AFX_IDP_PARSE_INT_RANGE);
  481. }
  482. void AFXAPI DDV_MinMaxShort(CDataExchange* pDX, short value, short minVal, short maxVal)
  483. {
  484. ASSERT(minVal <= maxVal);
  485. if (value < minVal || value > maxVal)
  486. _AfxFailMinMaxWithFormat(pDX, (long)minVal, (long)maxVal, _T("%ld"),
  487. AFX_IDP_PARSE_INT_RANGE);
  488. }
  489. void AFXAPI DDV_MinMaxInt(CDataExchange* pDX, int value, int minVal, int maxVal)
  490. {
  491. ASSERT(minVal <= maxVal);
  492. if (value < minVal || value > maxVal)
  493. _AfxFailMinMaxWithFormat(pDX, (long)minVal, (long)maxVal, _T("%ld"),
  494. AFX_IDP_PARSE_INT_RANGE);
  495. }
  496. void AFXAPI DDV_MinMaxLong(CDataExchange* pDX, long value, long minVal, long maxVal)
  497. {
  498. ASSERT(minVal <= maxVal);
  499. if (value < minVal || value > maxVal)
  500. _AfxFailMinMaxWithFormat(pDX, (long)minVal, (long)maxVal, _T("%ld"),
  501. AFX_IDP_PARSE_INT_RANGE);
  502. }
  503. void AFXAPI DDV_MinMaxUInt(CDataExchange* pDX, UINT value, UINT minVal, UINT maxVal)
  504. {
  505. ASSERT(minVal <= maxVal);
  506. if (value < minVal || value > maxVal)
  507. _AfxFailMinMaxWithFormat(pDX, (long)minVal, (long)maxVal, _T("%lu"),
  508. AFX_IDP_PARSE_INT_RANGE);
  509. }
  510. void AFXAPI DDV_MinMaxDWord(CDataExchange* pDX, DWORD value, DWORD minVal, DWORD maxVal)
  511. {
  512. ASSERT(minVal <= maxVal);
  513. if (value < minVal || value > maxVal)
  514. _AfxFailMinMaxWithFormat(pDX, (long)minVal, (long)maxVal, _T("%lu"),
  515. AFX_IDP_PARSE_INT_RANGE);
  516. }
  517. void AFXAPI DDV_MinMaxSlider(CDataExchange* pDX, DWORD value, DWORD minVal, DWORD maxVal)
  518. {
  519. ASSERT(minVal <= maxVal);
  520. if (!pDX->m_bSaveAndValidate)
  521. {
  522. if (minVal > value || maxVal < value)
  523. {
  524. #ifdef _DEBUG
  525. int nIDC = GetWindowLong(pDX->m_hWndLastControl, GWL_ID);
  526. TRACE1("Warning: initial dialog data is out of range in control ID %d.\n", nIDC);
  527. #endif
  528. return; // don't stop now
  529. }
  530. }
  531. ::SendMessage(pDX->m_hWndLastControl, TBM_SETRANGEMIN, FALSE, (LPARAM) minVal);
  532. ::SendMessage(pDX->m_hWndLastControl, TBM_SETRANGEMIN, TRUE, (LPARAM) maxVal);
  533. }
  534. /////////////////////////////////////////////////////////////////////////////
  535. // Max Chars Dialog Data Validation
  536. void AFXAPI DDV_MaxChars(CDataExchange* pDX, CString const& value, int nChars)
  537. {
  538. ASSERT(nChars >= 1); // allow them something
  539. if (pDX->m_bSaveAndValidate && value.GetLength() > nChars)
  540. {
  541. TCHAR szT[32];
  542. wsprintf(szT, _T("%d"), nChars);
  543. CString prompt;
  544. AfxFormatString1(prompt, AFX_IDP_PARSE_STRING_SIZE, szT);
  545. AfxMessageBox(prompt, MB_ICONEXCLAMATION, AFX_IDP_PARSE_STRING_SIZE);
  546. prompt.Empty(); // exception prep
  547. pDX->Fail();
  548. }
  549. else if (pDX->m_hWndLastControl != NULL && pDX->m_bEditLastControl)
  550. {
  551. // limit the control max-chars automatically
  552. ::SendMessage(pDX->m_hWndLastControl, EM_LIMITTEXT, nChars, 0);
  553. }
  554. }
  555. /////////////////////////////////////////////////////////////////////////////
  556. // Special DDX_ proc for subclassing controls
  557. void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl)
  558. {
  559. if (rControl.m_hWnd == NULL) // not subclassed yet
  560. {
  561. ASSERT(!pDX->m_bSaveAndValidate);
  562. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  563. if (!rControl.SubclassWindow(hWndCtrl))
  564. {
  565. ASSERT(FALSE); // possibly trying to subclass twice?
  566. AfxThrowNotSupportedException();
  567. }
  568. #ifndef _AFX_NO_OCC_SUPPORT
  569. else
  570. {
  571. // If the control has reparented itself (e.g., invisible control),
  572. // make sure that the CWnd gets properly wired to its control site.
  573. if (pDX->m_pDlgWnd->m_hWnd != ::GetParent(rControl.m_hWnd))
  574. rControl.AttachControlSite(pDX->m_pDlgWnd);
  575. }
  576. #endif //!_AFX_NO_OCC_SUPPORT
  577. }
  578. }
  579. /////////////////////////////////////////////////////////////////////////////
  580. // Global failure dialog helpers (used by database classes)
  581. void AFXAPI AfxFailMaxChars(CDataExchange* pDX, int nChars)
  582. {
  583. TCHAR lpszTemp[32];
  584. wsprintf(lpszTemp, _T("%d"), nChars);
  585. CString prompt;
  586. AfxFormatString1(prompt, AFX_IDP_PARSE_STRING_SIZE, lpszTemp);
  587. AfxMessageBox(prompt, MB_ICONEXCLAMATION, AFX_IDP_PARSE_STRING_SIZE);
  588. prompt.Empty(); // exception prep
  589. pDX->Fail();
  590. }
  591. void AFXAPI AfxFailRadio(CDataExchange* pDX)
  592. {
  593. CString prompt;
  594. AfxFormatStrings(prompt, AFX_IDP_PARSE_RADIO_BUTTON, NULL, 0);
  595. AfxMessageBox(prompt, MB_ICONEXCLAMATION, AFX_IDP_PARSE_RADIO_BUTTON);
  596. prompt.Empty(); // exception prep
  597. pDX->Fail();
  598. }
  599. /////////////////////////////////////////////////////////////////////////////