PageRenderTime 39ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/3rd_party/wtl/Include/atlribbon.h

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