| 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 |