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