1 // Windows Template Library - WTL version 9.10
2 // Copyright (C) Microsoft Corporation, WTL Team. 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 Public License (http://opensource.org/licenses/MS-PL)
7 // which can be found in the file MS-PL.txt at the root folder.
8
9 #ifndef __ATLRIBBON_H__
10 #define __ATLRIBBON_H__
11
12 #pragma once
13
14 #if (_MSC_VER < 1500)
15 #error atlribbon.h requires Visual C++ 2008 compiler or higher
16 #endif
17
18 #ifndef _UNICODE
19 #error atlribbon.h requires the Unicode character set
20 #endif
21
22 #if !defined(NTDDI_WIN7) || (NTDDI_VERSION < NTDDI_WIN7)
23 #error atlribbon.h requires the Windows 7 SDK or higher
24 #endif
25
26 #ifdef _WIN32_WCE
27 #error atlribbon.h is not supported on Windows CE
28 #endif
29
30 #ifndef __ATLAPP_H__
31 #error atlribbon.h requires atlapp.h to be included first
32 #endif
33
34 #if (_ATL_VER < 0x0700)
35 #include <shlwapi.h>
36 #pragma comment(lib, "shlwapi.lib")
37 #endif
38
39 #include <atlmisc.h> // for RecentDocumentList classes
40 #include <atlframe.h> // for Frame and UpdateUI classes
41 #include <atlctrls.h> // required for atlctrlw.h
42 #include <atlctrlw.h> // for CCommandBarCtrl
43
44 #if !defined(_WTL_USE_CSTRING) && !defined(__ATLSTR_H__)
45 #pragma warning(push)
46 #pragma warning(disable: 4530) // unwind semantics not enabled
47 #include <string>
48 #pragma warning(pop)
49 #endif
50
51 #include <dwmapi.h>
52 #pragma comment(lib, "dwmapi.lib")
53
54 #include <UIRibbon.h>
55 #include <UIRibbonPropertyHelpers.h>
56 #pragma comment(lib, "propsys.lib")
57
58 #include <Richedit.h> // for CHARFORMAT2
59
60
61 ///////////////////////////////////////////////////////////////////////////////
62 // Classes in this file:
63 //
64 // CRibbonUpdateUI : Automatic mapping of ribbon UI elements
65 //
66 // RibbonUI::Text
67 // RibbonUI::CharFormat
68 // RibbonUI::ICtrl
69 // RibbonUI::CtrlImpl
70 // RibbonUI::CommandCtrlImpl
71 // RibbonUI::ItemProperty
72 // RibbonUI::CollectionImplBase
73 // RibbonUI::CollectionImpl
74 // RibbonUI::TextCollectionImpl
75 // RibbonUI::ItemCollectionImpl
76 // RibbonUI::ComboCollectionImpl
77 // RibbonUI::CommandCollectionImpl
78 // RibbonUI::ToolbarCollectionImpl
79 // RibbonUI::SimpleCollectionImpl
80 // RibbonUI::CollectionCtrlImpl
81 // RibbonUI::ToolbarGalleryCtrlImpl
82 // RibbonUI::SimpleCollectionCtrlImpl
83 // RibbonUI::RecentItemsCtrlImpl
84 // RibbonUI::FontCtrlImpl
85 // RibbonUI::ColorCtrlImpl
86 // RibbonUI::SpinnerCtrlImpl
87 //
88 // RibbonUI::CRibbonImpl
89 // CRibbonImpl::CRibbonComboCtrl
90 // CRibbonImpl::CRibbonItemGalleryCtrl
91 // CRibbonImpl::CRibbonCommandGalleryCtrl
92 // CRibbonImpl::CRibbonToolbarGalleryCtrl
93 // CRibbonImpl::CRibbonSimpleComboCtrl
94 // CRibbonImpl::CRibbonSimpleGalleryCtrl
95 // CRibbonImpl::CRibbonRecentItemsCtrl
96 // CRibbonImpl::CRibbonColorCtrl
97 // CRibbonImpl::CRibbonFontCtrl
98 // CRibbonImpl::CRibbonSpinnerCtrl
99 // CRibbonImpl::CRibbonFloatSpinnerCtrl
100 // CRibbonImpl::CRibbonCommandCtrl
101 //
102 // CRibbonFrameWindowImplBase
103 // CRibbonFrameWindowImpl
104 // CRibbonMDIFrameWindowImpl
105 // CRibbonPersist
106 //
107 // Global functions:
108 // RibbonUI::SetPropertyVal()
109 // RibbonUI::GetImage()
110
111
112 // Constants
113
114 #ifndef RIBBONUI_MAX_TEXT
115 #define RIBBONUI_MAX_TEXT 128
116 #endif
117
118 #define TWIPS_PER_POINT 20 // For font size
119
120
121 namespace WTL
122 {
123
124 ///////////////////////////////////////////////////////////////////////////////
125 // CRibbonUpdateUI : Automatic mapping of ribbon UI elements
126
127 template <class T>
128 class CRibbonUpdateUI : public CAutoUpdateUI<T>
129 {
130 public:
131 enum
132 {
133 UPDUI_RIBBON = 0x0080,
134 UPDUI_PERSIST = 0x0020
135 };
136
IsRibbonElement(const _AtlUpdateUIMap & UIMap)137 bool IsRibbonElement(const _AtlUpdateUIMap& UIMap)
138 {
139 return (UIMap.m_wType & UPDUI_RIBBON) != 0;
140 }
141
IsRibbonID(UINT nID)142 bool IsRibbonID(UINT nID)
143 {
144 for(int i = 0; i < m_arrUIMap.GetSize(); i++)
145 {
146 if(m_arrUIMap[i].m_nID == nID)
147 return IsRibbonElement(m_arrUIMap[i]);
148 }
149
150 return false;
151 }
152
153 // Element
UIAddRibbonElement(UINT nID)154 bool UIAddRibbonElement(UINT nID)
155 {
156 return UIAddElement<UPDUI_RIBBON>(nID);
157 }
158
UIRemoveRibbonElement(UINT nID)159 bool UIRemoveRibbonElement(UINT nID)
160 {
161 return UIRemoveElement<UPDUI_RIBBON>(nID);
162 }
163
164 bool UIPersistElement(UINT nID, bool bPersist = true)
165 {
166 return bPersist ?
167 UIAddElement<UPDUI_PERSIST>(nID) :
168 UIRemoveElement<UPDUI_PERSIST>(nID);
169 }
170
171 // methods for Ribbon elements
172 BOOL UISetText(int nID, LPCWSTR sText, BOOL bForceUpdate = FALSE)
173 {
174 T* pT = static_cast<T*>(this);
175 BOOL bRes = CUpdateUIBase::UISetText(nID, sText, bForceUpdate);
176 if (pT->IsRibbonUI() && IsRibbonID(nID))
177 bRes = SUCCEEDED(pT->InvalidateProperty(nID, UI_PKEY_Label));
178 return bRes;
179 }
180
181 BOOL UISetText(int nID, UINT uIdResource, BOOL bForceUpdate = FALSE)
182 {
183 CTempBuffer<WCHAR> sText(RIBBONUI_MAX_TEXT);
184 int nRet = AtlLoadString(uIdResource, sText, RIBBONUI_MAX_TEXT);
185 if(nRet > 0)
186 UISetText(nID, sText, bForceUpdate);
187 return (nRet > 0) ? TRUE : FALSE;
188 }
189
UIGetText(int nID)190 LPCTSTR UIGetText(int nID)
191 {
192 T* pT = static_cast<T*>(this);
193 LPCTSTR sUI = CAutoUpdateUI::UIGetText(nID);
194
195 // replace 'tab' by 'space' for RibbonUI elements
196 if (sUI && pT->IsRibbonUI() && IsRibbonID(nID) && wcschr(sUI, L'\t'))
197 {
198 static WCHAR sText[RIBBONUI_MAX_TEXT] = { 0 };
199 wcscpy_s(sText, sUI);
200 WCHAR* pch = wcschr(sText, L'\t');
201 if (pch != NULL)
202 *pch = L' ';
203 return sText;
204 }
205 else
206 {
207 return sUI;
208 }
209 }
210
211 BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE)
212 {
213 T* pT = static_cast<T*>(this);
214 BOOL bRes = CUpdateUIBase::UIEnable(nID, bEnable, bForceUpdate);
215 if (pT->IsRibbonUI() && IsRibbonID(nID))
216 bRes = SUCCEEDED(pT->SetProperty((WORD)nID, UI_PKEY_Enabled, bEnable));
217 return bRes;
218 }
219
220 BOOL UISetCheck(int nID, INT nCheck, BOOL bForceUpdate = FALSE)
221 {
222 if ((nCheck == 0) || (nCheck == 1))
223 return UISetCheck(nID, nCheck != 0, bForceUpdate);
224 else
225 return CUpdateUIBase::UISetCheck(nID, nCheck, bForceUpdate);
226 }
227
228 BOOL UISetCheck(int nID, bool bCheck, BOOL bForceUpdate = FALSE)
229 {
230 T* pT = static_cast<T*>(this);
231 BOOL bRes = CUpdateUIBase::UISetCheck(nID, bCheck, bForceUpdate);
232 if (bRes && pT->IsRibbonUI() && IsRibbonID(nID))
233 bRes = SUCCEEDED(pT->SetProperty((WORD)nID, UI_PKEY_BooleanValue, bCheck));
234 return bRes;
235 }
236 };
237
238
239 ///////////////////////////////////////////////////////////////////////////////
240 // RibbonUI namespace
241 //
242
243 namespace RibbonUI
244 {
245
246 // Minimal string allocation support for various PROPERTYKEY values
247 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
248 typedef _CSTRING_NS::CString Text;
249 #else
250 class Text : public std::wstring
251 {
252 public:
253 Text(std::wstring& s) : std::wstring(s)
254 { }
255 Text(LPCWSTR s) : std::wstring(s)
256 { }
257 Text()
258 { }
259 bool IsEmpty()
260 {
261 return empty();
262 }
263 operator LPCWSTR()
264 {
265 return c_str();
266 }
267 Text& operator =(LPCWSTR s)
268 {
269 return static_cast<Text&>(std::wstring::operator =(s));
270 }
271 };
272 #endif
273
274 // PROPERTYKEY enum and helpers
275 enum k_KEY
276 {
277 // state
278 k_Enabled = 1, k_BooleanValue = 200,
279 // text properties
280 k_LabelDescription = 2, k_Keytip = 3, k_Label = 4, k_TooltipDescription = 5, k_TooltipTitle = 6,
281 // image properties
282 k_LargeImage = 7, k_LargeHighContrastImage = 8, k_SmallImage = 9, k_SmallHighContrastImage = 10,
283 // collection properties
284 k_ItemsSource = 101, k_Categories = 102, k_SelectedItem = 104,
285 // collection item properties
286 k_CommandId = 100, k_CategoryId = 103, k_CommandType = 105, k_ItemImage = 106,
287 // combo control property
288 k_StringValue = 202,
289 // spinner control properties
290 k_DecimalValue = 201, k_MaxValue = 203, k_MinValue, k_Increment, k_DecimalPlaces, k_FormatString, k_RepresentativeString = 208,
291 // font control properties
292 k_FontProperties = 300, k_FontProperties_Family, k_FontProperties_Size, k_FontProperties_Bold, k_FontProperties_Italic = 304,
293 k_FontProperties_Underline = 305, k_FontProperties_Strikethrough, k_FontProperties_VerticalPositioning, k_FontProperties_ForegroundColor = 308,
294 k_FontProperties_BackgroundColor = 309, k_FontProperties_ForegroundColorType, k_FontProperties_BackgroundColorType, k_FontProperties_ChangedProperties = 312,
295 k_FontProperties_DeltaSize = 313,
296 // recent items properties
297 k_RecentItems = 350, k_Pinned = 351,
298 // color control properties
299 k_Color = 400, k_ColorType = 401, k_ColorMode,
300 k_ThemeColorsCategoryLabel = 403, k_StandardColorsCategoryLabel, k_RecentColorsCategoryLabel = 405, k_AutomaticColorLabel = 406,
301 k_NoColorLabel = 407, k_MoreColorsLabel = 408,
302 k_ThemeColors = 409, k_StandardColors = 410, k_ThemeColorsTooltips = 411, k_StandardColorsTooltips = 412,
303 // Ribbon state
304 k_Viewable = 1000, k_Minimized = 1001, k_QuickAccessToolbarDock = 1002, k_ContextAvailable = 1100,
305 // Ribbon UI colors
306 k_GlobalBackgroundColor = 2000, k_GlobalHighlightColor, k_GlobalTextColor = 2002
307 };
308
k_(REFPROPERTYKEY key)309 inline k_KEY k_(REFPROPERTYKEY key)
310 {
311 return (k_KEY)key.fmtid.Data1;
312 }
313
314 // PROPERTYKEY value assignment and specializations
315 //
316 template <typename V>
SetPropertyVal(REFPROPERTYKEY key,V val,PROPVARIANT * ppv)317 HRESULT SetPropertyVal(REFPROPERTYKEY key, V val, PROPVARIANT* ppv)
318 {
319 switch (k_(key))
320 {
321 case k_Enabled:
322 case k_BooleanValue:
323 return InitPropVariantFromBoolean(val, ppv);
324 default:
325 return UIInitPropertyFromUInt32(key, val, ppv);
326 }
327 }
328
SetPropertyVal(REFPROPERTYKEY key,DOUBLE val,PROPVARIANT * ppv)329 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, DOUBLE val, PROPVARIANT* ppv)
330 {
331 return SetPropertyVal(key, (LONG)val, ppv);
332 }
333
SetPropertyVal(REFPROPERTYKEY key,IUIImage * val,PROPVARIANT * ppv)334 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, IUIImage* val, PROPVARIANT* ppv)
335 {
336 HRESULT hr = UIInitPropertyFromImage(key, val, ppv);
337 ATLVERIFY(val->Release() == 1);
338 return hr;
339 }
340
SetPropertyVal(REFPROPERTYKEY key,IUnknown * val,PROPVARIANT * ppv)341 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, IUnknown* val, PROPVARIANT* ppv)
342 {
343 return UIInitPropertyFromInterface(key, val, ppv);
344 }
345
SetPropertyVal(REFPROPERTYKEY key,IPropertyStore * val,PROPVARIANT * ppv)346 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, IPropertyStore* val, PROPVARIANT* ppv)
347 {
348 return UIInitPropertyFromInterface(key, val, ppv);
349 }
350
SetPropertyVal(REFPROPERTYKEY key,SAFEARRAY * val,PROPVARIANT * ppv)351 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, SAFEARRAY* val, PROPVARIANT* ppv)
352 {
353 return UIInitPropertyFromIUnknownArray(key, val, ppv);
354 }
355
SetPropertyVal(REFPROPERTYKEY key,DECIMAL * val,PROPVARIANT * ppv)356 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, DECIMAL* val, PROPVARIANT* ppv)
357 {
358 return UIInitPropertyFromDecimal(key, *val, ppv);
359 }
360
SetPropertyVal(REFPROPERTYKEY key,bool val,PROPVARIANT * ppv)361 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, bool val, PROPVARIANT* ppv)
362 {
363 return UIInitPropertyFromBoolean(key, val, ppv);
364 }
365
SetPropertyVal(REFPROPERTYKEY key,LPCWSTR val,PROPVARIANT * ppv)366 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, LPCWSTR val, PROPVARIANT* ppv)
367 {
368 return UIInitPropertyFromString(key, val, ppv);
369 }
370
371 // CharFormat helper struct for RibbonUI font control
372 //
373 struct CharFormat : CHARFORMAT2
374 {
375 // Default constructor
CharFormatCharFormat376 CharFormat()
377 {
378 cbSize = sizeof(CHARFORMAT2);
379 Reset();
380 }
381
382 // Copy constructor
CharFormatCharFormat383 CharFormat(const CharFormat& cf)
384 {
385 ::CopyMemory(this, &cf, sizeof(CHARFORMAT2));
386 }
387
388 // Assign operator
389 CharFormat& operator =(const CharFormat& cf)
390 {
391 ::CopyMemory(this, &cf, sizeof(CHARFORMAT2));
392 return (*this);
393 }
394
ResetCharFormat395 void Reset()
396 {
397 uValue = dwMask = dwEffects = 0;
398 PropVariantInit(&propvar);
399 }
400
401 void operator <<(IPropertyStore* pStore)
402 {
403 if (pStore == NULL)
404 {
405 ATLASSERT(FALSE);
406 return;
407 }
408
409 static void (CharFormat::*Getk_[])(IPropertyStore*) =
410 {
411 &CharFormat::Getk_Family,
412 &CharFormat::Getk_FontProperties_Size,
413 &CharFormat::Getk_MaskEffect<CFM_BOLD, CFE_BOLD, UI_PKEY_FontProperties_Bold>,
414 &CharFormat::Getk_MaskEffect<CFM_ITALIC, CFE_ITALIC, UI_PKEY_FontProperties_Italic>,
415 &CharFormat::Getk_MaskEffect<CFM_UNDERLINE, CFE_UNDERLINE, UI_PKEY_FontProperties_Underline>,
416 &CharFormat::Getk_MaskEffect<CFM_STRIKEOUT, CFE_STRIKEOUT, UI_PKEY_FontProperties_Strikethrough>,
417 &CharFormat::Getk_VerticalPositioning,
418 &CharFormat::Getk_Color<CFM_COLOR, UI_PKEY_FontProperties_ForegroundColor>,
419 &CharFormat::Getk_Color<CFM_BACKCOLOR, UI_PKEY_FontProperties_BackgroundColor>,
420 &CharFormat::Getk_ColorType<CFM_COLOR, CFE_AUTOCOLOR, UI_SWATCHCOLORTYPE_AUTOMATIC, UI_PKEY_FontProperties_ForegroundColorType>,
421 &CharFormat::Getk_ColorType<CFM_BACKCOLOR, CFE_AUTOBACKCOLOR, UI_SWATCHCOLORTYPE_NOCOLOR, UI_PKEY_FontProperties_BackgroundColorType>,
422 };
423
424 DWORD nProps = 0;
425 Reset();
426
427 ATLVERIFY(SUCCEEDED(pStore->GetCount(&nProps)));
428 for (DWORD iProp = 0; iProp < nProps; iProp++)
429 {
430 PROPERTYKEY key;
431 ATLVERIFY(SUCCEEDED(pStore->GetAt(iProp, &key)));
432 ATLASSERT(k_(key) >= k_FontProperties_Family);
433
434 if (k_(key) <= k_FontProperties_BackgroundColorType)
435 (this->*Getk_[k_(key) - k_FontProperties_Family])(pStore);
436 }
437 }
438
439 void operator >>(IPropertyStore* pStore)
440 {
441 if (pStore == NULL)
442 {
443 ATLASSERT(FALSE);
444 return;
445 }
446
447 PutFace(pStore);
448 PutSize(pStore);
449 PutMaskEffect(CFM_BOLD, CFE_BOLD, UI_PKEY_FontProperties_Bold, pStore);
450 PutMaskEffect(CFM_ITALIC, CFE_ITALIC, UI_PKEY_FontProperties_Italic, pStore);
451 PutMaskEffect(CFM_UNDERLINE, CFE_UNDERLINE, UI_PKEY_FontProperties_Underline, pStore);
452 PutMaskEffect(CFM_STRIKEOUT, CFE_STRIKEOUT, UI_PKEY_FontProperties_Strikethrough, pStore);
453 PutVerticalPos(pStore);
454 PutColor(pStore);
455 PutBackColor(pStore);
456 }
457
458 private:
459 PROPVARIANT propvar;
460 UINT uValue;
461
462 // Getk_ functions
Getk_FamilyCharFormat463 void Getk_Family(IPropertyStore* pStore)
464 {
465 if (SUCCEEDED(pStore->GetValue(UI_PKEY_FontProperties_Family, &propvar)))
466 {
467 PropVariantToString(propvar, szFaceName, LF_FACESIZE);
468 if (*szFaceName)
469 dwMask |= CFM_FACE;
470 }
471 }
472
Getk_FontProperties_SizeCharFormat473 void Getk_FontProperties_Size(IPropertyStore* pStore)
474 {
475 if (SUCCEEDED(pStore->GetValue(UI_PKEY_FontProperties_Size, &propvar)))
476 {
477 DECIMAL decSize = { 0 };
478 UIPropertyToDecimal(UI_PKEY_FontProperties_Size, propvar, &decSize);
479 DOUBLE dSize = 0;
480 VarR8FromDec(&decSize, &dSize);
481 if (dSize > 0)
482 {
483 dwMask |= CFM_SIZE;
484 yHeight = (LONG)(dSize * TWIPS_PER_POINT);
485 }
486 }
487 }
488
489 template <DWORD t_dwMask, DWORD t_dwEffects, REFPROPERTYKEY key>
Getk_MaskEffectCharFormat490 void Getk_MaskEffect(IPropertyStore* pStore)
491 {
492 if (SUCCEEDED(pStore->GetValue(key, &propvar)))
493 {
494 UIPropertyToUInt32(key, propvar, &uValue);
495 if ((UI_FONTPROPERTIES)uValue != UI_FONTPROPERTIES_NOTAVAILABLE)
496 {
497 dwMask |= t_dwMask;
498 dwEffects |= ((UI_FONTPROPERTIES) uValue == UI_FONTPROPERTIES_SET) ? t_dwEffects : 0;
499 }
500 }
501 }
502
Getk_VerticalPositioningCharFormat503 void Getk_VerticalPositioning(IPropertyStore* pStore)
504 {
505 if (SUCCEEDED(pStore->GetValue(UI_PKEY_FontProperties_VerticalPositioning, &propvar)))
506 {
507 UIPropertyToUInt32(UI_PKEY_FontProperties_VerticalPositioning, propvar, &uValue);
508 UI_FONTVERTICALPOSITION uVerticalPosition = (UI_FONTVERTICALPOSITION) uValue;
509 if ((uVerticalPosition != UI_FONTVERTICALPOSITION_NOTAVAILABLE))
510 {
511 dwMask |= (CFM_SUPERSCRIPT | CFM_SUBSCRIPT);
512 if (uVerticalPosition != UI_FONTVERTICALPOSITION_NOTSET)
513 {
514 dwEffects |= (uVerticalPosition == UI_FONTVERTICALPOSITION_SUPERSCRIPT) ? CFE_SUPERSCRIPT : CFE_SUBSCRIPT;
515 }
516 }
517 }
518 }
519
520 template <DWORD t_dwMask, REFPROPERTYKEY key>
Getk_ColorCharFormat521 void Getk_Color(IPropertyStore* pStore)
522 {
523 UINT32 color = 0;
524 if (SUCCEEDED(pStore->GetValue(key, &propvar)))
525 {
526 UIPropertyToUInt32(key, propvar, &color);
527 dwMask |= t_dwMask;
528
529 if (t_dwMask == CFM_COLOR)
530 crTextColor = color;
531 else
532 crBackColor = color;
533 }
534 }
535
536 template <DWORD t_dwMask, DWORD t_dwEffects, UI_SWATCHCOLORTYPE t_type, REFPROPERTYKEY key>
Getk_ColorTypeCharFormat537 void Getk_ColorType(IPropertyStore* pStore)
538 {
539 if (SUCCEEDED(pStore->GetValue(key, &propvar)))
540 {
541 UIPropertyToUInt32(key, propvar, &uValue);
542 if (t_type == (UI_SWATCHCOLORTYPE)uValue)
543 {
544 dwMask |= t_dwMask;
545 dwEffects |= t_dwEffects;
546 }
547 }
548 }
549
550 // Put functions
PutMaskEffectCharFormat551 void PutMaskEffect(WORD dwMaskVal, WORD dwEffectVal, REFPROPERTYKEY key, IPropertyStore* pStore)
552 {
553 PROPVARIANT var;
554 UI_FONTPROPERTIES uProp = UI_FONTPROPERTIES_NOTAVAILABLE;
555 if ((dwMask & dwMaskVal) != 0)
556 uProp = dwEffects & dwEffectVal ? UI_FONTPROPERTIES_SET : UI_FONTPROPERTIES_NOTSET;
557 SetPropertyVal(key, uProp, &var);
558 pStore->SetValue(key, var);
559 }
560
PutVerticalPosCharFormat561 void PutVerticalPos(IPropertyStore* pStore)
562 {
563 PROPVARIANT var;
564 UI_FONTVERTICALPOSITION uProp = UI_FONTVERTICALPOSITION_NOTAVAILABLE;
565
566 if ((dwMask & CFE_SUBSCRIPT) != 0)
567 {
568 if ((dwMask & CFM_SUBSCRIPT) && (dwEffects & CFE_SUBSCRIPT))
569 uProp = UI_FONTVERTICALPOSITION_SUBSCRIPT;
570 else
571 uProp = UI_FONTVERTICALPOSITION_SUPERSCRIPT;
572 }
573 else if ((dwMask & CFM_OFFSET) != 0)
574 {
575 if (yOffset > 0)
576 uProp = UI_FONTVERTICALPOSITION_SUPERSCRIPT;
577 else if (yOffset < 0)
578 uProp = UI_FONTVERTICALPOSITION_SUBSCRIPT;
579 }
580
581 SetPropertyVal(UI_PKEY_FontProperties_VerticalPositioning, uProp, &var);
582 pStore->SetValue(UI_PKEY_FontProperties_VerticalPositioning, var);
583 }
584
PutFaceCharFormat585 void PutFace(IPropertyStore* pStore)
586 {
587 PROPVARIANT var;
588 SetPropertyVal(UI_PKEY_FontProperties_Family,
589 dwMask & CFM_FACE ? szFaceName : L"", &var);
590 pStore->SetValue(UI_PKEY_FontProperties_Family, var);
591 }
592
PutSizeCharFormat593 void PutSize(IPropertyStore* pStore)
594 {
595 PROPVARIANT var;
596 DECIMAL decVal;
597
598 if ((dwMask & CFM_SIZE) != 0)
599 VarDecFromR8((DOUBLE)yHeight / TWIPS_PER_POINT, &decVal);
600 else
601 VarDecFromI4(0, &decVal);
602
603 SetPropertyVal(UI_PKEY_FontProperties_Size, &decVal, &var);
604 pStore->SetValue(UI_PKEY_FontProperties_Size, var);
605 }
606
PutColorCharFormat607 void PutColor(IPropertyStore* pStore)
608 {
609 if ((dwMask & CFM_COLOR) != 0)
610 {
611 if ((dwEffects & CFE_AUTOCOLOR) == 0)
612 {
613 SetPropertyVal(UI_PKEY_FontProperties_ForegroundColorType, UI_SWATCHCOLORTYPE_RGB, &propvar);
614 pStore->SetValue(UI_PKEY_FontProperties_ForegroundColorType, propvar);
615
616 SetPropertyVal(UI_PKEY_FontProperties_ForegroundColor, crTextColor, &propvar);
617 pStore->SetValue(UI_PKEY_FontProperties_ForegroundColor, propvar);
618 }
619 else
620 {
621 SetPropertyVal(UI_PKEY_FontProperties_ForegroundColorType, UI_SWATCHCOLORTYPE_AUTOMATIC, &propvar);
622 pStore->SetValue(UI_PKEY_FontProperties_ForegroundColorType, propvar);
623 }
624 }
625 }
626
PutBackColorCharFormat627 void PutBackColor(IPropertyStore* pStore)
628 {
629 if (((dwMask & CFM_BACKCOLOR) != 0) && ((dwEffects & CFE_AUTOBACKCOLOR) == 0))
630 {
631 SetPropertyVal(UI_PKEY_FontProperties_BackgroundColorType, UI_SWATCHCOLORTYPE_RGB, &propvar);
632 pStore->SetValue(UI_PKEY_FontProperties_BackgroundColorType, propvar);
633
634 SetPropertyVal(UI_PKEY_FontProperties_BackgroundColor, crBackColor, &propvar);
635 pStore->SetValue(UI_PKEY_FontProperties_BackgroundColor, propvar);
636 }
637 else
638 {
639 SetPropertyVal(UI_PKEY_FontProperties_BackgroundColorType, UI_SWATCHCOLORTYPE_NOCOLOR, &propvar);
640 pStore->SetValue(UI_PKEY_FontProperties_BackgroundColorType, propvar);
641 }
642 }
643 };
644
645 // IUIImage helper
646 //
GetImage(HBITMAP hbm,UI_OWNERSHIP owner)647 inline IUIImage* GetImage(HBITMAP hbm, UI_OWNERSHIP owner)
648 {
649 ATLASSERT(hbm);
650 IUIImage* pIUII = NULL;
651 ATL::CComPtr<IUIImageFromBitmap> pIFB;
652
653 if SUCCEEDED(pIFB.CoCreateInstance(CLSID_UIRibbonImageFromBitmapFactory))
654 ATLVERIFY(SUCCEEDED(pIFB->CreateImage(hbm, owner, &pIUII)));
655
656 return pIUII;
657 }
658
659
660 ///////////////////////////////////////////////////////////////////////////////
661 // Ribbon control classes
662
663 // RibbonUI::ICtrl abstract interface of RibbonUI::CRibbonImpl and all RibbonUI control classes
664 //
665 struct ICtrl
666 {
667 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
668 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
669 IUISimplePropertySet* pCommandExecutionProperties) = 0;
670
671 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
672 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue) = 0;
673 };
674
675 // RibbonUI::CtrlImpl base class for all ribbon controls
676 //
677 template <class T, UINT t_ID>
678 class ATL_NO_VTABLE CtrlImpl : public ICtrl
679 {
680 protected:
681 T* m_pWndRibbon;
682
683 public:
684 typedef T WndRibbon;
685
CtrlImpl()686 CtrlImpl() : m_pWndRibbon(T::pWndRibbon)
687 { }
688
GetWndRibbon()689 WndRibbon& GetWndRibbon()
690 {
691 return *m_pWndRibbon;
692 }
693
GetID()694 static WORD GetID()
695 {
696 return t_ID;
697 }
698
699 Text m_sTxt[5];
700
701 // Operations
Invalidate()702 HRESULT Invalidate()
703 {
704 return GetWndRibbon().InvalidateCtrl(GetID());
705 }
706
707 HRESULT Invalidate(REFPROPERTYKEY key, UI_INVALIDATIONS flags = UI_INVALIDATIONS_PROPERTY)
708 {
709 return GetWndRibbon().InvalidateProperty(GetID(), key, flags);
710 }
711
712 HRESULT SetText(REFPROPERTYKEY key, LPCWSTR sTxt, bool bUpdate = false)
713 {
714 ATLASSERT((k_(key) <= k_TooltipTitle) && (k_(key) >= k_LabelDescription));
715
716 m_sTxt[k_(key) - k_LabelDescription] = sTxt;
717
718 return bUpdate ?
719 GetWndRibbon().InvalidateProperty(GetID(), key) :
720 S_OK;
721 }
722
723 // Implementation
724 template <typename V>
SetProperty(REFPROPERTYKEY key,V val)725 HRESULT SetProperty(REFPROPERTYKEY key, V val)
726 {
727 return GetWndRibbon().SetProperty(GetID(), key, val);
728 }
729
OnGetText(REFPROPERTYKEY key,PROPVARIANT * ppv)730 HRESULT OnGetText(REFPROPERTYKEY key, PROPVARIANT* ppv)
731 {
732 ATLASSERT((k_(key) <= k_TooltipTitle) && (k_(key) >= k_LabelDescription));
733
734 const INT iText = k_(key) - k_LabelDescription;
735 if (m_sTxt[iText].IsEmpty())
736 if (LPCWSTR sText = GetWndRibbon().OnRibbonQueryText(GetID(), key))
737 m_sTxt[iText] = sText;
738
739 return !m_sTxt[iText].IsEmpty() ?
740 SetPropertyVal(key, (LPCWSTR)m_sTxt[iText], ppv) :
741 S_OK;
742 }
743
DoExecute(UINT nCmdID,UI_EXECUTIONVERB verb,const PROPERTYKEY * key,const PROPVARIANT * ppropvarValue,IUISimplePropertySet * pCommandExecutionProperties)744 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
745 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
746 IUISimplePropertySet* pCommandExecutionProperties)
747 {
748 ATLASSERT(nCmdID == t_ID);
749 return GetWndRibbon().DoExecute(nCmdID, verb, key, ppropvarValue, pCommandExecutionProperties);
750 }
751
DoUpdateProperty(UINT nCmdID,REFPROPERTYKEY key,const PROPVARIANT * ppropvarCurrentValue,PROPVARIANT * ppropvarNewValue)752 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
753 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
754 {
755 ATLASSERT(nCmdID == t_ID);
756
757 const INT iMax = k_TooltipTitle - k_LabelDescription;
758 const INT iVal = k_(key) - k_LabelDescription;
759
760 return (iVal <= iMax) && (iVal >= 0) ?
761 OnGetText(key, ppropvarNewValue) :
762 GetWndRibbon().DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
763 }
764 };
765
766 // CommandCtrlImpl base class for most ribbon controls
767 //
768 template <class T, UINT t_ID>
769 class CommandCtrlImpl : public CtrlImpl<T, t_ID>
770 {
771 public:
772 CBitmap m_hbm[4];
773
774 HRESULT SetImage(REFPROPERTYKEY key, HBITMAP hbm, bool bUpdate = false)
775 {
776 ATLASSERT((k_(key) <= k_SmallHighContrastImage) && (k_(key) >= k_LargeImage));
777
778 m_hbm[k_(key) - k_LargeImage].Attach(hbm);
779
780 return bUpdate ?
781 GetWndRibbon().InvalidateProperty(GetID(), key) :
782 S_OK;
783 }
784
OnGetImage(REFPROPERTYKEY key,PROPVARIANT * ppv)785 HRESULT OnGetImage(REFPROPERTYKEY key, PROPVARIANT* ppv)
786 {
787 ATLASSERT((k_(key) <= k_SmallHighContrastImage) && (k_(key) >= k_LargeImage));
788
789 const INT iImage = k_(key) - k_LargeImage;
790
791 if (m_hbm[iImage].IsNull())
792 m_hbm[iImage] = GetWndRibbon().OnRibbonQueryImage(GetID(), key);
793
794 return m_hbm[iImage].IsNull() ?
795 E_NOTIMPL :
796 SetPropertyVal(key, GetImage(m_hbm[iImage], UI_OWNERSHIP_COPY), ppv);
797 }
798
DoUpdateProperty(UINT nCmdID,REFPROPERTYKEY key,const PROPVARIANT * ppropvarCurrentValue,PROPVARIANT * ppropvarNewValue)799 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
800 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
801 {
802 ATLASSERT (nCmdID == GetID());
803
804 return (k_(key) <= k_SmallHighContrastImage) && (k_(key) >= k_LargeImage) ?
805 OnGetImage(key, ppropvarNewValue) :
806 CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
807 }
808 };
809
810
811 ///////////////////////////////////////////////////////////////////////////////
812 // Ribbon collection base classes
813
814 // ItemProperty class: ribbon callback for each item in a collection
815 //
816
817 #pragma warning(push)
818 #pragma warning(disable: 4512) // assignment operator could not be generated
819
820 template <class TCollection>
821 class ItemProperty : public IUISimplePropertySet
822 {
823 public:
ItemProperty(UINT i,TCollection * pCollection)824 ItemProperty(UINT i, TCollection* pCollection) : m_Index(i), m_pCollection(pCollection)
825 { }
826
827 const UINT m_Index;
828 TCollection* m_pCollection;
829
830 // IUISimplePropertySet method.
GetValue(REFPROPERTYKEY key,PROPVARIANT * value)831 STDMETHODIMP GetValue(REFPROPERTYKEY key, PROPVARIANT *value)
832 {
833 return m_pCollection->OnGetItem(m_Index, key, value);
834 }
835
836 // IUnknown methods.
AddRef()837 STDMETHODIMP_(ULONG) AddRef()
838 {
839 return 1;
840 }
841
Release()842 STDMETHODIMP_(ULONG) Release()
843 {
844 return 1;
845 }
846
QueryInterface(REFIID iid,void ** ppv)847 STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
848 {
849 if ((iid == __uuidof(IUnknown)) || (iid == __uuidof(IUISimplePropertySet)))
850 {
851 *ppv = this;
852 return S_OK;
853 }
854 else
855 {
856 return E_NOINTERFACE;
857 }
858 }
859 };
860
861 #pragma warning(pop)
862
863
864 // CollectionImplBase: base class for all RibbonUI collections
865 //
866 template <class TCollection, size_t t_size>
867 class CollectionImplBase
868 {
869 typedef CollectionImplBase<TCollection, t_size> thisClass;
870
871 public:
CollectionImplBase()872 CollectionImplBase()
873 {
874 for (int i = 0; i < t_size; i++)
875 m_apItems[i] = new ItemProperty<TCollection>(i, static_cast<TCollection*>(this));
876 }
877
~CollectionImplBase()878 ~CollectionImplBase()
879 {
880 for (int i = 0; i < t_size; i++)
881 delete m_apItems[i];
882 }
883
884 // Data members
885 ItemProperty<TCollection>* m_apItems[t_size];
886 };
887
888 // CollectionImpl: handles categories and collecton resizing
889 //
890 template <class TCtrl, size_t t_items, size_t t_categories>
891 class CollectionImpl : public CollectionImplBase<CollectionImpl<TCtrl, t_items, t_categories>, t_items + t_categories>
892 {
893 typedef CollectionImpl<TCtrl, t_items, t_categories> thisClass;
894 public:
895 typedef thisClass Collection;
896
CollectionImpl()897 CollectionImpl() : m_size(t_items)
898 {
899 ::FillMemory(m_auItemCat, sizeof(m_auItemCat), 0xff); // UI_COLLECTION_INVALIDINDEX
900 }
901
902 UINT32 m_auItemCat[t_items];
903 Text m_asCatName[__max(t_categories, 1)];
904 size_t m_size;
905
906 // Operations
907 HRESULT SetItemCategory(UINT uItem, UINT uCat, bool bUpdate = false)
908 {
909 ATLASSERT((uItem < t_items) && (uCat < t_categories));
910
911 m_auItemCat[uItem] = uCat;
912
913 return bUpdate ? InvalidateItems() : S_OK;
914 }
915
916 HRESULT SetCategoryText(UINT uCat, LPCWSTR sText, bool bUpdate = false)
917 {
918 ATLASSERT(uCat < t_categories);
919
920 m_asCatName[uCat] = sText;
921
922 return bUpdate ? InvalidateCategories() : S_OK;
923 }
924
925 HRESULT Resize(size_t size, bool bUpdate = false)
926 {
927 ATLASSERT(size <= t_items);
928
929 m_size = size;
930
931 return bUpdate ? InvalidateItems() : S_OK;
932 }
933
934 // Implementation
OnGetItem(UINT uIndex,REFPROPERTYKEY key,PROPVARIANT * value)935 HRESULT OnGetItem(UINT uIndex, REFPROPERTYKEY key, PROPVARIANT *value)
936 {
937 ATLASSERT(uIndex < t_items + t_categories);
938 TCtrl* pCtrl = static_cast<TCtrl*>(this);
939
940 return uIndex < t_items ?
941 pCtrl->DoGetItem(uIndex, key, value) :
942 pCtrl->DoGetCategory(uIndex - t_items, key, value);
943 }
944
DoGetItem(UINT uItem,REFPROPERTYKEY key,PROPVARIANT * value)945 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
946 {
947 ATLASSERT(k_(key) == k_CategoryId);
948 UINT32 uCat = UI_COLLECTION_INVALIDINDEX;
949
950 if (t_categories != 0)
951 {
952 if (m_auItemCat[uItem] == UI_COLLECTION_INVALIDINDEX)
953 {
954 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
955 m_auItemCat[uItem] = ribbon.OnRibbonQueryItemCategory(TCtrl::GetID(), uItem);
956 }
957 uCat = m_auItemCat[uItem];
958 }
959
960 return SetPropertyVal(key, uCat, value);
961 }
962
DoGetCategory(UINT uCat,REFPROPERTYKEY key,PROPVARIANT * value)963 HRESULT DoGetCategory(UINT uCat, REFPROPERTYKEY key, PROPVARIANT *value)
964 {
965 HRESULT hr = S_OK;
966
967 switch (k_(key))
968 {
969 case k_Label:
970 if (m_asCatName[uCat].IsEmpty())
971 {
972 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
973 m_asCatName[uCat] = ribbon.OnRibbonQueryCategoryText(TCtrl::GetID(), uCat);
974 }
975 hr = SetPropertyVal(key, (LPCWSTR)m_asCatName[uCat], value);
976 break;
977 case k_CategoryId:
978 hr = SetPropertyVal(key, uCat, value);
979 break;
980 default:
981 ATLASSERT(FALSE);
982 break;
983 }
984
985 return hr;
986 }
987
InvalidateItems()988 HRESULT InvalidateItems()
989 {
990 return static_cast<TCtrl*>(this)->Invalidate(UI_PKEY_ItemsSource);
991 }
992
InvalidateCategories()993 HRESULT InvalidateCategories()
994 {
995 return static_cast<TCtrl*>(this)->Invalidate(UI_PKEY_Categories);
996 }
997
DoUpdateProperty(UINT nCmdID,REFPROPERTYKEY key,const PROPVARIANT * ppropvarCurrentValue,PROPVARIANT *)998 HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
999 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* /*ppropvarNewValue*/)
1000 {
1001 ATLASSERT(nCmdID == TCtrl::GetID());
1002 nCmdID; // avoid level 4 warning
1003
1004 HRESULT hr = E_NOTIMPL;
1005 switch (k_(key))
1006 {
1007 case k_ItemsSource:
1008 {
1009 ATL::CComQIPtr<IUICollection> pIUICollection(ppropvarCurrentValue->punkVal);
1010 ATLASSERT(pIUICollection);
1011 hr = pIUICollection->Clear();
1012 for (UINT i = 0; i < m_size; i++)
1013 {
1014 if FAILED(hr = pIUICollection->Add(m_apItems[i]))
1015 break;
1016 }
1017 ATLASSERT(SUCCEEDED(hr));
1018 }
1019 break;
1020 case k_Categories:
1021 if (t_categories != 0)
1022 {
1023 ATL::CComQIPtr<IUICollection> pIUICategory(ppropvarCurrentValue->punkVal);
1024 ATLASSERT(pIUICategory.p);
1025 hr = pIUICategory->Clear();
1026 for (UINT i = t_items; i < (t_items + t_categories); i++)
1027 {
1028 if FAILED(hr = pIUICategory->Add(m_apItems[i]))
1029 break;
1030 }
1031 ATLASSERT(SUCCEEDED(hr));
1032 }
1033 break;
1034 }
1035
1036 return hr;
1037 }
1038 };
1039
1040 // TextCollectionImpl: handles item labels and selection
1041 //
1042 template <class TCtrl, size_t t_items, size_t t_categories = 0>
1043 class TextCollectionImpl : public CollectionImpl<TCtrl, t_items, t_categories>
1044 {
1045 typedef TextCollectionImpl<TCtrl, t_items, t_categories> thisClass;
1046 public:
1047 typedef thisClass TextCollection;
1048
TextCollectionImpl()1049 TextCollectionImpl() : m_uSelected(UI_COLLECTION_INVALIDINDEX)
1050 { }
1051
1052 Text m_asText[t_items];
1053 UINT m_uSelected;
1054
1055 // Operations
1056 HRESULT SetItemText(UINT uItem, LPCWSTR sText, bool bUpdate = false)
1057 {
1058 ATLASSERT(uItem < t_items);
1059
1060 m_asText[uItem] = sText;
1061
1062 return bUpdate ? InvalidateItems() : S_OK;
1063 }
1064
GetSelected()1065 UINT GetSelected()
1066 {
1067 return m_uSelected;
1068 }
1069
1070 HRESULT Select(UINT uItem, bool bUpdate = false)
1071 {
1072 ATLASSERT((uItem < t_items) || (uItem == UI_COLLECTION_INVALIDINDEX));
1073
1074 m_uSelected = uItem;
1075
1076 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1077 return bUpdate ?
1078 ribbon.SetProperty(TCtrl::GetID(), UI_PKEY_SelectedItem, uItem) :
1079 S_OK;
1080 }
1081
1082 // Implementation
DoGetItem(UINT uItem,REFPROPERTYKEY key,PROPVARIANT * value)1083 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
1084 {
1085 ATLASSERT(uItem < t_items);
1086
1087 if (k_(key) == k_Label)
1088 {
1089 if (m_asText[uItem].IsEmpty())
1090 {
1091 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1092 m_asText[uItem] = ribbon.OnRibbonQueryItemText(TCtrl::GetID(), uItem);
1093 }
1094 return SetPropertyVal(key, (LPCWSTR)m_asText[uItem], value);
1095 }
1096 else
1097 {
1098 return Collection::DoGetItem(uItem, key, value);
1099 }
1100 }
1101
DoUpdateProperty(UINT nCmdID,REFPROPERTYKEY key,const PROPVARIANT * ppropvarCurrentValue,PROPVARIANT * ppropvarNewValue)1102 HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
1103 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
1104 {
1105 ATLASSERT(nCmdID == TCtrl::GetID());
1106
1107 if (k_(key) == k_SelectedItem)
1108 {
1109 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1110 UINT uSel = UI_COLLECTION_INVALIDINDEX;
1111 if ((m_uSelected == UI_COLLECTION_INVALIDINDEX) &&
1112 ribbon.OnRibbonQuerySelectedItem(TCtrl::GetID(), uSel))
1113 m_uSelected = uSel;
1114
1115 return SetPropertyVal(key, m_uSelected, ppropvarNewValue);
1116 }
1117 else
1118 {
1119 return Collection::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1120 }
1121 }
1122 };
1123
1124 // ItemCollectionImpl: handles item image
1125 //
1126 template <class TCtrl, size_t t_items, size_t t_categories = 0>
1127 class ItemCollectionImpl : public TextCollectionImpl<TCtrl, t_items, t_categories>
1128 {
1129 typedef ItemCollectionImpl<TCtrl, t_items, t_categories> thisClass;
1130 public:
1131 typedef thisClass ItemCollection;
1132
ItemCollectionImpl()1133 ItemCollectionImpl()
1134 {
1135 ::ZeroMemory(m_aBitmap, sizeof(m_aBitmap));
1136 }
1137
1138 CBitmap m_aBitmap[t_items];
1139
1140 // Operations
1141 HRESULT SetItemImage(UINT uIndex, HBITMAP hbm, bool bUpdate = false)
1142 {
1143 ATLASSERT(uIndex < t_items);
1144
1145 m_aBitmap[uIndex] = hbm;
1146
1147 return bUpdate ? InvalidateItems() : S_OK;
1148 }
1149
1150 // Implementation
DoGetItem(UINT uItem,REFPROPERTYKEY key,PROPVARIANT * value)1151 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
1152 {
1153 ATLASSERT(uItem < t_items);
1154
1155 if (k_(key) == k_ItemImage)
1156 {
1157 if (m_aBitmap[uItem].IsNull())
1158 {
1159 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1160 m_aBitmap[uItem] = ribbon.OnRibbonQueryItemImage(TCtrl::GetID(), uItem);
1161 }
1162 return m_aBitmap[uItem].IsNull() ?
1163 E_NOTIMPL :
1164 SetPropertyVal(key, GetImage(m_aBitmap[uItem], UI_OWNERSHIP_COPY), value);
1165 }
1166 else
1167 {
1168 return TextCollection::DoGetItem(uItem, key, value);
1169 }
1170 }
1171 };
1172
1173 // ComboCollectionImpl: handles combo text
1174 //
1175 template <class TCtrl, size_t t_items, size_t t_categories = 0>
1176 class ComboCollectionImpl : public ItemCollectionImpl<TCtrl, t_items, t_categories>
1177 {
1178 typedef ComboCollectionImpl<TCtrl, t_items, t_categories> thisClass;
1179 public:
1180 typedef thisClass ComboCollection;
1181
1182 // Operations
SetComboText(LPCWSTR sText)1183 HRESULT SetComboText(LPCWSTR sText)
1184 {
1185 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1186 return ribbon.IsRibbonUI() ?
1187 ribbon.SetProperty(TCtrl::GetID(), UI_PKEY_StringValue, sText) :
1188 S_OK;
1189 }
1190
GetComboText()1191 LPCWSTR GetComboText()
1192 {
1193 static WCHAR sCombo[RIBBONUI_MAX_TEXT] = { 0 };
1194 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1195 PROPVARIANT var;
1196 if (ribbon.IsRibbonUI())
1197 {
1198 HRESULT hr = ribbon.GetIUIFrameworkPtr()->GetUICommandProperty(TCtrl::GetID(), UI_PKEY_StringValue, &var);
1199 hr = PropVariantToString(var, sCombo, RIBBONUI_MAX_TEXT);
1200 return sCombo;
1201 }
1202 return NULL;
1203 }
1204 };
1205
1206 // CommandCollectionImpl: handles RibbonUI command collection controls
1207 //
1208 template <class TCtrl, size_t t_items, size_t t_categories = 0>
1209 class CommandCollectionImpl : public CollectionImpl<TCtrl, t_items, t_categories>
1210 {
1211 typedef CommandCollectionImpl<TCtrl, t_items, t_categories> thisClass;
1212 public:
1213 typedef thisClass CommandCollection;
1214
CommandCollectionImpl()1215 CommandCollectionImpl()
1216 {
1217 ::ZeroMemory(m_auCmd, sizeof(m_auCmd));
1218 ::ZeroMemory(m_aCmdType, sizeof(m_aCmdType));
1219 }
1220
1221 UINT32 m_auCmd[t_items];
1222 BYTE m_aCmdType[t_items];
1223
1224 // Operations
1225 HRESULT SetItemCommand(UINT uItem, UINT32 uCommandID, bool bUpdate = false)
1226 {
1227 ATLASSERT(uItem < t_items);
1228
1229 if (uCommandID == m_auCmd[uItem])
1230 return S_OK;
1231
1232 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1233
1234 m_auCmd[uItem] = uCommandID;
1235 if (uCommandID != 0)
1236 ribbon.UIAddRibbonElement(uCommandID);
1237
1238 return bUpdate ? InvalidateItems() : S_OK;
1239 }
1240
1241 HRESULT SetItemCommandType(UINT uItem, UI_COMMANDTYPE type, bool bUpdate = false)
1242 {
1243 ATLASSERT(uItem < t_items);
1244
1245 m_aCmdType[uItem] = (BYTE)type;
1246
1247 return bUpdate ? InvalidateItems() : S_OK;
1248 }
1249
1250 // Implementation
DoGetItem(UINT uItem,REFPROPERTYKEY key,PROPVARIANT * value)1251 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
1252 {
1253 ATLASSERT(uItem < t_items);
1254 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1255
1256 HRESULT hr = E_FAIL;
1257 switch (k_(key))
1258 {
1259 case k_CommandId:
1260 if (m_auCmd[uItem] == 0)
1261 SetItemCommand(uItem, ribbon.OnRibbonQueryItemCommand(TCtrl::GetID(), uItem));
1262 hr = SetPropertyVal(key, m_auCmd[uItem], value);
1263 break;
1264 case k_CommandType:
1265 if (m_aCmdType[uItem] == UI_COMMANDTYPE_UNKNOWN)
1266 SetItemCommandType(uItem, ribbon.OnRibbonQueryItemCommandType(TCtrl::GetID(), uItem));
1267 hr = SetPropertyVal(key, UINT32(m_aCmdType[uItem]), value);
1268 break;
1269 case k_CategoryId:
1270 default:
1271 hr = Collection::DoGetItem(uItem, key, value);
1272 break;
1273 }
1274
1275 return hr;
1276 }
1277
1278 HRESULT Select(UINT /*uItem*/, bool /*bUpdate*/ = false)
1279 {
1280 ATLASSERT(FALSE);
1281 return S_OK;
1282 }
1283 };
1284
1285 // SimpleCollectionImpl: collection class for ribbon simple collection controls
1286 //
1287 template <class TCtrl, size_t t_size, UI_COMMANDTYPE t_CommandType = UI_COMMANDTYPE_ACTION>
1288 class SimpleCollectionImpl : public CollectionImplBase<SimpleCollectionImpl<TCtrl, t_size>, t_size>
1289 {
1290 typedef SimpleCollectionImpl<TCtrl, t_size, t_CommandType> thisClass;
1291 public:
1292 typedef CollectionImplBase<thisClass, t_size> CollectionBase;
1293 typedef thisClass SimpleCollection;
1294
1295 // Implementation
OnGetItem(UINT uItem,REFPROPERTYKEY key,PROPVARIANT * value)1296 HRESULT OnGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
1297 {
1298 ATLASSERT(uItem < t_size);
1299 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1300
1301 HRESULT hr = E_NOTIMPL;
1302 switch (k_(key))
1303 {
1304 case k_ItemImage:
1305 if (HBITMAP hbm = ribbon.DefRibbonQueryItemImage(TCtrl::GetID(), uItem))
1306 hr = SetPropertyVal(key, GetImage(hbm, UI_OWNERSHIP_TRANSFER), value);
1307 break;
1308 case k_Label:
1309 if (LPCWSTR sText = ribbon.DefRibbonQueryItemText(TCtrl::GetID(), uItem))
1310 hr = SetPropertyVal(key, (LPCWSTR)sText, value);
1311 break;
1312 case k_CommandType:
1313 hr = SetPropertyVal(key, t_CommandType, value);
1314 break;
1315 case k_CommandId:
1316 hr = SetPropertyVal(key, ribbon.DefRibbonQueryItemCommand(TCtrl::GetID(), uItem), value);
1317 break;
1318 case k_CategoryId:
1319 hr = SetPropertyVal(key, UI_COLLECTION_INVALIDINDEX, value);
1320 break;
1321 default:
1322 ATLASSERT(FALSE);
1323 break;
1324 }
1325
1326 return hr;
1327 }
1328 };
1329
1330
1331 ///////////////////////////////////////////////////////////////////////////////
1332 // Ribbon collection control classes
1333
1334 // CollectionCtrlImpl: specializable class for ribbon collection controls
1335 //
1336 template <class T, UINT t_ID, class TCollection>
1337 class CollectionCtrlImpl : public CommandCtrlImpl<T, t_ID>, public TCollection
1338 {
1339 typedef CollectionCtrlImpl<T, t_ID, TCollection> thisClass;
1340 public:
1341 typedef CommandCtrlImpl<T, t_ID> CommandCtrl;
1342 typedef TCollection Collection;
1343
1344 // Implementation
DoUpdateProperty(UINT nCmdID,REFPROPERTYKEY key,const PROPVARIANT * ppropvarCurrentValue,PROPVARIANT * ppropvarNewValue)1345 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
1346 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
1347 {
1348 ATLASSERT(nCmdID == GetID());
1349 ATLASSERT(ppropvarNewValue);
1350
1351 HRESULT hr = Collection::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1352 if FAILED(hr)
1353 hr = CommandCtrl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1354
1355 return hr;
1356 }
1357
DoExecute(UINT nCmdID,UI_EXECUTIONVERB verb,const PROPERTYKEY * key,const PROPVARIANT * ppropvarValue,IUISimplePropertySet *)1358 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
1359 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
1360 IUISimplePropertySet* /*pCommandExecutionProperties*/)
1361 {
1362 ATLASSERT (nCmdID == GetID());
1363 nCmdID; // avoid level4 warning
1364
1365 if (key == NULL) // gallery button pressed
1366 {
1367 GetWndRibbon().OnRibbonItemSelected(GetID(), UI_EXECUTIONVERB_EXECUTE, UI_COLLECTION_INVALIDINDEX);
1368 return S_OK;
1369 }
1370
1371 ATLASSERT(k_(*key) == k_SelectedItem);
1372 ATLASSERT(ppropvarValue);
1373
1374 HRESULT hr = S_OK;
1375 UINT32 uSel = 0xffff;
1376 hr = UIPropertyToUInt32(*key, *ppropvarValue, &uSel);
1377
1378 if (SUCCEEDED(hr))
1379 {
1380 if (GetWndRibbon().OnRibbonItemSelected(GetID(), verb, uSel))
1381 TCollection::Select(uSel);
1382 }
1383
1384 return hr;
1385 }
1386 };
1387
1388 // ToolbarGalleryCtrlImpl: base class for ribbon toolbar gallery controls
1389 //
1390 template <class T, UINT t_ID, UINT t_idTB, size_t t_size>
1391 class ToolbarGalleryCtrlImpl : public CollectionCtrlImpl<T, t_ID, CommandCollectionImpl<ToolbarGalleryCtrlImpl<T, t_ID, t_idTB, t_size>, t_size>>
1392 {
1393 public:
ToolbarGalleryCtrlImpl()1394 ToolbarGalleryCtrlImpl()
1395 {
1396 CResource tbres;
1397 ATLVERIFY(tbres.Load(RT_TOOLBAR, t_idTB));
1398 _AtlToolBarData* pData = (_AtlToolBarData*)tbres.Lock();
1399 ATLASSERT(pData);
1400 ATLASSERT(pData->wVersion == 1);
1401
1402 WORD* pItems = pData->items();
1403 INT j = 0;
1404 for (int i = 0; (i < pData->wItemCount) && (j < t_size); i++)
1405 {
1406 if (pItems[i] != 0)
1407 {
1408 m_aCmdType[j] = UI_COMMANDTYPE_ACTION;
1409 m_auCmd[j++] = pItems[i];
1410 }
1411 }
1412
1413 if (j < t_size)
1414 Resize(j);
1415 }
1416
DoGetItem(UINT uItem,REFPROPERTYKEY key,PROPVARIANT * value)1417 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
1418 {
1419 ATLASSERT(uItem < m_size);
1420 ATLASSERT(m_auCmd[uItem]);
1421
1422 HRESULT hr = E_FAIL;
1423 switch (k_(key))
1424 {
1425 case k_CommandId:
1426 hr = SetPropertyVal(key, m_auCmd[uItem], value);
1427 break;
1428 case k_CommandType:
1429 hr = SetPropertyVal(key, UINT32(m_aCmdType[uItem]), value);
1430 break;
1431 case k_CategoryId:
1432 hr = SetPropertyVal(key, UI_COLLECTION_INVALIDINDEX, value);
1433 break;
1434 default:
1435 ATLASSERT(FALSE);
1436 break;
1437 }
1438
1439 return hr;
1440 }
1441 };
1442
1443
1444 // SimpleCollectionCtrlImpl: base class for simple gallery and listbox controls
1445 //
1446 template <class T, UINT t_ID, size_t t_size, UI_COMMANDTYPE t_CommandType = UI_COMMANDTYPE_ACTION>
1447 class SimpleCollectionCtrlImpl :
1448 public CommandCtrlImpl<T, t_ID>,
1449 public SimpleCollectionImpl<SimpleCollectionCtrlImpl<T, t_ID, t_size, t_CommandType>, t_size, t_CommandType>
1450 {
1451 typedef SimpleCollectionCtrlImpl<T, t_ID, t_size, t_CommandType> thisClass;
1452 public:
1453 typedef thisClass SimpleCollection;
1454
SimpleCollectionCtrlImpl()1455 SimpleCollectionCtrlImpl() : m_uSelected(0)
1456 { }
1457
1458 UINT m_uSelected;
1459
1460 HRESULT Select(UINT uItem, bool bUpdate = false)
1461 {
1462 ATLASSERT((uItem < t_size) || (uItem == UI_COLLECTION_INVALIDINDEX));
1463
1464 m_uSelected = uItem;
1465
1466 return bUpdate ?
1467 GetWndRibbon().SetProperty(GetID(), UI_PKEY_SelectedItem, uItem) :
1468 S_OK;
1469 }
1470
1471 // Implementation
DoUpdateProperty(UINT nCmdID,REFPROPERTYKEY key,const PROPVARIANT * ppropvarCurrentValue,PROPVARIANT * ppropvarNewValue)1472 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
1473 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
1474 {
1475 ATLASSERT(nCmdID == GetID());
1476 ATLASSERT(ppropvarNewValue != NULL);
1477
1478 HRESULT hr = S_OK;
1479 switch (k_(key))
1480 {
1481 case k_ItemsSource:
1482 {
1483 ATL::CComQIPtr<IUICollection> pIUICollection(ppropvarCurrentValue->punkVal);
1484 ATLASSERT(pIUICollection.p);
1485 hr = pIUICollection->Clear();
1486 for (UINT i = 0; i < t_size; i++)
1487 {
1488 if FAILED(hr = pIUICollection->Add(m_apItems[i]))
1489 break;
1490 }
1491 ATLASSERT(SUCCEEDED(hr));
1492 }
1493 break;
1494 case k_SelectedItem:
1495 hr = SetPropertyVal(UI_PKEY_SelectedItem, m_uSelected, ppropvarNewValue);
1496 break;
1497 default:
1498 hr = CommandCtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1499 break;
1500 }
1501
1502 return hr;
1503 }
1504
DoExecute(UINT nCmdID,UI_EXECUTIONVERB verb,const PROPERTYKEY * key,const PROPVARIANT * ppropvarValue,IUISimplePropertySet *)1505 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
1506 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
1507 IUISimplePropertySet* /*pCommandExecutionProperties*/)
1508 {
1509 ATLASSERT (nCmdID == GetID());
1510 nCmdID; // avoid level 4 warning
1511
1512 HRESULT hr = S_OK;
1513 if (key == NULL) // gallery button pressed
1514 {
1515 GetWndRibbon().OnRibbonItemSelected(GetID(), UI_EXECUTIONVERB_EXECUTE, UI_COLLECTION_INVALIDINDEX);
1516 return hr;
1517 }
1518 ATLASSERT(k_(*key) == k_SelectedItem);
1519 ATLASSERT(ppropvarValue);
1520
1521 if SUCCEEDED(hr = UIPropertyToUInt32(*key, *ppropvarValue, &m_uSelected))
1522 GetWndRibbon().OnRibbonItemSelected(GetID(), verb, m_uSelected);
1523
1524 return hr;
1525 }
1526 };
1527
1528 // RecentItemsCtrlImpl
1529 //
1530 template <class T, UINT t_ID, class TDocList = CRecentDocumentList>
1531 class RecentItemsCtrlImpl :
1532 public CtrlImpl<T, t_ID>,
1533 public CollectionImplBase<RecentItemsCtrlImpl<T, t_ID, TDocList>, TDocList::m_nMaxEntries_Max>,
1534 public TDocList
1535 {
1536 typedef RecentItemsCtrlImpl<T, t_ID, TDocList> thisClass;
1537 public:
1538 typedef thisClass RecentItems;
1539
1540 // Implementation
OnGetItem(UINT uItem,REFPROPERTYKEY key,PROPVARIANT * value)1541 HRESULT OnGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
1542 {
1543 ATLASSERT((INT)uItem < GetMaxEntries());
1544
1545 LPCWSTR sPath = m_arrDocs[uItem].szDocName;
1546 HRESULT hr = E_NOTIMPL;
1547 switch (k_(key))
1548 {
1549 case k_Label:
1550 hr = SetPropertyVal(key, GetWndRibbon().OnRibbonQueryRecentItemName(sPath), value);
1551 break;
1552 case k_LabelDescription:
1553 hr = SetPropertyVal(key, sPath, value);
1554 break;
1555 default:
1556 ATLASSERT(FALSE);
1557 break;
1558 }
1559
1560 return hr;
1561 }
1562
DoUpdateProperty(UINT nCmdID,REFPROPERTYKEY key,const PROPVARIANT * ppropvarCurrentValue,PROPVARIANT * ppropvarNewValue)1563 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
1564 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
1565 {
1566 ATLASSERT(nCmdID == GetID());
1567 ATLASSERT(ppropvarNewValue);
1568
1569 HRESULT hr = S_OK;
1570 switch (k_(key))
1571 {
1572 case k_RecentItems:
1573 if (SAFEARRAY* psa = SafeArrayCreateVector(VT_UNKNOWN, 0, m_arrDocs.GetSize()))
1574 {
1575 const int iLastIndex = m_arrDocs.GetSize() - 1;
1576 for (LONG i = 0; i <= iLastIndex; i++)
1577 SafeArrayPutElement(psa, &i, m_apItems[iLastIndex - i]); // reverse order
1578
1579 hr = SetPropertyVal(key, psa, ppropvarNewValue);
1580 SafeArrayDestroy(psa);
1581 }
1582 break;
1583 default:
1584 hr = CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1585 break;
1586 }
1587
1588 return hr;
1589 }
1590
DoExecute(UINT nCmdID,UI_EXECUTIONVERB verb,const PROPERTYKEY * key,const PROPVARIANT * ppropvarValue,IUISimplePropertySet *)1591 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
1592 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
1593 IUISimplePropertySet* /*pCommandExecutionProperties*/)
1594 {
1595 ATLASSERT(nCmdID == GetID());
1596 nCmdID; // avoid level 4 warning
1597 ATLASSERT(verb == UI_EXECUTIONVERB_EXECUTE);
1598 verb; // avoid level 4 warning
1599 ATLASSERT((key) && (k_(*key) == k_SelectedItem));
1600 ATLASSERT(ppropvarValue);
1601
1602 UINT32 uSel = 0xffff;
1603 HRESULT hr = UIPropertyToUInt32(*key, *ppropvarValue, &uSel);
1604 if SUCCEEDED(hr)
1605 {
1606 ATLASSERT(uSel < (UINT)GetMaxEntries());
1607 GetWndRibbon().DefCommandExecute(ID_FILE_MRU_FIRST + uSel);
1608 }
1609
1610 return hr;
1611 }
1612 };
1613
1614
1615 ///////////////////////////////////////////////////////////////////////////////
1616 // Ribbon stand-alone control classes
1617
1618 // FontCtrlImpl
1619 //
1620 template <class T, UINT t_ID>
1621 class FontCtrlImpl : public CtrlImpl<T, t_ID>
1622 {
1623 public:
1624
1625 CharFormat m_cf;
1626
1627 // Implementation
DoExecute(UINT nCmdID,UI_EXECUTIONVERB verb,const PROPERTYKEY * key,const PROPVARIANT * ppropvarValue,IUISimplePropertySet * pCommandExecutionProperties)1628 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
1629 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
1630 IUISimplePropertySet* pCommandExecutionProperties)
1631 {
1632 ATLASSERT (nCmdID == GetID());
1633 nCmdID; // avoid level 4 warning
1634 ATLASSERT ((key) && (k_(*key) == k_FontProperties));
1635 key; // avoid level 4 warning
1636
1637 HRESULT hr = E_INVALIDARG;
1638 switch (verb)
1639 {
1640 case UI_EXECUTIONVERB_PREVIEW:
1641 case UI_EXECUTIONVERB_EXECUTE:
1642 ATLASSERT(pCommandExecutionProperties);
1643 PROPVARIANT propvar;
1644
1645 if (SUCCEEDED(hr = pCommandExecutionProperties->GetValue(UI_PKEY_FontProperties_ChangedProperties, &propvar)))
1646 m_cf << ATL::CComQIPtr<IPropertyStore>(propvar.punkVal);
1647 break;
1648
1649 case UI_EXECUTIONVERB_CANCELPREVIEW:
1650 ATLASSERT(ppropvarValue);
1651 ATL::CComPtr<IPropertyStore> pStore;
1652
1653 if (SUCCEEDED(hr = UIPropertyToInterface(UI_PKEY_FontProperties, *ppropvarValue, &pStore)))
1654 m_cf << pStore;
1655 break;
1656 }
1657
1658 if (SUCCEEDED(hr))
1659 GetWndRibbon().OnRibbonFontCtrlExecute(GetID(), verb, &m_cf);
1660 else
1661 ATLASSERT(FALSE);
1662
1663 return hr;
1664 }
1665
DoUpdateProperty(UINT nCmdID,REFPROPERTYKEY key,const PROPVARIANT * ppropvarCurrentValue,PROPVARIANT * ppropvarNewValue)1666 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
1667 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
1668 {
1669 if ((k_(key) == k_FontProperties) && (GetWndRibbon().OnRibbonQueryFont(t_ID, m_cf)))
1670 {
1671 ATL::CComQIPtr<IPropertyStore> pStore(ppropvarCurrentValue->punkVal);
1672 m_cf >> pStore;
1673 return SetPropertyVal(key, pStore.p, ppropvarNewValue);
1674 }
1675 else
1676 {
1677 return CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1678 }
1679 }
1680 };
1681
1682 // ColorCtrlImpl
1683 //
1684 template <class T, UINT t_ID>
1685 class ColorCtrlImpl : public CommandCtrlImpl<T, t_ID>
1686 {
1687 public:
ColorCtrlImpl()1688 ColorCtrlImpl() : m_colorType(UI_SWATCHCOLORTYPE_NOCOLOR), m_color(0x800080) /*MAGENTA*/
1689 { }
1690
1691 COLORREF m_color;
1692 UINT32 m_colorType; // value in UI_SWATCHCOLORTYPE
1693 Text m_sLabels[6]; // k_MoreColorsLabel to k_ThemeColorsCategoryLabel
1694 ATL::CSimpleArray<COLORREF> m_aColors[2];
1695 ATL::CSimpleArray<LPCWSTR> m_aTooltips[2];
1696
1697 // Operations
1698 HRESULT SetColor(COLORREF color, bool bUpdate = false)
1699 {
1700 if (m_colorType != UI_SWATCHCOLORTYPE_RGB)
1701 SetColorType(UI_SWATCHCOLORTYPE_RGB, bUpdate);
1702 m_color = color;
1703 return bUpdate ? SetProperty(UI_PKEY_Color, color) : S_OK;
1704 }
1705
1706 HRESULT SetColorType(UI_SWATCHCOLORTYPE type, bool bUpdate = false)
1707 {
1708 m_colorType = type;
1709 return bUpdate ? SetProperty(UI_PKEY_ColorType, type) : S_OK;
1710 }
1711
1712 HRESULT SetColorLabel(REFPROPERTYKEY key, LPCWSTR sLabel, bool bUpdate = false)
1713 {
1714 ATLASSERT((k_(key) >= k_ThemeColorsCategoryLabel) && (k_(key) <= k_MoreColorsLabel));
1715 m_sLabels[k_(key) - k_ThemeColorsCategoryLabel] = sLabel;
1716 return bUpdate ? SetProperty(key, sLabel) : S_OK;
1717 }
1718
1719 HRESULT SetColorArray(REFPROPERTYKEY key, COLORREF* pColor, bool bUpdate = false)
1720 {
1721 ATLASSERT((k_(key) == k_ThemeColors) || (k_(key) == k_StandardColors));
1722
1723 const INT ic = k_(key) - k_ThemeColors;
1724 m_aColors[ic].RemoveAll();
1725 while (*pColor != 0x800080) /*MAGENTA*/
1726 m_aColors[ic].Add(*pColor++);
1727
1728 if (bUpdate)
1729 {
1730 PROPVARIANT var;
1731 if SUCCEEDED(InitPropVariantFromUInt32Vector(m_aColors[ic].GetData(), m_aColors[ic].GetSize(), &var))
1732 return SetProperty(key, var);
1733 else
1734 return E_INVALIDARG;
1735 }
1736 else
1737 {
1738 return S_OK;
1739 }
1740 }
1741
1742 HRESULT SetColorTooltips(REFPROPERTYKEY key, LPCWSTR* ppsTT, bool bUpdate = false)
1743 {
1744 ATLASSERT((k_(key) == k_ThemeColorsTooltips) || (k_(key) == k_StandardColorsTooltips));
1745
1746 const INT ic = k_(key) - k_ThemeColorsTooltips;
1747 m_aTooltips[ic].RemoveAll();
1748 while (*ppsTT)
1749 m_aTooltips[ic].Add(*ppsTT++);
1750
1751 if (bUpdate)
1752 {
1753 PROPVARIANT var;
1754 if SUCCEEDED(InitPropVariantFromStringVector(m_aTooltips[ic].GetData(), m_aTooltips[ic].GetSize(), &var))
1755 return SetProperty(key, var);
1756 else
1757 return E_INVALIDARG;
1758 }
1759 else
1760 {
1761 return S_OK;
1762 }
1763 }
1764
1765 // Implementation
DoExecute(UINT nCmdID,UI_EXECUTIONVERB verb,const PROPERTYKEY * key,const PROPVARIANT * ppropvarValue,IUISimplePropertySet * pCommandExecutionProperties)1766 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
1767 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
1768 IUISimplePropertySet* pCommandExecutionProperties)
1769 {
1770 ATLASSERT (nCmdID == GetID());
1771 nCmdID; // avoid level 4 warning
1772 ATLASSERT (key && (k_(*key) == k_ColorType));
1773 key; // avoid level 4 warning
1774 ATLASSERT (ppropvarValue);
1775
1776 HRESULT hr = PropVariantToUInt32(*ppropvarValue, &m_colorType);
1777 ATLASSERT(SUCCEEDED(hr));
1778
1779 if (SUCCEEDED(hr) && (m_colorType == UI_SWATCHCOLORTYPE_RGB))
1780 {
1781 ATLASSERT(pCommandExecutionProperties);
1782 PROPVARIANT var;
1783 if SUCCEEDED(hr = pCommandExecutionProperties->GetValue(UI_PKEY_Color, &var))
1784 hr = PropVariantToUInt32(var, &m_color);
1785 }
1786
1787 if SUCCEEDED(hr)
1788 GetWndRibbon().OnRibbonColorCtrlExecute(GetID(), verb, (UI_SWATCHCOLORTYPE)m_colorType/*uType*/, m_color);
1789 else
1790 ATLASSERT(FALSE); // something was wrong
1791
1792 return hr;
1793 }
1794
DoUpdateProperty(UINT nCmdID,REFPROPERTYKEY key,const PROPVARIANT * ppropvarCurrentValue,PROPVARIANT * ppropvarNewValue)1795 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
1796 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
1797 {
1798 ATLASSERT (nCmdID == GetID());
1799
1800 HRESULT hr = E_NOTIMPL;
1801
1802 switch (k_(key))
1803 {
1804 case k_ColorType:
1805 hr = SetPropertyVal(key, m_colorType, ppropvarNewValue);
1806 break;
1807 case k_Color:
1808 if (m_color == 0x800080) /*MAGENTA*/
1809 m_color = GetWndRibbon().OnRibbonQueryColor(GetID());
1810 hr = SetPropertyVal(key, m_color, ppropvarNewValue);
1811 break;
1812 case k_ColorMode:
1813 break;
1814 case k_ThemeColorsCategoryLabel:
1815 case k_StandardColorsCategoryLabel:
1816 case k_RecentColorsCategoryLabel:
1817 case k_AutomaticColorLabel:
1818 case k_NoColorLabel:
1819 case k_MoreColorsLabel:
1820 {
1821 const UINT iLabel = k_(key) - k_ThemeColorsCategoryLabel;
1822 if (m_sLabels[iLabel].IsEmpty())
1823 if (LPCWSTR psLabel = GetWndRibbon().OnRibbonQueryColorLabel(GetID(), key))
1824 m_sLabels[iLabel] = psLabel;
1825 if (!m_sLabels[iLabel].IsEmpty())
1826 hr = SetPropertyVal(key, (LPCWSTR)m_sLabels[iLabel], ppropvarNewValue);
1827 }
1828 break;
1829 case k_ThemeColors:
1830 case k_StandardColors:
1831 {
1832 const INT ic = k_(key) - k_ThemeColors;
1833 if (!m_aColors[ic].GetSize())
1834 if (COLORREF* pColor = GetWndRibbon().OnRibbonQueryColorArray(GetID(), key))
1835 SetColorArray(key, pColor);
1836 if (INT iMax = m_aColors[ic].GetSize())
1837 hr = InitPropVariantFromUInt32Vector(m_aColors[ic].GetData(), iMax, ppropvarNewValue);
1838 }
1839 break;
1840 case k_ThemeColorsTooltips:
1841 case k_StandardColorsTooltips:
1842 {
1843 const INT ic = k_(key) - k_ThemeColorsTooltips;
1844 if (m_aTooltips[ic].GetSize() == 0)
1845 if (LPCWSTR* ppsTT = GetWndRibbon().OnRibbonQueryColorTooltips(GetID(), key))
1846 SetColorTooltips(key, ppsTT);
1847 if (INT iMax = m_aTooltips[ic].GetSize())
1848 hr = InitPropVariantFromStringVector(m_aTooltips[ic].GetData(), iMax, ppropvarNewValue);
1849 }
1850 break;
1851 default:
1852 hr = CommandCtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1853 break;
1854 }
1855
1856 return hr;
1857 }
1858 };
1859
1860 // SpinnerCtrlImpl
1861 //
1862 template <class T, UINT t_ID, typename V = LONG>
1863 class SpinnerCtrlImpl : public CtrlImpl<T, t_ID>
1864 {
1865 public:
SpinnerCtrlImpl()1866 SpinnerCtrlImpl()
1867 {
1868 m_Values[0] = m_Values[2] = m_Values[4] = 0;
1869 m_Values[1] = 100;
1870 m_Values[3] = 1;
1871 }
1872
1873 V m_Values[5];
1874 // k_DecimalValue = 201, k_MaxValue = 203, k_MinValue, k_Increment, k_DecimalPlaces
1875
1876 Text m_FormatString;
1877 Text m_RepresentativeString;
1878
1879 // Operations
1880 HRESULT SetDecimalPlaces(V vPlaces, bool bUpdate = false)
1881 {
1882 return SetValue(UI_PKEY_DecimalPlaces, vPlaces, bUpdate);
1883 }
1884
1885 HRESULT SetMin(V vMin, bool bUpdate = false)
1886 {
1887 return SetValue(UI_PKEY_MinValue, vMin, bUpdate);
1888 }
1889
1890 HRESULT SetMax(V vMax, bool bUpdate = false)
1891 {
1892 return SetValue(UI_PKEY_MaxValue, vMax, bUpdate);
1893 }
1894
1895 HRESULT SetVal(V vVal, bool bUpdate = false)
1896 {
1897 return SetValue(UI_PKEY_DecimalValue, vVal, bUpdate);
1898 }
1899
1900 HRESULT SetIncrement(V vIncrement, bool bUpdate = false)
1901 {
1902 return SetValue(UI_PKEY_Increment, vIncrement, bUpdate);
1903 }
1904
1905 HRESULT SetFormatString(LPCWSTR sFormat, bool bUpdate = false)
1906 {
1907 return SetText(UI_PKEY_FormatString, sFormat, bUpdate);
1908 }
1909
1910 HRESULT SetRepresentativeString(LPCWSTR sRepresentative, bool bUpdate = false)
1911 {
1912 return SetText(UI_PKEY_RepresentativeString, sRepresentative, bUpdate);
1913 }
1914
1915 // Implementation
1916 HRESULT SetText(REFPROPERTYKEY key, LPCWSTR sText, bool bUpdate = false)
1917 {
1918 switch (k_(key))
1919 {
1920 case k_FormatString:
1921 m_FormatString = sText;
1922 break;
1923 case k_RepresentativeString:
1924 m_RepresentativeString = sText;
1925 break;
1926 default:
1927 return CtrlImpl::SetText(key, sText, bUpdate);
1928 }
1929
1930 return bUpdate ?
1931 GetWndRibbon().InvalidateProperty(GetID(), key) :
1932 S_OK;
1933 }
1934
1935 HRESULT SetValue(REFPROPERTYKEY key, V val, bool bUpdate = false)
1936 {
1937 ATLASSERT((k_(key) <= k_DecimalPlaces) && (k_(key) >= k_DecimalValue));
1938
1939 const INT iVal = k_(key) == k_DecimalValue ? 0 : k_(key) - k_StringValue;
1940 m_Values[iVal] = val;
1941
1942 if (bUpdate)
1943 {
1944 if(k_(key) == k_DecimalValue)
1945 {
1946 DECIMAL decVal;
1947 InitDecimal(val, &decVal);
1948 return SetProperty(key, &decVal);
1949 }
1950 else
1951 {
1952 return GetWndRibbon().InvalidateProperty(GetID(), key);
1953 }
1954 }
1955 else
1956 {
1957 return S_OK;
1958 }
1959 }
1960
QueryValue(REFPROPERTYKEY key,LONG * plVal)1961 HRESULT QueryValue(REFPROPERTYKEY key, LONG* plVal)
1962 {
1963 return GetWndRibbon().OnRibbonQuerySpinnerValue(GetID(), key, plVal) ? S_OK : S_FALSE;
1964 }
1965
QueryValue(REFPROPERTYKEY key,DOUBLE * pdVal)1966 HRESULT QueryValue(REFPROPERTYKEY key, DOUBLE* pdVal)
1967 {
1968 return GetWndRibbon().OnRibbonQueryFloatSpinnerValue(GetID(), key, pdVal) ? S_OK : S_FALSE;
1969 }
1970
OnGetValue(REFPROPERTYKEY key,PROPVARIANT * ppv)1971 HRESULT OnGetValue(REFPROPERTYKEY key, PROPVARIANT* ppv)
1972 {
1973 ATLASSERT((k_(key) <= k_DecimalPlaces) && (k_(key) >= k_DecimalValue));
1974
1975 const INT iVal = k_(key) == k_DecimalValue ? 0 : k_(key) - k_StringValue;
1976
1977 QueryValue(key, m_Values + iVal);
1978
1979 if (k_(key) == k_DecimalPlaces)
1980 {
1981 return SetPropertyVal(key, m_Values[iVal], ppv);
1982 }
1983 else
1984 {
1985 DECIMAL decVal;
1986 InitDecimal(m_Values[iVal], &decVal);
1987 return SetPropertyVal(key, &decVal, ppv);
1988 }
1989 }
1990
OnGetText(REFPROPERTYKEY key,Text & sVal,PROPVARIANT * ppv)1991 HRESULT OnGetText(REFPROPERTYKEY key, Text& sVal, PROPVARIANT* ppv)
1992 {
1993 if (LPCWSTR sNew = GetWndRibbon().OnRibbonQueryText(GetID(), key))
1994 sVal = sNew;
1995 return SetPropertyVal(key, (LPCWSTR)sVal, ppv);
1996 }
1997
DoExecute(UINT nCmdID,UI_EXECUTIONVERB verb,const PROPERTYKEY * key,const PROPVARIANT * ppropvarValue,IUISimplePropertySet *)1998 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
1999 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
2000 IUISimplePropertySet* /*pCommandExecutionProperties*/)
2001 {
2002 ATLASSERT (nCmdID == GetID());
2003 nCmdID; // avoid level 4 warning
2004 ATLASSERT (key && (k_(*key) == k_DecimalValue));
2005 key; // avoid level 4 warning
2006 ATLASSERT (verb == UI_EXECUTIONVERB_EXECUTE);
2007 verb; // avoid level 4 warning
2008
2009 DECIMAL decVal;
2010
2011 HRESULT hr = UIPropertyToDecimal(UI_PKEY_DecimalValue, *ppropvarValue, &decVal);
2012 hr = InitVal(m_Values[0], &decVal);
2013
2014 GetWndRibbon().OnRibbonSpinnerCtrlExecute(GetID(), &m_Values[0]);
2015
2016 return hr;
2017 }
2018
DoUpdateProperty(UINT nCmdID,REFPROPERTYKEY key,const PROPVARIANT * ppropvarCurrentValue,PROPVARIANT * ppropvarNewValue)2019 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
2020 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
2021 {
2022 ATLASSERT (nCmdID == GetID());
2023
2024 HRESULT hr = E_NOTIMPL;
2025 switch (k_(key))
2026 {
2027 case k_DecimalPlaces:
2028 case k_DecimalValue:
2029 case k_Increment:
2030 case k_MaxValue:
2031 case k_MinValue:
2032 hr = OnGetValue(key, ppropvarNewValue);
2033 break;
2034 case k_FormatString:
2035 if (m_FormatString.IsEmpty())
2036 return OnGetText(key, m_FormatString, ppropvarNewValue);
2037 break;
2038 case k_RepresentativeString:
2039 if (m_RepresentativeString.IsEmpty())
2040 return OnGetText(key, m_RepresentativeString, ppropvarNewValue);
2041 break;
2042 default:
2043 hr = CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
2044 break;
2045 }
2046
2047 return hr;
2048 }
2049
2050 // decimal conversion helpers
InitDecimal(LONG & val,DECIMAL * pDecimal)2051 static HRESULT InitDecimal(LONG& val, DECIMAL* pDecimal)
2052 {
2053 return ::VarDecFromI4(val, pDecimal);
2054 }
2055
InitDecimal(DOUBLE & val,DECIMAL * pDecimal)2056 static HRESULT InitDecimal(DOUBLE& val, DECIMAL* pDecimal)
2057 {
2058 return ::VarDecFromR8(val, pDecimal);
2059 }
2060
InitVal(LONG & val,const DECIMAL * pDecimal)2061 static HRESULT InitVal(LONG& val, const DECIMAL* pDecimal)
2062 {
2063 return ::VarI4FromDec(pDecimal, &val);
2064 }
2065
InitVal(DOUBLE & val,const DECIMAL * pDecimal)2066 static HRESULT InitVal(DOUBLE& val, const DECIMAL* pDecimal)
2067 {
2068 return ::VarR8FromDec(pDecimal, &val);
2069 }
2070 };
2071
2072 // CRibbonImpl Ribbon implementation class
2073 //
2074 template <class T>
2075 class CRibbonImpl :
2076 public CRibbonUpdateUI<T>,
2077 public ICtrl,
2078 public IUIApplication,
2079 public IUICommandHandler
2080 {
2081 typedef CRibbonImpl<T> thisClass;
2082 public:
2083 typedef thisClass Ribbon;
2084 typedef T WndRibbon;
2085
CRibbonImpl()2086 CRibbonImpl() : m_bRibbonUI(false), m_hgRibbonSettings(NULL)
2087 {
2088 #ifdef _DEBUG
2089 m_cRef = 1;
2090 #endif
2091 pWndRibbon = static_cast<T*>(this);
2092 HRESULT hr = ::CoInitialize(NULL);
2093 if(SUCCEEDED(hr))
2094 if (RunTimeHelper::IsRibbonUIAvailable())
2095 hr = m_pIUIFramework.CoCreateInstance(CLSID_UIRibbonFramework);
2096 else
2097 ATLTRACE2(atlTraceUI, 0, _T("Ribbon UI not available\n"));
2098
2099 if FAILED(hr)
2100 ATLTRACE2(atlTraceUI, 0, _T("Ribbon construction failed\n"));
2101
2102 ATLASSERT(SUCCEEDED(hr));
2103 }
2104
~CRibbonImpl()2105 ~CRibbonImpl()
2106 {
2107 ::GlobalFree(m_hgRibbonSettings);
2108 m_pIUIFramework.Release();
2109 ::CoUninitialize();
2110 }
2111
GetRibbonCtrl(UINT)2112 ICtrl& GetRibbonCtrl(UINT)
2113 {
2114 return static_cast<ICtrl&>(*this);
2115 }
2116
2117 ATL::CComPtr<IUIFramework> m_pIUIFramework;
2118 HGLOBAL m_hgRibbonSettings;
2119 bool m_bRibbonUI;
2120
IsRibbonUI()2121 bool IsRibbonUI()
2122 {
2123 return m_bRibbonUI;
2124 }
2125
GetIUIFrameworkPtr()2126 IUIFramework* GetIUIFrameworkPtr()
2127 {
2128 return m_pIUIFramework;
2129 }
2130
2131 template <typename I>
GetRibbonViewPtr(UINT32 uID)2132 I* GetRibbonViewPtr(UINT32 uID)
2133 {
2134 ATLASSERT(m_pIUIFramework);
2135 ATL::CComPtr<I> pI;
2136 return m_pIUIFramework->GetView(uID, __uuidof(I), (void**) &pI) == S_OK ?
2137 pI :
2138 NULL;
2139 }
2140
GetRibbonPtr()2141 IUIRibbon* GetRibbonPtr()
2142 {
2143 return GetRibbonViewPtr<IUIRibbon>(0);
2144 }
2145
GetMenuPtr(UINT32 uID)2146 IUIContextualUI* GetMenuPtr(UINT32 uID)
2147 {
2148 ATLASSERT(uID);
2149 return GetRibbonViewPtr<IUIContextualUI>(uID);
2150 }
2151
GetRibbonHeight()2152 UINT GetRibbonHeight()
2153 {
2154 ATLASSERT(IsRibbonUI());
2155
2156 UINT32 cy = 0;
2157 if (ATL::CComPtr<IUIRibbon> pIUIRibbon = GetRibbonPtr())
2158 pIUIRibbon->GetHeight(&cy);
2159 return cy;
2160 }
2161
2162 HRESULT CreateRibbon(LPCWSTR sResName = L"APPLICATION_RIBBON")
2163 {
2164 T* pT = static_cast<T*>(this);
2165 ATLASSERT(GetIUIFrameworkPtr() && !IsRibbonUI());
2166 ATLASSERT(pT->IsWindow());
2167
2168 HRESULT hr = m_pIUIFramework->Initialize(pT->m_hWnd, this);
2169
2170 if (hr == S_OK)
2171 hr = m_pIUIFramework->LoadUI(ModuleHelper::GetResourceInstance(), sResName);
2172
2173 return hr;
2174 }
2175
DestroyRibbon()2176 HRESULT DestroyRibbon()
2177 {
2178 T* pT = static_cast<T*>(this);
2179 ATLASSERT(GetIUIFrameworkPtr() && IsRibbonUI());
2180 ATLASSERT(pT->IsWindow());
2181
2182 HRESULT hRes = m_pIUIFramework->Destroy();
2183 if (!RunTimeHelper::IsWin7())
2184 pT->SetWindowRgn(NULL, TRUE); // Vista Basic bug workaround
2185 return hRes;
2186 }
2187
2188 // Ribbon persistency
2189 HRESULT operator >>(IStream* pIStream)
2190 {
2191 ATLASSERT(GetIUIFrameworkPtr());
2192 ATLASSERT(pIStream);
2193
2194 HRESULT hr = E_FAIL;
2195 if (ATL::CComPtr<IUIRibbon> pIUIRibbon = GetRibbonPtr())
2196 {
2197 const LARGE_INTEGER li0 = { 0 };
2198 pIStream->Seek(li0, STREAM_SEEK_SET, NULL);
2199 hr = pIUIRibbon->SaveSettingsToStream(pIStream);
2200 pIStream->Commit(STGC_DEFAULT);
2201 }
2202
2203 return hr;
2204 }
2205
2206 HRESULT operator <<(IStream* pIStream)
2207 {
2208 ATLASSERT(GetIUIFrameworkPtr());
2209 ATLASSERT(pIStream);
2210
2211 HRESULT hr = E_FAIL;
2212 if (ATL::CComPtr<IUIRibbon> pIUIRibbon = GetRibbonPtr())
2213 {
2214 const LARGE_INTEGER li0 = { 0 };
2215 pIStream->Seek(li0, STREAM_SEEK_SET, NULL);
2216 hr = pIUIRibbon->LoadSettingsFromStream(pIStream);
2217 }
2218
2219 return hr;
2220 }
2221
ResetRibbonSettings()2222 void ResetRibbonSettings()
2223 {
2224 if (m_hgRibbonSettings != NULL)
2225 {
2226 ::GlobalFree(m_hgRibbonSettings);
2227 m_hgRibbonSettings = NULL;
2228 }
2229 }
2230
SaveRibbonSettings()2231 HRESULT SaveRibbonSettings()
2232 {
2233 ATLASSERT(GetIUIFrameworkPtr());
2234 ATLASSERT(static_cast<T*>(this)->IsWindow());
2235
2236 HRESULT hr = E_FAIL;
2237 ATL::CComPtr<IStream> pIStream;
2238
2239 if SUCCEEDED(hr = ::CreateStreamOnHGlobal(m_hgRibbonSettings, FALSE, &pIStream))
2240 hr = *this >> pIStream;
2241
2242 if (SUCCEEDED(hr) && (m_hgRibbonSettings == NULL))
2243 hr = ::GetHGlobalFromStream(pIStream, &m_hgRibbonSettings);
2244
2245 if FAILED(hr)
2246 ResetRibbonSettings();
2247
2248 return hr;
2249 }
2250
RestoreRibbonSettings()2251 HRESULT RestoreRibbonSettings()
2252 {
2253 ATLASSERT(GetIUIFrameworkPtr());
2254 ATLASSERT(m_hgRibbonSettings);
2255 ATLASSERT(static_cast<T*>(this)->IsWindow());
2256
2257 HRESULT hr = E_FAIL;
2258 ATL::CComPtr<IStream> pIStream;
2259
2260 if SUCCEEDED(hr = ::CreateStreamOnHGlobal(m_hgRibbonSettings, FALSE, &pIStream))
2261 hr = *this << pIStream;
2262
2263 if FAILED(hr)
2264 ResetRibbonSettings();
2265
2266 return hr;
2267 }
2268
2269 // QAT dock states
GetQATDock()2270 UI_CONTROLDOCK GetQATDock()
2271 {
2272 ATLASSERT(GetIUIFrameworkPtr());
2273 ATLASSERT(IsRibbonUI());
2274
2275 UINT32 uDock = 0;
2276 PROPVARIANT propvar;
2277 ATL::CComQIPtr<IPropertyStore>pIPS(GetRibbonPtr());
2278
2279 if ((pIPS != NULL) && SUCCEEDED(pIPS->GetValue(UI_PKEY_QuickAccessToolbarDock, &propvar)) &&
2280 SUCCEEDED(UIPropertyToUInt32(UI_PKEY_QuickAccessToolbarDock, propvar, &uDock)))
2281 return (UI_CONTROLDOCK)uDock;
2282
2283 ATLASSERT(FALSE); // something was wrong
2284 return (UI_CONTROLDOCK)0;
2285 }
2286
SetQATDock(UI_CONTROLDOCK dockState)2287 bool SetQATDock(UI_CONTROLDOCK dockState)
2288 {
2289 ATLASSERT(GetIUIFrameworkPtr());
2290 ATLASSERT(IsRibbonUI());
2291
2292 PROPVARIANT propvar;
2293 ATLVERIFY(SUCCEEDED(SetPropertyVal(UI_PKEY_QuickAccessToolbarDock, dockState, &propvar)));
2294
2295 ATL::CComQIPtr<IPropertyStore>pIPS(GetRibbonPtr());
2296 if ((pIPS != NULL) && SUCCEEDED(pIPS->SetValue(UI_PKEY_QuickAccessToolbarDock, propvar)))
2297 {
2298 pIPS->Commit();
2299 return true;
2300 }
2301
2302 ATLASSERT(FALSE); // something was wrong
2303 return false;
2304 }
2305
2306 // Ribbon display states
GetRibbonDisplayState(REFPROPERTYKEY key)2307 bool GetRibbonDisplayState(REFPROPERTYKEY key)
2308 {
2309 ATLASSERT(GetIUIFrameworkPtr());
2310 ATLASSERT(IsRibbonUI());
2311 ATLASSERT((k_(key) == k_Viewable) || (k_(key) == k_Minimized));
2312
2313 PROPVARIANT propvar;
2314 ATL::CComQIPtr<IPropertyStore>pIPS(GetRibbonPtr());
2315
2316 if ((pIPS != NULL) && SUCCEEDED(pIPS->GetValue(key, &propvar)))
2317 {
2318 BOOL bState = FALSE;
2319 if SUCCEEDED(UIPropertyToBoolean(key, propvar, &bState))
2320 return (bState != FALSE);
2321 }
2322
2323 ATLASSERT(FALSE); // something was wrong
2324 return false;
2325 }
2326
2327 bool SetRibbonDisplayState(REFPROPERTYKEY key, bool bState = true)
2328 {
2329 ATLASSERT(GetIUIFrameworkPtr());
2330 ATLASSERT(IsRibbonUI());
2331 ATLASSERT((k_(key) == k_Viewable) || (k_(key) == k_Minimized));
2332
2333 PROPVARIANT propvar;
2334 ATLVERIFY(SUCCEEDED(SetPropertyVal(key, bState, &propvar)));
2335
2336 ATL::CComQIPtr<IPropertyStore>pIPS(GetRibbonPtr());
2337
2338 if ((pIPS != NULL) && SUCCEEDED(pIPS->SetValue(key, propvar)))
2339 {
2340 pIPS->Commit();
2341 return true;
2342 }
2343
2344 ATLASSERT(FALSE); // something was wrong
2345 return false;
2346 }
2347
IsRibbonMinimized()2348 bool IsRibbonMinimized()
2349 {
2350 return GetRibbonDisplayState(UI_PKEY_Minimized);
2351 }
2352
2353 bool MinimizeRibbon(bool bMinimize = true)
2354 {
2355 return SetRibbonDisplayState(UI_PKEY_Minimized, bMinimize);
2356 }
2357
IsRibbonHidden()2358 bool IsRibbonHidden()
2359 {
2360 return !GetRibbonDisplayState(UI_PKEY_Viewable);
2361 }
2362
2363 bool HideRibbon(bool bHide = true)
2364 {
2365 return SetRibbonDisplayState(UI_PKEY_Viewable, !bHide);
2366 }
2367
2368 // Ribbon colors
GetRibbonColor(REFPROPERTYKEY key)2369 UI_HSBCOLOR GetRibbonColor(REFPROPERTYKEY key)
2370 {
2371 ATLASSERT(GetIUIFrameworkPtr());
2372 ATLASSERT(IsRibbonUI());
2373 ATLASSERT((k_(key) >= k_GlobalBackgroundColor) && (k_(key) <= k_GlobalTextColor));
2374
2375 PROPVARIANT propvar;
2376 ATL::CComQIPtr<IPropertyStore>pIPS(GetIUIFrameworkPtr());
2377
2378 if ((pIPS != NULL) && SUCCEEDED(pIPS->GetValue(key, &propvar)))
2379 {
2380 UINT32 color = 0;
2381 if SUCCEEDED(UIPropertyToUInt32(key, propvar, &color))
2382 return color;
2383 }
2384
2385 ATLASSERT(FALSE); // something was wrong
2386 return 0;
2387 }
2388
SetRibbonColor(REFPROPERTYKEY key,UI_HSBCOLOR color)2389 bool SetRibbonColor(REFPROPERTYKEY key, UI_HSBCOLOR color)
2390 {
2391 ATLASSERT(GetIUIFrameworkPtr());
2392 ATLASSERT(IsRibbonUI());
2393 ATLASSERT((k_(key) >= k_GlobalBackgroundColor) && (k_(key) <= k_GlobalTextColor));
2394
2395 PROPVARIANT propvar;
2396 ATLVERIFY(SUCCEEDED(SetPropertyVal(key, color, &propvar)));
2397
2398 ATL::CComQIPtr<IPropertyStore>pIPS(GetIUIFrameworkPtr());
2399
2400 if ((pIPS != NULL) && SUCCEEDED(pIPS->SetValue(key, propvar)))
2401 {
2402 pIPS->Commit();
2403 return true;
2404 }
2405
2406 ATLASSERT(FALSE); // something was wrong
2407 return false;
2408 }
2409
2410 // Ribbon modes
SetRibbonModes(INT32 iModes)2411 HRESULT SetRibbonModes(INT32 iModes)
2412 {
2413 ATLASSERT(IsRibbonUI());
2414 return GetIUIFrameworkPtr()->SetModes(iModes);
2415 }
2416
2417 // Ribbon contextual tab
GetRibbonContextAvail(UINT32 uID)2418 UI_CONTEXTAVAILABILITY GetRibbonContextAvail(UINT32 uID)
2419 {
2420 ATLASSERT(GetIUIFrameworkPtr());
2421
2422 PROPVARIANT propvar;
2423 if (IsRibbonUI() &&
2424 SUCCEEDED(GetIUIFrameworkPtr()->GetUICommandProperty(uID, UI_PKEY_ContextAvailable, &propvar)))
2425 {
2426 UINT uav;
2427 if (SUCCEEDED(PropVariantToUInt32(propvar, &uav)))
2428 {
2429 CUpdateUIBase::UIEnable(uID, uav != UI_CONTEXTAVAILABILITY_NOTAVAILABLE);
2430 CUpdateUIBase::UISetCheck(uID, uav == UI_CONTEXTAVAILABILITY_ACTIVE);
2431 return (UI_CONTEXTAVAILABILITY)uav;
2432 }
2433 }
2434
2435 return UI_CONTEXTAVAILABILITY_NOTAVAILABLE;
2436 }
2437
SetRibbonContextAvail(UINT32 uID,UI_CONTEXTAVAILABILITY cav)2438 HRESULT SetRibbonContextAvail(UINT32 uID, UI_CONTEXTAVAILABILITY cav)
2439 {
2440 CUpdateUIBase::UIEnable(uID, cav != UI_CONTEXTAVAILABILITY_NOTAVAILABLE);
2441 CUpdateUIBase::UISetCheck(uID, cav == UI_CONTEXTAVAILABILITY_ACTIVE);
2442
2443 return SetProperty((WORD)uID, UI_PKEY_ContextAvailable, UINT32(cav));
2444 }
2445
2446 // Ribbon context menu
HasRibbonMenu(UINT32 uID)2447 bool HasRibbonMenu(UINT32 uID)
2448 {
2449 ATL::CComPtr<IUIContextualUI> pI = GetMenuPtr(uID);
2450 return pI != NULL;
2451 }
2452
TrackRibbonMenu(UINT32 uID,INT32 x,INT32 y)2453 HRESULT TrackRibbonMenu(UINT32 uID, INT32 x, INT32 y)
2454 {
2455 ATLASSERT(HasRibbonMenu(uID));
2456
2457 return IsRibbonUI() ?
2458 ATL::CComPtr<IUIContextualUI>(GetMenuPtr(uID))->ShowAtLocation(x, y) :
2459 E_FAIL;
2460 }
2461
TrackRibbonMenu(UINT32 uID,LPARAM lParam)2462 HRESULT TrackRibbonMenu(UINT32 uID, LPARAM lParam)
2463 {
2464 return TrackRibbonMenu(uID, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
2465 }
2466
2467 // Overrideables
OnRibbonQueryImage(UINT nCmdID,REFPROPERTYKEY)2468 HBITMAP OnRibbonQueryImage(UINT nCmdID, REFPROPERTYKEY /*key*/)
2469 {
2470 return DefRibbonQueryImage(nCmdID);
2471 }
2472
OnRibbonQueryText(UINT nCmdID,REFPROPERTYKEY key)2473 LPCWSTR OnRibbonQueryText(UINT nCmdID, REFPROPERTYKEY key)
2474 {
2475 return DefRibbonQueryText(nCmdID, key);
2476 }
2477
OnRibbonQueryState(UINT nCmdID,REFPROPERTYKEY key)2478 bool OnRibbonQueryState(UINT nCmdID, REFPROPERTYKEY key)
2479 {
2480 return DefRibbonQueryState(nCmdID, key);
2481 }
2482
OnRibbonQueryTabAvail(UINT nCmdID)2483 UI_CONTEXTAVAILABILITY OnRibbonQueryTabAvail(UINT nCmdID)
2484 {
2485 DWORD dwState = UIGetState(nCmdID);
2486 return ((dwState & UPDUI_DISABLED) == UPDUI_DISABLED) ?
2487 UI_CONTEXTAVAILABILITY_NOTAVAILABLE :
2488 (((dwState & UPDUI_CHECKED) == UPDUI_CHECKED) ?
2489 UI_CONTEXTAVAILABILITY_ACTIVE :
2490 UI_CONTEXTAVAILABILITY_AVAILABLE);
2491 }
2492
OnRibbonQueryComboText(UINT32)2493 LPCWSTR OnRibbonQueryComboText(UINT32 /*uCtrlID*/)
2494 {
2495 return NULL;
2496 }
2497
OnRibbonQueryCategoryText(UINT32,UINT32)2498 LPCWSTR OnRibbonQueryCategoryText(UINT32 /*uCtrlID*/, UINT32 /*uCat*/)
2499 {
2500 return L"Category";
2501 }
2502
OnRibbonQueryItemCategory(UINT32,UINT32)2503 UINT32 OnRibbonQueryItemCategory(UINT32 /*uCtrlID*/, UINT32 /*uItem*/)
2504 {
2505 return 0;
2506 }
2507
OnRibbonQueryItemText(UINT32 uCtrlID,UINT32 uItem)2508 LPCWSTR OnRibbonQueryItemText(UINT32 uCtrlID, UINT32 uItem)
2509 {
2510 return DefRibbonQueryItemText(uCtrlID, uItem);
2511 }
2512
OnRibbonQuerySelectedItem(UINT32,UINT32 &)2513 bool OnRibbonQuerySelectedItem(UINT32 /*uCtrlID*/, UINT32& /*uSel*/)
2514 {
2515 return false;
2516 }
2517
OnRibbonQueryItemImage(UINT32 uCtrlID,UINT32 uItem)2518 HBITMAP OnRibbonQueryItemImage(UINT32 uCtrlID, UINT32 uItem)
2519 {
2520 return DefRibbonQueryItemImage(uCtrlID, uItem);
2521 }
2522
OnRibbonQueryItemCommand(UINT32 uCtrlID,UINT32 uItem)2523 UINT32 OnRibbonQueryItemCommand(UINT32 uCtrlID, UINT32 uItem)
2524 {
2525 return DefRibbonQueryItemCommand(uCtrlID, uItem);
2526 }
2527
OnRibbonQueryItemCommandType(UINT32,UINT32)2528 UI_COMMANDTYPE OnRibbonQueryItemCommandType(UINT32 /*uCtrlID*/, UINT32 /*uItem*/)
2529 {
2530 return UI_COMMANDTYPE_ACTION;
2531 }
2532
OnRibbonQueryRecentItemName(LPCWSTR sPath)2533 LPCWSTR OnRibbonQueryRecentItemName(LPCWSTR sPath)
2534 {
2535 return ::PathFindFileName(sPath);
2536 }
2537
OnRibbonQueryFont(UINT,CHARFORMAT2 &)2538 bool OnRibbonQueryFont(UINT /*nId*/, CHARFORMAT2& /*cf*/)
2539 {
2540 return false;
2541 }
2542
OnRibbonQuerySpinnerValue(UINT,REFPROPERTYKEY,LONG *)2543 bool OnRibbonQuerySpinnerValue(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/, LONG* /*pVal*/)
2544 {
2545 return false;
2546 }
2547
OnRibbonQueryFloatSpinnerValue(UINT,REFPROPERTYKEY,DOUBLE *)2548 bool OnRibbonQueryFloatSpinnerValue(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/, DOUBLE* /*pVal*/)
2549 {
2550 return false;
2551 }
2552
OnRibbonQueryColor(UINT)2553 COLORREF OnRibbonQueryColor(UINT /*nCmdID*/)
2554 {
2555 return 0x800080; /*MAGENTA*/
2556 }
2557
OnRibbonQueryColorLabel(UINT,REFPROPERTYKEY)2558 LPCWSTR OnRibbonQueryColorLabel(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/)
2559 {
2560 return NULL;
2561 }
2562
OnRibbonQueryColorArray(UINT,REFPROPERTYKEY)2563 COLORREF* OnRibbonQueryColorArray(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/)
2564 {
2565 return NULL;
2566 }
2567
OnRibbonQueryColorTooltips(UINT,REFPROPERTYKEY)2568 LPCWSTR* OnRibbonQueryColorTooltips(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/)
2569 {
2570 return NULL;
2571 }
2572
OnRibbonItemSelected(UINT32 uCtrlID,UI_EXECUTIONVERB verb,UINT32 uItem)2573 bool OnRibbonItemSelected(UINT32 uCtrlID, UI_EXECUTIONVERB verb, UINT32 uItem)
2574 {
2575 DefCommandExecute(MAKELONG(uCtrlID, verb), uItem);
2576 return true;
2577 }
2578
OnRibbonColorCtrlExecute(UINT32 uCtrlID,UI_EXECUTIONVERB verb,UI_SWATCHCOLORTYPE uType,COLORREF color)2579 void OnRibbonColorCtrlExecute(UINT32 uCtrlID, UI_EXECUTIONVERB verb, UI_SWATCHCOLORTYPE uType, COLORREF color)
2580 {
2581 DefRibbonColorCtrlExecute(uCtrlID, verb, uType, color);
2582 }
2583
OnRibbonFontCtrlExecute(UINT32 uCtrlID,UI_EXECUTIONVERB verb,CHARFORMAT2 * pcf)2584 void OnRibbonFontCtrlExecute(UINT32 uCtrlID, UI_EXECUTIONVERB verb, CHARFORMAT2* pcf)
2585 {
2586 DefCommandExecute(MAKELONG(uCtrlID, verb), (LPARAM)pcf);
2587 }
2588
OnRibbonSpinnerCtrlExecute(UINT32 uCtrlID,LONG * pVal)2589 void OnRibbonSpinnerCtrlExecute(UINT32 uCtrlID, LONG* pVal)
2590 {
2591 DefCommandExecute(uCtrlID, *pVal);
2592 }
2593
OnRibbonSpinnerCtrlExecute(UINT32 uCtrlID,DOUBLE * pVal)2594 void OnRibbonSpinnerCtrlExecute(UINT32 uCtrlID, DOUBLE* pVal)
2595 {
2596 DefCommandExecute(uCtrlID, (LPARAM)pVal);
2597 }
2598
OnRibbonCommandExecute(UINT32 uCmdID)2599 void OnRibbonCommandExecute(UINT32 uCmdID)
2600 {
2601 DefCommandExecute(uCmdID);
2602 }
2603
2604 // Default implementations
DefRibbonQueryImage(UINT nCmdID)2605 HBITMAP DefRibbonQueryImage(UINT nCmdID)
2606 {
2607 return AtlLoadBitmapImage(nCmdID, LR_CREATEDIBSECTION);
2608 }
2609
DefRibbonQueryState(UINT nCmdID,REFPROPERTYKEY key)2610 bool DefRibbonQueryState(UINT nCmdID, REFPROPERTYKEY key)
2611 {
2612 DWORD dwState = UIGetState(nCmdID);
2613 bool bRet = false;
2614 switch (k_(key))
2615 {
2616 case k_BooleanValue:
2617 bRet = (dwState & UPDUI_CHECKED) == UPDUI_CHECKED;
2618 break;
2619 case k_Enabled:
2620 bRet = (dwState & UPDUI_DISABLED) != UPDUI_DISABLED;
2621 break;
2622 default:
2623 ATLASSERT(FALSE);
2624 break;
2625 }
2626
2627 return bRet;
2628 }
2629
DefRibbonQueryText(UINT nCmdID,REFPROPERTYKEY key)2630 LPCTSTR DefRibbonQueryText(UINT nCmdID, REFPROPERTYKEY key)
2631 {
2632 static WCHAR sText[RIBBONUI_MAX_TEXT] = { 0 };
2633
2634 if (k_(key) == k_Label)
2635 return UIGetText(nCmdID);
2636
2637 if (AtlLoadString(nCmdID, sText, RIBBONUI_MAX_TEXT))
2638 {
2639 PWCHAR pTitle = wcschr(sText, L'\n');
2640 switch (k_(key))
2641 {
2642 case k_Keytip:
2643 if (PWCHAR pAmp = wcschr(sText, L'&'))
2644 pTitle = pAmp;
2645 if (pTitle != NULL)
2646 *(pTitle + 2) = NULL; // fall through
2647 case k_TooltipTitle:
2648 return pTitle ? ++pTitle : NULL;
2649 case k_TooltipDescription:
2650 case k_LabelDescription:
2651 if (pTitle != NULL)
2652 *pTitle = NULL;
2653 return sText;
2654 }
2655 }
2656
2657 return NULL;
2658 }
2659
DefRibbonQueryItemText(UINT32 uCtrlID,UINT32 uItem)2660 LPCWSTR DefRibbonQueryItemText(UINT32 uCtrlID, UINT32 uItem)
2661 {
2662 return DefRibbonQueryText(uCtrlID + 1 + uItem, UI_PKEY_LabelDescription);
2663 }
2664
DefRibbonQueryItemImage(UINT32 uCtrlID,UINT32 uItem)2665 HBITMAP DefRibbonQueryItemImage(UINT32 uCtrlID, UINT32 uItem)
2666 {
2667 return DefRibbonQueryImage(uCtrlID + 1 + uItem);
2668 }
2669
DefRibbonQueryItemCommand(UINT32 uCtrlID,UINT32 uItem)2670 UINT32 DefRibbonQueryItemCommand(UINT32 uCtrlID, UINT32 uItem)
2671 {
2672 return uCtrlID + 1 + uItem;
2673 }
2674
DefRibbonColorCtrlExecute(UINT32 uCtrlID,UI_EXECUTIONVERB verb,UI_SWATCHCOLORTYPE uType,COLORREF color)2675 void DefRibbonColorCtrlExecute(UINT32 uCtrlID, UI_EXECUTIONVERB verb, UI_SWATCHCOLORTYPE uType, COLORREF color)
2676 {
2677 switch(uType)
2678 {
2679 case UI_SWATCHCOLORTYPE_RGB:
2680 break;
2681 case UI_SWATCHCOLORTYPE_AUTOMATIC:
2682 color = ::GetSysColor(COLOR_WINDOWTEXT);
2683 break;
2684 case UI_SWATCHCOLORTYPE_NOCOLOR:
2685 color = ::GetSysColor(COLOR_WINDOW);
2686 break;
2687 default:
2688 ATLASSERT(FALSE);
2689 break;
2690 }
2691
2692 DefCommandExecute(MAKELONG(uCtrlID, verb), color);
2693 }
2694
2695 void DefCommandExecute(UINT32 uCmd, LPARAM lParam = 0)
2696 {
2697 static_cast<T*>(this)->PostMessage(WM_COMMAND, uCmd, lParam);
2698 }
2699
2700 // Elements setting helpers
InvalidateCtrl(UINT32 nID)2701 HRESULT InvalidateCtrl(UINT32 nID)
2702 {
2703 return IsRibbonUI() ?
2704 GetIUIFrameworkPtr()->InvalidateUICommand(nID, UI_INVALIDATIONS_ALLPROPERTIES, NULL) :
2705 E_FAIL;
2706 }
2707
2708 HRESULT InvalidateProperty(UINT32 nID, REFPROPERTYKEY key, UI_INVALIDATIONS flags = UI_INVALIDATIONS_PROPERTY)
2709 {
2710 return IsRibbonUI() ?
2711 GetIUIFrameworkPtr()->InvalidateUICommand(nID, flags, &key) :
2712 E_FAIL;
2713 }
2714
2715 template <typename V>
SetProperty(WORD wID,REFPROPERTYKEY key,V val)2716 HRESULT SetProperty(WORD wID, REFPROPERTYKEY key, V val)
2717 {
2718 if (IsRibbonUI())
2719 {
2720 PROPVARIANT var;
2721 if (SUCCEEDED(RibbonUI::SetPropertyVal(key, val, &var)))
2722 {
2723 return SetProperty(wID, key, var);
2724 }
2725 return E_INVALIDARG;
2726 }
2727 else
2728 {
2729 return E_FAIL;
2730 }
2731 }
2732
2733 template <>
SetProperty(WORD nID,REFPROPERTYKEY key,PROPVARIANT var)2734 HRESULT SetProperty(WORD nID, REFPROPERTYKEY key, PROPVARIANT var)
2735 {
2736 return IsRibbonUI() ?
2737 GetIUIFrameworkPtr()->SetUICommandProperty(nID, key, var) :
2738 E_FAIL;
2739 }
2740
2741 // Interfaces
2742 // IUIApplication
OnViewChanged(UINT32,UI_VIEWTYPE,IUnknown *,UI_VIEWVERB verb,INT32)2743 STDMETHODIMP OnViewChanged(UINT32, UI_VIEWTYPE, IUnknown*, UI_VIEWVERB verb, INT32)
2744 {
2745 switch (verb)
2746 {
2747 case UI_VIEWVERB_CREATE:
2748 m_bRibbonUI = true;
2749 if (m_hgRibbonSettings != NULL)
2750 RestoreRibbonSettings();
2751 break;
2752 case UI_VIEWVERB_SIZE:
2753 static_cast<T*>(this)->UpdateLayout(FALSE);
2754 break;
2755 case UI_VIEWVERB_DESTROY:
2756 SaveRibbonSettings();
2757 m_bRibbonUI = false;
2758 break;
2759 }
2760
2761 return S_OK;
2762 }
2763
OnCreateUICommand(UINT32 nCmdID,UI_COMMANDTYPE typeID,IUICommandHandler ** ppCommandHandler)2764 STDMETHODIMP OnCreateUICommand(UINT32 nCmdID, UI_COMMANDTYPE typeID, IUICommandHandler** ppCommandHandler)
2765 {
2766 UIAddRibbonElement(nCmdID);
2767 if (typeID == UI_COMMANDTYPE_CONTEXT)
2768 CUpdateUIBase::UIEnable(nCmdID, false);
2769 *ppCommandHandler = this;
2770 return S_OK;
2771 }
2772
OnDestroyUICommand(UINT32 nCmdID,UI_COMMANDTYPE,IUICommandHandler *)2773 STDMETHODIMP OnDestroyUICommand(UINT32 nCmdID, UI_COMMANDTYPE, IUICommandHandler*)
2774 {
2775 UIRemoveRibbonElement(nCmdID);
2776 return S_OK;
2777 }
2778
2779 // IUICommandHandler
Execute(UINT nCmdID,UI_EXECUTIONVERB verb,const PROPERTYKEY * key,const PROPVARIANT * ppropvarValue,IUISimplePropertySet * pCommandExecutionProperties)2780 STDMETHODIMP Execute(UINT nCmdID,
2781 UI_EXECUTIONVERB verb,
2782 const PROPERTYKEY* key,
2783 const PROPVARIANT* ppropvarValue,
2784 IUISimplePropertySet* pCommandExecutionProperties)
2785 {
2786 T* pT =static_cast<T*>(this);
2787 return pT->GetRibbonCtrl(nCmdID).DoExecute(nCmdID, verb, key, ppropvarValue, pCommandExecutionProperties);
2788 }
2789
UpdateProperty(UINT nCmdID,REFPROPERTYKEY key,const PROPVARIANT * ppropvarCurrentValue,PROPVARIANT * ppropvarNewValue)2790 STDMETHODIMP UpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
2791 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
2792 {
2793 T* pT =static_cast<T*>(this);
2794 return pT->GetRibbonCtrl(nCmdID).DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
2795 }
2796
2797 #ifdef _DEBUG
2798 // IUnknown methods (heavyweight)
AddRef()2799 STDMETHODIMP_(ULONG) AddRef()
2800 {
2801 return InterlockedIncrement(&m_cRef);
2802 }
2803
Release()2804 STDMETHODIMP_(ULONG) Release()
2805 {
2806 LONG cRef = InterlockedDecrement(&m_cRef);
2807 if (cRef == 0) // NoOp for breakpoint
2808 {
2809 cRef = 0;
2810 }
2811
2812 return cRef;
2813 }
2814
QueryInterface(REFIID iid,void ** ppv)2815 STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
2816 {
2817 if (ppv == NULL)
2818 {
2819 return E_POINTER;
2820 }
2821 else if ((iid == __uuidof(IUnknown)) ||
2822 (iid == __uuidof(IUICommandHandler)) ||
2823 (iid == __uuidof(IUIApplication)))
2824 {
2825 *ppv = this;
2826 AddRef();
2827 return S_OK;
2828 }
2829 else
2830 {
2831 return E_NOINTERFACE;
2832 }
2833 }
2834
2835 LONG m_cRef;
2836 #else
2837 // IUnknown methods (lightweight)
QueryInterface(REFIID iid,void ** ppv)2838 STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
2839 {
2840 if ((iid == __uuidof(IUnknown)) ||
2841 (iid == __uuidof(IUICommandHandler)) ||
2842 (iid == __uuidof(IUIApplication)))
2843 {
2844 *ppv = this;
2845 return S_OK;
2846 }
2847 return E_NOINTERFACE;
2848 }
AddRef()2849 ULONG STDMETHODCALLTYPE AddRef()
2850 {
2851 return 1;
2852 }
Release()2853 ULONG STDMETHODCALLTYPE Release()
2854 {
2855 return 1;
2856 }
2857 #endif
2858
2859 // CRibbonImpl ICtrl implementation
DoExecute(UINT nCmdID,UI_EXECUTIONVERB verb,const PROPERTYKEY * key,const PROPVARIANT * ppropvarValue,IUISimplePropertySet *)2860 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
2861 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
2862 IUISimplePropertySet* /*pCommandExecutionProperties*/)
2863 {
2864 if (key != NULL)
2865 {
2866 if(k_(*key) != k_BooleanValue)
2867 {
2868 ATLTRACE2(atlTraceUI, 0, _T("Control ID %d is not handled\n"), nCmdID);
2869 return E_NOTIMPL;
2870 }
2871 BOOL bChecked = FALSE;
2872 ATLVERIFY(SUCCEEDED(PropVariantToBoolean(*ppropvarValue, &bChecked)));
2873 CUpdateUIBase::UISetCheck(nCmdID, bChecked);
2874 }
2875
2876 ATLASSERT(verb == UI_EXECUTIONVERB_EXECUTE);
2877 verb; // avoid level 4 warning
2878
2879 static_cast<T*>(this)->OnRibbonCommandExecute(nCmdID);
2880
2881 return S_OK;
2882 }
2883
DoUpdateProperty(UINT nCmdID,REFPROPERTYKEY key,const PROPVARIANT *,PROPVARIANT * ppropvarNewValue)2884 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
2885 const PROPVARIANT* /*ppropvarCurrentValue*/, PROPVARIANT* ppropvarNewValue)
2886 {
2887 T* pT = static_cast<T*>(this);
2888 HRESULT hr = E_NOTIMPL;
2889 switch (k_(key))
2890 {
2891 case k_LargeImage:
2892 case k_LargeHighContrastImage:
2893 case k_SmallImage:
2894 case k_SmallHighContrastImage:
2895 if (HBITMAP hbm = pT->OnRibbonQueryImage(nCmdID, key))
2896 hr = SetPropertyVal(key, GetImage(hbm, UI_OWNERSHIP_TRANSFER), ppropvarNewValue);
2897 break;
2898 case k_Label:
2899 case k_Keytip:
2900 case k_TooltipTitle:
2901 case k_TooltipDescription:
2902 case k_LabelDescription:
2903 if (LPCWSTR sText = pT->OnRibbonQueryText(nCmdID, key))
2904 hr = SetPropertyVal(key, sText, ppropvarNewValue);
2905 break;
2906 case k_BooleanValue:
2907 case k_Enabled:
2908 hr = SetPropertyVal(key, pT->OnRibbonQueryState(nCmdID, key), ppropvarNewValue);
2909 break;
2910 case k_ContextAvailable:
2911 hr = SetPropertyVal(key, pT->OnRibbonQueryTabAvail(nCmdID), ppropvarNewValue);
2912 break;
2913 }
2914
2915 return hr;
2916 }
2917
2918 // CRibbonImpl::CRibbonXXXCtrl specialized classes
2919 //CRibbonComboCtrl
2920 template <UINT t_ID, size_t t_items, size_t t_categories = 0>
2921 class CRibbonComboCtrl : public CollectionCtrlImpl<T, t_ID, ComboCollectionImpl<CRibbonComboCtrl<t_ID, t_items, t_categories>, t_items, t_categories>>
2922 {
2923 public:
CRibbonComboCtrl()2924 CRibbonComboCtrl()
2925 { }
2926 };
2927
2928 // CRibbonItemGalleryCtrl
2929 template <UINT t_ID, size_t t_items, size_t t_categories = 0>
2930 class CRibbonItemGalleryCtrl : public CollectionCtrlImpl<T, t_ID, ItemCollectionImpl<CRibbonItemGalleryCtrl<t_ID, t_items, t_categories>, t_items, t_categories>>
2931 {
2932 public:
CRibbonItemGalleryCtrl()2933 CRibbonItemGalleryCtrl()
2934 { }
2935 };
2936
2937 // CRibbonCommandGalleryCtrl
2938 template <UINT t_ID, size_t t_items, size_t t_categories = 0>
2939 class CRibbonCommandGalleryCtrl : public CollectionCtrlImpl<T, t_ID, CommandCollectionImpl<CRibbonCommandGalleryCtrl<t_ID, t_items, t_categories>, t_items, t_categories>>
2940 {
2941 public:
CRibbonCommandGalleryCtrl()2942 CRibbonCommandGalleryCtrl()
2943 { }
2944 };
2945
2946 // CRibbonToolbarGalleryCtrl
2947 template <UINT t_ID, UINT t_idTB, size_t t_size>
2948 class CRibbonToolbarGalleryCtrl : public ToolbarGalleryCtrlImpl<T, t_ID, t_idTB, t_size>
2949 { };
2950
2951 // CRibbonSimpleComboCtrl
2952 template <UINT t_ID, size_t t_size>
2953 class CRibbonSimpleComboCtrl : public SimpleCollectionCtrlImpl<T, t_ID, t_size>
2954 { };
2955
2956 // CRibbonSimpleGalleryCtrl
2957 template <UINT t_ID, size_t t_size, UI_COMMANDTYPE t_CommandType = UI_COMMANDTYPE_ACTION>
2958 class CRibbonSimpleGalleryCtrl : public SimpleCollectionCtrlImpl<T, t_ID, t_size, t_CommandType>
2959 { };
2960
2961 //CRibbonRecentItemsCtrl
2962 template <UINT t_ID, class TDocList = CRecentDocumentList>
2963 class CRibbonRecentItemsCtrl : public RecentItemsCtrlImpl<T, t_ID, TDocList>
2964 {
2965 public:
CRibbonRecentItemsCtrl()2966 CRibbonRecentItemsCtrl()
2967 { }
2968 };
2969
2970 // CRibbonColorCtrl
2971 template <UINT t_ID>
2972 class CRibbonColorCtrl : public ColorCtrlImpl<T, t_ID>
2973 {
2974 public:
CRibbonColorCtrl()2975 CRibbonColorCtrl()
2976 { }
2977 };
2978
2979 //CRibbonFontCtrl
2980 template <UINT t_ID>
2981 class CRibbonFontCtrl : public FontCtrlImpl<T, t_ID>
2982 {
2983 public:
CRibbonFontCtrl()2984 CRibbonFontCtrl()
2985 { }
2986 };
2987
2988 // CRibbonSpinnerCtrl
2989 template <UINT t_ID>
2990 class CRibbonSpinnerCtrl : public SpinnerCtrlImpl<T, t_ID, LONG>
2991 {
2992 public:
CRibbonSpinnerCtrl()2993 CRibbonSpinnerCtrl()
2994 { }
2995 };
2996
2997 // CRibbonFloatSpinnerCtrl
2998 template <UINT t_ID>
2999 class CRibbonFloatSpinnerCtrl : public SpinnerCtrlImpl<T, t_ID, DOUBLE>
3000 {
3001 public:
CRibbonFloatSpinnerCtrl()3002 CRibbonFloatSpinnerCtrl()
3003 {
3004 m_Values[4] = 1; // 1 decimal
3005 }
3006 };
3007
3008 // CRibbonCommandCtrl
3009 template <UINT t_ID>
3010 class CRibbonCommandCtrl : public CommandCtrlImpl<T, t_ID>
3011 {
3012 public:
CRibbonCommandCtrl()3013 CRibbonCommandCtrl()
3014 { }
3015 };
3016
3017 // Control classes access to T instance (re-initialized in constructor)
3018 static T* pWndRibbon;
3019 };
3020
3021 template <class T>
3022 __declspec(selectany) T* CRibbonImpl<T>::pWndRibbon;
3023
3024 // Control map element
3025 #pragma warning(push)
3026 #pragma warning(disable: 4510 610 4512) // missing default constructor, can't be instatiated, assignment operator could not be generated
3027 typedef struct
3028 {
3029 UINT uID;
3030 ICtrl& ctrl;
3031 } _ribbonCtrl;
3032 #pragma warning(pop)
3033
3034 }; // namespace RibbonUI
3035
3036
3037 ///////////////////////////////////////////////////////////////////////////////
3038 // RibbonUI Control map
3039
3040 // Control map macros
3041 #define BEGIN_RIBBON_CONTROL_MAP(theClass) \
3042 WTL::RibbonUI::ICtrl& GetRibbonCtrl(UINT id) \
3043 { \
3044 WTL::RibbonUI::_ribbonCtrl _ctrls[] = \
3045 {
3046
3047 #define RIBBON_CONTROL(member) {member.GetID(), static_cast<WTL::RibbonUI::ICtrl&>(member)},
3048
3049 #define END_RIBBON_CONTROL_MAP() \
3050 {0, *this} \
3051 }; \
3052 int i = 0; \
3053 for(; i < _countof(_ctrls) - 1; i++) \
3054 if (_ctrls[i].uID == id) \
3055 break; \
3056 return _ctrls[i].ctrl; \
3057 }
3058
3059 // Control message map macros
3060 #define RIBBON_GALLERY_CONTROL_HANDLER(id, func) \
3061 if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
3062 { \
3063 bHandled = TRUE; \
3064 lResult = func((UI_EXECUTIONVERB)HIWORD(wParam), LOWORD(wParam), (UINT)lParam, bHandled); \
3065 if(bHandled) \
3066 return TRUE; \
3067 }
3068
3069 #define RIBBON_COMBO_CONTROL_HANDLER(id, func) \
3070 RIBBON_GALLERY_CONTROL_HANDLER(id, func)
3071
3072 #define RIBBON_FONT_CONTROL_HANDLER(id, func) \
3073 if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
3074 { \
3075 bHandled = TRUE; \
3076 lResult = func((UI_EXECUTIONVERB)HIWORD(wParam), LOWORD(wParam), (CHARFORMAT2*)lParam, bHandled); \
3077 if(bHandled) \
3078 return TRUE; \
3079 }
3080
3081 #define RIBBON_COLOR_CONTROL_HANDLER(id, func) \
3082 if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
3083 { \
3084 bHandled = TRUE; \
3085 lResult = func((UI_EXECUTIONVERB)HIWORD(wParam), LOWORD(wParam), (COLORREF)lParam, bHandled); \
3086 if(bHandled) \
3087 return TRUE; \
3088 }
3089
3090 #define RIBBON_SPINNER_CONTROL_HANDLER(id, func) \
3091 if(uMsg == WM_COMMAND && id == wParam) \
3092 { \
3093 bHandled = TRUE; \
3094 lResult = func((WORD)wParam, (LONG)lParam, bHandled); \
3095 if(bHandled) \
3096 return TRUE; \
3097 }
3098
3099 #define RIBBON_FLOATSPINNER_CONTROL_HANDLER(id, func) \
3100 if(uMsg == WM_COMMAND && id == wParam) \
3101 { \
3102 bHandled = TRUE; \
3103 lResult = func((WORD)wParam, (DOUBLE*)lParam, bHandled); \
3104 if(bHandled) \
3105 return TRUE; \
3106 }
3107
3108 // Handler prototypes
3109 /*
3110 LRESULT OnRibbonGalleryCtrl(UI_EXECUTIONVERB verb, WORD wID, UINT uSel, BOOL& bHandled);
3111 LRESULT OnRibbonComboCtrl(UI_EXECUTIONVERB verb, WORD wID, UINT uSel, BOOL& bHandled);
3112 LRESULT OnRibbonFontCtrl(UI_EXECUTIONVERB verb, WORD wID, CHARFORMAT2* pcf, BOOL& bHandled);
3113 LRESULT OnRibbonColorCtrl(UI_EXECUTIONVERB verb, WORD wID, COLORREF color, BOOL& bHandled);
3114 LRESULT OnRibbonSpinnerCtrl(WORD wID, LONG lVal, BOOL& bHandled);
3115 LRESULT OnRibbonFloatSpinnerCtrl(WORD wID, DOUBLE* pdVal, BOOL& bHandled);
3116 */
3117
3118
3119 ///////////////////////////////////////////////////////////////////////////////
3120 // Ribbon frame classes
3121
3122 // CRibbonFrameWindowImplBase
3123 //
3124 template <class T, class TFrameImpl>
3125 class ATL_NO_VTABLE CRibbonFrameWindowImplBase : public TFrameImpl, public RibbonUI::CRibbonImpl<T>
3126 {
3127 typedef TFrameImpl baseFrame;
3128 bool m_bUseCommandBarBitmaps;
3129 bool m_bWin7Fix;
3130
3131 public:
3132 // Construction
3133 CRibbonFrameWindowImplBase(bool bUseCommandBarBitmaps = true) :
m_bUseCommandBarBitmaps(bUseCommandBarBitmaps)3134 m_bUseCommandBarBitmaps(bUseCommandBarBitmaps), m_bWin7Fix(false)
3135 {
3136 __if_not_exists(T::m_CmdBar)
3137 {
3138 m_bUseCommandBarBitmaps = false;
3139 }
3140 }
3141
3142 // Win7 Aero fix helpers
ResetFrame()3143 void ResetFrame()
3144 {
3145 const MARGINS margins = { 0 };
3146 ::DwmExtendFrameIntoClientArea(m_hWnd, &margins);
3147 }
3148
CalcWin7Fix()3149 INT CalcWin7Fix()
3150 {
3151 ResetFrame();
3152 RECT rc = { 0 };
3153 ::AdjustWindowRectEx(&rc, T::GetWndStyle(0), GetMenu() != NULL, T::GetWndExStyle(0));
3154 return -rc.top;
3155 }
3156
NeedWin7Fix()3157 bool NeedWin7Fix()
3158 {
3159 BOOL bComp = FALSE;
3160 return m_bWin7Fix && RunTimeHelper::IsWin7() && SUCCEEDED(DwmIsCompositionEnabled(&bComp)) && bComp;
3161 }
3162
3163 // Operations
UseCommandBarBitmaps(bool bUse)3164 bool UseCommandBarBitmaps(bool bUse)
3165 {
3166 __if_exists(T::m_CmdBar)
3167 {
3168 return m_bUseCommandBarBitmaps = bUse;
3169 }
3170 __if_not_exists(T::m_CmdBar)
3171 {
3172 bUse; // avoid level 4 warning
3173 return false;
3174 }
3175 }
3176
3177 bool ShowRibbonUI(bool bShow, INT32 imodes = UI_MAKEAPPMODE(0), LPCWSTR sResName = L"APPLICATION_RIBBON")
3178 {
3179 if (!RunTimeHelper::IsRibbonUIAvailable())
3180 return false;
3181
3182 ATLASSERT(GetIUIFrameworkPtr());
3183
3184 if (IsRibbonUI() == bShow)
3185 return bShow;
3186
3187 bool bVisible = (IsWindowVisible() != FALSE);
3188 if(bVisible && !bShow)
3189 SetRedraw(FALSE);
3190
3191 if (bShow && ::IsWindow(m_hWndToolBar))
3192 {
3193 ::ShowWindow(m_hWndToolBar, SW_HIDE);
3194 UpdateLayout();
3195 }
3196
3197 m_bWin7Fix = !bShow;
3198
3199 HRESULT hr = bShow ? CreateRibbon(sResName) : DestroyRibbon();
3200
3201 m_bWin7Fix = SUCCEEDED(hr) && !bShow;
3202
3203 if (SUCCEEDED(hr))
3204 {
3205 if(::IsWindow(m_hWndToolBar) && !bShow)
3206 {
3207 ::ShowWindow(m_hWndToolBar, SW_SHOWNA);
3208 UpdateLayout();
3209 }
3210 else if (bShow)
3211 {
3212 PostMessage(WM_SIZE);
3213 SetRibbonModes(imodes);
3214 }
3215 }
3216
3217 if(bVisible && !bShow)
3218 {
3219 SetRedraw(TRUE);
3220 RedrawWindow(NULL, NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
3221 }
3222
3223 return SUCCEEDED(hr) ? bShow : !bShow;
3224 }
3225
3226 // Overrideables
OnRibbonQueryImage(UINT nCmdID,REFPROPERTYKEY key)3227 HBITMAP OnRibbonQueryImage(UINT nCmdID, REFPROPERTYKEY key)
3228 {
3229 if ((key == UI_PKEY_SmallImage) && m_bUseCommandBarBitmaps)
3230 {
3231 if (HBITMAP hbm = GetCommandBarBitmap(nCmdID))
3232 return (HBITMAP)::CopyImage(hbm, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
3233 }
3234
3235 return DefRibbonQueryImage(nCmdID);
3236 }
3237
3238 BEGIN_MSG_MAP(CRibbonFrameWindowImplBase)
3239 if (!IsRibbonUI() && NeedWin7Fix())
3240 {
3241 MESSAGE_HANDLER(WM_SIZING, OnSizing)
3242 MESSAGE_HANDLER(WM_SIZE, OnSize)
3243 MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
3244 MESSAGE_HANDLER(WM_NCCALCSIZE, OnNCCalcSize)
3245 }
3246 CHAIN_MSG_MAP(CRibbonUpdateUI<T>)
CHAIN_MSG_MAP(baseFrame)3247 CHAIN_MSG_MAP(baseFrame)
3248 END_MSG_MAP()
3249
3250 // Message handlers for Win7 Aero
3251 LRESULT OnSizing(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
3252 {
3253 switch (wParam)
3254 {
3255 case WMSZ_TOP:
3256 case WMSZ_TOPLEFT:
3257 case WMSZ_TOPRIGHT:
3258 SetWindowPos(NULL, (LPRECT)lParam, SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
3259 break;
3260 default:
3261 DefWindowProc();
3262 break;
3263 }
3264
3265 return 1; // handled
3266 }
3267
OnSize(UINT,WPARAM wParam,LPARAM,BOOL & bHandled)3268 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
3269 {
3270 if (wParam != SIZE_MINIMIZED)
3271 SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
3272
3273 bHandled = FALSE;
3274 return 1;
3275 }
3276
OnActivate(UINT,WPARAM wParam,LPARAM,BOOL & bHandled)3277 LRESULT OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
3278 {
3279 if(wParam != WA_INACTIVE)
3280 SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
3281
3282 bHandled = FALSE;
3283 return 1;
3284 }
3285
OnNCCalcSize(UINT,WPARAM wParam,LPARAM lParam,BOOL &)3286 LRESULT OnNCCalcSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
3287 {
3288 ATLASSERT(!IsRibbonUI() && NeedWin7Fix());
3289
3290 LRESULT lRet = DefWindowProc();
3291
3292 if(wParam)
3293 {
3294 LPNCCALCSIZE_PARAMS pParams = (LPNCCALCSIZE_PARAMS)lParam;
3295 pParams->rgrc[0].top = pParams->rgrc[1].top + CalcWin7Fix();
3296 }
3297
3298 return lRet;
3299 }
3300
3301 // Overrides
3302 void UpdateLayout(BOOL bResizeBars = TRUE)
3303 {
3304 RECT rect = { 0 };
3305 GetClientRect(&rect);
3306
3307 if (IsRibbonUI() && !IsRibbonHidden())
3308 {
3309 rect.top += GetRibbonHeight();
3310 }
3311 else if (!IsRibbonUI() && NeedWin7Fix())
3312 {
3313 ResetFrame();
3314 }
3315
3316 // position bars and offset their dimensions
3317 UpdateBarsPosition(rect, bResizeBars);
3318
3319 // resize client window
3320 if(m_hWndClient != NULL)
3321 ::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
3322 rect.right - rect.left, rect.bottom - rect.top,
3323 SWP_NOZORDER | SWP_NOACTIVATE);
3324 }
3325
3326 // Implementation
GetCommandBarBitmap(UINT nCmdID)3327 HBITMAP GetCommandBarBitmap(UINT nCmdID)
3328 {
3329 __if_exists (T::m_CmdBar)
3330 {
3331 ATLASSERT(RunTimeHelper::IsVista());
3332 T* pT =static_cast<T*>(this);
3333 int nIndex = pT->m_CmdBar.m_arrCommand.Find((WORD&)nCmdID);
3334 return (nIndex == -1) ? NULL : pT->m_CmdBar.m_arrVistaBitmap[nIndex];
3335 }
3336 __if_not_exists (T::m_CmdBar)
3337 {
3338 nCmdID; // avoid level 4 warning
3339 return NULL;
3340 }
3341 }
3342 };
3343
3344 // CRibbonFrameWindowImpl
3345 //
3346 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
3347 class ATL_NO_VTABLE CRibbonFrameWindowImpl : public CRibbonFrameWindowImplBase<T, CFrameWindowImpl<T, TBase, TWinTraits>>
3348 { };
3349
3350 // CRibbonMDIFrameWindowImpl
3351 //
3352 template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CFrameWinTraits>
3353 class ATL_NO_VTABLE CRibbonMDIFrameWindowImpl : public CRibbonFrameWindowImplBase<T, CMDIFrameWindowImpl<T, TBase, TWinTraits>>
3354 { };
3355
3356
3357 ///////////////////////////////////////////////////////////////////////////////
3358 // CRibbonPersist helper for RibbonUI persistency
3359
3360 class CRibbonPersist
3361 {
3362 public:
CRibbonPersist(LPCWSTR sAppKey)3363 CRibbonPersist(LPCWSTR sAppKey)
3364 {
3365 ATLASSERT(sAppKey && *sAppKey);
3366 m_Key.Create(HKEY_CURRENT_USER, sAppKey);
3367 ATLASSERT(m_Key.m_hKey);
3368 }
3369
3370 CRegKeyEx m_Key;
3371
3372 LONG Save(bool bRibbonUI, HGLOBAL hgSettings = NULL)
3373 {
3374 CRegKeyEx key;
3375 const DWORD dwUI = bRibbonUI;
3376
3377 LONG lRet = key.Create(m_Key, L"Ribbon");
3378 if(lRet != ERROR_SUCCESS)
3379 return lRet;
3380
3381 lRet = key.SetDWORDValue(L"UI", dwUI);
3382 if(lRet != ERROR_SUCCESS)
3383 return lRet;
3384
3385 if (hgSettings != NULL)
3386 {
3387 LPBYTE pVal = (LPBYTE)::GlobalLock(hgSettings);
3388 if (pVal != NULL)
3389 {
3390 lRet = key.SetBinaryValue(L"Settings", pVal, (ULONG)::GlobalSize(hgSettings));
3391 ::GlobalUnlock(hgSettings);
3392 }
3393 else
3394 {
3395 lRet = GetLastError();
3396 }
3397 }
3398
3399 return lRet;
3400 }
3401
Restore(bool & bRibbonUI,HGLOBAL & hgSettings)3402 LONG Restore(bool& bRibbonUI, HGLOBAL& hgSettings)
3403 {
3404 ATLASSERT(hgSettings == NULL);
3405
3406 CRegKeyEx key;
3407
3408 LONG lRet = key.Open(m_Key, L"Ribbon");
3409 if(lRet != ERROR_SUCCESS)
3410 return lRet;
3411
3412 DWORD dwUI = 0xffff;
3413 lRet = key.QueryDWORDValue(L"UI", dwUI);
3414 if(lRet == ERROR_SUCCESS)
3415 bRibbonUI = dwUI == 1;
3416 else
3417 return lRet;
3418
3419 ULONG ulSize = 0;
3420 lRet = key.QueryBinaryValue(L"Settings", NULL, &ulSize);
3421 if (lRet == ERROR_SUCCESS)
3422 {
3423 ATLASSERT(ulSize != 0);
3424
3425 hgSettings = ::GlobalAlloc(GHND, ulSize);
3426 if (hgSettings != NULL)
3427 {
3428 LPBYTE pData = (LPBYTE)::GlobalLock(hgSettings);
3429 if (pData != NULL)
3430 {
3431 lRet = key.QueryBinaryValue(L"Settings", pData, &ulSize);
3432 }
3433 else
3434 {
3435 lRet = GetLastError();
3436 ::GlobalFree(hgSettings);
3437 hgSettings = NULL;
3438 }
3439 }
3440 else
3441 {
3442 lRet = GetLastError();
3443 }
3444 }
3445 return lRet;
3446 }
3447
Delete()3448 LONG Delete()
3449 {
3450 return m_Key.DeleteSubKey(L"Ribbon");
3451 }
3452 };
3453
3454 } // namespace WTL
3455
3456 #endif // __ATLRIBBON_H__
3457