/3rd_party/wtl/Include/atlribbon.h
C++ Header | 3446 lines | 2686 code | 533 blank | 227 comment | 429 complexity | c9eaf028c94020793111b9ac5f0efb9e MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, JSON, MPL-2.0-no-copyleft-exception, GPL-2.0, GPL-3.0, LGPL-3.0, BSD-2-Clause
Large files files are truncated, but you can click here to view the full file
1// Windows Template Library - WTL version 8.1 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// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) 7// which can be found in the file CPL.TXT at the root of this distribution. 8// By using this software in any fashion, you are agreeing to be bound by 9// the terms of this license. You must not remove this notice, or 10// any other, from this software. 11 12#ifndef __ATLRIBBON_H__ 13#define __ATLRIBBON_H__ 14 15#pragma once 16 17#if (_MSC_VER < 1500) 18 #error atlribbon.h requires Visual C++ 2008 compiler or higher 19#endif 20 21#ifndef _UNICODE 22 #error atlribbon.h requires the Unicode character set 23#endif 24 25#if !defined(NTDDI_WIN7) || (NTDDI_VERSION < NTDDI_WIN7) 26 #error atlribbon.h requires the Windows 7 SDK or higher 27#endif 28 29#ifdef _WIN32_WCE 30 #error atlribbon.h is not supported on Windows CE 31#endif 32 33#ifndef __ATLAPP_H__ 34 #error atlribbon.h requires atlapp.h to be included first 35#endif 36 37#if (_ATL_VER < 0x0700) 38 #include <shlwapi.h> 39 #pragma comment(lib, "shlwapi.lib") 40#endif 41 42#include <atlmisc.h> // for RecentDocumentList classes 43#include <atlframe.h> // for Frame and UpdateUI classes 44#include <atlctrls.h> // required for atlctrlw.h 45#include <atlctrlw.h> // for CCommandBarCtrl 46 47#if !defined(_WTL_USE_CSTRING) && !defined(__ATLSTR_H__) 48 #pragma warning(disable : 4530) // unwind semantics not enabled 49 #include <string> 50 #pragma warning(default : 4530) 51#endif 52 53#include <dwmapi.h> 54#pragma comment(lib, "dwmapi.lib") 55 56#include <UIRibbon.h> 57#include <UIRibbonPropertyHelpers.h> 58#pragma comment(lib, "propsys.lib") 59 60#include <Richedit.h> // for CHARFORMAT2 61 62 63/////////////////////////////////////////////////////////////////////////////// 64// Classes in this file: 65// 66// CRibbonUpdateUI : Automatic mapping of ribbon UI elements 67// 68// RibbonUI::Text 69// RibbonUI::CharFormat 70// RibbonUI::ICtrl 71// RibbonUI::CtrlImpl 72// RibbonUI::CommandCtrlImpl 73// RibbonUI::ItemProperty 74// RibbonUI::CollectionImplBase 75// RibbonUI::CollectionImpl 76// RibbonUI::TextCollectionImpl 77// RibbonUI::ItemCollectionImpl 78// RibbonUI::ComboCollectionImpl 79// RibbonUI::CommandCollectionImpl 80// RibbonUI::ToolbarCollectionImpl 81// RibbonUI::SimpleCollectionImpl 82// RibbonUI::CollectionCtrlImpl 83// RibbonUI::ToolbarGalleryCtrlImpl 84// RibbonUI::SimpleCollectionCtrlImpl 85// RibbonUI::RecentItemsCtrlImpl 86// RibbonUI::FontCtrlImpl 87// RibbonUI::ColorCtrlImpl 88// RibbonUI::SpinnerCtrlImpl 89// 90// RibbonUI::CRibbonImpl 91// CRibbonImpl::CRibbonComboCtrl 92// CRibbonImpl::CRibbonItemGalleryCtrl 93// CRibbonImpl::CRibbonCommandGalleryCtrl 94// CRibbonImpl::CRibbonToolbarGalleryCtrl 95// CRibbonImpl::CRibbonSimpleComboCtrl 96// CRibbonImpl::CRibbonSimpleGalleryCtrl 97// CRibbonImpl::CRibbonRecentItemsCtrl 98// CRibbonImpl::CRibbonColorCtrl 99// CRibbonImpl::CRibbonFontCtrl 100// CRibbonImpl::CRibbonSpinnerCtrl 101// CRibbonImpl::CRibbonFloatSpinnerCtrl 102// CRibbonImpl::CRibbonCommandCtrl 103// 104// CRibbonFrameWindowImplBase 105// CRibbonFrameWindowImpl 106// CRibbonMDIFrameWindowImpl 107// CRibbonPersist 108// 109// Global functions: 110// RibbonUI::SetPropertyVal() 111// RibbonUI::GetImage() 112 113 114// Constants 115 116#ifndef RIBBONUI_MAX_TEXT 117 #define RIBBONUI_MAX_TEXT 128 118#endif 119 120#define TWIPS_PER_POINT 20 // For font size 121 122 123namespace WTL 124{ 125 126/////////////////////////////////////////////////////////////////////////////// 127// CRibbonUpdateUI : Automatic mapping of ribbon UI elements 128 129template <class T> 130class CRibbonUpdateUI : public CAutoUpdateUI<T> 131{ 132public: 133 enum 134 { 135 UPDUI_RIBBON = 0x0080, 136 UPDUI_PERSIST = 0x0020 137 }; 138 139 bool IsRibbonElement(const _AtlUpdateUIMap& UIMap) 140 { 141 return (UIMap.m_wType & UPDUI_RIBBON) != 0; 142 } 143 144 bool IsRibbonID(UINT nID) 145 { 146 for(int i = 0; i < m_arrUIMap.GetSize(); i++) 147 { 148 if(m_arrUIMap[i].m_nID == nID) 149 return IsRibbonElement(m_arrUIMap[i]); 150 } 151 152 return false; 153 } 154 155// Element 156 bool UIAddRibbonElement(UINT nID) 157 { 158 return UIAddElement<UPDUI_RIBBON>(nID); 159 } 160 161 bool UIRemoveRibbonElement(UINT nID) 162 { 163 return UIRemoveElement<UPDUI_RIBBON>(nID); 164 } 165 166 bool UIPersistElement(UINT nID, bool bPersist = true) 167 { 168 return bPersist ? 169 UIAddElement<UPDUI_PERSIST>(nID) : 170 UIRemoveElement<UPDUI_PERSIST>(nID); 171 } 172 173// methods for Ribbon elements 174 BOOL UISetText(int nID, LPCWSTR sText, BOOL bForceUpdate = FALSE) 175 { 176 T* pT = static_cast<T*>(this); 177 BOOL bRes = CUpdateUIBase::UISetText(nID, sText, bForceUpdate); 178 if (pT->IsRibbonUI() && IsRibbonID(nID)) 179 bRes = SUCCEEDED(pT->InvalidateProperty(nID, UI_PKEY_Label)); 180 return bRes; 181 } 182 183 BOOL UISetText(int nID, UINT uIdResource, BOOL bForceUpdate = FALSE) 184 { 185 CTempBuffer<WCHAR> sText(RIBBONUI_MAX_TEXT); 186 return AtlLoadString(uIdResource, sText, RIBBONUI_MAX_TEXT) ? 187 UISetText(nID, sText, bForceUpdate) : 188 E_FAIL; 189 } 190 191 LPCTSTR UIGetText(int nID) 192 { 193 T* pT = static_cast<T*>(this); 194 LPCTSTR sUI = CAutoUpdateUI::UIGetText(nID); 195 196 // replace 'tab' by 'space' for RibbonUI elements 197 if (sUI && pT->IsRibbonUI() && IsRibbonID(nID) && wcschr(sUI, L'\t')) 198 { 199 static WCHAR sText[RIBBONUI_MAX_TEXT] = { 0 }; 200 wcscpy_s(sText, sUI); 201 *wcschr(sText, L'\t') = L' '; 202 return sText; 203 } 204 else 205 { 206 return sUI; 207 } 208 } 209 210 BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE) 211 { 212 T* pT = static_cast<T*>(this); 213 BOOL bRes = CUpdateUIBase::UIEnable(nID, bEnable, bForceUpdate); 214 if (pT->IsRibbonUI() && IsRibbonID(nID)) 215 bRes = SUCCEEDED(pT->SetProperty((WORD)nID, UI_PKEY_Enabled, bEnable)); 216 return bRes; 217 } 218 219 BOOL UISetCheck(int nID, INT nCheck, BOOL bForceUpdate = FALSE) 220 { 221 if ((nCheck == 0) || (nCheck == 1)) 222 return UISetCheck(nID, nCheck != 0, bForceUpdate); 223 else 224 return CUpdateUIBase::UISetCheck(nID, nCheck, bForceUpdate); 225 } 226 227 BOOL UISetCheck(int nID, bool bCheck, BOOL bForceUpdate = FALSE) 228 { 229 T* pT = static_cast<T*>(this); 230 BOOL bRes = CUpdateUIBase::UISetCheck(nID, bCheck, bForceUpdate); 231 if (bRes && pT->IsRibbonUI() && IsRibbonID(nID)) 232 bRes = SUCCEEDED(pT->SetProperty((WORD)nID, UI_PKEY_BooleanValue, bCheck)); 233 return bRes; 234 } 235}; 236 237 238/////////////////////////////////////////////////////////////////////////////// 239// RibbonUI namespace 240// 241 242namespace RibbonUI 243{ 244 245// Minimal string allocation support for various PROPERTYKEY values 246#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) 247 typedef _CSTRING_NS::CString Text; 248#else 249 class Text : public std::wstring 250 { 251 public: 252 Text(std::wstring& s) : std::wstring(s) 253 { } 254 Text(LPCWSTR s) : std::wstring(s) 255 { } 256 Text() 257 { } 258 bool IsEmpty() 259 { 260 return empty(); 261 } 262 operator LPCWSTR() 263 { 264 return c_str(); 265 } 266 Text& operator =(LPCWSTR s) 267 { 268 return static_cast<Text&>(std::wstring::operator =(s)); 269 } 270 }; 271#endif 272 273// PROPERTYKEY enum and helpers 274enum k_KEY 275{ 276 // state 277 k_Enabled = 1, k_BooleanValue = 200, 278 // text properties 279 k_LabelDescription = 2, k_Keytip = 3, k_Label = 4, k_TooltipDescription = 5, k_TooltipTitle = 6, 280 // image properties 281 k_LargeImage = 7, k_LargeHighContrastImage = 8, k_SmallImage = 9, k_SmallHighContrastImage = 10, 282 // collection properties 283 k_ItemsSource = 101, k_Categories = 102, k_SelectedItem = 104, 284 // collection item properties 285 k_CommandId = 100, k_CategoryId = 103, k_CommandType = 105, k_ItemImage = 106, 286 // combo control property 287 k_StringValue = 202, 288 // spinner control properties 289 k_DecimalValue = 201, k_MaxValue = 203, k_MinValue, k_Increment, k_DecimalPlaces, k_FormatString, k_RepresentativeString = 208, 290 // font control properties 291 k_FontProperties = 300, k_FontProperties_Family, k_FontProperties_Size, k_FontProperties_Bold, k_FontProperties_Italic = 304, 292 k_FontProperties_Underline = 305, k_FontProperties_Strikethrough, k_FontProperties_VerticalPositioning, k_FontProperties_ForegroundColor = 308, 293 k_FontProperties_BackgroundColor = 309, k_FontProperties_ForegroundColorType, k_FontProperties_BackgroundColorType, k_FontProperties_ChangedProperties = 312, 294 k_FontProperties_DeltaSize = 313, 295 // recent items properties 296 k_RecentItems = 350, k_Pinned = 351, 297 // color control properties 298 k_Color = 400, k_ColorType = 401, k_ColorMode, 299 k_ThemeColorsCategoryLabel = 403, k_StandardColorsCategoryLabel, k_RecentColorsCategoryLabel = 405, k_AutomaticColorLabel = 406, 300 k_NoColorLabel = 407, k_MoreColorsLabel = 408, 301 k_ThemeColors = 409, k_StandardColors = 410, k_ThemeColorsTooltips = 411, k_StandardColorsTooltips = 412, 302 // Ribbon state 303 k_Viewable = 1000, k_Minimized = 1001, k_QuickAccessToolbarDock = 1002, k_ContextAvailable = 1100, 304 // Ribbon UI colors 305 k_GlobalBackgroundColor = 2000, k_GlobalHighlightColor, k_GlobalTextColor = 2002 306}; 307 308inline k_KEY k_(REFPROPERTYKEY key) 309{ 310 return (k_KEY)key.fmtid.Data1; 311} 312 313// PROPERTYKEY value assignment and specializations 314// 315template <typename V> 316HRESULT SetPropertyVal(REFPROPERTYKEY key, V val, PROPVARIANT* ppv) 317{ 318 switch (k_(key)) 319 { 320 case k_Enabled: 321 case k_BooleanValue: 322 return InitPropVariantFromBoolean(val, ppv); 323 default: 324 return UIInitPropertyFromUInt32(key, val, ppv); 325 } 326} 327 328inline HRESULT SetPropertyVal(REFPROPERTYKEY key, DOUBLE val, PROPVARIANT* ppv) 329{ 330 return SetPropertyVal(key, (LONG)val, ppv); 331} 332 333inline HRESULT SetPropertyVal(REFPROPERTYKEY key, IUIImage* val, PROPVARIANT* ppv) 334{ 335 HRESULT hr = UIInitPropertyFromImage(key, val, ppv); 336 ATLVERIFY(val->Release() == 1); 337 return hr; 338} 339 340inline HRESULT SetPropertyVal(REFPROPERTYKEY key, IUnknown* val, PROPVARIANT* ppv) 341{ 342 return UIInitPropertyFromInterface(key, val, ppv); 343} 344 345inline HRESULT SetPropertyVal(REFPROPERTYKEY key, IPropertyStore* val, PROPVARIANT* ppv) 346{ 347 return UIInitPropertyFromInterface(key, val, ppv); 348} 349 350inline HRESULT SetPropertyVal(REFPROPERTYKEY key, SAFEARRAY* val, PROPVARIANT* ppv) 351{ 352 return UIInitPropertyFromIUnknownArray(key, val, ppv); 353} 354 355inline HRESULT SetPropertyVal(REFPROPERTYKEY key, DECIMAL* val, PROPVARIANT* ppv) 356{ 357 return UIInitPropertyFromDecimal(key, *val, ppv); 358} 359 360inline HRESULT SetPropertyVal(REFPROPERTYKEY key, bool val, PROPVARIANT* ppv) 361{ 362 return UIInitPropertyFromBoolean(key, val, ppv); 363} 364 365inline HRESULT SetPropertyVal(REFPROPERTYKEY key, LPCWSTR val, PROPVARIANT* ppv) 366{ 367 return UIInitPropertyFromString(key, val, ppv); 368} 369 370// CharFormat helper struct for RibbonUI font control 371// 372struct CharFormat : CHARFORMAT2 373{ 374 // Default constructor 375 CharFormat() 376 { 377 cbSize = sizeof CHARFORMAT2; 378 Reset(); 379 } 380 381 // Copy constructor 382 CharFormat(const CharFormat& cf) 383 { 384 CopyMemory(this, &cf, sizeof CHARFORMAT2); 385 } 386 387 // Assign operator 388 CharFormat& operator =(const CharFormat& cf) 389 { 390 CopyMemory(this, &cf, sizeof CHARFORMAT2); 391 return (*this); 392 } 393 394 void Reset() 395 { 396 uValue = dwMask = dwEffects = 0; 397 PropVariantInit(&propvar); 398 } 399 400 void operator <<(IPropertyStore* pStore) 401 { 402 if (pStore == NULL) 403 { 404 ATLASSERT(FALSE); 405 return; 406 } 407 408 static void (CharFormat::*Getk_[])(IPropertyStore*) = 409 { 410 &CharFormat::Getk_Family, 411 &CharFormat::Getk_FontProperties_Size, 412 &CharFormat::Getk_MaskEffect<CFM_BOLD, CFE_BOLD, UI_PKEY_FontProperties_Bold>, 413 &CharFormat::Getk_MaskEffect<CFM_ITALIC, CFE_ITALIC, UI_PKEY_FontProperties_Italic>, 414 &CharFormat::Getk_MaskEffect<CFM_UNDERLINE, CFE_UNDERLINE, UI_PKEY_FontProperties_Underline>, 415 &CharFormat::Getk_MaskEffect<CFM_STRIKEOUT, CFE_STRIKEOUT, UI_PKEY_FontProperties_Strikethrough>, 416 &CharFormat::Getk_VerticalPositioning, 417 &CharFormat::Getk_Color<CFM_COLOR, UI_PKEY_FontProperties_ForegroundColor>, 418 &CharFormat::Getk_Color<CFM_BACKCOLOR, UI_PKEY_FontProperties_BackgroundColor>, 419 &CharFormat::Getk_ColorType<CFM_COLOR, CFE_AUTOCOLOR, UI_SWATCHCOLORTYPE_AUTOMATIC, UI_PKEY_FontProperties_ForegroundColorType>, 420 &CharFormat::Getk_ColorType<CFM_BACKCOLOR, CFE_AUTOBACKCOLOR, UI_SWATCHCOLORTYPE_NOCOLOR, UI_PKEY_FontProperties_BackgroundColorType>, 421 }; 422 423 DWORD nProps = 0; 424 Reset(); 425 426 ATLVERIFY(SUCCEEDED(pStore->GetCount(&nProps))); 427 for (DWORD iProp = 0; iProp < nProps; iProp++) 428 { 429 PROPERTYKEY key; 430 ATLVERIFY(SUCCEEDED(pStore->GetAt(iProp, &key))); 431 ATLASSERT(k_(key) >= k_FontProperties_Family); 432 433 if (k_(key) <= k_FontProperties_BackgroundColorType) 434 (this->*Getk_[k_(key) - k_FontProperties_Family])(pStore); 435 } 436 } 437 438 void operator >>(IPropertyStore* pStore) 439 { 440 if (pStore == NULL) 441 { 442 ATLASSERT(FALSE); 443 return; 444 } 445 446 PutFace(pStore); 447 PutSize(pStore); 448 PutMaskEffect(CFM_BOLD, CFE_BOLD, UI_PKEY_FontProperties_Bold, pStore); 449 PutMaskEffect(CFM_ITALIC, CFE_ITALIC, UI_PKEY_FontProperties_Italic, pStore); 450 PutMaskEffect(CFM_UNDERLINE, CFE_UNDERLINE, UI_PKEY_FontProperties_Underline, pStore); 451 PutMaskEffect(CFM_STRIKEOUT, CFE_STRIKEOUT, UI_PKEY_FontProperties_Strikethrough, pStore); 452 PutVerticalPos(pStore); 453 PutColor(pStore); 454 PutBackColor(pStore); 455 } 456 457private: 458 PROPVARIANT propvar; 459 UINT uValue; 460 461 // Getk_ functions 462 void Getk_Family(IPropertyStore* pStore) 463 { 464 if (SUCCEEDED(pStore->GetValue(UI_PKEY_FontProperties_Family, &propvar))) 465 { 466 PropVariantToString(propvar, szFaceName, LF_FACESIZE); 467 if (*szFaceName) 468 dwMask |= CFM_FACE; 469 } 470 } 471 472 void Getk_FontProperties_Size(IPropertyStore* pStore) 473 { 474 if (SUCCEEDED(pStore->GetValue(UI_PKEY_FontProperties_Size, &propvar))) 475 { 476 DECIMAL decSize; 477 UIPropertyToDecimal(UI_PKEY_FontProperties_Size, propvar, &decSize); 478 DOUBLE dSize; 479 VarR8FromDec(&decSize, &dSize); 480 if (dSize > 0) 481 { 482 dwMask |= CFM_SIZE; 483 yHeight = (LONG)(dSize * TWIPS_PER_POINT); 484 } 485 } 486 } 487 488 template <DWORD t_dwMask, DWORD t_dwEffects, REFPROPERTYKEY key> 489 void Getk_MaskEffect(IPropertyStore* pStore) 490 { 491 if (SUCCEEDED(pStore->GetValue(key, &propvar))) 492 { 493 UIPropertyToUInt32(key, propvar, &uValue); 494 if ((UI_FONTPROPERTIES)uValue != UI_FONTPROPERTIES_NOTAVAILABLE) 495 { 496 dwMask |= t_dwMask; 497 dwEffects |= ((UI_FONTPROPERTIES) uValue == UI_FONTPROPERTIES_SET) ? t_dwEffects : 0; 498 } 499 } 500 } 501 502 void Getk_VerticalPositioning(IPropertyStore* pStore) 503 { 504 if (SUCCEEDED(pStore->GetValue(UI_PKEY_FontProperties_VerticalPositioning, &propvar))) 505 { 506 UIPropertyToUInt32(UI_PKEY_FontProperties_VerticalPositioning, propvar, &uValue); 507 UI_FONTVERTICALPOSITION uVerticalPosition = (UI_FONTVERTICALPOSITION) uValue; 508 if ((uVerticalPosition != UI_FONTVERTICALPOSITION_NOTAVAILABLE)) 509 { 510 dwMask |= (CFM_SUPERSCRIPT | CFM_SUBSCRIPT); 511 if (uVerticalPosition != UI_FONTVERTICALPOSITION_NOTSET) 512 { 513 dwEffects |= (uVerticalPosition == UI_FONTVERTICALPOSITION_SUPERSCRIPT) ? CFE_SUPERSCRIPT : CFE_SUBSCRIPT; 514 } 515 } 516 } 517 } 518 519 template <DWORD t_dwMask, REFPROPERTYKEY key> 520 void Getk_Color(IPropertyStore* pStore) 521 { 522 UINT32 color; 523 if (SUCCEEDED(pStore->GetValue(key, &propvar))) 524 { 525 UIPropertyToUInt32(key, propvar, &color); 526 dwMask |= t_dwMask; 527 528 if (t_dwMask == CFM_COLOR) 529 crTextColor = color; 530 else 531 crBackColor = color; 532 } 533 } 534 535 template <DWORD t_dwMask, DWORD t_dwEffects, UI_SWATCHCOLORTYPE t_type, REFPROPERTYKEY key> 536 void Getk_ColorType(IPropertyStore* pStore) 537 { 538 if (SUCCEEDED(pStore->GetValue(key, &propvar))) 539 { 540 UIPropertyToUInt32(key, propvar, &uValue); 541 if (t_type == (UI_SWATCHCOLORTYPE)uValue) 542 { 543 dwMask |= t_dwMask; 544 dwEffects |= t_dwEffects; 545 } 546 } 547 } 548 549 // Put functions 550 void PutMaskEffect(WORD dwMaskVal, WORD dwEffectVal, REFPROPERTYKEY key, IPropertyStore* pStore) 551 { 552 PROPVARIANT propvar; 553 UI_FONTPROPERTIES uProp = UI_FONTPROPERTIES_NOTAVAILABLE; 554 if ((dwMask & dwMaskVal) != 0) 555 uProp = dwEffects & dwEffectVal ? UI_FONTPROPERTIES_SET : UI_FONTPROPERTIES_NOTSET; 556 SetPropertyVal(key, uProp, &propvar); 557 pStore->SetValue(key, propvar); 558 } 559 560 void PutVerticalPos(IPropertyStore* pStore) 561 { 562 PROPVARIANT propvar; 563 UI_FONTVERTICALPOSITION uProp = UI_FONTVERTICALPOSITION_NOTAVAILABLE; 564 565 if ((dwMask & CFE_SUBSCRIPT) != 0) 566 { 567 if ((dwMask & CFM_SUBSCRIPT) && (dwEffects & CFE_SUBSCRIPT)) 568 uProp = UI_FONTVERTICALPOSITION_SUBSCRIPT; 569 else 570 uProp = UI_FONTVERTICALPOSITION_SUPERSCRIPT; 571 } 572 else if ((dwMask & CFM_OFFSET) != 0) 573 { 574 if (yOffset > 0) 575 uProp = UI_FONTVERTICALPOSITION_SUPERSCRIPT; 576 else if (yOffset < 0) 577 uProp = UI_FONTVERTICALPOSITION_SUBSCRIPT; 578 } 579 580 SetPropertyVal(UI_PKEY_FontProperties_VerticalPositioning, uProp, &propvar); 581 pStore->SetValue(UI_PKEY_FontProperties_VerticalPositioning, propvar); 582 } 583 584 void PutFace(IPropertyStore* pStore) 585 { 586 PROPVARIANT propvar; 587 SetPropertyVal(UI_PKEY_FontProperties_Family, 588 dwMask & CFM_FACE ? szFaceName : L"", &propvar); 589 pStore->SetValue(UI_PKEY_FontProperties_Family, propvar); 590 } 591 592 void PutSize(IPropertyStore* pStore) 593 { 594 PROPVARIANT propvar; 595 DECIMAL decVal; 596 597 if ((dwMask & CFM_SIZE) != 0) 598 VarDecFromR8((DOUBLE)yHeight / TWIPS_PER_POINT, &decVal); 599 else 600 VarDecFromI4(0, &decVal); 601 602 SetPropertyVal(UI_PKEY_FontProperties_Size, &decVal, &propvar); 603 pStore->SetValue(UI_PKEY_FontProperties_Size, propvar); 604 } 605 606 void PutColor(IPropertyStore* pStore) 607 { 608 if ((dwMask & CFM_COLOR) != 0) 609 if ((dwEffects & CFE_AUTOCOLOR) == 0) 610 { 611 SetPropertyVal(UI_PKEY_FontProperties_ForegroundColorType, UI_SWATCHCOLORTYPE_RGB, &propvar); 612 pStore->SetValue(UI_PKEY_FontProperties_ForegroundColorType, propvar); 613 614 SetPropertyVal(UI_PKEY_FontProperties_ForegroundColor, crTextColor, &propvar); 615 pStore->SetValue(UI_PKEY_FontProperties_ForegroundColor, propvar); 616 } 617 else 618 { 619 SetPropertyVal(UI_PKEY_FontProperties_ForegroundColorType, UI_SWATCHCOLORTYPE_AUTOMATIC, &propvar); 620 pStore->SetValue(UI_PKEY_FontProperties_ForegroundColorType, propvar); 621 } 622 } 623 624 void PutBackColor(IPropertyStore* pStore) 625 { 626 if (((dwMask & CFM_BACKCOLOR) != 0) && ((dwEffects & CFE_AUTOBACKCOLOR) == 0)) 627 { 628 SetPropertyVal(UI_PKEY_FontProperties_BackgroundColorType, UI_SWATCHCOLORTYPE_RGB, &propvar); 629 pStore->SetValue(UI_PKEY_FontProperties_BackgroundColorType, propvar); 630 631 SetPropertyVal(UI_PKEY_FontProperties_BackgroundColor, crBackColor, &propvar); 632 pStore->SetValue(UI_PKEY_FontProperties_BackgroundColor, propvar); 633 } 634 else 635 { 636 SetPropertyVal(UI_PKEY_FontProperties_BackgroundColorType, UI_SWATCHCOLORTYPE_NOCOLOR, &propvar); 637 pStore->SetValue(UI_PKEY_FontProperties_BackgroundColorType, propvar); 638 } 639 } 640}; 641 642// IUIImage helper 643// 644inline IUIImage* GetImage(HBITMAP hbm, UI_OWNERSHIP owner) 645{ 646 ATLASSERT(hbm); 647 IUIImage* pIUII = NULL; 648 ATL::CComPtr<IUIImageFromBitmap> pIFB; 649 650 if SUCCEEDED(pIFB.CoCreateInstance(CLSID_UIRibbonImageFromBitmapFactory)) 651 ATLVERIFY(SUCCEEDED(pIFB->CreateImage(hbm, owner, &pIUII))); 652 653 return pIUII; 654} 655 656 657/////////////////////////////////////////////////////////////////////////////// 658// Ribbon control classes 659 660// RibbonUI::ICtrl abstract interface of RibbonUI::CRibbonImpl and all RibbonUI control classes 661// 662struct ICtrl 663{ 664 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb, 665 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue, 666 IUISimplePropertySet* pCommandExecutionProperties) = 0; 667 668 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key, 669 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue) = 0; 670}; 671 672// RibbonUI::CtrlImpl base class for all ribbon controls 673// 674template <class T, UINT t_ID> 675class ATL_NO_VTABLE CtrlImpl : public ICtrl 676{ 677protected: 678 T* m_pWndRibbon; 679 680public: 681 typedef T WndRibbon; 682 683 CtrlImpl() : m_pWndRibbon(T::pWndRibbon) 684 { } 685 686 WndRibbon& GetWndRibbon() 687 { 688 return *m_pWndRibbon; 689 } 690 691 static WORD GetID() 692 { 693 return t_ID; 694 } 695 696 Text m_sTxt[5]; 697 698 // Operations 699 HRESULT Invalidate() 700 { 701 return GetWndRibbon().InvalidateCtrl(GetID()); 702 } 703 704 HRESULT Invalidate(REFPROPERTYKEY key, UI_INVALIDATIONS flags = UI_INVALIDATIONS_PROPERTY) 705 { 706 return GetWndRibbon().InvalidateProperty(GetID(), key, flags); 707 } 708 709 HRESULT SetText(REFPROPERTYKEY key, LPCWSTR sTxt, bool bUpdate = false) 710 { 711 ATLASSERT((k_(key) <= k_TooltipTitle) && (k_(key) >= k_LabelDescription)); 712 713 m_sTxt[k_(key) - k_LabelDescription] = sTxt; 714 715 return bUpdate ? 716 GetWndRibbon().InvalidateProperty(GetID(), key) : 717 S_OK; 718 } 719 720 // Implementation 721 template <typename V> 722 HRESULT SetProperty(REFPROPERTYKEY key, V val) 723 { 724 return GetWndRibbon().SetProperty(GetID(), key, val); 725 } 726 727 HRESULT OnGetText(REFPROPERTYKEY key, PROPVARIANT* ppv) 728 { 729 ATLASSERT((k_(key) <= k_TooltipTitle) && (k_(key) >= k_LabelDescription)); 730 731 const INT iText = k_(key) - k_LabelDescription; 732 if (m_sTxt[iText].IsEmpty()) 733 if (LPCWSTR sText = GetWndRibbon().OnRibbonQueryText(GetID(), key)) 734 m_sTxt[iText] = sText; 735 736 return !m_sTxt[iText].IsEmpty() ? 737 SetPropertyVal(key, (LPCWSTR)m_sTxt[iText], ppv) : 738 S_OK; 739 } 740 741 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb, 742 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue, 743 IUISimplePropertySet* pCommandExecutionProperties) 744 { 745 ATLASSERT(nCmdID == t_ID); 746 return GetWndRibbon().DoExecute(nCmdID, verb, key, ppropvarValue, pCommandExecutionProperties); 747 } 748 749 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key, 750 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue) 751 { 752 ATLASSERT(nCmdID == t_ID); 753 754 const INT iMax = k_TooltipTitle - k_LabelDescription; 755 const INT iVal = k_(key) - k_LabelDescription; 756 757 return (iVal <= iMax) && (iVal >= 0) ? 758 OnGetText(key, ppropvarNewValue) : 759 GetWndRibbon().DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue); 760 } 761}; 762 763// CommandCtrlImpl base class for most ribbon controls 764// 765template <class T, UINT t_ID> 766class CommandCtrlImpl : public CtrlImpl<T, t_ID> 767{ 768public: 769 CBitmap m_hbm[4]; 770 771 HRESULT SetImage(REFPROPERTYKEY key, HBITMAP hbm, bool bUpdate = false) 772 { 773 ATLASSERT((k_(key) <= k_SmallHighContrastImage) && (k_(key) >= k_LargeImage)); 774 775 m_hbm[k_(key) - k_LargeImage].Attach(hbm); 776 777 return bUpdate ? 778 GetWndRibbon().InvalidateProperty(GetID(), key) : 779 S_OK; 780 } 781 782 HRESULT OnGetImage(REFPROPERTYKEY key, PROPVARIANT* ppv) 783 { 784 ATLASSERT((k_(key) <= k_SmallHighContrastImage) && (k_(key) >= k_LargeImage)); 785 786 const INT iImage = k_(key) - k_LargeImage; 787 788 if (m_hbm[iImage].IsNull()) 789 m_hbm[iImage] = GetWndRibbon().OnRibbonQueryImage(GetID(), key); 790 791 return m_hbm[iImage].IsNull() ? 792 E_NOTIMPL : 793 SetPropertyVal(key, GetImage(m_hbm[iImage], UI_OWNERSHIP_COPY), ppv); 794 } 795 796 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key, 797 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue) 798 { 799 ATLASSERT (nCmdID == GetID()); 800 801 return (k_(key) <= k_SmallHighContrastImage) && (k_(key) >= k_LargeImage) ? 802 OnGetImage(key, ppropvarNewValue) : 803 CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue); 804 } 805}; 806 807 808/////////////////////////////////////////////////////////////////////////////// 809// Ribbon collection base classes 810 811// ItemProperty class: ribbon callback for each item in a collection 812// 813template <class TCollection> 814class ItemProperty : public IUISimplePropertySet 815{ 816public: 817 ItemProperty(UINT i, TCollection* pCollection) : m_Index(i), m_pCollection(pCollection) 818 { } 819 820 const UINT m_Index; 821 TCollection* m_pCollection; 822 823 // IUISimplePropertySet method. 824 STDMETHODIMP GetValue(REFPROPERTYKEY key, PROPVARIANT *value) 825 { 826 return m_pCollection->OnGetItem(m_Index, key, value); 827 } 828 829 // IUnknown methods. 830 STDMETHODIMP_(ULONG) AddRef() 831 { 832 return 1; 833 } 834 835 STDMETHODIMP_(ULONG) Release() 836 { 837 return 1; 838 } 839 840 STDMETHODIMP QueryInterface(REFIID iid, void** ppv) 841 { 842 if ((iid == __uuidof(IUnknown)) || (iid == __uuidof(IUISimplePropertySet))) 843 { 844 *ppv = this; 845 return S_OK; 846 } 847 else 848 { 849 return E_NOINTERFACE; 850 } 851 } 852}; 853 854 855// CollectionImplBase: base class for all RibbonUI collections 856// 857template <class TCollection, size_t t_size> 858class CollectionImplBase 859{ 860 typedef CollectionImplBase<TCollection, t_size> thisClass; 861 862public: 863 CollectionImplBase() 864 { 865 for (int i = 0; i < t_size; i++) 866 m_apItems[i] = new ItemProperty<TCollection>(i, static_cast<TCollection*>(this)); 867 } 868 869 ~CollectionImplBase() 870 { 871 for (int i = 0; i < t_size; i++) 872 delete m_apItems[i]; 873 } 874 875// Data members 876 ItemProperty<TCollection>* m_apItems[t_size]; 877}; 878 879// CollectionImpl: handles categories and collecton resizing 880// 881template <class TCtrl, size_t t_items, size_t t_categories> 882class CollectionImpl : public CollectionImplBase<CollectionImpl<TCtrl, t_items, t_categories>, t_items + t_categories> 883{ 884 typedef CollectionImpl<TCtrl, t_items, t_categories> thisClass; 885public: 886 typedef thisClass Collection; 887 888 CollectionImpl() : m_size(t_items) 889 { 890 FillMemory(m_auItemCat, sizeof m_auItemCat, 0xff); // UI_COLLECTION_INVALIDINDEX 891 } 892 893 UINT32 m_auItemCat[t_items]; 894 Text m_asCatName[max(t_categories, 1)]; 895 size_t m_size; 896 897// Operations 898 HRESULT SetItemCategory(UINT uItem, UINT uCat, bool bUpdate = false) 899 { 900 ATLASSERT((uItem < t_items) && (uCat < t_categories)); 901 902 m_auItemCat[uItem] = uCat; 903 904 return bUpdate ? InvalidateItems() : S_OK; 905 } 906 907 HRESULT SetCategoryText(UINT uCat, LPCWSTR sText, bool bUpdate = false) 908 { 909 ATLASSERT(uCat < t_categories); 910 911 m_asCatName[uCat] = sText; 912 913 return bUpdate ? InvalidateCategories() : S_OK; 914 } 915 916 HRESULT Resize(size_t size, bool bUpdate = false) 917 { 918 ATLASSERT(size <= t_items); 919 920 m_size = size; 921 922 return bUpdate ? InvalidateItems() : S_OK; 923 } 924 925// Implementation 926 HRESULT OnGetItem(UINT uIndex, REFPROPERTYKEY key, PROPVARIANT *value) 927 { 928 ATLASSERT(uIndex < t_items + t_categories); 929 TCtrl* pCtrl = static_cast<TCtrl*>(this); 930 931 return uIndex < t_items ? 932 pCtrl->DoGetItem(uIndex, key, value) : 933 pCtrl->DoGetCategory(uIndex - t_items, key, value); 934 } 935 936 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value) 937 { 938 ATLASSERT(k_(key) == k_CategoryId); 939 UINT32 uCat = UI_COLLECTION_INVALIDINDEX; 940 941 if (t_categories != 0) 942 { 943 if (m_auItemCat[uItem] == UI_COLLECTION_INVALIDINDEX) 944 { 945 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon(); 946 m_auItemCat[uItem] = ribbon.OnRibbonQueryItemCategory(TCtrl::GetID(), uItem); 947 } 948 uCat = m_auItemCat[uItem]; 949 } 950 951 return SetPropertyVal(key, uCat, value); 952 } 953 954 HRESULT DoGetCategory(UINT uCat, REFPROPERTYKEY key, PROPVARIANT *value) 955 { 956 HRESULT hr = S_OK; 957 958 switch (k_(key)) 959 { 960 case k_Label: 961 if (m_asCatName[uCat].IsEmpty()) 962 { 963 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon(); 964 m_asCatName[uCat] = ribbon.OnRibbonQueryCategoryText(TCtrl::GetID(), uCat); 965 } 966 hr = SetPropertyVal(key, (LPCWSTR)m_asCatName[uCat], value); 967 break; 968 case k_CategoryId: 969 hr = SetPropertyVal(key, uCat, value); 970 break; 971 default: 972 ATLASSERT(FALSE); 973 break; 974 } 975 976 return hr; 977 } 978 979 HRESULT InvalidateItems() 980 { 981 return static_cast<TCtrl*>(this)->Invalidate(UI_PKEY_ItemsSource); 982 } 983 984 HRESULT InvalidateCategories() 985 { 986 return static_cast<TCtrl*>(this)->Invalidate(UI_PKEY_Categories); 987 } 988 989 HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key, 990 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* /*ppropvarNewValue*/) 991 { 992 ATLASSERT(nCmdID == TCtrl::GetID()); 993 nCmdID; // avoid level 4 warning 994 995 HRESULT hr = E_NOTIMPL; 996 switch (k_(key)) 997 { 998 case k_ItemsSource: 999 { 1000 ATL::CComQIPtr<IUICollection> pIUICollection(ppropvarCurrentValue->punkVal); 1001 ATLASSERT(pIUICollection); 1002 hr = pIUICollection->Clear(); 1003 for (UINT i = 0; i < m_size; i++) 1004 { 1005 if FAILED(hr = pIUICollection->Add(m_apItems[i])) 1006 break; 1007 } 1008 ATLASSERT(SUCCEEDED(hr)); 1009 } 1010 break; 1011 case k_Categories: 1012 if (t_categories != 0) 1013 { 1014 ATL::CComQIPtr<IUICollection> pIUICategory(ppropvarCurrentValue->punkVal); 1015 ATLASSERT(pIUICategory.p); 1016 hr = pIUICategory->Clear(); 1017 for (UINT i = t_items; i < t_items + t_categories; i++) 1018 { 1019 if FAILED(hr = pIUICategory->Add(m_apItems[i])) 1020 break; 1021 } 1022 ATLASSERT(SUCCEEDED(hr)); 1023 } 1024 break; 1025 } 1026 1027 return hr; 1028 } 1029}; 1030 1031// TextCollectionImpl: handles item labels and selection 1032// 1033template <class TCtrl, size_t t_items, size_t t_categories = 0> 1034class TextCollectionImpl : public CollectionImpl<TCtrl, t_items, t_categories> 1035{ 1036 typedef TextCollectionImpl<TCtrl, t_items, t_categories> thisClass; 1037public: 1038 typedef thisClass TextCollection; 1039 1040 TextCollectionImpl() : m_uSelected(UI_COLLECTION_INVALIDINDEX) 1041 { } 1042 1043 Text m_asText[t_items]; 1044 UINT m_uSelected; 1045 1046 // Operations 1047 HRESULT SetItemText(UINT uItem, LPCWSTR sText, bool bUpdate = false) 1048 { 1049 ATLASSERT(uItem < t_items); 1050 1051 m_asText[uItem] = sText; 1052 1053 return bUpdate ? InvalidateItems() : S_OK; 1054 } 1055 1056 UINT GetSelected() 1057 { 1058 return m_uSelected; 1059 } 1060 1061 HRESULT Select(UINT uItem, bool bUpdate = false) 1062 { 1063 ATLASSERT((uItem < t_items) || (uItem == UI_COLLECTION_INVALIDINDEX)); 1064 1065 m_uSelected = uItem; 1066 1067 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon(); 1068 return bUpdate ? 1069 ribbon.SetProperty(TCtrl::GetID(), UI_PKEY_SelectedItem, uItem) : 1070 S_OK; 1071 } 1072 1073// Implementation 1074 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value) 1075 { 1076 ATLASSERT(uItem < t_items); 1077 1078 if (k_(key) == k_Label) 1079 { 1080 if (m_asText[uItem].IsEmpty()) 1081 { 1082 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon(); 1083 m_asText[uItem] = ribbon.OnRibbonQueryItemText(TCtrl::GetID(), uItem); 1084 } 1085 return SetPropertyVal(key, (LPCWSTR)m_asText[uItem], value); 1086 } 1087 else 1088 { 1089 return Collection::DoGetItem(uItem, key, value); 1090 } 1091 } 1092 1093 HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key, 1094 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue) 1095 { 1096 ATLASSERT(nCmdID == TCtrl::GetID()); 1097 1098 if (k_(key) == k_SelectedItem) 1099 { 1100 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon(); 1101 UINT uSel = UI_COLLECTION_INVALIDINDEX; 1102 if ((m_uSelected == UI_COLLECTION_INVALIDINDEX) && 1103 ribbon.OnRibbonQuerySelectedItem(TCtrl::GetID(), uSel)) 1104 m_uSelected = uSel; 1105 1106 return SetPropertyVal(key, m_uSelected, ppropvarNewValue); 1107 } 1108 else 1109 { 1110 return Collection::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue); 1111 } 1112 } 1113}; 1114 1115// ItemCollectionImpl: handles item image 1116// 1117template <class TCtrl, size_t t_items, size_t t_categories = 0> 1118class ItemCollectionImpl : public TextCollectionImpl<TCtrl, t_items, t_categories> 1119{ 1120 typedef ItemCollectionImpl<TCtrl, t_items, t_categories> thisClass; 1121public: 1122 typedef thisClass ItemCollection; 1123 1124 ItemCollectionImpl() 1125 { 1126 ZeroMemory(m_aBitmap, sizeof m_aBitmap); 1127 } 1128 1129 CBitmap m_aBitmap[t_items]; 1130 1131 // Operations 1132 HRESULT SetItemImage(UINT uIndex, HBITMAP hbm, bool bUpdate = false) 1133 { 1134 ATLASSERT(uIndex < t_items); 1135 1136 m_aBitmap[uIndex] = hbm; 1137 1138 return bUpdate ? InvalidateItems() : S_OK; 1139 } 1140 1141// Implementation 1142 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value) 1143 { 1144 ATLASSERT(uItem < t_items); 1145 1146 if (k_(key) == k_ItemImage) 1147 { 1148 if (m_aBitmap[uItem].IsNull()) 1149 { 1150 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon(); 1151 m_aBitmap[uItem] = ribbon.OnRibbonQueryItemImage(TCtrl::GetID(), uItem); 1152 } 1153 return m_aBitmap[uItem].IsNull() ? 1154 E_NOTIMPL : 1155 SetPropertyVal(key, GetImage(m_aBitmap[uItem], UI_OWNERSHIP_COPY), value); 1156 } 1157 else 1158 { 1159 return TextCollection::DoGetItem(uItem, key, value); 1160 } 1161 } 1162}; 1163 1164// ComboCollectionImpl: handles combo text 1165// 1166template <class TCtrl, size_t t_items, size_t t_categories = 0> 1167class ComboCollectionImpl : public ItemCollectionImpl<TCtrl, t_items, t_categories> 1168{ 1169 typedef ComboCollectionImpl<TCtrl, t_items, t_categories> thisClass; 1170public: 1171 typedef thisClass ComboCollection; 1172 1173 // Operations 1174 HRESULT SetComboText(LPCWSTR sText) 1175 { 1176 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon(); 1177 return ribbon.IsRibbonUI() ? 1178 ribbon.SetProperty(TCtrl::GetID(), UI_PKEY_StringValue, sText) : 1179 S_OK; 1180 } 1181 1182 LPCWSTR GetComboText() 1183 { 1184 static WCHAR sCombo[RIBBONUI_MAX_TEXT] = { 0 }; 1185 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon(); 1186 PROPVARIANT var; 1187 if (ribbon.IsRibbonUI()) 1188 { 1189 HRESULT hr = ribbon.GetIUIFrameworkPtr()->GetUICommandProperty(TCtrl::GetID(), UI_PKEY_StringValue, &var); 1190 hr = PropVariantToString(var, sCombo, RIBBONUI_MAX_TEXT); 1191 return sCombo; 1192 } 1193 return NULL; 1194 } 1195}; 1196 1197// CommandCollectionImpl: handles RibbonUI command collection controls 1198// 1199template <class TCtrl, size_t t_items, size_t t_categories = 0> 1200class CommandCollectionImpl : public CollectionImpl<TCtrl, t_items, t_categories> 1201{ 1202 typedef CommandCollectionImpl<TCtrl, t_items, t_categories> thisClass; 1203public: 1204 typedef thisClass CommandCollection; 1205 1206 CommandCollectionImpl() 1207 { 1208 ZeroMemory(m_auCmd, sizeof m_auCmd); 1209 ZeroMemory(m_aCmdType, sizeof m_aCmdType); 1210 } 1211 1212 UINT32 m_auCmd[t_items]; 1213 BYTE m_aCmdType[t_items]; 1214 1215 // Operations 1216 HRESULT SetItemCommand(UINT uItem, UINT32 uCommandID, bool bUpdate = false) 1217 { 1218 ATLASSERT(uItem < t_items); 1219 1220 if (uCommandID == m_auCmd[uItem]) 1221 return S_OK; 1222 1223 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon(); 1224 1225 m_auCmd[uItem] = uCommandID; 1226 if (uCommandID != 0) 1227 ribbon.UIAddRibbonElement(uCommandID); 1228 1229 return bUpdate ? InvalidateItems() : S_OK; 1230 } 1231 1232 HRESULT SetItemCommandType(UINT uItem, UI_COMMANDTYPE type, bool bUpdate = false) 1233 { 1234 ATLASSERT(uItem < t_items); 1235 1236 m_aCmdType[uItem] = (BYTE)type; 1237 1238 return bUpdate ? InvalidateItems() : S_OK; 1239 } 1240 1241// Implementation 1242 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value) 1243 { 1244 ATLASSERT(uItem < t_items); 1245 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon(); 1246 1247 HRESULT hr = E_FAIL; 1248 switch (k_(key)) 1249 { 1250 case k_CommandId: 1251 if (m_auCmd[uItem] == 0) 1252 SetItemCommand(uItem, ribbon.OnRibbonQueryItemCommand(TCtrl::GetID(), uItem)); 1253 hr = SetPropertyVal(key, m_auCmd[uItem], value); 1254 break; 1255 case k_CommandType: 1256 if (m_aCmdType[uItem] == UI_COMMANDTYPE_UNKNOWN) 1257 SetItemCommandType(uItem, ribbon.OnRibbonQueryItemCommandType(TCtrl::GetID(), uItem)); 1258 hr = SetPropertyVal(key, UINT32(m_aCmdType[uItem]), value); 1259 break; 1260 case k_CategoryId: 1261 default: 1262 hr = Collection::DoGetItem(uItem, key, value); 1263 break; 1264 } 1265 1266 return hr; 1267 } 1268 1269 HRESULT Select(UINT /*uItem*/, bool /*bUpdate*/ = false) 1270 { 1271 ATLASSERT(FALSE); 1272 return S_OK; 1273 } 1274}; 1275 1276// SimpleCollectionImpl: collection class for ribbon simple collection controls 1277// 1278template <class TCtrl, size_t t_size, UI_COMMANDTYPE t_CommandType = UI_COMMANDTYPE_ACTION> 1279class SimpleCollectionImpl : public CollectionImplBase<SimpleCollectionImpl<TCtrl, t_size>, t_size> 1280{ 1281 typedef SimpleCollectionImpl<TCtrl, t_size, t_CommandType> thisClass; 1282public: 1283 typedef CollectionImplBase<thisClass, t_size> CollectionBase; 1284 typedef thisClass SimpleCollection; 1285 1286// Implementation 1287 HRESULT OnGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value) 1288 { 1289 ATLASSERT(uItem < t_size); 1290 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon(); 1291 1292 HRESULT hr = E_NOTIMPL; 1293 switch (k_(key)) 1294 { 1295 case k_ItemImage: 1296 if (HBITMAP hbm = ribbon.DefRibbonQueryItemImage(TCtrl::GetID(), uItem)) 1297 hr = SetPropertyVal(key, GetImage(hbm, UI_OWNERSHIP_TRANSFER), value); 1298 break; 1299 case k_Label: 1300 if (LPCWSTR sText = ribbon.DefRibbonQueryItemText(TCtrl::GetID(), uItem)) 1301 hr = SetPropertyVal(key, (LPCWSTR)sText, value); 1302 break; 1303 case k_CommandType: 1304 hr = SetPropertyVal(key, t_CommandType, value); 1305 break; 1306 case k_CommandId: 1307 hr = SetPropertyVal(key, ribbon.DefRibbonQueryItemCommand(TCtrl::GetID(), uItem), value); 1308 break; 1309 case k_CategoryId: 1310 hr = SetPropertyVal(key, UI_COLLECTION_INVALIDINDEX, value); 1311 break; 1312 default: 1313 ATLASSERT(FALSE); 1314 break; 1315 } 1316 1317 return hr; 1318 } 1319}; 1320 1321 1322/////////////////////////////////////////////////////////////////////////////// 1323// Ribbon collection control classes 1324 1325// CollectionCtrlImpl: specializable class for ribbon collection controls 1326// 1327template <class T, UINT t_ID, class TCollection> 1328class CollectionCtrlImpl : public CommandCtrlImpl<T, t_ID>, public TCollection 1329{ 1330 typedef CollectionCtrlImpl<T, t_ID, TCollection> thisClass; 1331public: 1332 typedef CommandCtrlImpl<T, t_ID> CommandCtrl; 1333 typedef TCollection Collection; 1334 1335 // Implementation 1336 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key, 1337 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue) 1338 { 1339 ATLASSERT(nCmdID == GetID()); 1340 ATLASSERT(ppropvarNewValue); 1341 1342 HRESULT hr = Collection::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue); 1343 if FAILED(hr) 1344 hr = CommandCtrl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue); 1345 1346 return hr; 1347 } 1348 1349 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb, 1350 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue, 1351 IUISimplePropertySet* /*pCommandExecutionProperties*/) 1352 { 1353 ATLASSERT (nCmdID == GetID()); 1354 nCmdID; // avoid level4 warning 1355 1356 if (key == NULL) // gallery button pressed 1357 { 1358 GetWndRibbon().OnRibbonItemSelected(GetID(), UI_EXECUTIONVERB_EXECUTE, UI_COLLECTION_INVALIDINDEX); 1359 return S_OK; 1360 } 1361 1362 ATLASSERT(k_(*key) == k_SelectedItem); 1363 ATLASSERT(ppropvarValue); 1364 1365 HRESULT hr = S_OK; 1366 UINT32 uSel = 0xffff; 1367 hr = UIPropertyToUInt32(*key, *ppropvarValue, &uSel); 1368 1369 if (SUCCEEDED(hr)) 1370 { 1371 if (GetWndRibbon().OnRibbonItemSelected(GetID(), verb, uSel)) 1372 TCollection::Select(uSel); 1373 } 1374 1375 return hr; 1376 } 1377}; 1378 1379// ToolbarGalleryCtrlImpl: base class for ribbon toolbar gallery controls 1380// 1381template <class T, UINT t_ID, UINT t_idTB, size_t t_size> 1382class ToolbarGalleryCtrlImpl : public CollectionCtrlImpl<T, t_ID, CommandCollectionImpl<ToolbarGalleryCtrlImpl<T, t_ID, t_idTB, t_size>, t_size>> 1383{ 1384public: 1385 ToolbarGalleryCtrlImpl() 1386 { 1387 CResource tbres; 1388 ATLVERIFY(tbres.Load(RT_TOOLBAR, t_idTB)); 1389 _AtlToolBarData* pData = (_AtlToolBarData*)tbres.Lock(); 1390 ATLASSERT(pData); 1391 ATLASSERT(pData->wVersion == 1); 1392 1393 WORD* pItems = pData->items(); 1394 INT j = 0; 1395 for (int i = 0; (i < pData->wItemCount) && (j < t_size); i++) 1396 { 1397 if (pItems[i] != 0) 1398 { 1399 m_aCmdType[j] = UI_COMMANDTYPE_ACTION; 1400 m_auCmd[j++] = pItems[i]; 1401 } 1402 } 1403 1404 if (j < t_size) 1405 Resize(j); 1406 } 1407 1408 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value) 1409 { 1410 ATLASSERT(uItem < m_size); 1411 ATLASSERT(m_auCmd[uItem]); 1412 1413 HRESULT hr = E_FAIL; 1414 switch (k_(key)) 1415 { 1416 case k_CommandId: 1417 hr = SetPropertyVal(key, m_auCmd[uItem], value); 1418 break; 1419 case k_CommandType: 1420 hr = SetPropertyVal(key, UINT32(m_aCmdType[uItem]), value); 1421 break; 1422 case k_CategoryId: 1423 hr = SetPropertyVal(key, UI_COLLECTION_INVALIDINDEX, value); 1424 break; 1425 default: 1426 ATLASSERT(FALSE); 1427 break; 1428 } 1429 1430 return hr; 1431 } 1432}; 1433 1434 1435// SimpleCollectionCtrlImpl: base class for simple gallery and listbox controls 1436// 1437template <class T, UINT t_ID, size_t t_size, UI_COMMANDTYPE t_CommandType = UI_COMMANDTYPE_ACTION> 1438class SimpleCollectionCtrlImpl : 1439 public CommandCtrlImpl<T, t_ID>, 1440 public SimpleCollectionImpl<SimpleCollectionCtrlImpl<T, t_ID, t_size, t_CommandType>, t_size, t_CommandType> 1441{ 1442 typedef SimpleCollectionCtrlImpl<T, t_ID, t_size, t_CommandType> thisClass; 1443public: 1444 typedef thisClass SimpleCollection; 1445 1446 SimpleCollectionCtrlImpl() : m_uSelected(0) 1447 { } 1448 1449 UINT m_uSelected; 1450 1451 HRESULT Select(UINT uItem, bool bUpdate = false) 1452 { 1453 ATLASSERT((uItem < t_size) || (uItem == UI_COLLECTION_INVALIDINDEX)); 1454 1455 m_uSelected = uItem; 1456 1457 return bUpdate ? 1458 GetWndRibbon().SetProperty(GetID(), UI_PKEY_SelectedItem, uItem) : 1459 S_OK; 1460 } 1461 1462 // Implementation 1463 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key, 1464 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue) 1465 { 1466 ATLASSERT(nCmdID == GetID()); 1467 ATLASSERT(ppropvarNewValue != NULL); 1468 1469 HRESULT hr = S_OK; 1470 switch (k_(key)) 1471 { 1472 case k_ItemsSource: 1473 { 1474 ATL::CComQIPtr<IUICollection> pIUICollection(ppropvarCurrentValue->punkVal); 1475 ATLASSERT(pIUICollection.p); 1476 hr = pIUICollection->Clear(); 1477 for (UINT i = 0; i < t_size; i++) 1478 { 1479 if FAILED(hr = pIUICollection->Add(m_apItems[i])) 1480 break; 1481 } 1482 ATLASSERT(SUCCEEDED(hr)); 1483 } 1484 break; 1485 case k_SelectedItem: 1486 hr = SetPropertyVal(UI_PKEY_SelectedItem, m_uSelected, ppropvarNewValue); 1487 break; 1488 default: 1489 hr = CommandCtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue); 1490 break; 1491 } 1492 1493 return hr; 1494 } 1495 1496 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb, 1497 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue, 1498 IUISimplePropertySet* /*pCommandExecutionProperties*/) 1499 { 1500 ATLASSERT (nCmdID == GetID()); 1501 nCmdID; // avoid level 4 warning 1502 1503 HRESULT hr = S_OK; 1504 if (key == NULL) // gallery button pressed 1505 { 1506 GetWndRibbon().OnRibbonItemSelected(GetID(), UI_EXECUTIONVERB_EXECUTE, UI_COLLECTION_INVALIDINDEX); 1507 return hr; 1508 } 1509 ATLASSERT(k_(*key) == k_SelectedItem); 1510 ATLASSERT(ppropvarValue); 1511 1512 if SUCCEEDED(hr = UIPropertyToUInt32(*key, *ppropvarValue, &m_uSelected)) 1513 GetWndRibbon().OnRibbonItemSelected(GetID(), verb, m_uSelected); 1514 1515 return hr; 1516 } 1517}; 1518 1519// RecentItemsCtrlImpl 1520// 1521template <class T, UINT t_ID, class TDocList = CRecentDocumentList> 1522class RecentItemsCtrlImpl : 1523 public CtrlImpl<T, t_ID>, 1524 public CollectionImplBase<RecentItemsCtrlImpl<T, t_ID, TDocList>, TDocList::m_nMaxEntries_Max>, 1525 public TDocList 1526{ 1527 typedef RecentItemsCtrlImpl<T, t_ID, TDocList> thisClass; 1528public: 1529 typedef thisClass RecentItems; 1530 1531 // Implementation 1532 HRESULT OnGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value) 1533 { 1534 ATLASSERT((INT)uItem < GetMaxEntries()); 1535 1536 LPCWSTR sPath = m_arrDocs[uItem].szDocName; 1537 HRESULT hr = E_NOTIMPL; 1538 switch (k_(key)) 1539 { 1540 case k_Label: 1541 hr = SetPropertyVal(key, GetWndRibbon().OnRibbonQueryRecentItemName(sPath), value); 1542 break; 1543 case k_LabelDescription: 1544 hr = SetPropertyVal(key, sPath, value); 1545 break; 1546 default: 1547 ATLASSERT(FALSE); 1548 break; 1549 } 1550 1551 return hr; 1552 } 1553 1554 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key, 1555 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue) 1556 { 1557 ATLASSERT(nCmdID == GetID()); 1558 ATLASSERT(ppropvarNewValue); 1559 1560 HRESULT hr = S_OK; 1561 switch (k_(key)) 1562 { 1563 case k_RecentItems: 1564 if (SAFEARRAY* psa = SafeArrayCreateVector(VT_UNKNOWN, 0, m_arrDocs.GetSize())) 1565 { 1566 const int iLastIndex = m_arrDocs.GetSize() - 1; 1567 for (LONG i = 0; i <= iLastIndex; i++) 1568 SafeArrayPutElement(psa, &i, m_apItems[iLastIndex - i]); // reverse order 1569 1570 hr = SetPropertyVal(key, psa, ppropvarNewValue); 1571 SafeArrayDestroy(psa); 1572 } 1573 break; 1574 default: 1575 hr = CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue); 1576 break; 1577 } 1578 1579 return hr; 1580 } 1581 1582 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb, 1583 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue, 1584 IUISimplePropertySet* /*pCommandExecutionProperties*/) 1585 { 1586 ATLASSERT(nCmdID == GetID()); 1587 nCmdID; // avoid level 4 warning 1588 ATLASSERT(verb == UI_EXECUTIONVERB_EXECUTE); 1589 verb; // avoid level 4 warning 1590 ATLASSERT((key) && (k_(*key) == k_SelectedItem)); 1591 ATLASSERT(ppropvarValue); 1592 1593 UINT32 uSel = 0xffff; 1594 HRESULT hr = UIPropertyToUInt32(*key, *ppropvarValue, &uSel); 1595 if SUCCEEDED(hr) 1596 { 1597 ATLASSERT(uSel < (UINT)GetMaxEntries()); 1598 GetWndRibbon().DefCommandExecute(ID_FILE_MRU_FIRST + uSel); 1599 } 1600 1601 return hr; 1602 } 1603}; 1604 1605 1606/////////////////////////////////////////////////////////////////////////////// 1607// Ribbon stand-alone control classes 1608 1609// FontCtrlImpl 1610// 1611template <class T, UINT t_ID> 1612class FontCtrlImpl : public CtrlImpl<T, t_ID> 1613{ 1614public: 1615 1616 CharFormat m_cf; 1617 1618// Implementation 1619 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb, 1620 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue, 1621 IUISimplePropertySet* pCommandExecutionProperties) 1622 { 1623 ATLASSERT (nCmdID == GetID()); 1624 nCmdID; // avoid level 4 warning 1625 ATLASSERT ((key) && (k_(*key) == k_FontProperties)); 1626 key; // avoid level 4 warning 1627 1628 HRESULT hr = E_INVALIDARG; 1629 switch (verb) 1630 { 1631 case UI_EXECUTIONVERB_PREVIEW: 1632 case UI_EXECUTIONVERB_EXECUTE: 1633 ATLASSERT(pCommandExecutionProperties); 1634 PROPVARIANT propvar; 1635 1636 if (SUCCEEDED(hr = pCommandExecutionProperties->GetValue(UI_PKEY_FontProperties_ChangedProperties, &propvar))) 1637 m_cf << ATL::CComQIPtr<IPropertyStore>(propvar.punkVal); 1638 break; 1639 1640 case UI_EXECUTIONVERB_CANCELPREVIEW: 1641 ATLASSERT(ppropvarValue); 1642 ATL::CComPtr<IPropertyStore> pStore; 1643 1644 if (SUCCEEDED(hr = UIPropertyToInterface(UI_PKEY_FontProperties, *ppropvarValue, &pStore))) 1645 m_cf << pStore; 1646 break; 1647 } 1648 1649 if (SUCCEEDED(hr)) 1650 GetWndRibbon().OnRibbonFontCtrlExecute(GetID(), verb, &m_cf); 1651 else 1652 ATLASSERT(FALSE); 1653 1654 return hr; 1655 } 1656 1657 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key, 1658 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue) 1659 { 1660 if ((k_(key) == k_FontProperties) && (GetWndRibbon().OnRibbonQueryFont(t_ID, m_cf))) 1661 { 1662 ATL::CComQIPtr<IPropertyStore> pStore(ppropvarCurrentValue->punkVal); 1663 m_cf >> pStore; 1664 return SetPropertyVal(key, pStore.p, ppropvarNewValue); 1665 } 1666 else 1667 { 1668 return CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue); 1669 } 1670 } 1671}; 1672 1673// ColorCtrlImpl 1674// 1675template <class T, UINT t_ID> 1676class ColorCtrlImpl : public CommandCtrlImpl<T, t_ID> 1677{ 1678public: 1679 ColorCtrlImpl() : m_colorType(UI_SWATCHCOLORTYPE_NOCOLOR), m_color(0x800080) /*MAGENTA*/ 1680 { } 1681 1682 COLORREF m_color; 1683 UINT32 m_colorType; // value in UI_SWATCHCOLORTYPE 1684 Text m_sLabels[6]; // k_MoreColorsLabel to k_ThemeColorsCategoryLabel 1685 ATL::CSimpleArray<COLORREF> m_aColors[2]; 1686 ATL::CSimpleArray<LPCWSTR> m_aTooltips[2]; 1687 1688 // Operations 1689 HRESULT SetColor(COLORREF color, bool bUpdate = false) 1690 { 1691 if (m_colorType != UI_SWATCHCOLORTYPE_RGB) 1692 SetColorType(UI_SWATCHCOLORTYPE_RGB, bUpdate); 1693 m_color = color; 1694 return bUpdate ? SetProperty(UI_PKEY_Color, color) : S_OK; 1695 } 1696 1697 HRESULT SetColorType(UI_SWATCHCOLORTYPE type, bool bUpdate = false) 1698 { 1699 m_colorType = type; 1700 return bUpdate ? SetProperty(UI_PKEY_ColorType, type) : S_OK; 1701 } 1702 1703 HRESULT SetColorLabel(REFPROPERTYKEY key, LPCWSTR sLabel, bool bUpdate = false) 1704 { 1705 ATLASSERT((k_(key) >= k_ThemeColorsCategoryLabel) && (k_(key) <= k_MoreColorsLabel)); 1706 m_sLabels[k_(key) - k_ThemeColorsCategoryLabel] = sLabel; 1707 return bUpdate ? SetProperty(key, sLabel) : S_OK; 1708 } 1709 1710 HRESULT SetColorArray(REFPROPERTYKEY key, COLORREF* pColor, bool bUpdate = false) 1711 { 1712 ATLASSERT((k_(key) == k_ThemeColors) || (k_(key) == k_StandardColors)); 1713 1714 const INT ic = k_(key) - k_ThemeColors; 1715 m_aColors[ic].RemoveAll(); 1716 while (*pColor != 0x800080) /*MAGENTA*/ 1717 m_aColors[ic].Add(*pColor++); 1718 1719 if (bUpdate) 1720 { 1721 PROPVARIANT var; 1722 if SUCCEEDED(InitPropVariantFromUInt32Vector(m_aColors[ic].GetData(), m_aColors[ic].GetSize(), &var)) 1723 return SetProperty(key, var); 1724 else 1725 return E_INVALIDARG; 1726 } 1727 else 1728 { 1729 return S_OK; 1730 } 1731 } 1732 1733 HRESULT SetColorTooltips(REFPROPERTYKEY key, LPCWSTR* ppsTT, bool bUpdate = false) 1734 { 1735 ATLASSERT((k_(key) == k_ThemeColorsTooltips) || (k_(key) == k_StandardColorsTooltips)); 1736 1737 const INT ic = k_(key) - k_ThemeColorsTooltips; 1738 m_aTooltips[ic].RemoveAll(); 1739 while (*ppsTT) 1740 m_aTooltips[ic].Add(*ppsTT++); 1741 1742 if (bUpdate) 1743 { 1744 PROPVARIANT var; 1745 if SUCCEEDED(InitPropVariantFromStringVector(m_aTooltips[ic].GetData(), m_aTooltips[ic].GetSize(), &var)) 1746 return SetProperty(key, var); 1747 else 1748 return E_INVALIDARG; 1749 } 1750 else 1751 { 1752 return S_OK; 1753 } 1754 } 1755 1756 // Implementation 1757 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb, 1758 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue, 1759 IUISimplePropertySet* pCommandExecutionProperties) 1760 { 1761 ATLASSERT (nCmdID == GetID()); 1762 nCmdID; // avoid level 4 warning 1763 ATLASSERT (key && (k_(*key) == k_ColorType)); 1764 key; // avoid level 4 warning 1765 ATLASSERT (ppropvarValue); 1766 1767 HRESULT hr = PropVariantToUInt32(*ppropvarValue, &m_colorType); 1768 ATLASSERT(SUCCEEDED(hr)); 1769 1770 if (SUCCEEDED(hr…
Large files files are truncated, but you can click here to view the full file