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 |