OLD | NEW |
| (Empty) |
1 // Windows Template Library - WTL version 8.0 | |
2 // Copyright (C) Microsoft Corporation. All rights reserved. | |
3 // | |
4 // This file is a part of the Windows Template Library. | |
5 // The use and distribution terms for this software are covered by the | |
6 // Microsoft Permissive License (Ms-PL) which can be found in the file | |
7 // Ms-PL.txt at the root of this distribution. | |
8 | |
9 #ifndef __ATLDDX_H__ | |
10 #define __ATLDDX_H__ | |
11 | |
12 #pragma once | |
13 | |
14 #ifndef __cplusplus | |
15 #error ATL requires C++ compilation (use a .cpp suffix) | |
16 #endif | |
17 | |
18 #ifndef __ATLAPP_H__ | |
19 #error atlddx.h requires atlapp.h to be included first | |
20 #endif | |
21 | |
22 #if defined(_ATL_USE_DDX_FLOAT) && defined(_ATL_MIN_CRT) | |
23 #error Cannot use floating point DDX with _ATL_MIN_CRT defined | |
24 #endif // defined(_ATL_USE_DDX_FLOAT) && defined(_ATL_MIN_CRT) | |
25 | |
26 #ifdef _ATL_USE_DDX_FLOAT | |
27 #include <float.h> | |
28 #endif // _ATL_USE_DDX_FLOAT | |
29 | |
30 | |
31 /////////////////////////////////////////////////////////////////////////////// | |
32 // Classes in this file: | |
33 // | |
34 // CWinDataExchange<T> | |
35 | |
36 | |
37 namespace WTL | |
38 { | |
39 | |
40 // Constants | |
41 #define DDX_LOAD FALSE | |
42 #define DDX_SAVE TRUE | |
43 | |
44 // DDX map macros | |
45 #define BEGIN_DDX_MAP(thisClass) \ | |
46 BOOL DoDataExchange(BOOL bSaveAndValidate = FALSE, UINT nCtlID = (UINT)-
1) \ | |
47 { \ | |
48 bSaveAndValidate; \ | |
49 nCtlID; | |
50 | |
51 #define DDX_TEXT(nID, var) \ | |
52 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
53 { \ | |
54 if(!DDX_Text(nID, var, sizeof(var), bSaveAndValidate)) \ | |
55 return FALSE; \ | |
56 } | |
57 | |
58 #define DDX_TEXT_LEN(nID, var, len) \ | |
59 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
60 { \ | |
61 if(!DDX_Text(nID, var, sizeof(var), bSaveAndValidate, TR
UE, len)) \ | |
62 return FALSE; \ | |
63 } | |
64 | |
65 #define DDX_INT(nID, var) \ | |
66 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
67 { \ | |
68 if(!DDX_Int(nID, var, TRUE, bSaveAndValidate)) \ | |
69 return FALSE; \ | |
70 } | |
71 | |
72 #define DDX_INT_RANGE(nID, var, min, max) \ | |
73 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
74 { \ | |
75 if(!DDX_Int(nID, var, TRUE, bSaveAndValidate, TRUE, min,
max)) \ | |
76 return FALSE; \ | |
77 } | |
78 | |
79 #define DDX_UINT(nID, var) \ | |
80 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
81 { \ | |
82 if(!DDX_Int(nID, var, FALSE, bSaveAndValidate)) \ | |
83 return FALSE; \ | |
84 } | |
85 | |
86 #define DDX_UINT_RANGE(nID, var, min, max) \ | |
87 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
88 { \ | |
89 if(!DDX_Int(nID, var, FALSE, bSaveAndValidate, TRUE, min
, max)) \ | |
90 return FALSE; \ | |
91 } | |
92 | |
93 #ifdef _ATL_USE_DDX_FLOAT | |
94 #define DDX_FLOAT(nID, var) \ | |
95 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
96 { \ | |
97 if(!DDX_Float(nID, var, bSaveAndValidate)) \ | |
98 return FALSE; \ | |
99 } | |
100 | |
101 #define DDX_FLOAT_RANGE(nID, var, min, max) \ | |
102 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
103 { \ | |
104 if(!DDX_Float(nID, var, bSaveAndValidate, TRUE, min, max
)) \ | |
105 return FALSE; \ | |
106 } | |
107 #define DDX_FLOAT_P(nID, var, precision) \ | |
108 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
109 { \ | |
110 if(!DDX_Float(nID, var, bSaveAndValidate, FALSE, 0, 0, p
recision)) \ | |
111 return FALSE; \ | |
112 } | |
113 | |
114 #define DDX_FLOAT_P_RANGE(nID, var, min, max, precision) \ | |
115 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
116 { \ | |
117 if(!DDX_Float(nID, var, bSaveAndValidate, TRUE, min, max
, precision)) \ | |
118 return FALSE; \ | |
119 } | |
120 #endif // _ATL_USE_DDX_FLOAT | |
121 | |
122 #define DDX_CONTROL(nID, obj) \ | |
123 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
124 DDX_Control(nID, obj, bSaveAndValidate); | |
125 | |
126 #define DDX_CONTROL_HANDLE(nID, obj) \ | |
127 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
128 DDX_Control_Handle(nID, obj, bSaveAndValidate); | |
129 | |
130 #define DDX_CHECK(nID, var) \ | |
131 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
132 DDX_Check(nID, var, bSaveAndValidate); | |
133 | |
134 #define DDX_RADIO(nID, var) \ | |
135 if(nCtlID == (UINT)-1 || nCtlID == nID) \ | |
136 DDX_Radio(nID, var, bSaveAndValidate); | |
137 | |
138 #define END_DDX_MAP() \ | |
139 return TRUE; \ | |
140 } | |
141 | |
142 | |
143 /////////////////////////////////////////////////////////////////////////////// | |
144 // CWinDataExchange - provides support for DDX | |
145 | |
146 template <class T> | |
147 class CWinDataExchange | |
148 { | |
149 public: | |
150 // Data exchange method - override in your derived class | |
151 BOOL DoDataExchange(BOOL /*bSaveAndValidate*/ = FALSE, UINT /*nCtlID*/ =
(UINT)-1) | |
152 { | |
153 // this one should never be called, override it in | |
154 // your derived class by implementing DDX map | |
155 ATLASSERT(FALSE); | |
156 return FALSE; | |
157 } | |
158 | |
159 // Helpers for validation error reporting | |
160 enum _XDataType | |
161 { | |
162 ddxDataNull = 0, | |
163 ddxDataText = 1, | |
164 ddxDataInt = 2, | |
165 ddxDataFloat = 3, | |
166 ddxDataDouble = 4 | |
167 }; | |
168 | |
169 struct _XTextData | |
170 { | |
171 int nLength; | |
172 int nMaxLength; | |
173 }; | |
174 | |
175 struct _XIntData | |
176 { | |
177 long nVal; | |
178 long nMin; | |
179 long nMax; | |
180 }; | |
181 | |
182 struct _XFloatData | |
183 { | |
184 double nVal; | |
185 double nMin; | |
186 double nMax; | |
187 }; | |
188 | |
189 struct _XData | |
190 { | |
191 _XDataType nDataType; | |
192 union | |
193 { | |
194 _XTextData textData; | |
195 _XIntData intData; | |
196 _XFloatData floatData; | |
197 }; | |
198 }; | |
199 | |
200 // Text exchange | |
201 BOOL DDX_Text(UINT nID, LPTSTR lpstrText, int cbSize, BOOL bSave, BOOL b
Validate = FALSE, int nLength = 0) | |
202 { | |
203 T* pT = static_cast<T*>(this); | |
204 BOOL bSuccess = TRUE; | |
205 | |
206 if(bSave) | |
207 { | |
208 HWND hWndCtrl = pT->GetDlgItem(nID); | |
209 int nRetLen = ::GetWindowText(hWndCtrl, lpstrText, cbSiz
e / sizeof(TCHAR)); | |
210 if(nRetLen < ::GetWindowTextLength(hWndCtrl)) | |
211 bSuccess = FALSE; | |
212 } | |
213 else | |
214 { | |
215 ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength); | |
216 bSuccess = pT->SetDlgItemText(nID, lpstrText); | |
217 } | |
218 | |
219 if(!bSuccess) | |
220 { | |
221 pT->OnDataExchangeError(nID, bSave); | |
222 } | |
223 else if(bSave && bValidate) // validation | |
224 { | |
225 ATLASSERT(nLength > 0); | |
226 if(lstrlen(lpstrText) > nLength) | |
227 { | |
228 _XData data = { ddxDataText }; | |
229 data.textData.nLength = lstrlen(lpstrText); | |
230 data.textData.nMaxLength = nLength; | |
231 pT->OnDataValidateError(nID, bSave, data); | |
232 bSuccess = FALSE; | |
233 } | |
234 } | |
235 return bSuccess; | |
236 } | |
237 | |
238 BOOL DDX_Text(UINT nID, BSTR& bstrText, int /*cbSize*/, BOOL bSave, BOOL
bValidate = FALSE, int nLength = 0) | |
239 { | |
240 T* pT = static_cast<T*>(this); | |
241 BOOL bSuccess = TRUE; | |
242 | |
243 if(bSave) | |
244 { | |
245 bSuccess = pT->GetDlgItemText(nID, bstrText); | |
246 } | |
247 else | |
248 { | |
249 USES_CONVERSION; | |
250 LPTSTR lpstrText = OLE2T(bstrText); | |
251 ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength); | |
252 bSuccess = pT->SetDlgItemText(nID, lpstrText); | |
253 } | |
254 | |
255 if(!bSuccess) | |
256 { | |
257 pT->OnDataExchangeError(nID, bSave); | |
258 } | |
259 else if(bSave && bValidate) // validation | |
260 { | |
261 ATLASSERT(nLength > 0); | |
262 if((int)::SysStringLen(bstrText) > nLength) | |
263 { | |
264 _XData data = { ddxDataText }; | |
265 data.textData.nLength = (int)::SysStringLen(bstr
Text); | |
266 data.textData.nMaxLength = nLength; | |
267 pT->OnDataValidateError(nID, bSave, data); | |
268 bSuccess = FALSE; | |
269 } | |
270 } | |
271 return bSuccess; | |
272 } | |
273 | |
274 BOOL DDX_Text(UINT nID, ATL::CComBSTR& bstrText, int /*cbSize*/, BOOL bS
ave, BOOL bValidate = FALSE, int nLength = 0) | |
275 { | |
276 T* pT = static_cast<T*>(this); | |
277 BOOL bSuccess = TRUE; | |
278 | |
279 if(bSave) | |
280 { | |
281 bSuccess = pT->GetDlgItemText(nID, (BSTR&)bstrText); | |
282 } | |
283 else | |
284 { | |
285 USES_CONVERSION; | |
286 LPTSTR lpstrText = OLE2T(bstrText); | |
287 ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength); | |
288 bSuccess = pT->SetDlgItemText(nID, lpstrText); | |
289 } | |
290 | |
291 if(!bSuccess) | |
292 { | |
293 pT->OnDataExchangeError(nID, bSave); | |
294 } | |
295 else if(bSave && bValidate) // validation | |
296 { | |
297 ATLASSERT(nLength > 0); | |
298 if((int)bstrText.Length() > nLength) | |
299 { | |
300 _XData data = { ddxDataText }; | |
301 data.textData.nLength = (int)bstrText.Length(); | |
302 data.textData.nMaxLength = nLength; | |
303 pT->OnDataValidateError(nID, bSave, data); | |
304 bSuccess = FALSE; | |
305 } | |
306 } | |
307 return bSuccess; | |
308 } | |
309 | |
310 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) | |
311 BOOL DDX_Text(UINT nID, _CSTRING_NS::CString& strText, int /*cbSize*/, B
OOL bSave, BOOL bValidate = FALSE, int nLength = 0) | |
312 { | |
313 T* pT = static_cast<T*>(this); | |
314 BOOL bSuccess = TRUE; | |
315 | |
316 if(bSave) | |
317 { | |
318 HWND hWndCtrl = pT->GetDlgItem(nID); | |
319 int nLen = ::GetWindowTextLength(hWndCtrl); | |
320 int nRetLen = -1; | |
321 LPTSTR lpstr = strText.GetBufferSetLength(nLen); | |
322 if(lpstr != NULL) | |
323 { | |
324 nRetLen = ::GetWindowText(hWndCtrl, lpstr, nLen
+ 1); | |
325 strText.ReleaseBuffer(); | |
326 } | |
327 if(nRetLen < nLen) | |
328 bSuccess = FALSE; | |
329 } | |
330 else | |
331 { | |
332 bSuccess = pT->SetDlgItemText(nID, strText); | |
333 } | |
334 | |
335 if(!bSuccess) | |
336 { | |
337 pT->OnDataExchangeError(nID, bSave); | |
338 } | |
339 else if(bSave && bValidate) // validation | |
340 { | |
341 ATLASSERT(nLength > 0); | |
342 if(strText.GetLength() > nLength) | |
343 { | |
344 _XData data = { ddxDataText }; | |
345 data.textData.nLength = strText.GetLength(); | |
346 data.textData.nMaxLength = nLength; | |
347 pT->OnDataValidateError(nID, bSave, data); | |
348 bSuccess = FALSE; | |
349 } | |
350 } | |
351 return bSuccess; | |
352 } | |
353 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) | |
354 | |
355 // Numeric exchange | |
356 template <class Type> | |
357 BOOL DDX_Int(UINT nID, Type& nVal, BOOL bSigned, BOOL bSave, BOOL bValid
ate = FALSE, Type nMin = 0, Type nMax = 0) | |
358 { | |
359 T* pT = static_cast<T*>(this); | |
360 BOOL bSuccess = TRUE; | |
361 | |
362 if(bSave) | |
363 { | |
364 nVal = (Type)pT->GetDlgItemInt(nID, &bSuccess, bSigned); | |
365 } | |
366 else | |
367 { | |
368 ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax); | |
369 bSuccess = pT->SetDlgItemInt(nID, nVal, bSigned); | |
370 } | |
371 | |
372 if(!bSuccess) | |
373 { | |
374 pT->OnDataExchangeError(nID, bSave); | |
375 } | |
376 else if(bSave && bValidate) // validation | |
377 { | |
378 ATLASSERT(nMin != nMax); | |
379 if(nVal < nMin || nVal > nMax) | |
380 { | |
381 _XData data = { ddxDataInt }; | |
382 data.intData.nVal = (long)nVal; | |
383 data.intData.nMin = (long)nMin; | |
384 data.intData.nMax = (long)nMax; | |
385 pT->OnDataValidateError(nID, bSave, data); | |
386 bSuccess = FALSE; | |
387 } | |
388 } | |
389 return bSuccess; | |
390 } | |
391 | |
392 // Float exchange | |
393 #ifdef _ATL_USE_DDX_FLOAT | |
394 static BOOL _AtlSimpleFloatParse(LPCTSTR lpszText, double& d) | |
395 { | |
396 ATLASSERT(lpszText != NULL); | |
397 while (*lpszText == _T(' ') || *lpszText == _T('\t')) | |
398 lpszText++; | |
399 | |
400 TCHAR chFirst = lpszText[0]; | |
401 d = _tcstod(lpszText, (LPTSTR*)&lpszText); | |
402 if (d == 0.0 && chFirst != _T('0')) | |
403 return FALSE; // could not convert | |
404 while (*lpszText == _T(' ') || *lpszText == _T('\t')) | |
405 lpszText++; | |
406 | |
407 if (*lpszText != _T('\0')) | |
408 return FALSE; // not terminated properly | |
409 | |
410 return TRUE; | |
411 } | |
412 | |
413 BOOL DDX_Float(UINT nID, float& nVal, BOOL bSave, BOOL bValidate = FALSE
, float nMin = 0.F, float nMax = 0.F, int nPrecision = FLT_DIG) | |
414 { | |
415 T* pT = static_cast<T*>(this); | |
416 BOOL bSuccess = TRUE; | |
417 const int cchBuff = 32; | |
418 TCHAR szBuff[cchBuff] = { 0 }; | |
419 | |
420 if(bSave) | |
421 { | |
422 pT->GetDlgItemText(nID, szBuff, cchBuff); | |
423 double d = 0; | |
424 if(_AtlSimpleFloatParse(szBuff, d)) | |
425 nVal = (float)d; | |
426 else | |
427 bSuccess = FALSE; | |
428 } | |
429 else | |
430 { | |
431 ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax); | |
432 SecureHelper::sprintf_x(szBuff, cchBuff, _T("%.*g"), nPr
ecision, nVal); | |
433 bSuccess = pT->SetDlgItemText(nID, szBuff); | |
434 } | |
435 | |
436 if(!bSuccess) | |
437 { | |
438 pT->OnDataExchangeError(nID, bSave); | |
439 } | |
440 else if(bSave && bValidate) // validation | |
441 { | |
442 ATLASSERT(nMin != nMax); | |
443 if(nVal < nMin || nVal > nMax) | |
444 { | |
445 _XData data = { ddxDataFloat }; | |
446 data.floatData.nVal = (double)nVal; | |
447 data.floatData.nMin = (double)nMin; | |
448 data.floatData.nMax = (double)nMax; | |
449 pT->OnDataValidateError(nID, bSave, data); | |
450 bSuccess = FALSE; | |
451 } | |
452 } | |
453 return bSuccess; | |
454 } | |
455 | |
456 BOOL DDX_Float(UINT nID, double& nVal, BOOL bSave, BOOL bValidate = FALS
E, double nMin = 0., double nMax = 0., int nPrecision = DBL_DIG) | |
457 { | |
458 T* pT = static_cast<T*>(this); | |
459 BOOL bSuccess = TRUE; | |
460 const int cchBuff = 32; | |
461 TCHAR szBuff[cchBuff] = { 0 }; | |
462 | |
463 if(bSave) | |
464 { | |
465 pT->GetDlgItemText(nID, szBuff, cchBuff); | |
466 double d = 0; | |
467 if(_AtlSimpleFloatParse(szBuff, d)) | |
468 nVal = d; | |
469 else | |
470 bSuccess = FALSE; | |
471 } | |
472 else | |
473 { | |
474 ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax); | |
475 SecureHelper::sprintf_x(szBuff, cchBuff, _T("%.*g"), nPr
ecision, nVal); | |
476 bSuccess = pT->SetDlgItemText(nID, szBuff); | |
477 } | |
478 | |
479 if(!bSuccess) | |
480 { | |
481 pT->OnDataExchangeError(nID, bSave); | |
482 } | |
483 else if(bSave && bValidate) // validation | |
484 { | |
485 ATLASSERT(nMin != nMax); | |
486 if(nVal < nMin || nVal > nMax) | |
487 { | |
488 _XData data = { ddxDataFloat }; | |
489 data.floatData.nVal = nVal; | |
490 data.floatData.nMin = nMin; | |
491 data.floatData.nMax = nMax; | |
492 pT->OnDataValidateError(nID, bSave, data); | |
493 bSuccess = FALSE; | |
494 } | |
495 } | |
496 return bSuccess; | |
497 } | |
498 #endif // _ATL_USE_DDX_FLOAT | |
499 | |
500 // Full control subclassing (for CWindowImpl derived controls) | |
501 template <class TControl> | |
502 void DDX_Control(UINT nID, TControl& ctrl, BOOL bSave) | |
503 { | |
504 if(!bSave && ctrl.m_hWnd == NULL) | |
505 { | |
506 T* pT = static_cast<T*>(this); | |
507 ctrl.SubclassWindow(pT->GetDlgItem(nID)); | |
508 } | |
509 } | |
510 | |
511 // Simple control attaching (for HWND wrapper controls) | |
512 template <class TControl> | |
513 void DDX_Control_Handle(UINT nID, TControl& ctrl, BOOL bSave) | |
514 { | |
515 if(!bSave && ctrl.m_hWnd == NULL) | |
516 { | |
517 T* pT = static_cast<T*>(this); | |
518 ctrl = pT->GetDlgItem(nID); | |
519 } | |
520 } | |
521 | |
522 // Control state | |
523 void DDX_Check(UINT nID, int& nValue, BOOL bSave) | |
524 { | |
525 T* pT = static_cast<T*>(this); | |
526 HWND hWndCtrl = pT->GetDlgItem(nID); | |
527 if(bSave) | |
528 { | |
529 nValue = (int)::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L
); | |
530 ATLASSERT(nValue >= 0 && nValue <= 2); | |
531 } | |
532 else | |
533 { | |
534 if(nValue < 0 || nValue > 2) | |
535 { | |
536 ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - dial
og data checkbox value (%d) out of range.\n"), nValue); | |
537 nValue = 0; // default to off | |
538 } | |
539 ::SendMessage(hWndCtrl, BM_SETCHECK, nValue, 0L); | |
540 } | |
541 } | |
542 | |
543 // variant that supports bool (checked/not-checked, no intermediate stat
e) | |
544 void DDX_Check(UINT nID, bool& bCheck, BOOL bSave) | |
545 { | |
546 int nValue = bCheck ? 1 : 0; | |
547 DDX_Check(nID, nValue, bSave); | |
548 | |
549 if(bSave) | |
550 { | |
551 if(nValue == 2) | |
552 ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - chec
kbox state (%d) out of supported range.\n"), nValue); | |
553 bCheck = (nValue == 1); | |
554 } | |
555 } | |
556 | |
557 void DDX_Radio(UINT nID, int& nValue, BOOL bSave) | |
558 { | |
559 T* pT = static_cast<T*>(this); | |
560 HWND hWndCtrl = pT->GetDlgItem(nID); | |
561 ATLASSERT(hWndCtrl != NULL); | |
562 | |
563 // must be first in a group of auto radio buttons | |
564 ATLASSERT(::GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP); | |
565 ATLASSERT(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_R
ADIOBUTTON); | |
566 | |
567 if(bSave) | |
568 nValue = -1; // value if none found | |
569 | |
570 // walk all children in group | |
571 int nButton = 0; | |
572 do | |
573 { | |
574 if(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_
RADIOBUTTON) | |
575 { | |
576 // control in group is a radio button | |
577 if(bSave) | |
578 { | |
579 if(::SendMessage(hWndCtrl, BM_GETCHECK,
0, 0L) != 0) | |
580 { | |
581 ATLASSERT(nValue == -1); // o
nly set once | |
582 nValue = nButton; | |
583 } | |
584 } | |
585 else | |
586 { | |
587 // select button | |
588 ::SendMessage(hWndCtrl, BM_SETCHECK, (nB
utton == nValue), 0L); | |
589 } | |
590 nButton++; | |
591 } | |
592 else | |
593 { | |
594 ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - skip
ping non-radio button in group.\n")); | |
595 } | |
596 hWndCtrl = ::GetWindow(hWndCtrl, GW_HWNDNEXT); | |
597 } | |
598 while (hWndCtrl != NULL && !(GetWindowLong(hWndCtrl, GWL_STYLE)
& WS_GROUP)); | |
599 } | |
600 | |
601 // Overrideables | |
602 void OnDataExchangeError(UINT nCtrlID, BOOL /*bSave*/) | |
603 { | |
604 // Override to display an error message | |
605 ::MessageBeep((UINT)-1); | |
606 T* pT = static_cast<T*>(this); | |
607 ::SetFocus(pT->GetDlgItem(nCtrlID)); | |
608 } | |
609 | |
610 void OnDataValidateError(UINT nCtrlID, BOOL /*bSave*/, _XData& /*data*/) | |
611 { | |
612 // Override to display an error message | |
613 ::MessageBeep((UINT)-1); | |
614 T* pT = static_cast<T*>(this); | |
615 ::SetFocus(pT->GetDlgItem(nCtrlID)); | |
616 } | |
617 }; | |
618 | |
619 }; // namespace WTL | |
620 | |
621 #endif // __ATLDDX_H__ | |
OLD | NEW |