3447 lines
86 KiB
C
3447 lines
86 KiB
C
|
// Windows Template Library - WTL version 8.1
|
||
|
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// This file is a part of the Windows Template Library.
|
||
|
// The use and distribution terms for this software are covered by the
|
||
|
// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
|
||
|
// which can be found in the file CPL.TXT at the root of this distribution.
|
||
|
// By using this software in any fashion, you are agreeing to be bound by
|
||
|
// the terms of this license. You must not remove this notice, or
|
||
|
// any other, from this software.
|
||
|
|
||
|
#ifndef __ATLRIBBON_H__
|
||
|
#define __ATLRIBBON_H__
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#if (_MSC_VER < 1500)
|
||
|
#error atlribbon.h requires Visual C++ 2008 compiler or higher
|
||
|
#endif
|
||
|
|
||
|
#ifndef _UNICODE
|
||
|
#error atlribbon.h requires the Unicode character set
|
||
|
#endif
|
||
|
|
||
|
#if !defined(NTDDI_WIN7) || (NTDDI_VERSION < NTDDI_WIN7)
|
||
|
#error atlribbon.h requires the Windows 7 SDK or higher
|
||
|
#endif
|
||
|
|
||
|
#ifdef _WIN32_WCE
|
||
|
#error atlribbon.h is not supported on Windows CE
|
||
|
#endif
|
||
|
|
||
|
#ifndef __ATLAPP_H__
|
||
|
#error atlribbon.h requires atlapp.h to be included first
|
||
|
#endif
|
||
|
|
||
|
#if (_ATL_VER < 0x0700)
|
||
|
#include <shlwapi.h>
|
||
|
#pragma comment(lib, "shlwapi.lib")
|
||
|
#endif
|
||
|
|
||
|
#include <atlmisc.h> // for RecentDocumentList classes
|
||
|
#include <atlframe.h> // for Frame and UpdateUI classes
|
||
|
#include <atlctrls.h> // required for atlctrlw.h
|
||
|
#include <atlctrlw.h> // for CCommandBarCtrl
|
||
|
|
||
|
#if !defined(_WTL_USE_CSTRING) && !defined(__ATLSTR_H__)
|
||
|
#pragma warning(disable : 4530) // unwind semantics not enabled
|
||
|
#include <string>
|
||
|
#pragma warning(default : 4530)
|
||
|
#endif
|
||
|
|
||
|
#include <dwmapi.h>
|
||
|
#pragma comment(lib, "dwmapi.lib")
|
||
|
|
||
|
#include <UIRibbon.h>
|
||
|
#include <UIRibbonPropertyHelpers.h>
|
||
|
#pragma comment(lib, "propsys.lib")
|
||
|
|
||
|
#include <Richedit.h> // for CHARFORMAT2
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Classes in this file:
|
||
|
//
|
||
|
// CRibbonUpdateUI : Automatic mapping of ribbon UI elements
|
||
|
//
|
||
|
// RibbonUI::Text
|
||
|
// RibbonUI::CharFormat
|
||
|
// RibbonUI::ICtrl
|
||
|
// RibbonUI::CtrlImpl
|
||
|
// RibbonUI::CommandCtrlImpl
|
||
|
// RibbonUI::ItemProperty
|
||
|
// RibbonUI::CollectionImplBase
|
||
|
// RibbonUI::CollectionImpl
|
||
|
// RibbonUI::TextCollectionImpl
|
||
|
// RibbonUI::ItemCollectionImpl
|
||
|
// RibbonUI::ComboCollectionImpl
|
||
|
// RibbonUI::CommandCollectionImpl
|
||
|
// RibbonUI::ToolbarCollectionImpl
|
||
|
// RibbonUI::SimpleCollectionImpl
|
||
|
// RibbonUI::CollectionCtrlImpl
|
||
|
// RibbonUI::ToolbarGalleryCtrlImpl
|
||
|
// RibbonUI::SimpleCollectionCtrlImpl
|
||
|
// RibbonUI::RecentItemsCtrlImpl
|
||
|
// RibbonUI::FontCtrlImpl
|
||
|
// RibbonUI::ColorCtrlImpl
|
||
|
// RibbonUI::SpinnerCtrlImpl
|
||
|
//
|
||
|
// RibbonUI::CRibbonImpl
|
||
|
// CRibbonImpl::CRibbonComboCtrl
|
||
|
// CRibbonImpl::CRibbonItemGalleryCtrl
|
||
|
// CRibbonImpl::CRibbonCommandGalleryCtrl
|
||
|
// CRibbonImpl::CRibbonToolbarGalleryCtrl
|
||
|
// CRibbonImpl::CRibbonSimpleComboCtrl
|
||
|
// CRibbonImpl::CRibbonSimpleGalleryCtrl
|
||
|
// CRibbonImpl::CRibbonRecentItemsCtrl
|
||
|
// CRibbonImpl::CRibbonColorCtrl
|
||
|
// CRibbonImpl::CRibbonFontCtrl
|
||
|
// CRibbonImpl::CRibbonSpinnerCtrl
|
||
|
// CRibbonImpl::CRibbonFloatSpinnerCtrl
|
||
|
// CRibbonImpl::CRibbonCommandCtrl
|
||
|
//
|
||
|
// CRibbonFrameWindowImplBase
|
||
|
// CRibbonFrameWindowImpl
|
||
|
// CRibbonMDIFrameWindowImpl
|
||
|
// CRibbonPersist
|
||
|
//
|
||
|
// Global functions:
|
||
|
// RibbonUI::SetPropertyVal()
|
||
|
// RibbonUI::GetImage()
|
||
|
|
||
|
|
||
|
// Constants
|
||
|
|
||
|
#ifndef RIBBONUI_MAX_TEXT
|
||
|
#define RIBBONUI_MAX_TEXT 128
|
||
|
#endif
|
||
|
|
||
|
#define TWIPS_PER_POINT 20 // For font size
|
||
|
|
||
|
|
||
|
namespace WTL
|
||
|
{
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// CRibbonUpdateUI : Automatic mapping of ribbon UI elements
|
||
|
|
||
|
template <class T>
|
||
|
class CRibbonUpdateUI : public CAutoUpdateUI<T>
|
||
|
{
|
||
|
public:
|
||
|
enum
|
||
|
{
|
||
|
UPDUI_RIBBON = 0x0080,
|
||
|
UPDUI_PERSIST = 0x0020
|
||
|
};
|
||
|
|
||
|
bool IsRibbonElement(const _AtlUpdateUIMap& UIMap)
|
||
|
{
|
||
|
return (UIMap.m_wType & UPDUI_RIBBON) != 0;
|
||
|
}
|
||
|
|
||
|
bool IsRibbonID(UINT nID)
|
||
|
{
|
||
|
for(int i = 0; i < m_arrUIMap.GetSize(); i++)
|
||
|
{
|
||
|
if(m_arrUIMap[i].m_nID == nID)
|
||
|
return IsRibbonElement(m_arrUIMap[i]);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Element
|
||
|
bool UIAddRibbonElement(UINT nID)
|
||
|
{
|
||
|
return UIAddElement<UPDUI_RIBBON>(nID);
|
||
|
}
|
||
|
|
||
|
bool UIRemoveRibbonElement(UINT nID)
|
||
|
{
|
||
|
return UIRemoveElement<UPDUI_RIBBON>(nID);
|
||
|
}
|
||
|
|
||
|
bool UIPersistElement(UINT nID, bool bPersist = true)
|
||
|
{
|
||
|
return bPersist ?
|
||
|
UIAddElement<UPDUI_PERSIST>(nID) :
|
||
|
UIRemoveElement<UPDUI_PERSIST>(nID);
|
||
|
}
|
||
|
|
||
|
// methods for Ribbon elements
|
||
|
BOOL UISetText(int nID, LPCWSTR sText, BOOL bForceUpdate = FALSE)
|
||
|
{
|
||
|
T* pT = static_cast<T*>(this);
|
||
|
BOOL bRes = CUpdateUIBase::UISetText(nID, sText, bForceUpdate);
|
||
|
if (pT->IsRibbonUI() && IsRibbonID(nID))
|
||
|
bRes = SUCCEEDED(pT->InvalidateProperty(nID, UI_PKEY_Label));
|
||
|
return bRes;
|
||
|
}
|
||
|
|
||
|
BOOL UISetText(int nID, UINT uIdResource, BOOL bForceUpdate = FALSE)
|
||
|
{
|
||
|
CTempBuffer<WCHAR> sText(RIBBONUI_MAX_TEXT);
|
||
|
return AtlLoadString(uIdResource, sText, RIBBONUI_MAX_TEXT) ?
|
||
|
UISetText(nID, sText, bForceUpdate) :
|
||
|
E_FAIL;
|
||
|
}
|
||
|
|
||
|
LPCTSTR UIGetText(int nID)
|
||
|
{
|
||
|
T* pT = static_cast<T*>(this);
|
||
|
LPCTSTR sUI = CAutoUpdateUI::UIGetText(nID);
|
||
|
|
||
|
// replace 'tab' by 'space' for RibbonUI elements
|
||
|
if (sUI && pT->IsRibbonUI() && IsRibbonID(nID) && wcschr(sUI, L'\t'))
|
||
|
{
|
||
|
static WCHAR sText[RIBBONUI_MAX_TEXT] = { 0 };
|
||
|
wcscpy_s(sText, sUI);
|
||
|
*wcschr(sText, L'\t') = L' ';
|
||
|
return sText;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return sUI;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE)
|
||
|
{
|
||
|
T* pT = static_cast<T*>(this);
|
||
|
BOOL bRes = CUpdateUIBase::UIEnable(nID, bEnable, bForceUpdate);
|
||
|
if (pT->IsRibbonUI() && IsRibbonID(nID))
|
||
|
bRes = SUCCEEDED(pT->SetProperty((WORD)nID, UI_PKEY_Enabled, bEnable));
|
||
|
return bRes;
|
||
|
}
|
||
|
|
||
|
BOOL UISetCheck(int nID, INT nCheck, BOOL bForceUpdate = FALSE)
|
||
|
{
|
||
|
if ((nCheck == 0) || (nCheck == 1))
|
||
|
return UISetCheck(nID, nCheck != 0, bForceUpdate);
|
||
|
else
|
||
|
return CUpdateUIBase::UISetCheck(nID, nCheck, bForceUpdate);
|
||
|
}
|
||
|
|
||
|
BOOL UISetCheck(int nID, bool bCheck, BOOL bForceUpdate = FALSE)
|
||
|
{
|
||
|
T* pT = static_cast<T*>(this);
|
||
|
BOOL bRes = CUpdateUIBase::UISetCheck(nID, bCheck, bForceUpdate);
|
||
|
if (bRes && pT->IsRibbonUI() && IsRibbonID(nID))
|
||
|
bRes = SUCCEEDED(pT->SetProperty((WORD)nID, UI_PKEY_BooleanValue, bCheck));
|
||
|
return bRes;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// RibbonUI namespace
|
||
|
//
|
||
|
|
||
|
namespace RibbonUI
|
||
|
{
|
||
|
|
||
|
// Minimal string allocation support for various PROPERTYKEY values
|
||
|
#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
|
||
|
typedef _CSTRING_NS::CString Text;
|
||
|
#else
|
||
|
class Text : public std::wstring
|
||
|
{
|
||
|
public:
|
||
|
Text(std::wstring& s) : std::wstring(s)
|
||
|
{ }
|
||
|
Text(LPCWSTR s) : std::wstring(s)
|
||
|
{ }
|
||
|
Text()
|
||
|
{ }
|
||
|
bool IsEmpty()
|
||
|
{
|
||
|
return empty();
|
||
|
}
|
||
|
operator LPCWSTR()
|
||
|
{
|
||
|
return c_str();
|
||
|
}
|
||
|
Text& operator =(LPCWSTR s)
|
||
|
{
|
||
|
return static_cast<Text&>(std::wstring::operator =(s));
|
||
|
}
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
// PROPERTYKEY enum and helpers
|
||
|
enum k_KEY
|
||
|
{
|
||
|
// state
|
||
|
k_Enabled = 1, k_BooleanValue = 200,
|
||
|
// text properties
|
||
|
k_LabelDescription = 2, k_Keytip = 3, k_Label = 4, k_TooltipDescription = 5, k_TooltipTitle = 6,
|
||
|
// image properties
|
||
|
k_LargeImage = 7, k_LargeHighContrastImage = 8, k_SmallImage = 9, k_SmallHighContrastImage = 10,
|
||
|
// collection properties
|
||
|
k_ItemsSource = 101, k_Categories = 102, k_SelectedItem = 104,
|
||
|
// collection item properties
|
||
|
k_CommandId = 100, k_CategoryId = 103, k_CommandType = 105, k_ItemImage = 106,
|
||
|
// combo control property
|
||
|
k_StringValue = 202,
|
||
|
// spinner control properties
|
||
|
k_DecimalValue = 201, k_MaxValue = 203, k_MinValue, k_Increment, k_DecimalPlaces, k_FormatString, k_RepresentativeString = 208,
|
||
|
// font control properties
|
||
|
k_FontProperties = 300, k_FontProperties_Family, k_FontProperties_Size, k_FontProperties_Bold, k_FontProperties_Italic = 304,
|
||
|
k_FontProperties_Underline = 305, k_FontProperties_Strikethrough, k_FontProperties_VerticalPositioning, k_FontProperties_ForegroundColor = 308,
|
||
|
k_FontProperties_BackgroundColor = 309, k_FontProperties_ForegroundColorType, k_FontProperties_BackgroundColorType, k_FontProperties_ChangedProperties = 312,
|
||
|
k_FontProperties_DeltaSize = 313,
|
||
|
// recent items properties
|
||
|
k_RecentItems = 350, k_Pinned = 351,
|
||
|
// color control properties
|
||
|
k_Color = 400, k_ColorType = 401, k_ColorMode,
|
||
|
k_ThemeColorsCategoryLabel = 403, k_StandardColorsCategoryLabel, k_RecentColorsCategoryLabel = 405, k_AutomaticColorLabel = 406,
|
||
|
k_NoColorLabel = 407, k_MoreColorsLabel = 408,
|
||
|
k_ThemeColors = 409, k_StandardColors = 410, k_ThemeColorsTooltips = 411, k_StandardColorsTooltips = 412,
|
||
|
// Ribbon state
|
||
|
k_Viewable = 1000, k_Minimized = 1001, k_QuickAccessToolbarDock = 1002, k_ContextAvailable = 1100,
|
||
|
// Ribbon UI colors
|
||
|
k_GlobalBackgroundColor = 2000, k_GlobalHighlightColor, k_GlobalTextColor = 2002
|
||
|
};
|
||
|
|
||
|
inline k_KEY k_(REFPROPERTYKEY key)
|
||
|
{
|
||
|
return (k_KEY)key.fmtid.Data1;
|
||
|
}
|
||
|
|
||
|
// PROPERTYKEY value assignment and specializations
|
||
|
//
|
||
|
template <typename V>
|
||
|
HRESULT SetPropertyVal(REFPROPERTYKEY key, V val, PROPVARIANT* ppv)
|
||
|
{
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_Enabled:
|
||
|
case k_BooleanValue:
|
||
|
return InitPropVariantFromBoolean(val, ppv);
|
||
|
default:
|
||
|
return UIInitPropertyFromUInt32(key, val, ppv);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline HRESULT SetPropertyVal(REFPROPERTYKEY key, DOUBLE val, PROPVARIANT* ppv)
|
||
|
{
|
||
|
return SetPropertyVal(key, (LONG)val, ppv);
|
||
|
}
|
||
|
|
||
|
inline HRESULT SetPropertyVal(REFPROPERTYKEY key, IUIImage* val, PROPVARIANT* ppv)
|
||
|
{
|
||
|
HRESULT hr = UIInitPropertyFromImage(key, val, ppv);
|
||
|
ATLVERIFY(val->Release() == 1);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
inline HRESULT SetPropertyVal(REFPROPERTYKEY key, IUnknown* val, PROPVARIANT* ppv)
|
||
|
{
|
||
|
return UIInitPropertyFromInterface(key, val, ppv);
|
||
|
}
|
||
|
|
||
|
inline HRESULT SetPropertyVal(REFPROPERTYKEY key, IPropertyStore* val, PROPVARIANT* ppv)
|
||
|
{
|
||
|
return UIInitPropertyFromInterface(key, val, ppv);
|
||
|
}
|
||
|
|
||
|
inline HRESULT SetPropertyVal(REFPROPERTYKEY key, SAFEARRAY* val, PROPVARIANT* ppv)
|
||
|
{
|
||
|
return UIInitPropertyFromIUnknownArray(key, val, ppv);
|
||
|
}
|
||
|
|
||
|
inline HRESULT SetPropertyVal(REFPROPERTYKEY key, DECIMAL* val, PROPVARIANT* ppv)
|
||
|
{
|
||
|
return UIInitPropertyFromDecimal(key, *val, ppv);
|
||
|
}
|
||
|
|
||
|
inline HRESULT SetPropertyVal(REFPROPERTYKEY key, bool val, PROPVARIANT* ppv)
|
||
|
{
|
||
|
return UIInitPropertyFromBoolean(key, val, ppv);
|
||
|
}
|
||
|
|
||
|
inline HRESULT SetPropertyVal(REFPROPERTYKEY key, LPCWSTR val, PROPVARIANT* ppv)
|
||
|
{
|
||
|
return UIInitPropertyFromString(key, val, ppv);
|
||
|
}
|
||
|
|
||
|
// CharFormat helper struct for RibbonUI font control
|
||
|
//
|
||
|
struct CharFormat : CHARFORMAT2
|
||
|
{
|
||
|
// Default constructor
|
||
|
CharFormat()
|
||
|
{
|
||
|
cbSize = sizeof CHARFORMAT2;
|
||
|
Reset();
|
||
|
}
|
||
|
|
||
|
// Copy constructor
|
||
|
CharFormat(const CharFormat& cf)
|
||
|
{
|
||
|
CopyMemory(this, &cf, sizeof CHARFORMAT2);
|
||
|
}
|
||
|
|
||
|
// Assign operator
|
||
|
CharFormat& operator =(const CharFormat& cf)
|
||
|
{
|
||
|
CopyMemory(this, &cf, sizeof CHARFORMAT2);
|
||
|
return (*this);
|
||
|
}
|
||
|
|
||
|
void Reset()
|
||
|
{
|
||
|
uValue = dwMask = dwEffects = 0;
|
||
|
PropVariantInit(&propvar);
|
||
|
}
|
||
|
|
||
|
void operator <<(IPropertyStore* pStore)
|
||
|
{
|
||
|
if (pStore == NULL)
|
||
|
{
|
||
|
ATLASSERT(FALSE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static void (CharFormat::*Getk_[])(IPropertyStore*) =
|
||
|
{
|
||
|
&CharFormat::Getk_Family,
|
||
|
&CharFormat::Getk_FontProperties_Size,
|
||
|
&CharFormat::Getk_MaskEffect<CFM_BOLD, CFE_BOLD, UI_PKEY_FontProperties_Bold>,
|
||
|
&CharFormat::Getk_MaskEffect<CFM_ITALIC, CFE_ITALIC, UI_PKEY_FontProperties_Italic>,
|
||
|
&CharFormat::Getk_MaskEffect<CFM_UNDERLINE, CFE_UNDERLINE, UI_PKEY_FontProperties_Underline>,
|
||
|
&CharFormat::Getk_MaskEffect<CFM_STRIKEOUT, CFE_STRIKEOUT, UI_PKEY_FontProperties_Strikethrough>,
|
||
|
&CharFormat::Getk_VerticalPositioning,
|
||
|
&CharFormat::Getk_Color<CFM_COLOR, UI_PKEY_FontProperties_ForegroundColor>,
|
||
|
&CharFormat::Getk_Color<CFM_BACKCOLOR, UI_PKEY_FontProperties_BackgroundColor>,
|
||
|
&CharFormat::Getk_ColorType<CFM_COLOR, CFE_AUTOCOLOR, UI_SWATCHCOLORTYPE_AUTOMATIC, UI_PKEY_FontProperties_ForegroundColorType>,
|
||
|
&CharFormat::Getk_ColorType<CFM_BACKCOLOR, CFE_AUTOBACKCOLOR, UI_SWATCHCOLORTYPE_NOCOLOR, UI_PKEY_FontProperties_BackgroundColorType>,
|
||
|
};
|
||
|
|
||
|
DWORD nProps = 0;
|
||
|
Reset();
|
||
|
|
||
|
ATLVERIFY(SUCCEEDED(pStore->GetCount(&nProps)));
|
||
|
for (DWORD iProp = 0; iProp < nProps; iProp++)
|
||
|
{
|
||
|
PROPERTYKEY key;
|
||
|
ATLVERIFY(SUCCEEDED(pStore->GetAt(iProp, &key)));
|
||
|
ATLASSERT(k_(key) >= k_FontProperties_Family);
|
||
|
|
||
|
if (k_(key) <= k_FontProperties_BackgroundColorType)
|
||
|
(this->*Getk_[k_(key) - k_FontProperties_Family])(pStore);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void operator >>(IPropertyStore* pStore)
|
||
|
{
|
||
|
if (pStore == NULL)
|
||
|
{
|
||
|
ATLASSERT(FALSE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
PutFace(pStore);
|
||
|
PutSize(pStore);
|
||
|
PutMaskEffect(CFM_BOLD, CFE_BOLD, UI_PKEY_FontProperties_Bold, pStore);
|
||
|
PutMaskEffect(CFM_ITALIC, CFE_ITALIC, UI_PKEY_FontProperties_Italic, pStore);
|
||
|
PutMaskEffect(CFM_UNDERLINE, CFE_UNDERLINE, UI_PKEY_FontProperties_Underline, pStore);
|
||
|
PutMaskEffect(CFM_STRIKEOUT, CFE_STRIKEOUT, UI_PKEY_FontProperties_Strikethrough, pStore);
|
||
|
PutVerticalPos(pStore);
|
||
|
PutColor(pStore);
|
||
|
PutBackColor(pStore);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
PROPVARIANT propvar;
|
||
|
UINT uValue;
|
||
|
|
||
|
// Getk_ functions
|
||
|
void Getk_Family(IPropertyStore* pStore)
|
||
|
{
|
||
|
if (SUCCEEDED(pStore->GetValue(UI_PKEY_FontProperties_Family, &propvar)))
|
||
|
{
|
||
|
PropVariantToString(propvar, szFaceName, LF_FACESIZE);
|
||
|
if (*szFaceName)
|
||
|
dwMask |= CFM_FACE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Getk_FontProperties_Size(IPropertyStore* pStore)
|
||
|
{
|
||
|
if (SUCCEEDED(pStore->GetValue(UI_PKEY_FontProperties_Size, &propvar)))
|
||
|
{
|
||
|
DECIMAL decSize;
|
||
|
UIPropertyToDecimal(UI_PKEY_FontProperties_Size, propvar, &decSize);
|
||
|
DOUBLE dSize;
|
||
|
VarR8FromDec(&decSize, &dSize);
|
||
|
if (dSize > 0)
|
||
|
{
|
||
|
dwMask |= CFM_SIZE;
|
||
|
yHeight = (LONG)(dSize * TWIPS_PER_POINT);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <DWORD t_dwMask, DWORD t_dwEffects, REFPROPERTYKEY key>
|
||
|
void Getk_MaskEffect(IPropertyStore* pStore)
|
||
|
{
|
||
|
if (SUCCEEDED(pStore->GetValue(key, &propvar)))
|
||
|
{
|
||
|
UIPropertyToUInt32(key, propvar, &uValue);
|
||
|
if ((UI_FONTPROPERTIES)uValue != UI_FONTPROPERTIES_NOTAVAILABLE)
|
||
|
{
|
||
|
dwMask |= t_dwMask;
|
||
|
dwEffects |= ((UI_FONTPROPERTIES) uValue == UI_FONTPROPERTIES_SET) ? t_dwEffects : 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Getk_VerticalPositioning(IPropertyStore* pStore)
|
||
|
{
|
||
|
if (SUCCEEDED(pStore->GetValue(UI_PKEY_FontProperties_VerticalPositioning, &propvar)))
|
||
|
{
|
||
|
UIPropertyToUInt32(UI_PKEY_FontProperties_VerticalPositioning, propvar, &uValue);
|
||
|
UI_FONTVERTICALPOSITION uVerticalPosition = (UI_FONTVERTICALPOSITION) uValue;
|
||
|
if ((uVerticalPosition != UI_FONTVERTICALPOSITION_NOTAVAILABLE))
|
||
|
{
|
||
|
dwMask |= (CFM_SUPERSCRIPT | CFM_SUBSCRIPT);
|
||
|
if (uVerticalPosition != UI_FONTVERTICALPOSITION_NOTSET)
|
||
|
{
|
||
|
dwEffects |= (uVerticalPosition == UI_FONTVERTICALPOSITION_SUPERSCRIPT) ? CFE_SUPERSCRIPT : CFE_SUBSCRIPT;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <DWORD t_dwMask, REFPROPERTYKEY key>
|
||
|
void Getk_Color(IPropertyStore* pStore)
|
||
|
{
|
||
|
UINT32 color;
|
||
|
if (SUCCEEDED(pStore->GetValue(key, &propvar)))
|
||
|
{
|
||
|
UIPropertyToUInt32(key, propvar, &color);
|
||
|
dwMask |= t_dwMask;
|
||
|
|
||
|
if (t_dwMask == CFM_COLOR)
|
||
|
crTextColor = color;
|
||
|
else
|
||
|
crBackColor = color;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <DWORD t_dwMask, DWORD t_dwEffects, UI_SWATCHCOLORTYPE t_type, REFPROPERTYKEY key>
|
||
|
void Getk_ColorType(IPropertyStore* pStore)
|
||
|
{
|
||
|
if (SUCCEEDED(pStore->GetValue(key, &propvar)))
|
||
|
{
|
||
|
UIPropertyToUInt32(key, propvar, &uValue);
|
||
|
if (t_type == (UI_SWATCHCOLORTYPE)uValue)
|
||
|
{
|
||
|
dwMask |= t_dwMask;
|
||
|
dwEffects |= t_dwEffects;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Put functions
|
||
|
void PutMaskEffect(WORD dwMaskVal, WORD dwEffectVal, REFPROPERTYKEY key, IPropertyStore* pStore)
|
||
|
{
|
||
|
PROPVARIANT propvar;
|
||
|
UI_FONTPROPERTIES uProp = UI_FONTPROPERTIES_NOTAVAILABLE;
|
||
|
if ((dwMask & dwMaskVal) != 0)
|
||
|
uProp = dwEffects & dwEffectVal ? UI_FONTPROPERTIES_SET : UI_FONTPROPERTIES_NOTSET;
|
||
|
SetPropertyVal(key, uProp, &propvar);
|
||
|
pStore->SetValue(key, propvar);
|
||
|
}
|
||
|
|
||
|
void PutVerticalPos(IPropertyStore* pStore)
|
||
|
{
|
||
|
PROPVARIANT propvar;
|
||
|
UI_FONTVERTICALPOSITION uProp = UI_FONTVERTICALPOSITION_NOTAVAILABLE;
|
||
|
|
||
|
if ((dwMask & CFE_SUBSCRIPT) != 0)
|
||
|
{
|
||
|
if ((dwMask & CFM_SUBSCRIPT) && (dwEffects & CFE_SUBSCRIPT))
|
||
|
uProp = UI_FONTVERTICALPOSITION_SUBSCRIPT;
|
||
|
else
|
||
|
uProp = UI_FONTVERTICALPOSITION_SUPERSCRIPT;
|
||
|
}
|
||
|
else if ((dwMask & CFM_OFFSET) != 0)
|
||
|
{
|
||
|
if (yOffset > 0)
|
||
|
uProp = UI_FONTVERTICALPOSITION_SUPERSCRIPT;
|
||
|
else if (yOffset < 0)
|
||
|
uProp = UI_FONTVERTICALPOSITION_SUBSCRIPT;
|
||
|
}
|
||
|
|
||
|
SetPropertyVal(UI_PKEY_FontProperties_VerticalPositioning, uProp, &propvar);
|
||
|
pStore->SetValue(UI_PKEY_FontProperties_VerticalPositioning, propvar);
|
||
|
}
|
||
|
|
||
|
void PutFace(IPropertyStore* pStore)
|
||
|
{
|
||
|
PROPVARIANT propvar;
|
||
|
SetPropertyVal(UI_PKEY_FontProperties_Family,
|
||
|
dwMask & CFM_FACE ? szFaceName : L"", &propvar);
|
||
|
pStore->SetValue(UI_PKEY_FontProperties_Family, propvar);
|
||
|
}
|
||
|
|
||
|
void PutSize(IPropertyStore* pStore)
|
||
|
{
|
||
|
PROPVARIANT propvar;
|
||
|
DECIMAL decVal;
|
||
|
|
||
|
if ((dwMask & CFM_SIZE) != 0)
|
||
|
VarDecFromR8((DOUBLE)yHeight / TWIPS_PER_POINT, &decVal);
|
||
|
else
|
||
|
VarDecFromI4(0, &decVal);
|
||
|
|
||
|
SetPropertyVal(UI_PKEY_FontProperties_Size, &decVal, &propvar);
|
||
|
pStore->SetValue(UI_PKEY_FontProperties_Size, propvar);
|
||
|
}
|
||
|
|
||
|
void PutColor(IPropertyStore* pStore)
|
||
|
{
|
||
|
if ((dwMask & CFM_COLOR) != 0)
|
||
|
if ((dwEffects & CFE_AUTOCOLOR) == 0)
|
||
|
{
|
||
|
SetPropertyVal(UI_PKEY_FontProperties_ForegroundColorType, UI_SWATCHCOLORTYPE_RGB, &propvar);
|
||
|
pStore->SetValue(UI_PKEY_FontProperties_ForegroundColorType, propvar);
|
||
|
|
||
|
SetPropertyVal(UI_PKEY_FontProperties_ForegroundColor, crTextColor, &propvar);
|
||
|
pStore->SetValue(UI_PKEY_FontProperties_ForegroundColor, propvar);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetPropertyVal(UI_PKEY_FontProperties_ForegroundColorType, UI_SWATCHCOLORTYPE_AUTOMATIC, &propvar);
|
||
|
pStore->SetValue(UI_PKEY_FontProperties_ForegroundColorType, propvar);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PutBackColor(IPropertyStore* pStore)
|
||
|
{
|
||
|
if (((dwMask & CFM_BACKCOLOR) != 0) && ((dwEffects & CFE_AUTOBACKCOLOR) == 0))
|
||
|
{
|
||
|
SetPropertyVal(UI_PKEY_FontProperties_BackgroundColorType, UI_SWATCHCOLORTYPE_RGB, &propvar);
|
||
|
pStore->SetValue(UI_PKEY_FontProperties_BackgroundColorType, propvar);
|
||
|
|
||
|
SetPropertyVal(UI_PKEY_FontProperties_BackgroundColor, crBackColor, &propvar);
|
||
|
pStore->SetValue(UI_PKEY_FontProperties_BackgroundColor, propvar);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetPropertyVal(UI_PKEY_FontProperties_BackgroundColorType, UI_SWATCHCOLORTYPE_NOCOLOR, &propvar);
|
||
|
pStore->SetValue(UI_PKEY_FontProperties_BackgroundColorType, propvar);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// IUIImage helper
|
||
|
//
|
||
|
inline IUIImage* GetImage(HBITMAP hbm, UI_OWNERSHIP owner)
|
||
|
{
|
||
|
ATLASSERT(hbm);
|
||
|
IUIImage* pIUII = NULL;
|
||
|
ATL::CComPtr<IUIImageFromBitmap> pIFB;
|
||
|
|
||
|
if SUCCEEDED(pIFB.CoCreateInstance(CLSID_UIRibbonImageFromBitmapFactory))
|
||
|
ATLVERIFY(SUCCEEDED(pIFB->CreateImage(hbm, owner, &pIUII)));
|
||
|
|
||
|
return pIUII;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Ribbon control classes
|
||
|
|
||
|
// RibbonUI::ICtrl abstract interface of RibbonUI::CRibbonImpl and all RibbonUI control classes
|
||
|
//
|
||
|
struct ICtrl
|
||
|
{
|
||
|
virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
|
||
|
const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
|
||
|
IUISimplePropertySet* pCommandExecutionProperties) = 0;
|
||
|
|
||
|
virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue) = 0;
|
||
|
};
|
||
|
|
||
|
// RibbonUI::CtrlImpl base class for all ribbon controls
|
||
|
//
|
||
|
template <class T, UINT t_ID>
|
||
|
class ATL_NO_VTABLE CtrlImpl : public ICtrl
|
||
|
{
|
||
|
protected:
|
||
|
T* m_pWndRibbon;
|
||
|
|
||
|
public:
|
||
|
typedef T WndRibbon;
|
||
|
|
||
|
CtrlImpl() : m_pWndRibbon(T::pWndRibbon)
|
||
|
{ }
|
||
|
|
||
|
WndRibbon& GetWndRibbon()
|
||
|
{
|
||
|
return *m_pWndRibbon;
|
||
|
}
|
||
|
|
||
|
static WORD GetID()
|
||
|
{
|
||
|
return t_ID;
|
||
|
}
|
||
|
|
||
|
Text m_sTxt[5];
|
||
|
|
||
|
// Operations
|
||
|
HRESULT Invalidate()
|
||
|
{
|
||
|
return GetWndRibbon().InvalidateCtrl(GetID());
|
||
|
}
|
||
|
|
||
|
HRESULT Invalidate(REFPROPERTYKEY key, UI_INVALIDATIONS flags = UI_INVALIDATIONS_PROPERTY)
|
||
|
{
|
||
|
return GetWndRibbon().InvalidateProperty(GetID(), key, flags);
|
||
|
}
|
||
|
|
||
|
HRESULT SetText(REFPROPERTYKEY key, LPCWSTR sTxt, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT((k_(key) <= k_TooltipTitle) && (k_(key) >= k_LabelDescription));
|
||
|
|
||
|
m_sTxt[k_(key) - k_LabelDescription] = sTxt;
|
||
|
|
||
|
return bUpdate ?
|
||
|
GetWndRibbon().InvalidateProperty(GetID(), key) :
|
||
|
S_OK;
|
||
|
}
|
||
|
|
||
|
// Implementation
|
||
|
template <typename V>
|
||
|
HRESULT SetProperty(REFPROPERTYKEY key, V val)
|
||
|
{
|
||
|
return GetWndRibbon().SetProperty(GetID(), key, val);
|
||
|
}
|
||
|
|
||
|
HRESULT OnGetText(REFPROPERTYKEY key, PROPVARIANT* ppv)
|
||
|
{
|
||
|
ATLASSERT((k_(key) <= k_TooltipTitle) && (k_(key) >= k_LabelDescription));
|
||
|
|
||
|
const INT iText = k_(key) - k_LabelDescription;
|
||
|
if (m_sTxt[iText].IsEmpty())
|
||
|
if (LPCWSTR sText = GetWndRibbon().OnRibbonQueryText(GetID(), key))
|
||
|
m_sTxt[iText] = sText;
|
||
|
|
||
|
return !m_sTxt[iText].IsEmpty() ?
|
||
|
SetPropertyVal(key, (LPCWSTR)m_sTxt[iText], ppv) :
|
||
|
S_OK;
|
||
|
}
|
||
|
|
||
|
virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
|
||
|
const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
|
||
|
IUISimplePropertySet* pCommandExecutionProperties)
|
||
|
{
|
||
|
ATLASSERT(nCmdID == t_ID);
|
||
|
return GetWndRibbon().DoExecute(nCmdID, verb, key, ppropvarValue, pCommandExecutionProperties);
|
||
|
}
|
||
|
|
||
|
virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
|
||
|
{
|
||
|
ATLASSERT(nCmdID == t_ID);
|
||
|
|
||
|
const INT iMax = k_TooltipTitle - k_LabelDescription;
|
||
|
const INT iVal = k_(key) - k_LabelDescription;
|
||
|
|
||
|
return (iVal <= iMax) && (iVal >= 0) ?
|
||
|
OnGetText(key, ppropvarNewValue) :
|
||
|
GetWndRibbon().DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// CommandCtrlImpl base class for most ribbon controls
|
||
|
//
|
||
|
template <class T, UINT t_ID>
|
||
|
class CommandCtrlImpl : public CtrlImpl<T, t_ID>
|
||
|
{
|
||
|
public:
|
||
|
CBitmap m_hbm[4];
|
||
|
|
||
|
HRESULT SetImage(REFPROPERTYKEY key, HBITMAP hbm, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT((k_(key) <= k_SmallHighContrastImage) && (k_(key) >= k_LargeImage));
|
||
|
|
||
|
m_hbm[k_(key) - k_LargeImage].Attach(hbm);
|
||
|
|
||
|
return bUpdate ?
|
||
|
GetWndRibbon().InvalidateProperty(GetID(), key) :
|
||
|
S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT OnGetImage(REFPROPERTYKEY key, PROPVARIANT* ppv)
|
||
|
{
|
||
|
ATLASSERT((k_(key) <= k_SmallHighContrastImage) && (k_(key) >= k_LargeImage));
|
||
|
|
||
|
const INT iImage = k_(key) - k_LargeImage;
|
||
|
|
||
|
if (m_hbm[iImage].IsNull())
|
||
|
m_hbm[iImage] = GetWndRibbon().OnRibbonQueryImage(GetID(), key);
|
||
|
|
||
|
return m_hbm[iImage].IsNull() ?
|
||
|
E_NOTIMPL :
|
||
|
SetPropertyVal(key, GetImage(m_hbm[iImage], UI_OWNERSHIP_COPY), ppv);
|
||
|
}
|
||
|
|
||
|
virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
|
||
|
{
|
||
|
ATLASSERT (nCmdID == GetID());
|
||
|
|
||
|
return (k_(key) <= k_SmallHighContrastImage) && (k_(key) >= k_LargeImage) ?
|
||
|
OnGetImage(key, ppropvarNewValue) :
|
||
|
CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Ribbon collection base classes
|
||
|
|
||
|
// ItemProperty class: ribbon callback for each item in a collection
|
||
|
//
|
||
|
template <class TCollection>
|
||
|
class ItemProperty : public IUISimplePropertySet
|
||
|
{
|
||
|
public:
|
||
|
ItemProperty(UINT i, TCollection* pCollection) : m_Index(i), m_pCollection(pCollection)
|
||
|
{ }
|
||
|
|
||
|
const UINT m_Index;
|
||
|
TCollection* m_pCollection;
|
||
|
|
||
|
// IUISimplePropertySet method.
|
||
|
STDMETHODIMP GetValue(REFPROPERTYKEY key, PROPVARIANT *value)
|
||
|
{
|
||
|
return m_pCollection->OnGetItem(m_Index, key, value);
|
||
|
}
|
||
|
|
||
|
// IUnknown methods.
|
||
|
STDMETHODIMP_(ULONG) AddRef()
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) Release()
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
|
||
|
{
|
||
|
if ((iid == __uuidof(IUnknown)) || (iid == __uuidof(IUISimplePropertySet)))
|
||
|
{
|
||
|
*ppv = this;
|
||
|
return S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return E_NOINTERFACE;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
// CollectionImplBase: base class for all RibbonUI collections
|
||
|
//
|
||
|
template <class TCollection, size_t t_size>
|
||
|
class CollectionImplBase
|
||
|
{
|
||
|
typedef CollectionImplBase<TCollection, t_size> thisClass;
|
||
|
|
||
|
public:
|
||
|
CollectionImplBase()
|
||
|
{
|
||
|
for (int i = 0; i < t_size; i++)
|
||
|
m_apItems[i] = new ItemProperty<TCollection>(i, static_cast<TCollection*>(this));
|
||
|
}
|
||
|
|
||
|
~CollectionImplBase()
|
||
|
{
|
||
|
for (int i = 0; i < t_size; i++)
|
||
|
delete m_apItems[i];
|
||
|
}
|
||
|
|
||
|
// Data members
|
||
|
ItemProperty<TCollection>* m_apItems[t_size];
|
||
|
};
|
||
|
|
||
|
// CollectionImpl: handles categories and collecton resizing
|
||
|
//
|
||
|
template <class TCtrl, size_t t_items, size_t t_categories>
|
||
|
class CollectionImpl : public CollectionImplBase<CollectionImpl<TCtrl, t_items, t_categories>, t_items + t_categories>
|
||
|
{
|
||
|
typedef CollectionImpl<TCtrl, t_items, t_categories> thisClass;
|
||
|
public:
|
||
|
typedef thisClass Collection;
|
||
|
|
||
|
CollectionImpl() : m_size(t_items)
|
||
|
{
|
||
|
FillMemory(m_auItemCat, sizeof m_auItemCat, 0xff); // UI_COLLECTION_INVALIDINDEX
|
||
|
}
|
||
|
|
||
|
UINT32 m_auItemCat[t_items];
|
||
|
Text m_asCatName[max(t_categories, 1)];
|
||
|
size_t m_size;
|
||
|
|
||
|
// Operations
|
||
|
HRESULT SetItemCategory(UINT uItem, UINT uCat, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT((uItem < t_items) && (uCat < t_categories));
|
||
|
|
||
|
m_auItemCat[uItem] = uCat;
|
||
|
|
||
|
return bUpdate ? InvalidateItems() : S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT SetCategoryText(UINT uCat, LPCWSTR sText, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT(uCat < t_categories);
|
||
|
|
||
|
m_asCatName[uCat] = sText;
|
||
|
|
||
|
return bUpdate ? InvalidateCategories() : S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT Resize(size_t size, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT(size <= t_items);
|
||
|
|
||
|
m_size = size;
|
||
|
|
||
|
return bUpdate ? InvalidateItems() : S_OK;
|
||
|
}
|
||
|
|
||
|
// Implementation
|
||
|
HRESULT OnGetItem(UINT uIndex, REFPROPERTYKEY key, PROPVARIANT *value)
|
||
|
{
|
||
|
ATLASSERT(uIndex < t_items + t_categories);
|
||
|
TCtrl* pCtrl = static_cast<TCtrl*>(this);
|
||
|
|
||
|
return uIndex < t_items ?
|
||
|
pCtrl->DoGetItem(uIndex, key, value) :
|
||
|
pCtrl->DoGetCategory(uIndex - t_items, key, value);
|
||
|
}
|
||
|
|
||
|
HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
|
||
|
{
|
||
|
ATLASSERT(k_(key) == k_CategoryId);
|
||
|
UINT32 uCat = UI_COLLECTION_INVALIDINDEX;
|
||
|
|
||
|
if (t_categories != 0)
|
||
|
{
|
||
|
if (m_auItemCat[uItem] == UI_COLLECTION_INVALIDINDEX)
|
||
|
{
|
||
|
TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
|
||
|
m_auItemCat[uItem] = ribbon.OnRibbonQueryItemCategory(TCtrl::GetID(), uItem);
|
||
|
}
|
||
|
uCat = m_auItemCat[uItem];
|
||
|
}
|
||
|
|
||
|
return SetPropertyVal(key, uCat, value);
|
||
|
}
|
||
|
|
||
|
HRESULT DoGetCategory(UINT uCat, REFPROPERTYKEY key, PROPVARIANT *value)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_Label:
|
||
|
if (m_asCatName[uCat].IsEmpty())
|
||
|
{
|
||
|
TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
|
||
|
m_asCatName[uCat] = ribbon.OnRibbonQueryCategoryText(TCtrl::GetID(), uCat);
|
||
|
}
|
||
|
hr = SetPropertyVal(key, (LPCWSTR)m_asCatName[uCat], value);
|
||
|
break;
|
||
|
case k_CategoryId:
|
||
|
hr = SetPropertyVal(key, uCat, value);
|
||
|
break;
|
||
|
default:
|
||
|
ATLASSERT(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT InvalidateItems()
|
||
|
{
|
||
|
return static_cast<TCtrl*>(this)->Invalidate(UI_PKEY_ItemsSource);
|
||
|
}
|
||
|
|
||
|
HRESULT InvalidateCategories()
|
||
|
{
|
||
|
return static_cast<TCtrl*>(this)->Invalidate(UI_PKEY_Categories);
|
||
|
}
|
||
|
|
||
|
HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* /*ppropvarNewValue*/)
|
||
|
{
|
||
|
ATLASSERT(nCmdID == TCtrl::GetID());
|
||
|
nCmdID; // avoid level 4 warning
|
||
|
|
||
|
HRESULT hr = E_NOTIMPL;
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_ItemsSource:
|
||
|
{
|
||
|
ATL::CComQIPtr<IUICollection> pIUICollection(ppropvarCurrentValue->punkVal);
|
||
|
ATLASSERT(pIUICollection);
|
||
|
hr = pIUICollection->Clear();
|
||
|
for (UINT i = 0; i < m_size; i++)
|
||
|
{
|
||
|
if FAILED(hr = pIUICollection->Add(m_apItems[i]))
|
||
|
break;
|
||
|
}
|
||
|
ATLASSERT(SUCCEEDED(hr));
|
||
|
}
|
||
|
break;
|
||
|
case k_Categories:
|
||
|
if (t_categories != 0)
|
||
|
{
|
||
|
ATL::CComQIPtr<IUICollection> pIUICategory(ppropvarCurrentValue->punkVal);
|
||
|
ATLASSERT(pIUICategory.p);
|
||
|
hr = pIUICategory->Clear();
|
||
|
for (UINT i = t_items; i < t_items + t_categories; i++)
|
||
|
{
|
||
|
if FAILED(hr = pIUICategory->Add(m_apItems[i]))
|
||
|
break;
|
||
|
}
|
||
|
ATLASSERT(SUCCEEDED(hr));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// TextCollectionImpl: handles item labels and selection
|
||
|
//
|
||
|
template <class TCtrl, size_t t_items, size_t t_categories = 0>
|
||
|
class TextCollectionImpl : public CollectionImpl<TCtrl, t_items, t_categories>
|
||
|
{
|
||
|
typedef TextCollectionImpl<TCtrl, t_items, t_categories> thisClass;
|
||
|
public:
|
||
|
typedef thisClass TextCollection;
|
||
|
|
||
|
TextCollectionImpl() : m_uSelected(UI_COLLECTION_INVALIDINDEX)
|
||
|
{ }
|
||
|
|
||
|
Text m_asText[t_items];
|
||
|
UINT m_uSelected;
|
||
|
|
||
|
// Operations
|
||
|
HRESULT SetItemText(UINT uItem, LPCWSTR sText, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT(uItem < t_items);
|
||
|
|
||
|
m_asText[uItem] = sText;
|
||
|
|
||
|
return bUpdate ? InvalidateItems() : S_OK;
|
||
|
}
|
||
|
|
||
|
UINT GetSelected()
|
||
|
{
|
||
|
return m_uSelected;
|
||
|
}
|
||
|
|
||
|
HRESULT Select(UINT uItem, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT((uItem < t_items) || (uItem == UI_COLLECTION_INVALIDINDEX));
|
||
|
|
||
|
m_uSelected = uItem;
|
||
|
|
||
|
TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
|
||
|
return bUpdate ?
|
||
|
ribbon.SetProperty(TCtrl::GetID(), UI_PKEY_SelectedItem, uItem) :
|
||
|
S_OK;
|
||
|
}
|
||
|
|
||
|
// Implementation
|
||
|
HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
|
||
|
{
|
||
|
ATLASSERT(uItem < t_items);
|
||
|
|
||
|
if (k_(key) == k_Label)
|
||
|
{
|
||
|
if (m_asText[uItem].IsEmpty())
|
||
|
{
|
||
|
TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
|
||
|
m_asText[uItem] = ribbon.OnRibbonQueryItemText(TCtrl::GetID(), uItem);
|
||
|
}
|
||
|
return SetPropertyVal(key, (LPCWSTR)m_asText[uItem], value);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return Collection::DoGetItem(uItem, key, value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
|
||
|
{
|
||
|
ATLASSERT(nCmdID == TCtrl::GetID());
|
||
|
|
||
|
if (k_(key) == k_SelectedItem)
|
||
|
{
|
||
|
TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
|
||
|
UINT uSel = UI_COLLECTION_INVALIDINDEX;
|
||
|
if ((m_uSelected == UI_COLLECTION_INVALIDINDEX) &&
|
||
|
ribbon.OnRibbonQuerySelectedItem(TCtrl::GetID(), uSel))
|
||
|
m_uSelected = uSel;
|
||
|
|
||
|
return SetPropertyVal(key, m_uSelected, ppropvarNewValue);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return Collection::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// ItemCollectionImpl: handles item image
|
||
|
//
|
||
|
template <class TCtrl, size_t t_items, size_t t_categories = 0>
|
||
|
class ItemCollectionImpl : public TextCollectionImpl<TCtrl, t_items, t_categories>
|
||
|
{
|
||
|
typedef ItemCollectionImpl<TCtrl, t_items, t_categories> thisClass;
|
||
|
public:
|
||
|
typedef thisClass ItemCollection;
|
||
|
|
||
|
ItemCollectionImpl()
|
||
|
{
|
||
|
ZeroMemory(m_aBitmap, sizeof m_aBitmap);
|
||
|
}
|
||
|
|
||
|
CBitmap m_aBitmap[t_items];
|
||
|
|
||
|
// Operations
|
||
|
HRESULT SetItemImage(UINT uIndex, HBITMAP hbm, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT(uIndex < t_items);
|
||
|
|
||
|
m_aBitmap[uIndex] = hbm;
|
||
|
|
||
|
return bUpdate ? InvalidateItems() : S_OK;
|
||
|
}
|
||
|
|
||
|
// Implementation
|
||
|
HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
|
||
|
{
|
||
|
ATLASSERT(uItem < t_items);
|
||
|
|
||
|
if (k_(key) == k_ItemImage)
|
||
|
{
|
||
|
if (m_aBitmap[uItem].IsNull())
|
||
|
{
|
||
|
TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
|
||
|
m_aBitmap[uItem] = ribbon.OnRibbonQueryItemImage(TCtrl::GetID(), uItem);
|
||
|
}
|
||
|
return m_aBitmap[uItem].IsNull() ?
|
||
|
E_NOTIMPL :
|
||
|
SetPropertyVal(key, GetImage(m_aBitmap[uItem], UI_OWNERSHIP_COPY), value);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return TextCollection::DoGetItem(uItem, key, value);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// ComboCollectionImpl: handles combo text
|
||
|
//
|
||
|
template <class TCtrl, size_t t_items, size_t t_categories = 0>
|
||
|
class ComboCollectionImpl : public ItemCollectionImpl<TCtrl, t_items, t_categories>
|
||
|
{
|
||
|
typedef ComboCollectionImpl<TCtrl, t_items, t_categories> thisClass;
|
||
|
public:
|
||
|
typedef thisClass ComboCollection;
|
||
|
|
||
|
// Operations
|
||
|
HRESULT SetComboText(LPCWSTR sText)
|
||
|
{
|
||
|
TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
|
||
|
return ribbon.IsRibbonUI() ?
|
||
|
ribbon.SetProperty(TCtrl::GetID(), UI_PKEY_StringValue, sText) :
|
||
|
S_OK;
|
||
|
}
|
||
|
|
||
|
LPCWSTR GetComboText()
|
||
|
{
|
||
|
static WCHAR sCombo[RIBBONUI_MAX_TEXT] = { 0 };
|
||
|
TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
|
||
|
PROPVARIANT var;
|
||
|
if (ribbon.IsRibbonUI())
|
||
|
{
|
||
|
HRESULT hr = ribbon.GetIUIFrameworkPtr()->GetUICommandProperty(TCtrl::GetID(), UI_PKEY_StringValue, &var);
|
||
|
hr = PropVariantToString(var, sCombo, RIBBONUI_MAX_TEXT);
|
||
|
return sCombo;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// CommandCollectionImpl: handles RibbonUI command collection controls
|
||
|
//
|
||
|
template <class TCtrl, size_t t_items, size_t t_categories = 0>
|
||
|
class CommandCollectionImpl : public CollectionImpl<TCtrl, t_items, t_categories>
|
||
|
{
|
||
|
typedef CommandCollectionImpl<TCtrl, t_items, t_categories> thisClass;
|
||
|
public:
|
||
|
typedef thisClass CommandCollection;
|
||
|
|
||
|
CommandCollectionImpl()
|
||
|
{
|
||
|
ZeroMemory(m_auCmd, sizeof m_auCmd);
|
||
|
ZeroMemory(m_aCmdType, sizeof m_aCmdType);
|
||
|
}
|
||
|
|
||
|
UINT32 m_auCmd[t_items];
|
||
|
BYTE m_aCmdType[t_items];
|
||
|
|
||
|
// Operations
|
||
|
HRESULT SetItemCommand(UINT uItem, UINT32 uCommandID, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT(uItem < t_items);
|
||
|
|
||
|
if (uCommandID == m_auCmd[uItem])
|
||
|
return S_OK;
|
||
|
|
||
|
TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
|
||
|
|
||
|
m_auCmd[uItem] = uCommandID;
|
||
|
if (uCommandID != 0)
|
||
|
ribbon.UIAddRibbonElement(uCommandID);
|
||
|
|
||
|
return bUpdate ? InvalidateItems() : S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT SetItemCommandType(UINT uItem, UI_COMMANDTYPE type, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT(uItem < t_items);
|
||
|
|
||
|
m_aCmdType[uItem] = (BYTE)type;
|
||
|
|
||
|
return bUpdate ? InvalidateItems() : S_OK;
|
||
|
}
|
||
|
|
||
|
// Implementation
|
||
|
HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
|
||
|
{
|
||
|
ATLASSERT(uItem < t_items);
|
||
|
TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
|
||
|
|
||
|
HRESULT hr = E_FAIL;
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_CommandId:
|
||
|
if (m_auCmd[uItem] == 0)
|
||
|
SetItemCommand(uItem, ribbon.OnRibbonQueryItemCommand(TCtrl::GetID(), uItem));
|
||
|
hr = SetPropertyVal(key, m_auCmd[uItem], value);
|
||
|
break;
|
||
|
case k_CommandType:
|
||
|
if (m_aCmdType[uItem] == UI_COMMANDTYPE_UNKNOWN)
|
||
|
SetItemCommandType(uItem, ribbon.OnRibbonQueryItemCommandType(TCtrl::GetID(), uItem));
|
||
|
hr = SetPropertyVal(key, UINT32(m_aCmdType[uItem]), value);
|
||
|
break;
|
||
|
case k_CategoryId:
|
||
|
default:
|
||
|
hr = Collection::DoGetItem(uItem, key, value);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT Select(UINT /*uItem*/, bool /*bUpdate*/ = false)
|
||
|
{
|
||
|
ATLASSERT(FALSE);
|
||
|
return S_OK;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// SimpleCollectionImpl: collection class for ribbon simple collection controls
|
||
|
//
|
||
|
template <class TCtrl, size_t t_size, UI_COMMANDTYPE t_CommandType = UI_COMMANDTYPE_ACTION>
|
||
|
class SimpleCollectionImpl : public CollectionImplBase<SimpleCollectionImpl<TCtrl, t_size>, t_size>
|
||
|
{
|
||
|
typedef SimpleCollectionImpl<TCtrl, t_size, t_CommandType> thisClass;
|
||
|
public:
|
||
|
typedef CollectionImplBase<thisClass, t_size> CollectionBase;
|
||
|
typedef thisClass SimpleCollection;
|
||
|
|
||
|
// Implementation
|
||
|
HRESULT OnGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
|
||
|
{
|
||
|
ATLASSERT(uItem < t_size);
|
||
|
TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
|
||
|
|
||
|
HRESULT hr = E_NOTIMPL;
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_ItemImage:
|
||
|
if (HBITMAP hbm = ribbon.DefRibbonQueryItemImage(TCtrl::GetID(), uItem))
|
||
|
hr = SetPropertyVal(key, GetImage(hbm, UI_OWNERSHIP_TRANSFER), value);
|
||
|
break;
|
||
|
case k_Label:
|
||
|
if (LPCWSTR sText = ribbon.DefRibbonQueryItemText(TCtrl::GetID(), uItem))
|
||
|
hr = SetPropertyVal(key, (LPCWSTR)sText, value);
|
||
|
break;
|
||
|
case k_CommandType:
|
||
|
hr = SetPropertyVal(key, t_CommandType, value);
|
||
|
break;
|
||
|
case k_CommandId:
|
||
|
hr = SetPropertyVal(key, ribbon.DefRibbonQueryItemCommand(TCtrl::GetID(), uItem), value);
|
||
|
break;
|
||
|
case k_CategoryId:
|
||
|
hr = SetPropertyVal(key, UI_COLLECTION_INVALIDINDEX, value);
|
||
|
break;
|
||
|
default:
|
||
|
ATLASSERT(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Ribbon collection control classes
|
||
|
|
||
|
// CollectionCtrlImpl: specializable class for ribbon collection controls
|
||
|
//
|
||
|
template <class T, UINT t_ID, class TCollection>
|
||
|
class CollectionCtrlImpl : public CommandCtrlImpl<T, t_ID>, public TCollection
|
||
|
{
|
||
|
typedef CollectionCtrlImpl<T, t_ID, TCollection> thisClass;
|
||
|
public:
|
||
|
typedef CommandCtrlImpl<T, t_ID> CommandCtrl;
|
||
|
typedef TCollection Collection;
|
||
|
|
||
|
// Implementation
|
||
|
virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
|
||
|
{
|
||
|
ATLASSERT(nCmdID == GetID());
|
||
|
ATLASSERT(ppropvarNewValue);
|
||
|
|
||
|
HRESULT hr = Collection::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
|
||
|
if FAILED(hr)
|
||
|
hr = CommandCtrl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
|
||
|
const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
|
||
|
IUISimplePropertySet* /*pCommandExecutionProperties*/)
|
||
|
{
|
||
|
ATLASSERT (nCmdID == GetID());
|
||
|
nCmdID; // avoid level4 warning
|
||
|
|
||
|
if (key == NULL) // gallery button pressed
|
||
|
{
|
||
|
GetWndRibbon().OnRibbonItemSelected(GetID(), UI_EXECUTIONVERB_EXECUTE, UI_COLLECTION_INVALIDINDEX);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
ATLASSERT(k_(*key) == k_SelectedItem);
|
||
|
ATLASSERT(ppropvarValue);
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
UINT32 uSel = 0xffff;
|
||
|
hr = UIPropertyToUInt32(*key, *ppropvarValue, &uSel);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if (GetWndRibbon().OnRibbonItemSelected(GetID(), verb, uSel))
|
||
|
TCollection::Select(uSel);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// ToolbarGalleryCtrlImpl: base class for ribbon toolbar gallery controls
|
||
|
//
|
||
|
template <class T, UINT t_ID, UINT t_idTB, size_t t_size>
|
||
|
class ToolbarGalleryCtrlImpl : public CollectionCtrlImpl<T, t_ID, CommandCollectionImpl<ToolbarGalleryCtrlImpl<T, t_ID, t_idTB, t_size>, t_size>>
|
||
|
{
|
||
|
public:
|
||
|
ToolbarGalleryCtrlImpl()
|
||
|
{
|
||
|
CResource tbres;
|
||
|
ATLVERIFY(tbres.Load(RT_TOOLBAR, t_idTB));
|
||
|
_AtlToolBarData* pData = (_AtlToolBarData*)tbres.Lock();
|
||
|
ATLASSERT(pData);
|
||
|
ATLASSERT(pData->wVersion == 1);
|
||
|
|
||
|
WORD* pItems = pData->items();
|
||
|
INT j = 0;
|
||
|
for (int i = 0; (i < pData->wItemCount) && (j < t_size); i++)
|
||
|
{
|
||
|
if (pItems[i] != 0)
|
||
|
{
|
||
|
m_aCmdType[j] = UI_COMMANDTYPE_ACTION;
|
||
|
m_auCmd[j++] = pItems[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (j < t_size)
|
||
|
Resize(j);
|
||
|
}
|
||
|
|
||
|
HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
|
||
|
{
|
||
|
ATLASSERT(uItem < m_size);
|
||
|
ATLASSERT(m_auCmd[uItem]);
|
||
|
|
||
|
HRESULT hr = E_FAIL;
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_CommandId:
|
||
|
hr = SetPropertyVal(key, m_auCmd[uItem], value);
|
||
|
break;
|
||
|
case k_CommandType:
|
||
|
hr = SetPropertyVal(key, UINT32(m_aCmdType[uItem]), value);
|
||
|
break;
|
||
|
case k_CategoryId:
|
||
|
hr = SetPropertyVal(key, UI_COLLECTION_INVALIDINDEX, value);
|
||
|
break;
|
||
|
default:
|
||
|
ATLASSERT(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
// SimpleCollectionCtrlImpl: base class for simple gallery and listbox controls
|
||
|
//
|
||
|
template <class T, UINT t_ID, size_t t_size, UI_COMMANDTYPE t_CommandType = UI_COMMANDTYPE_ACTION>
|
||
|
class SimpleCollectionCtrlImpl :
|
||
|
public CommandCtrlImpl<T, t_ID>,
|
||
|
public SimpleCollectionImpl<SimpleCollectionCtrlImpl<T, t_ID, t_size, t_CommandType>, t_size, t_CommandType>
|
||
|
{
|
||
|
typedef SimpleCollectionCtrlImpl<T, t_ID, t_size, t_CommandType> thisClass;
|
||
|
public:
|
||
|
typedef thisClass SimpleCollection;
|
||
|
|
||
|
SimpleCollectionCtrlImpl() : m_uSelected(0)
|
||
|
{ }
|
||
|
|
||
|
UINT m_uSelected;
|
||
|
|
||
|
HRESULT Select(UINT uItem, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT((uItem < t_size) || (uItem == UI_COLLECTION_INVALIDINDEX));
|
||
|
|
||
|
m_uSelected = uItem;
|
||
|
|
||
|
return bUpdate ?
|
||
|
GetWndRibbon().SetProperty(GetID(), UI_PKEY_SelectedItem, uItem) :
|
||
|
S_OK;
|
||
|
}
|
||
|
|
||
|
// Implementation
|
||
|
virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
|
||
|
{
|
||
|
ATLASSERT(nCmdID == GetID());
|
||
|
ATLASSERT(ppropvarNewValue != NULL);
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_ItemsSource:
|
||
|
{
|
||
|
ATL::CComQIPtr<IUICollection> pIUICollection(ppropvarCurrentValue->punkVal);
|
||
|
ATLASSERT(pIUICollection.p);
|
||
|
hr = pIUICollection->Clear();
|
||
|
for (UINT i = 0; i < t_size; i++)
|
||
|
{
|
||
|
if FAILED(hr = pIUICollection->Add(m_apItems[i]))
|
||
|
break;
|
||
|
}
|
||
|
ATLASSERT(SUCCEEDED(hr));
|
||
|
}
|
||
|
break;
|
||
|
case k_SelectedItem:
|
||
|
hr = SetPropertyVal(UI_PKEY_SelectedItem, m_uSelected, ppropvarNewValue);
|
||
|
break;
|
||
|
default:
|
||
|
hr = CommandCtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
|
||
|
const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
|
||
|
IUISimplePropertySet* /*pCommandExecutionProperties*/)
|
||
|
{
|
||
|
ATLASSERT (nCmdID == GetID());
|
||
|
nCmdID; // avoid level 4 warning
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
if (key == NULL) // gallery button pressed
|
||
|
{
|
||
|
GetWndRibbon().OnRibbonItemSelected(GetID(), UI_EXECUTIONVERB_EXECUTE, UI_COLLECTION_INVALIDINDEX);
|
||
|
return hr;
|
||
|
}
|
||
|
ATLASSERT(k_(*key) == k_SelectedItem);
|
||
|
ATLASSERT(ppropvarValue);
|
||
|
|
||
|
if SUCCEEDED(hr = UIPropertyToUInt32(*key, *ppropvarValue, &m_uSelected))
|
||
|
GetWndRibbon().OnRibbonItemSelected(GetID(), verb, m_uSelected);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// RecentItemsCtrlImpl
|
||
|
//
|
||
|
template <class T, UINT t_ID, class TDocList = CRecentDocumentList>
|
||
|
class RecentItemsCtrlImpl :
|
||
|
public CtrlImpl<T, t_ID>,
|
||
|
public CollectionImplBase<RecentItemsCtrlImpl<T, t_ID, TDocList>, TDocList::m_nMaxEntries_Max>,
|
||
|
public TDocList
|
||
|
{
|
||
|
typedef RecentItemsCtrlImpl<T, t_ID, TDocList> thisClass;
|
||
|
public:
|
||
|
typedef thisClass RecentItems;
|
||
|
|
||
|
// Implementation
|
||
|
HRESULT OnGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
|
||
|
{
|
||
|
ATLASSERT((INT)uItem < GetMaxEntries());
|
||
|
|
||
|
LPCWSTR sPath = m_arrDocs[uItem].szDocName;
|
||
|
HRESULT hr = E_NOTIMPL;
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_Label:
|
||
|
hr = SetPropertyVal(key, GetWndRibbon().OnRibbonQueryRecentItemName(sPath), value);
|
||
|
break;
|
||
|
case k_LabelDescription:
|
||
|
hr = SetPropertyVal(key, sPath, value);
|
||
|
break;
|
||
|
default:
|
||
|
ATLASSERT(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
|
||
|
{
|
||
|
ATLASSERT(nCmdID == GetID());
|
||
|
ATLASSERT(ppropvarNewValue);
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_RecentItems:
|
||
|
if (SAFEARRAY* psa = SafeArrayCreateVector(VT_UNKNOWN, 0, m_arrDocs.GetSize()))
|
||
|
{
|
||
|
const int iLastIndex = m_arrDocs.GetSize() - 1;
|
||
|
for (LONG i = 0; i <= iLastIndex; i++)
|
||
|
SafeArrayPutElement(psa, &i, m_apItems[iLastIndex - i]); // reverse order
|
||
|
|
||
|
hr = SetPropertyVal(key, psa, ppropvarNewValue);
|
||
|
SafeArrayDestroy(psa);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
hr = CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
|
||
|
const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
|
||
|
IUISimplePropertySet* /*pCommandExecutionProperties*/)
|
||
|
{
|
||
|
ATLASSERT(nCmdID == GetID());
|
||
|
nCmdID; // avoid level 4 warning
|
||
|
ATLASSERT(verb == UI_EXECUTIONVERB_EXECUTE);
|
||
|
verb; // avoid level 4 warning
|
||
|
ATLASSERT((key) && (k_(*key) == k_SelectedItem));
|
||
|
ATLASSERT(ppropvarValue);
|
||
|
|
||
|
UINT32 uSel = 0xffff;
|
||
|
HRESULT hr = UIPropertyToUInt32(*key, *ppropvarValue, &uSel);
|
||
|
if SUCCEEDED(hr)
|
||
|
{
|
||
|
ATLASSERT(uSel < (UINT)GetMaxEntries());
|
||
|
GetWndRibbon().DefCommandExecute(ID_FILE_MRU_FIRST + uSel);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Ribbon stand-alone control classes
|
||
|
|
||
|
// FontCtrlImpl
|
||
|
//
|
||
|
template <class T, UINT t_ID>
|
||
|
class FontCtrlImpl : public CtrlImpl<T, t_ID>
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
CharFormat m_cf;
|
||
|
|
||
|
// Implementation
|
||
|
virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
|
||
|
const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
|
||
|
IUISimplePropertySet* pCommandExecutionProperties)
|
||
|
{
|
||
|
ATLASSERT (nCmdID == GetID());
|
||
|
nCmdID; // avoid level 4 warning
|
||
|
ATLASSERT ((key) && (k_(*key) == k_FontProperties));
|
||
|
key; // avoid level 4 warning
|
||
|
|
||
|
HRESULT hr = E_INVALIDARG;
|
||
|
switch (verb)
|
||
|
{
|
||
|
case UI_EXECUTIONVERB_PREVIEW:
|
||
|
case UI_EXECUTIONVERB_EXECUTE:
|
||
|
ATLASSERT(pCommandExecutionProperties);
|
||
|
PROPVARIANT propvar;
|
||
|
|
||
|
if (SUCCEEDED(hr = pCommandExecutionProperties->GetValue(UI_PKEY_FontProperties_ChangedProperties, &propvar)))
|
||
|
m_cf << ATL::CComQIPtr<IPropertyStore>(propvar.punkVal);
|
||
|
break;
|
||
|
|
||
|
case UI_EXECUTIONVERB_CANCELPREVIEW:
|
||
|
ATLASSERT(ppropvarValue);
|
||
|
ATL::CComPtr<IPropertyStore> pStore;
|
||
|
|
||
|
if (SUCCEEDED(hr = UIPropertyToInterface(UI_PKEY_FontProperties, *ppropvarValue, &pStore)))
|
||
|
m_cf << pStore;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
GetWndRibbon().OnRibbonFontCtrlExecute(GetID(), verb, &m_cf);
|
||
|
else
|
||
|
ATLASSERT(FALSE);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
|
||
|
{
|
||
|
if ((k_(key) == k_FontProperties) && (GetWndRibbon().OnRibbonQueryFont(t_ID, m_cf)))
|
||
|
{
|
||
|
ATL::CComQIPtr<IPropertyStore> pStore(ppropvarCurrentValue->punkVal);
|
||
|
m_cf >> pStore;
|
||
|
return SetPropertyVal(key, pStore.p, ppropvarNewValue);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// ColorCtrlImpl
|
||
|
//
|
||
|
template <class T, UINT t_ID>
|
||
|
class ColorCtrlImpl : public CommandCtrlImpl<T, t_ID>
|
||
|
{
|
||
|
public:
|
||
|
ColorCtrlImpl() : m_colorType(UI_SWATCHCOLORTYPE_NOCOLOR), m_color(0x800080) /*MAGENTA*/
|
||
|
{ }
|
||
|
|
||
|
COLORREF m_color;
|
||
|
UINT32 m_colorType; // value in UI_SWATCHCOLORTYPE
|
||
|
Text m_sLabels[6]; // k_MoreColorsLabel to k_ThemeColorsCategoryLabel
|
||
|
ATL::CSimpleArray<COLORREF> m_aColors[2];
|
||
|
ATL::CSimpleArray<LPCWSTR> m_aTooltips[2];
|
||
|
|
||
|
// Operations
|
||
|
HRESULT SetColor(COLORREF color, bool bUpdate = false)
|
||
|
{
|
||
|
if (m_colorType != UI_SWATCHCOLORTYPE_RGB)
|
||
|
SetColorType(UI_SWATCHCOLORTYPE_RGB, bUpdate);
|
||
|
m_color = color;
|
||
|
return bUpdate ? SetProperty(UI_PKEY_Color, color) : S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT SetColorType(UI_SWATCHCOLORTYPE type, bool bUpdate = false)
|
||
|
{
|
||
|
m_colorType = type;
|
||
|
return bUpdate ? SetProperty(UI_PKEY_ColorType, type) : S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT SetColorLabel(REFPROPERTYKEY key, LPCWSTR sLabel, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT((k_(key) >= k_ThemeColorsCategoryLabel) && (k_(key) <= k_MoreColorsLabel));
|
||
|
m_sLabels[k_(key) - k_ThemeColorsCategoryLabel] = sLabel;
|
||
|
return bUpdate ? SetProperty(key, sLabel) : S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT SetColorArray(REFPROPERTYKEY key, COLORREF* pColor, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT((k_(key) == k_ThemeColors) || (k_(key) == k_StandardColors));
|
||
|
|
||
|
const INT ic = k_(key) - k_ThemeColors;
|
||
|
m_aColors[ic].RemoveAll();
|
||
|
while (*pColor != 0x800080) /*MAGENTA*/
|
||
|
m_aColors[ic].Add(*pColor++);
|
||
|
|
||
|
if (bUpdate)
|
||
|
{
|
||
|
PROPVARIANT var;
|
||
|
if SUCCEEDED(InitPropVariantFromUInt32Vector(m_aColors[ic].GetData(), m_aColors[ic].GetSize(), &var))
|
||
|
return SetProperty(key, var);
|
||
|
else
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT SetColorTooltips(REFPROPERTYKEY key, LPCWSTR* ppsTT, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT((k_(key) == k_ThemeColorsTooltips) || (k_(key) == k_StandardColorsTooltips));
|
||
|
|
||
|
const INT ic = k_(key) - k_ThemeColorsTooltips;
|
||
|
m_aTooltips[ic].RemoveAll();
|
||
|
while (*ppsTT)
|
||
|
m_aTooltips[ic].Add(*ppsTT++);
|
||
|
|
||
|
if (bUpdate)
|
||
|
{
|
||
|
PROPVARIANT var;
|
||
|
if SUCCEEDED(InitPropVariantFromStringVector(m_aTooltips[ic].GetData(), m_aTooltips[ic].GetSize(), &var))
|
||
|
return SetProperty(key, var);
|
||
|
else
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Implementation
|
||
|
virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
|
||
|
const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
|
||
|
IUISimplePropertySet* pCommandExecutionProperties)
|
||
|
{
|
||
|
ATLASSERT (nCmdID == GetID());
|
||
|
nCmdID; // avoid level 4 warning
|
||
|
ATLASSERT (key && (k_(*key) == k_ColorType));
|
||
|
key; // avoid level 4 warning
|
||
|
ATLASSERT (ppropvarValue);
|
||
|
|
||
|
HRESULT hr = PropVariantToUInt32(*ppropvarValue, &m_colorType);
|
||
|
ATLASSERT(SUCCEEDED(hr));
|
||
|
|
||
|
if (SUCCEEDED(hr) && (m_colorType == UI_SWATCHCOLORTYPE_RGB))
|
||
|
{
|
||
|
ATLASSERT(pCommandExecutionProperties);
|
||
|
PROPVARIANT var;
|
||
|
if SUCCEEDED(hr = pCommandExecutionProperties->GetValue(UI_PKEY_Color, &var))
|
||
|
hr = PropVariantToUInt32(var, &m_color);
|
||
|
}
|
||
|
|
||
|
if SUCCEEDED(hr)
|
||
|
GetWndRibbon().OnRibbonColorCtrlExecute(GetID(), verb, (UI_SWATCHCOLORTYPE)m_colorType/*uType*/, m_color);
|
||
|
else
|
||
|
ATLASSERT(FALSE); // something was wrong
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
|
||
|
{
|
||
|
ATLASSERT (nCmdID == GetID());
|
||
|
|
||
|
HRESULT hr = E_NOTIMPL;
|
||
|
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_ColorType:
|
||
|
hr = SetPropertyVal(key, m_colorType, ppropvarNewValue);
|
||
|
break;
|
||
|
case k_Color:
|
||
|
if (m_color == 0x800080) /*MAGENTA*/
|
||
|
m_color = GetWndRibbon().OnRibbonQueryColor(GetID());
|
||
|
hr = SetPropertyVal(key, m_color, ppropvarNewValue);
|
||
|
break;
|
||
|
case k_ColorMode:
|
||
|
break;
|
||
|
case k_ThemeColorsCategoryLabel:
|
||
|
case k_StandardColorsCategoryLabel:
|
||
|
case k_RecentColorsCategoryLabel:
|
||
|
case k_AutomaticColorLabel:
|
||
|
case k_NoColorLabel:
|
||
|
case k_MoreColorsLabel:
|
||
|
{
|
||
|
const UINT iLabel = k_(key) - k_ThemeColorsCategoryLabel;
|
||
|
if (m_sLabels[iLabel].IsEmpty())
|
||
|
if (LPCWSTR psLabel = GetWndRibbon().OnRibbonQueryColorLabel(GetID(), key))
|
||
|
m_sLabels[iLabel] = psLabel;
|
||
|
if (!m_sLabels[iLabel].IsEmpty())
|
||
|
hr = SetPropertyVal(key, (LPCWSTR)m_sLabels[iLabel], ppropvarNewValue);
|
||
|
}
|
||
|
break;
|
||
|
case k_ThemeColors:
|
||
|
case k_StandardColors:
|
||
|
{
|
||
|
const INT ic = k_(key) - k_ThemeColors;
|
||
|
if (!m_aColors[ic].GetSize())
|
||
|
if (COLORREF* pColor = GetWndRibbon().OnRibbonQueryColorArray(GetID(), key))
|
||
|
SetColorArray(key, pColor);
|
||
|
if (INT iMax = m_aColors[ic].GetSize())
|
||
|
hr = InitPropVariantFromUInt32Vector(m_aColors[ic].GetData(), iMax, ppropvarNewValue);
|
||
|
}
|
||
|
break;
|
||
|
case k_ThemeColorsTooltips:
|
||
|
case k_StandardColorsTooltips:
|
||
|
{
|
||
|
const INT ic = k_(key) - k_ThemeColorsTooltips;
|
||
|
if (m_aTooltips[ic].GetSize() == 0)
|
||
|
if (LPCWSTR* ppsTT = GetWndRibbon().OnRibbonQueryColorTooltips(GetID(), key))
|
||
|
SetColorTooltips(key, ppsTT);
|
||
|
if (INT iMax = m_aTooltips[ic].GetSize())
|
||
|
hr = InitPropVariantFromStringVector(m_aTooltips[ic].GetData(), iMax, ppropvarNewValue);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
hr = CommandCtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// SpinnerCtrlImpl
|
||
|
//
|
||
|
template <class T, UINT t_ID, typename V = LONG>
|
||
|
class SpinnerCtrlImpl : public CtrlImpl<T, t_ID>
|
||
|
{
|
||
|
public:
|
||
|
SpinnerCtrlImpl()
|
||
|
{
|
||
|
m_Values[0] = m_Values[2] = m_Values[4] = 0;
|
||
|
m_Values[1] = 100;
|
||
|
m_Values[3] = 1;
|
||
|
}
|
||
|
|
||
|
V m_Values[5];
|
||
|
// k_DecimalValue = 201, k_MaxValue = 203, k_MinValue, k_Increment, k_DecimalPlaces
|
||
|
|
||
|
Text m_FormatString;
|
||
|
Text m_RepresentativeString;
|
||
|
|
||
|
// Operations
|
||
|
HRESULT SetDecimalPlaces(V vPlaces, bool bUpdate = false)
|
||
|
{
|
||
|
return SetValue(UI_PKEY_DecimalPlaces, vPlaces, bUpdate);
|
||
|
}
|
||
|
|
||
|
HRESULT SetMin(V vMin, bool bUpdate = false)
|
||
|
{
|
||
|
return SetValue(UI_PKEY_MinValue, vMin, bUpdate);
|
||
|
}
|
||
|
|
||
|
HRESULT SetMax(V vMax, bool bUpdate = false)
|
||
|
{
|
||
|
return SetValue(UI_PKEY_MaxValue, vMax, bUpdate);
|
||
|
}
|
||
|
|
||
|
HRESULT SetVal(V vVal, bool bUpdate = false)
|
||
|
{
|
||
|
return SetValue(UI_PKEY_DecimalValue, vVal, bUpdate);
|
||
|
}
|
||
|
|
||
|
HRESULT SetIncrement(V vIncrement, bool bUpdate = false)
|
||
|
{
|
||
|
return SetValue(UI_PKEY_Increment, vIncrement, bUpdate);
|
||
|
}
|
||
|
|
||
|
HRESULT SetFormatString(LPCWSTR sFormat, bool bUpdate = false)
|
||
|
{
|
||
|
return SetText(UI_PKEY_FormatString, sFormat, bUpdate);
|
||
|
}
|
||
|
|
||
|
HRESULT SetRepresentativeString(LPCWSTR sRepresentative, bool bUpdate = false)
|
||
|
{
|
||
|
return SetText(UI_PKEY_RepresentativeString, sRepresentative, bUpdate);
|
||
|
}
|
||
|
|
||
|
// Implementation
|
||
|
HRESULT SetText(REFPROPERTYKEY key, LPCWSTR sText, bool bUpdate = false)
|
||
|
{
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_FormatString:
|
||
|
m_FormatString = sText;
|
||
|
break;
|
||
|
case k_RepresentativeString:
|
||
|
m_RepresentativeString = sText;
|
||
|
break;
|
||
|
default:
|
||
|
return CtrlImpl::SetText(key, sText, bUpdate);
|
||
|
}
|
||
|
|
||
|
return bUpdate ?
|
||
|
GetWndRibbon().InvalidateProperty(GetID(), key) :
|
||
|
S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT SetValue(REFPROPERTYKEY key, V val, bool bUpdate = false)
|
||
|
{
|
||
|
ATLASSERT((k_(key) <= k_DecimalPlaces) && (k_(key) >= k_DecimalValue));
|
||
|
|
||
|
const INT iVal = k_(key) == k_DecimalValue ? 0 : k_(key) - k_StringValue;
|
||
|
m_Values[iVal] = val;
|
||
|
|
||
|
if (bUpdate)
|
||
|
{
|
||
|
if(k_(key) == k_DecimalValue)
|
||
|
{
|
||
|
DECIMAL decVal;
|
||
|
InitDecimal(val, &decVal);
|
||
|
return SetProperty(key, &decVal);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return GetWndRibbon().InvalidateProperty(GetID(), key);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT QueryValue(REFPROPERTYKEY key, LONG* plVal)
|
||
|
{
|
||
|
return GetWndRibbon().OnRibbonQuerySpinnerValue(GetID(), key, plVal);
|
||
|
}
|
||
|
|
||
|
HRESULT QueryValue(REFPROPERTYKEY key, DOUBLE* pdVal)
|
||
|
{
|
||
|
return GetWndRibbon().OnRibbonQueryFloatSpinnerValue(GetID(), key, pdVal);
|
||
|
}
|
||
|
|
||
|
HRESULT OnGetValue(REFPROPERTYKEY key, PROPVARIANT* ppv)
|
||
|
{
|
||
|
ATLASSERT((k_(key) <= k_DecimalPlaces) && (k_(key) >= k_DecimalValue));
|
||
|
|
||
|
const INT iVal = k_(key) == k_DecimalValue ? 0 : k_(key) - k_StringValue;
|
||
|
|
||
|
QueryValue(key, m_Values + iVal);
|
||
|
|
||
|
if (k_(key) == k_DecimalPlaces)
|
||
|
{
|
||
|
return SetPropertyVal(key, m_Values[iVal], ppv);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DECIMAL decVal;
|
||
|
InitDecimal(m_Values[iVal], &decVal);
|
||
|
return SetPropertyVal(key, &decVal, ppv);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT OnGetText(REFPROPERTYKEY key, Text& sVal, PROPVARIANT* ppv)
|
||
|
{
|
||
|
if (LPCWSTR sNew = GetWndRibbon().OnRibbonQueryText(GetID(), key))
|
||
|
sVal = sNew;
|
||
|
return SetPropertyVal(key, (LPCWSTR)sVal, ppv);
|
||
|
}
|
||
|
|
||
|
virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
|
||
|
const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
|
||
|
IUISimplePropertySet* /*pCommandExecutionProperties*/)
|
||
|
{
|
||
|
ATLASSERT (nCmdID == GetID());
|
||
|
nCmdID; // avoid level 4 warning
|
||
|
ATLASSERT (key && (k_(*key) == k_DecimalValue));
|
||
|
key; // avoid level 4 warning
|
||
|
ATLASSERT (verb == UI_EXECUTIONVERB_EXECUTE);
|
||
|
verb; // avoid level 4 warning
|
||
|
|
||
|
DECIMAL decVal;
|
||
|
|
||
|
HRESULT hr = UIPropertyToDecimal(UI_PKEY_DecimalValue, *ppropvarValue, &decVal);
|
||
|
hr = InitVal(m_Values[0], &decVal);
|
||
|
|
||
|
GetWndRibbon().OnRibbonSpinnerCtrlExecute(GetID(), &m_Values[0]);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
|
||
|
{
|
||
|
ATLASSERT (nCmdID == GetID());
|
||
|
|
||
|
HRESULT hr = E_NOTIMPL;
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_DecimalPlaces:
|
||
|
case k_DecimalValue:
|
||
|
case k_Increment:
|
||
|
case k_MaxValue:
|
||
|
case k_MinValue:
|
||
|
hr = OnGetValue(key, ppropvarNewValue);
|
||
|
break;
|
||
|
case k_FormatString:
|
||
|
if (m_FormatString.IsEmpty())
|
||
|
return OnGetText(key, m_FormatString, ppropvarNewValue);
|
||
|
break;
|
||
|
case k_RepresentativeString:
|
||
|
if (m_RepresentativeString.IsEmpty())
|
||
|
return OnGetText(key, m_RepresentativeString, ppropvarNewValue);
|
||
|
break;
|
||
|
default:
|
||
|
hr = CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// decimal conversion helpers
|
||
|
static HRESULT InitDecimal(LONG& val, DECIMAL* pDecimal)
|
||
|
{
|
||
|
return ::VarDecFromI4(val, pDecimal);
|
||
|
}
|
||
|
|
||
|
static HRESULT InitDecimal(DOUBLE& val, DECIMAL* pDecimal)
|
||
|
{
|
||
|
return ::VarDecFromR8(val, pDecimal);
|
||
|
}
|
||
|
|
||
|
static HRESULT InitVal(LONG& val, const DECIMAL* pDecimal)
|
||
|
{
|
||
|
return ::VarI4FromDec(pDecimal, &val);
|
||
|
}
|
||
|
|
||
|
static HRESULT InitVal(DOUBLE& val, const DECIMAL* pDecimal)
|
||
|
{
|
||
|
return ::VarR8FromDec(pDecimal, &val);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// CRibbonImpl Ribbon implementation class
|
||
|
//
|
||
|
template <class T>
|
||
|
class CRibbonImpl :
|
||
|
public CRibbonUpdateUI<T>,
|
||
|
public ICtrl,
|
||
|
public IUIApplication,
|
||
|
public IUICommandHandler
|
||
|
{
|
||
|
typedef CRibbonImpl<T> thisClass;
|
||
|
public:
|
||
|
typedef thisClass Ribbon;
|
||
|
typedef T WndRibbon;
|
||
|
|
||
|
CRibbonImpl() : m_bRibbonUI(false), m_hgRibbonSettings(NULL)
|
||
|
{
|
||
|
#ifdef _DEBUG
|
||
|
m_cRef = 1;
|
||
|
#endif
|
||
|
pWndRibbon = static_cast<T*>(this);
|
||
|
HRESULT hr = ::CoInitialize(NULL);
|
||
|
if(SUCCEEDED(hr))
|
||
|
if (RunTimeHelper::IsRibbonUIAvailable())
|
||
|
hr = m_pIUIFramework.CoCreateInstance(CLSID_UIRibbonFramework);
|
||
|
else
|
||
|
ATLTRACE(L"Ribbon UI not available\n");
|
||
|
|
||
|
if FAILED(hr)
|
||
|
ATLTRACE(L"Ribbon construction failed\n");
|
||
|
|
||
|
ATLASSERT(SUCCEEDED(hr));
|
||
|
}
|
||
|
|
||
|
~CRibbonImpl()
|
||
|
{
|
||
|
::GlobalFree(m_hgRibbonSettings);
|
||
|
m_pIUIFramework.Release();
|
||
|
::CoUninitialize();
|
||
|
}
|
||
|
|
||
|
ICtrl& GetRibbonCtrl(UINT)
|
||
|
{
|
||
|
return static_cast<ICtrl&>(*this);
|
||
|
}
|
||
|
|
||
|
ATL::CComPtr<IUIFramework> m_pIUIFramework;
|
||
|
HGLOBAL m_hgRibbonSettings;
|
||
|
bool m_bRibbonUI;
|
||
|
|
||
|
bool IsRibbonUI()
|
||
|
{
|
||
|
return m_bRibbonUI;
|
||
|
}
|
||
|
|
||
|
IUIFramework* GetIUIFrameworkPtr()
|
||
|
{
|
||
|
return m_pIUIFramework;
|
||
|
}
|
||
|
|
||
|
template <typename I>
|
||
|
I* GetRibbonViewPtr(UINT32 uID)
|
||
|
{
|
||
|
ATLASSERT(m_pIUIFramework);
|
||
|
ATL::CComPtr<I> pI;
|
||
|
return m_pIUIFramework->GetView(uID, __uuidof(I), (void**) &pI) == S_OK ?
|
||
|
pI :
|
||
|
NULL;
|
||
|
}
|
||
|
|
||
|
IUIRibbon* GetRibbonPtr()
|
||
|
{
|
||
|
return GetRibbonViewPtr<IUIRibbon>(0);
|
||
|
}
|
||
|
|
||
|
IUIContextualUI* GetMenuPtr(UINT32 uID)
|
||
|
{
|
||
|
ATLASSERT(uID);
|
||
|
return GetRibbonViewPtr<IUIContextualUI>(uID);
|
||
|
}
|
||
|
|
||
|
UINT GetRibbonHeight()
|
||
|
{
|
||
|
ATLASSERT(IsRibbonUI());
|
||
|
|
||
|
UINT32 cy = 0;
|
||
|
if (ATL::CComPtr<IUIRibbon> pIUIRibbon = GetRibbonPtr())
|
||
|
pIUIRibbon->GetHeight(&cy);
|
||
|
return cy;
|
||
|
}
|
||
|
|
||
|
HRESULT CreateRibbon(LPCWSTR sResName = L"APPLICATION_RIBBON")
|
||
|
{
|
||
|
T* pT = static_cast<T*>(this);
|
||
|
ATLASSERT(GetIUIFrameworkPtr() && !IsRibbonUI());
|
||
|
ATLASSERT(pT->IsWindow());
|
||
|
|
||
|
HRESULT hr = m_pIUIFramework->Initialize(pT->m_hWnd, this);
|
||
|
|
||
|
if (hr == S_OK)
|
||
|
hr = m_pIUIFramework->LoadUI(ModuleHelper::GetResourceInstance(), sResName);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT DestroyRibbon()
|
||
|
{
|
||
|
T* pT = static_cast<T*>(this);
|
||
|
ATLASSERT(GetIUIFrameworkPtr() && IsRibbonUI());
|
||
|
ATLASSERT(pT->IsWindow());
|
||
|
|
||
|
HRESULT hRes = m_pIUIFramework->Destroy();
|
||
|
if (!RunTimeHelper::IsWin7())
|
||
|
pT->SetWindowRgn(NULL, TRUE); // Vista Basic bug workaround
|
||
|
return hRes;
|
||
|
}
|
||
|
|
||
|
// Ribbon persistency
|
||
|
HRESULT operator >>(IStream* pIStream)
|
||
|
{
|
||
|
ATLASSERT(GetIUIFrameworkPtr());
|
||
|
ATLASSERT(pIStream);
|
||
|
|
||
|
HRESULT hr = E_FAIL;
|
||
|
if (ATL::CComPtr<IUIRibbon> pIUIRibbon = GetRibbonPtr())
|
||
|
{
|
||
|
const LARGE_INTEGER li0 = { 0 };
|
||
|
pIStream->Seek(li0, STREAM_SEEK_SET, NULL);
|
||
|
hr = pIUIRibbon->SaveSettingsToStream(pIStream);
|
||
|
pIStream->Commit(STGC_DEFAULT);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT operator <<(IStream* pIStream)
|
||
|
{
|
||
|
ATLASSERT(GetIUIFrameworkPtr());
|
||
|
ATLASSERT(pIStream);
|
||
|
|
||
|
HRESULT hr = E_FAIL;
|
||
|
if (ATL::CComPtr<IUIRibbon> pIUIRibbon = GetRibbonPtr())
|
||
|
{
|
||
|
const LARGE_INTEGER li0 = { 0 };
|
||
|
pIStream->Seek(li0, STREAM_SEEK_SET, NULL);
|
||
|
hr = pIUIRibbon->LoadSettingsFromStream(pIStream);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
void ResetRibbonSettings()
|
||
|
{
|
||
|
if (m_hgRibbonSettings != NULL)
|
||
|
{
|
||
|
::GlobalFree(m_hgRibbonSettings);
|
||
|
m_hgRibbonSettings = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT SaveRibbonSettings()
|
||
|
{
|
||
|
ATLASSERT(GetIUIFrameworkPtr());
|
||
|
ATLASSERT(static_cast<T*>(this)->IsWindow());
|
||
|
|
||
|
HRESULT hr = E_FAIL;
|
||
|
ATL::CComPtr<IStream> pIStream;
|
||
|
|
||
|
if SUCCEEDED(hr = ::CreateStreamOnHGlobal(m_hgRibbonSettings, FALSE, &pIStream))
|
||
|
hr = *this >> pIStream;
|
||
|
|
||
|
if (SUCCEEDED(hr) && (m_hgRibbonSettings == NULL))
|
||
|
hr = ::GetHGlobalFromStream(pIStream, &m_hgRibbonSettings);
|
||
|
|
||
|
if FAILED(hr)
|
||
|
ResetRibbonSettings();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT RestoreRibbonSettings()
|
||
|
{
|
||
|
ATLASSERT(GetIUIFrameworkPtr());
|
||
|
ATLASSERT(m_hgRibbonSettings);
|
||
|
ATLASSERT(static_cast<T*>(this)->IsWindow());
|
||
|
|
||
|
HRESULT hr = E_FAIL;
|
||
|
ATL::CComPtr<IStream> pIStream;
|
||
|
|
||
|
if SUCCEEDED(hr = ::CreateStreamOnHGlobal(m_hgRibbonSettings, FALSE, &pIStream))
|
||
|
hr = *this << pIStream;
|
||
|
|
||
|
if FAILED(hr)
|
||
|
ResetRibbonSettings();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// QAT dock states
|
||
|
UI_CONTROLDOCK GetQATDock()
|
||
|
{
|
||
|
ATLASSERT(GetIUIFrameworkPtr());
|
||
|
ATLASSERT(IsRibbonUI());
|
||
|
|
||
|
UINT32 uDock = 0;
|
||
|
PROPVARIANT propvar;
|
||
|
ATL::CComQIPtr<IPropertyStore>pIPS(GetRibbonPtr());
|
||
|
|
||
|
if ((pIPS != NULL) && SUCCEEDED(pIPS->GetValue(UI_PKEY_QuickAccessToolbarDock, &propvar)) &&
|
||
|
SUCCEEDED(UIPropertyToUInt32(UI_PKEY_QuickAccessToolbarDock, propvar, &uDock)))
|
||
|
return (UI_CONTROLDOCK)uDock;
|
||
|
|
||
|
ATLASSERT(FALSE); // something was wrong
|
||
|
return (UI_CONTROLDOCK)0;
|
||
|
}
|
||
|
|
||
|
bool SetQATDock(UI_CONTROLDOCK dockState)
|
||
|
{
|
||
|
ATLASSERT(GetIUIFrameworkPtr());
|
||
|
ATLASSERT(IsRibbonUI());
|
||
|
|
||
|
PROPVARIANT propvar;
|
||
|
ATLVERIFY(SUCCEEDED(SetPropertyVal(UI_PKEY_QuickAccessToolbarDock, dockState, &propvar)));
|
||
|
|
||
|
ATL::CComQIPtr<IPropertyStore>pIPS(GetRibbonPtr());
|
||
|
if ((pIPS != NULL) && SUCCEEDED(pIPS->SetValue(UI_PKEY_QuickAccessToolbarDock, propvar)))
|
||
|
{
|
||
|
pIPS->Commit();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
ATLASSERT(FALSE); // something was wrong
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Ribbon display states
|
||
|
bool GetRibbonDisplayState(REFPROPERTYKEY key)
|
||
|
{
|
||
|
ATLASSERT(GetIUIFrameworkPtr());
|
||
|
ATLASSERT(IsRibbonUI());
|
||
|
ATLASSERT((k_(key) == k_Viewable) || (k_(key) == k_Minimized));
|
||
|
|
||
|
PROPVARIANT propvar;
|
||
|
ATL::CComQIPtr<IPropertyStore>pIPS(GetRibbonPtr());
|
||
|
|
||
|
if ((pIPS != NULL) && SUCCEEDED(pIPS->GetValue(key, &propvar)))
|
||
|
{
|
||
|
BOOL bState = FALSE;
|
||
|
if SUCCEEDED(UIPropertyToBoolean(key, propvar, &bState))
|
||
|
return (bState != FALSE);
|
||
|
}
|
||
|
|
||
|
ATLASSERT(FALSE); // something was wrong
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool SetRibbonDisplayState(REFPROPERTYKEY key, bool bState = true)
|
||
|
{
|
||
|
ATLASSERT(GetIUIFrameworkPtr());
|
||
|
ATLASSERT(IsRibbonUI());
|
||
|
ATLASSERT((k_(key) == k_Viewable) || (k_(key) == k_Minimized));
|
||
|
|
||
|
PROPVARIANT propvar;
|
||
|
ATLVERIFY(SUCCEEDED(SetPropertyVal(key, bState, &propvar)));
|
||
|
|
||
|
ATL::CComQIPtr<IPropertyStore>pIPS(GetRibbonPtr());
|
||
|
|
||
|
if ((pIPS != NULL) && SUCCEEDED(pIPS->SetValue(key, propvar)))
|
||
|
{
|
||
|
pIPS->Commit();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
ATLASSERT(FALSE); // something was wrong
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool IsRibbonMinimized()
|
||
|
{
|
||
|
return GetRibbonDisplayState(UI_PKEY_Minimized);
|
||
|
}
|
||
|
|
||
|
bool MinimizeRibbon(bool bMinimize = true)
|
||
|
{
|
||
|
return SetRibbonDisplayState(UI_PKEY_Minimized, bMinimize);
|
||
|
}
|
||
|
|
||
|
bool IsRibbonHidden()
|
||
|
{
|
||
|
return !GetRibbonDisplayState(UI_PKEY_Viewable);
|
||
|
}
|
||
|
|
||
|
bool HideRibbon(bool bHide = true)
|
||
|
{
|
||
|
return SetRibbonDisplayState(UI_PKEY_Viewable, !bHide);
|
||
|
}
|
||
|
|
||
|
// Ribbon colors
|
||
|
UI_HSBCOLOR GetRibbonColor(REFPROPERTYKEY key)
|
||
|
{
|
||
|
ATLASSERT(GetIUIFrameworkPtr());
|
||
|
ATLASSERT(IsRibbonUI());
|
||
|
ATLASSERT((k_(key) >= k_GlobalBackgroundColor) && (k_(key) <= k_GlobalTextColor));
|
||
|
|
||
|
PROPVARIANT propvar;
|
||
|
ATL::CComQIPtr<IPropertyStore>pIPS(GetIUIFrameworkPtr());
|
||
|
|
||
|
if ((pIPS != NULL) && SUCCEEDED(pIPS->GetValue(key, &propvar)))
|
||
|
{
|
||
|
UINT32 color = 0;
|
||
|
if SUCCEEDED(UIPropertyToUInt32(key, propvar, &color))
|
||
|
return color;
|
||
|
}
|
||
|
|
||
|
ATLASSERT(FALSE); // something was wrong
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
bool SetRibbonColor(REFPROPERTYKEY key, UI_HSBCOLOR color)
|
||
|
{
|
||
|
ATLASSERT(GetIUIFrameworkPtr());
|
||
|
ATLASSERT(IsRibbonUI());
|
||
|
ATLASSERT((k_(key) >= k_GlobalBackgroundColor) && (k_(key) <= k_GlobalTextColor));
|
||
|
|
||
|
PROPVARIANT propvar;
|
||
|
ATLVERIFY(SUCCEEDED(SetPropertyVal(key, color, &propvar)));
|
||
|
|
||
|
ATL::CComQIPtr<IPropertyStore>pIPS(GetIUIFrameworkPtr());
|
||
|
|
||
|
if ((pIPS != NULL) && SUCCEEDED(pIPS->SetValue(key, propvar)))
|
||
|
{
|
||
|
pIPS->Commit();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
ATLASSERT(FALSE); // something was wrong
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Ribbon modes
|
||
|
HRESULT SetRibbonModes(INT32 iModes)
|
||
|
{
|
||
|
ATLASSERT(IsRibbonUI());
|
||
|
return GetIUIFrameworkPtr()->SetModes(iModes);
|
||
|
}
|
||
|
|
||
|
// Ribbon contextual tab
|
||
|
UI_CONTEXTAVAILABILITY GetRibbonContextAvail(UINT32 uID)
|
||
|
{
|
||
|
ATLASSERT(GetIUIFrameworkPtr());
|
||
|
|
||
|
PROPVARIANT propvar;
|
||
|
if (IsRibbonUI() &&
|
||
|
SUCCEEDED(GetIUIFrameworkPtr()->GetUICommandProperty(uID, UI_PKEY_ContextAvailable, &propvar)))
|
||
|
{
|
||
|
UINT uav;
|
||
|
if (SUCCEEDED(PropVariantToUInt32(propvar, &uav)))
|
||
|
{
|
||
|
CUpdateUIBase::UIEnable(uID, uav != UI_CONTEXTAVAILABILITY_NOTAVAILABLE);
|
||
|
CUpdateUIBase::UISetCheck(uID, uav == UI_CONTEXTAVAILABILITY_ACTIVE);
|
||
|
return (UI_CONTEXTAVAILABILITY)uav;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return UI_CONTEXTAVAILABILITY_NOTAVAILABLE;
|
||
|
}
|
||
|
|
||
|
HRESULT SetRibbonContextAvail(UINT32 uID, UI_CONTEXTAVAILABILITY cav)
|
||
|
{
|
||
|
CUpdateUIBase::UIEnable(uID, cav != UI_CONTEXTAVAILABILITY_NOTAVAILABLE);
|
||
|
CUpdateUIBase::UISetCheck(uID, cav == UI_CONTEXTAVAILABILITY_ACTIVE);
|
||
|
|
||
|
return SetProperty((WORD)uID, UI_PKEY_ContextAvailable, UINT32(cav));
|
||
|
}
|
||
|
|
||
|
// Ribbon context menu
|
||
|
bool HasRibbonMenu(UINT32 uID)
|
||
|
{
|
||
|
ATL::CComPtr<IUIContextualUI> pI = GetMenuPtr(uID);
|
||
|
return pI != NULL;
|
||
|
}
|
||
|
|
||
|
HRESULT TrackRibbonMenu(UINT32 uID, INT32 x, INT32 y)
|
||
|
{
|
||
|
ATLASSERT(HasRibbonMenu(uID));
|
||
|
|
||
|
return IsRibbonUI() ?
|
||
|
ATL::CComPtr<IUIContextualUI>(GetMenuPtr(uID))->ShowAtLocation(x, y) :
|
||
|
E_FAIL;
|
||
|
}
|
||
|
|
||
|
HRESULT TrackRibbonMenu(UINT32 uID, LPARAM lParam)
|
||
|
{
|
||
|
return TrackRibbonMenu(uID, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||
|
}
|
||
|
|
||
|
// Overrideables
|
||
|
HBITMAP OnRibbonQueryImage(UINT nCmdID, REFPROPERTYKEY /*key*/)
|
||
|
{
|
||
|
return DefRibbonQueryImage(nCmdID);
|
||
|
}
|
||
|
|
||
|
LPCWSTR OnRibbonQueryText(UINT nCmdID, REFPROPERTYKEY key)
|
||
|
{
|
||
|
return DefRibbonQueryText(nCmdID, key);
|
||
|
}
|
||
|
|
||
|
bool OnRibbonQueryState(UINT nCmdID, REFPROPERTYKEY key)
|
||
|
{
|
||
|
return DefRibbonQueryState(nCmdID, key);
|
||
|
}
|
||
|
|
||
|
UI_CONTEXTAVAILABILITY OnRibbonQueryTabAvail(UINT nCmdID)
|
||
|
{
|
||
|
DWORD dwState = UIGetState(nCmdID);
|
||
|
return ((dwState & UPDUI_DISABLED) == UPDUI_DISABLED) ?
|
||
|
UI_CONTEXTAVAILABILITY_NOTAVAILABLE :
|
||
|
(((dwState & UPDUI_CHECKED) == UPDUI_CHECKED) ?
|
||
|
UI_CONTEXTAVAILABILITY_ACTIVE :
|
||
|
UI_CONTEXTAVAILABILITY_AVAILABLE);
|
||
|
}
|
||
|
|
||
|
LPCWSTR OnRibbonQueryComboText(UINT32 /*uCtrlID*/)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
LPCWSTR OnRibbonQueryCategoryText(UINT32 /*uCtrlID*/, UINT32 /*uCat*/)
|
||
|
{
|
||
|
return L"Category";
|
||
|
}
|
||
|
|
||
|
UINT32 OnRibbonQueryItemCategory(UINT32 /*uCtrlID*/, UINT32 /*uItem*/)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
LPCWSTR OnRibbonQueryItemText(UINT32 uCtrlID, UINT32 uItem)
|
||
|
{
|
||
|
return DefRibbonQueryItemText(uCtrlID, uItem);
|
||
|
}
|
||
|
|
||
|
bool OnRibbonQuerySelectedItem(UINT32 /*uCtrlID*/, UINT32& /*uSel*/)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
HBITMAP OnRibbonQueryItemImage(UINT32 uCtrlID, UINT32 uItem)
|
||
|
{
|
||
|
return DefRibbonQueryItemImage(uCtrlID, uItem);
|
||
|
}
|
||
|
|
||
|
UINT32 OnRibbonQueryItemCommand(UINT32 uCtrlID, UINT32 uItem)
|
||
|
{
|
||
|
return DefRibbonQueryItemCommand(uCtrlID, uItem);
|
||
|
}
|
||
|
|
||
|
UI_COMMANDTYPE OnRibbonQueryItemCommandType(UINT32 /*uCtrlID*/, UINT32 /*uItem*/)
|
||
|
{
|
||
|
return UI_COMMANDTYPE_ACTION;
|
||
|
}
|
||
|
|
||
|
LPCWSTR OnRibbonQueryRecentItemName(LPCWSTR sPath)
|
||
|
{
|
||
|
return ::PathFindFileName(sPath);
|
||
|
}
|
||
|
|
||
|
bool OnRibbonQueryFont(UINT /*nId*/, CHARFORMAT2& /*cf*/)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool OnRibbonQuerySpinnerValue(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/, LONG* /*pVal*/)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool OnRibbonQueryFloatSpinnerValue(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/, DOUBLE* /*pVal*/)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
COLORREF OnRibbonQueryColor(UINT /*nCmdID*/)
|
||
|
{
|
||
|
return 0x800080; /*MAGENTA*/
|
||
|
}
|
||
|
|
||
|
LPCWSTR OnRibbonQueryColorLabel(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
COLORREF* OnRibbonQueryColorArray(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
LPCWSTR* OnRibbonQueryColorTooltips(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
bool OnRibbonItemSelected(UINT32 uCtrlID, UI_EXECUTIONVERB verb, UINT32 uItem)
|
||
|
{
|
||
|
DefCommandExecute(MAKELONG(uCtrlID, verb), uItem);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void OnRibbonColorCtrlExecute(UINT32 uCtrlID, UI_EXECUTIONVERB verb, UI_SWATCHCOLORTYPE uType, COLORREF color)
|
||
|
{
|
||
|
DefRibbonColorCtrlExecute(uCtrlID, verb, uType, color);
|
||
|
}
|
||
|
|
||
|
void OnRibbonFontCtrlExecute(UINT32 uCtrlID, UI_EXECUTIONVERB verb, CHARFORMAT2* pcf)
|
||
|
{
|
||
|
DefCommandExecute(MAKELONG(uCtrlID, verb), (LPARAM)pcf);
|
||
|
}
|
||
|
|
||
|
void OnRibbonSpinnerCtrlExecute(UINT32 uCtrlID, LONG* pVal)
|
||
|
{
|
||
|
DefCommandExecute(uCtrlID, *pVal);
|
||
|
}
|
||
|
|
||
|
void OnRibbonSpinnerCtrlExecute(UINT32 uCtrlID, DOUBLE* pVal)
|
||
|
{
|
||
|
DefCommandExecute(uCtrlID, (LPARAM)pVal);
|
||
|
}
|
||
|
|
||
|
void OnRibbonCommandExecute(UINT32 uCmdID)
|
||
|
{
|
||
|
DefCommandExecute(uCmdID);
|
||
|
}
|
||
|
|
||
|
// Default implementations
|
||
|
HBITMAP DefRibbonQueryImage(UINT nCmdID)
|
||
|
{
|
||
|
return AtlLoadBitmapImage(nCmdID, LR_CREATEDIBSECTION);
|
||
|
}
|
||
|
|
||
|
bool DefRibbonQueryState(UINT nCmdID, REFPROPERTYKEY key)
|
||
|
{
|
||
|
DWORD dwState = UIGetState(nCmdID);
|
||
|
bool bRet = false;
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_BooleanValue:
|
||
|
bRet = (dwState & UPDUI_CHECKED) == UPDUI_CHECKED;
|
||
|
break;
|
||
|
case k_Enabled:
|
||
|
bRet = (dwState & UPDUI_DISABLED) != UPDUI_DISABLED;
|
||
|
break;
|
||
|
default:
|
||
|
ATLASSERT(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
LPCTSTR DefRibbonQueryText(UINT nCmdID, REFPROPERTYKEY key)
|
||
|
{
|
||
|
static WCHAR sText[RIBBONUI_MAX_TEXT] = { 0 };
|
||
|
|
||
|
if (k_(key) == k_Label)
|
||
|
return UIGetText(nCmdID);
|
||
|
|
||
|
if (AtlLoadString(nCmdID, sText, RIBBONUI_MAX_TEXT))
|
||
|
{
|
||
|
PWCHAR pTitle = wcschr(sText, L'\n');
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_Keytip:
|
||
|
if (PWCHAR pAmp = wcschr(sText, L'&'))
|
||
|
pTitle = pAmp;
|
||
|
if (pTitle != NULL)
|
||
|
*(pTitle + 2) = NULL; // fall through
|
||
|
case k_TooltipTitle:
|
||
|
return pTitle ? ++pTitle : NULL;
|
||
|
case k_TooltipDescription:
|
||
|
case k_LabelDescription:
|
||
|
if (pTitle != NULL)
|
||
|
*pTitle = NULL;
|
||
|
return sText;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
LPCWSTR DefRibbonQueryItemText(UINT32 uCtrlID, UINT32 uItem)
|
||
|
{
|
||
|
return DefRibbonQueryText(uCtrlID + 1 + uItem, UI_PKEY_LabelDescription);
|
||
|
}
|
||
|
|
||
|
HBITMAP DefRibbonQueryItemImage(UINT32 uCtrlID, UINT32 uItem)
|
||
|
{
|
||
|
return DefRibbonQueryImage(uCtrlID + 1 + uItem);
|
||
|
}
|
||
|
|
||
|
UINT32 DefRibbonQueryItemCommand(UINT32 uCtrlID, UINT32 uItem)
|
||
|
{
|
||
|
return uCtrlID + 1 + uItem;
|
||
|
}
|
||
|
|
||
|
void DefRibbonColorCtrlExecute(UINT32 uCtrlID, UI_EXECUTIONVERB verb, UI_SWATCHCOLORTYPE uType, COLORREF color)
|
||
|
{
|
||
|
switch(uType)
|
||
|
{
|
||
|
case UI_SWATCHCOLORTYPE_RGB:
|
||
|
break;
|
||
|
case UI_SWATCHCOLORTYPE_AUTOMATIC:
|
||
|
color = ::GetSysColor(COLOR_WINDOWTEXT);
|
||
|
break;
|
||
|
case UI_SWATCHCOLORTYPE_NOCOLOR:
|
||
|
color = ::GetSysColor(COLOR_WINDOW);
|
||
|
break;
|
||
|
default:
|
||
|
ATLASSERT(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
DefCommandExecute(MAKELONG(uCtrlID, verb), color);
|
||
|
}
|
||
|
|
||
|
void DefCommandExecute(UINT32 uCmd, LPARAM lParam = 0)
|
||
|
{
|
||
|
static_cast<T*>(this)->PostMessage(WM_COMMAND, uCmd, lParam);
|
||
|
}
|
||
|
|
||
|
// Elements setting helpers
|
||
|
HRESULT InvalidateCtrl(UINT32 nID)
|
||
|
{
|
||
|
return IsRibbonUI() ?
|
||
|
GetIUIFrameworkPtr()->InvalidateUICommand(nID, UI_INVALIDATIONS_ALLPROPERTIES, NULL) :
|
||
|
E_FAIL;
|
||
|
}
|
||
|
|
||
|
HRESULT InvalidateProperty(UINT32 nID, REFPROPERTYKEY key, UI_INVALIDATIONS flags = UI_INVALIDATIONS_PROPERTY)
|
||
|
{
|
||
|
return IsRibbonUI() ?
|
||
|
GetIUIFrameworkPtr()->InvalidateUICommand(nID, flags, &key) :
|
||
|
E_FAIL;
|
||
|
}
|
||
|
|
||
|
template <typename V>
|
||
|
HRESULT SetProperty(WORD wID, REFPROPERTYKEY key, V val)
|
||
|
{
|
||
|
if (IsRibbonUI())
|
||
|
{
|
||
|
PROPVARIANT var;
|
||
|
if (SUCCEEDED(RibbonUI::SetPropertyVal(key, val, &var)))
|
||
|
{
|
||
|
return SetProperty(wID, key, var);
|
||
|
}
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <>
|
||
|
HRESULT SetProperty(WORD nID, REFPROPERTYKEY key, PROPVARIANT var)
|
||
|
{
|
||
|
return IsRibbonUI() ?
|
||
|
GetIUIFrameworkPtr()->SetUICommandProperty(nID, key, var) :
|
||
|
E_FAIL;
|
||
|
}
|
||
|
|
||
|
// Interfaces
|
||
|
// IUIApplication
|
||
|
STDMETHODIMP OnViewChanged(UINT32, UI_VIEWTYPE, IUnknown*, UI_VIEWVERB verb, INT32)
|
||
|
{
|
||
|
switch (verb)
|
||
|
{
|
||
|
case UI_VIEWVERB_CREATE:
|
||
|
m_bRibbonUI = true;
|
||
|
if (m_hgRibbonSettings != NULL)
|
||
|
RestoreRibbonSettings();
|
||
|
break;
|
||
|
case UI_VIEWVERB_SIZE:
|
||
|
static_cast<T*>(this)->UpdateLayout(FALSE);
|
||
|
break;
|
||
|
case UI_VIEWVERB_DESTROY:
|
||
|
SaveRibbonSettings();
|
||
|
m_bRibbonUI = false;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP OnCreateUICommand(UINT32 nCmdID, UI_COMMANDTYPE typeID, IUICommandHandler** ppCommandHandler)
|
||
|
{
|
||
|
UIAddRibbonElement(nCmdID);
|
||
|
if (typeID == UI_COMMANDTYPE_CONTEXT)
|
||
|
CUpdateUIBase::UIEnable(nCmdID, false);
|
||
|
*ppCommandHandler = this;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP OnDestroyUICommand(UINT32 nCmdID, UI_COMMANDTYPE, IUICommandHandler*)
|
||
|
{
|
||
|
UIRemoveRibbonElement(nCmdID);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// IUICommandHandler
|
||
|
STDMETHODIMP Execute(UINT nCmdID,
|
||
|
UI_EXECUTIONVERB verb,
|
||
|
const PROPERTYKEY* key,
|
||
|
const PROPVARIANT* ppropvarValue,
|
||
|
IUISimplePropertySet* pCommandExecutionProperties)
|
||
|
{
|
||
|
T* pT =static_cast<T*>(this);
|
||
|
return pT->GetRibbonCtrl(nCmdID).DoExecute(nCmdID, verb, key, ppropvarValue, pCommandExecutionProperties);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP UpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
|
||
|
{
|
||
|
T* pT =static_cast<T*>(this);
|
||
|
return pT->GetRibbonCtrl(nCmdID).DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
|
||
|
}
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
// IUnknown methods (heavyweight)
|
||
|
STDMETHODIMP_(ULONG) AddRef()
|
||
|
{
|
||
|
return InterlockedIncrement(&m_cRef);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) Release()
|
||
|
{
|
||
|
LONG cRef = InterlockedDecrement(&m_cRef);
|
||
|
if (cRef == 0) // NoOp for breakpoint
|
||
|
{
|
||
|
cRef = 0;
|
||
|
}
|
||
|
|
||
|
return cRef;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
|
||
|
{
|
||
|
if (ppv == NULL)
|
||
|
{
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
else if ((iid == __uuidof(IUnknown)) ||
|
||
|
(iid == __uuidof(IUICommandHandler)) ||
|
||
|
(iid == __uuidof(IUIApplication)))
|
||
|
{
|
||
|
*ppv = this;
|
||
|
AddRef();
|
||
|
return S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return E_NOINTERFACE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LONG m_cRef;
|
||
|
#else
|
||
|
// IUnknown methods (lightweight)
|
||
|
STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
|
||
|
{
|
||
|
if ((iid == __uuidof(IUnknown)) ||
|
||
|
(iid == __uuidof(IUICommandHandler)) ||
|
||
|
(iid == __uuidof(IUIApplication)))
|
||
|
{
|
||
|
*ppv = this;
|
||
|
return S_OK;
|
||
|
}
|
||
|
return E_NOINTERFACE;
|
||
|
}
|
||
|
ULONG STDMETHODCALLTYPE AddRef()
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
ULONG STDMETHODCALLTYPE Release()
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// CRibbonImpl ICtrl implementation
|
||
|
virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
|
||
|
const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
|
||
|
IUISimplePropertySet* /*pCommandExecutionProperties*/)
|
||
|
{
|
||
|
if (key != NULL)
|
||
|
{
|
||
|
if(k_(*key) != k_BooleanValue)
|
||
|
{
|
||
|
ATLTRACE(L"Control ID %d is not handled\n", nCmdID);
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
BOOL bChecked = FALSE;
|
||
|
ATLVERIFY(SUCCEEDED(PropVariantToBoolean(*ppropvarValue, &bChecked)));
|
||
|
CUpdateUIBase::UISetCheck(nCmdID, bChecked);
|
||
|
}
|
||
|
|
||
|
ATLASSERT(verb == UI_EXECUTIONVERB_EXECUTE);
|
||
|
verb; // avoid level 4 warning
|
||
|
|
||
|
static_cast<T*>(this)->OnRibbonCommandExecute(nCmdID);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
|
||
|
const PROPVARIANT* /*ppropvarCurrentValue*/, PROPVARIANT* ppropvarNewValue)
|
||
|
{
|
||
|
T* pT = static_cast<T*>(this);
|
||
|
HRESULT hr = E_NOTIMPL;
|
||
|
switch (k_(key))
|
||
|
{
|
||
|
case k_LargeImage:
|
||
|
case k_LargeHighContrastImage:
|
||
|
case k_SmallImage:
|
||
|
case k_SmallHighContrastImage:
|
||
|
if (HBITMAP hbm = pT->OnRibbonQueryImage(nCmdID, key))
|
||
|
hr = SetPropertyVal(key, GetImage(hbm, UI_OWNERSHIP_TRANSFER), ppropvarNewValue);
|
||
|
break;
|
||
|
case k_Label:
|
||
|
case k_Keytip:
|
||
|
case k_TooltipTitle:
|
||
|
case k_TooltipDescription:
|
||
|
case k_LabelDescription:
|
||
|
if (LPCWSTR sText = pT->OnRibbonQueryText(nCmdID, key))
|
||
|
hr = SetPropertyVal(key, sText, ppropvarNewValue);
|
||
|
break;
|
||
|
case k_BooleanValue:
|
||
|
case k_Enabled:
|
||
|
hr = SetPropertyVal(key, pT->OnRibbonQueryState(nCmdID, key), ppropvarNewValue);
|
||
|
break;
|
||
|
case k_ContextAvailable:
|
||
|
hr = SetPropertyVal(key, pT->OnRibbonQueryTabAvail(nCmdID), ppropvarNewValue);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// CRibbonImpl::CRibbonXXXCtrl specialized classes
|
||
|
//CRibbonComboCtrl
|
||
|
template <UINT t_ID, size_t t_items, size_t t_categories = 0>
|
||
|
class CRibbonComboCtrl : public CollectionCtrlImpl<T, t_ID, ComboCollectionImpl<CRibbonComboCtrl<t_ID, t_items, t_categories>, t_items, t_categories>>
|
||
|
{
|
||
|
public:
|
||
|
CRibbonComboCtrl()
|
||
|
{ }
|
||
|
};
|
||
|
|
||
|
// CRibbonItemGalleryCtrl
|
||
|
template <UINT t_ID, size_t t_items, size_t t_categories = 0>
|
||
|
class CRibbonItemGalleryCtrl : public CollectionCtrlImpl<T, t_ID, ItemCollectionImpl<CRibbonItemGalleryCtrl<t_ID, t_items, t_categories>, t_items, t_categories>>
|
||
|
{
|
||
|
public:
|
||
|
CRibbonItemGalleryCtrl()
|
||
|
{ }
|
||
|
};
|
||
|
|
||
|
// CRibbonCommandGalleryCtrl
|
||
|
template <UINT t_ID, size_t t_items, size_t t_categories = 0>
|
||
|
class CRibbonCommandGalleryCtrl : public CollectionCtrlImpl<T, t_ID, CommandCollectionImpl<CRibbonCommandGalleryCtrl<t_ID, t_items, t_categories>, t_items, t_categories>>
|
||
|
{
|
||
|
public:
|
||
|
CRibbonCommandGalleryCtrl()
|
||
|
{ }
|
||
|
};
|
||
|
|
||
|
// CRibbonToolbarGalleryCtrl
|
||
|
template <UINT t_ID, UINT t_idTB, size_t t_size>
|
||
|
class CRibbonToolbarGalleryCtrl : public ToolbarGalleryCtrlImpl<T, t_ID, t_idTB, t_size>
|
||
|
{ };
|
||
|
|
||
|
// CRibbonSimpleComboCtrl
|
||
|
template <UINT t_ID, size_t t_size>
|
||
|
class CRibbonSimpleComboCtrl : public SimpleCollectionCtrlImpl<T, t_ID, t_size>
|
||
|
{ };
|
||
|
|
||
|
// CRibbonSimpleGalleryCtrl
|
||
|
template <UINT t_ID, size_t t_size, UI_COMMANDTYPE t_CommandType = UI_COMMANDTYPE_ACTION>
|
||
|
class CRibbonSimpleGalleryCtrl : public SimpleCollectionCtrlImpl<T, t_ID, t_size, t_CommandType>
|
||
|
{ };
|
||
|
|
||
|
//CRibbonRecentItemsCtrl
|
||
|
template <UINT t_ID, class TDocList = CRecentDocumentList>
|
||
|
class CRibbonRecentItemsCtrl : public RecentItemsCtrlImpl<T, t_ID, TDocList>
|
||
|
{
|
||
|
public:
|
||
|
CRibbonRecentItemsCtrl()
|
||
|
{ }
|
||
|
};
|
||
|
|
||
|
// CRibbonColorCtrl
|
||
|
template <UINT t_ID>
|
||
|
class CRibbonColorCtrl : public ColorCtrlImpl<T, t_ID>
|
||
|
{
|
||
|
public:
|
||
|
CRibbonColorCtrl()
|
||
|
{ }
|
||
|
};
|
||
|
|
||
|
//CRibbonFontCtrl
|
||
|
template <UINT t_ID>
|
||
|
class CRibbonFontCtrl : public FontCtrlImpl<T, t_ID>
|
||
|
{
|
||
|
public:
|
||
|
CRibbonFontCtrl()
|
||
|
{ }
|
||
|
};
|
||
|
|
||
|
// CRibbonSpinnerCtrl
|
||
|
template <UINT t_ID>
|
||
|
class CRibbonSpinnerCtrl : public SpinnerCtrlImpl<T, t_ID, LONG>
|
||
|
{
|
||
|
public:
|
||
|
CRibbonSpinnerCtrl()
|
||
|
{ }
|
||
|
};
|
||
|
|
||
|
// CRibbonFloatSpinnerCtrl
|
||
|
template <UINT t_ID>
|
||
|
class CRibbonFloatSpinnerCtrl : public SpinnerCtrlImpl<T, t_ID, DOUBLE>
|
||
|
{
|
||
|
public:
|
||
|
CRibbonFloatSpinnerCtrl()
|
||
|
{
|
||
|
m_Values[4] = 1; // 1 decimal
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// CRibbonCommandCtrl
|
||
|
template <UINT t_ID>
|
||
|
class CRibbonCommandCtrl : public CommandCtrlImpl<T, t_ID>
|
||
|
{
|
||
|
public:
|
||
|
CRibbonCommandCtrl()
|
||
|
{ }
|
||
|
};
|
||
|
|
||
|
// Control classes access to T instance (re-initialized in constructor)
|
||
|
static T* pWndRibbon;
|
||
|
};
|
||
|
|
||
|
template <class T>
|
||
|
__declspec(selectany) T* CRibbonImpl<T>::pWndRibbon;
|
||
|
|
||
|
// Control map element
|
||
|
#pragma warning (disable : 4510 610) // missing default constructor
|
||
|
typedef struct
|
||
|
{
|
||
|
UINT uID;
|
||
|
ICtrl& ctrl;
|
||
|
} _ribbonCtrl;
|
||
|
#pragma warning (default : 4510 610) // missing default constructor
|
||
|
|
||
|
}; // namespace RibbonUI
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// RibbonUI Control map
|
||
|
|
||
|
// Control map macros
|
||
|
#define BEGIN_RIBBON_CONTROL_MAP(theClass) \
|
||
|
RibbonUI::ICtrl& GetRibbonCtrl(UINT id) \
|
||
|
{ \
|
||
|
RibbonUI::_ribbonCtrl _ctrls[] = \
|
||
|
{
|
||
|
|
||
|
#define RIBBON_CONTROL(member) {member.GetID(), static_cast<RibbonUI::ICtrl&>(member)},
|
||
|
|
||
|
#define END_RIBBON_CONTROL_MAP() \
|
||
|
{0, *this} \
|
||
|
}; \
|
||
|
int i = 0; \
|
||
|
for(; i < _countof(_ctrls) - 1; i++) \
|
||
|
if (_ctrls[i].uID == id) \
|
||
|
break; \
|
||
|
return _ctrls[i].ctrl; \
|
||
|
}
|
||
|
|
||
|
// Control message map macros
|
||
|
#define RIBBON_GALLERY_CONTROL_HANDLER(id, func) \
|
||
|
if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
|
||
|
{ \
|
||
|
bHandled = TRUE; \
|
||
|
lResult = func((UI_EXECUTIONVERB)HIWORD(wParam), LOWORD(wParam), (UINT)lParam, bHandled); \
|
||
|
if(bHandled) \
|
||
|
return TRUE; \
|
||
|
}
|
||
|
|
||
|
#define RIBBON_COMBO_CONTROL_HANDLER(id, func) \
|
||
|
RIBBON_GALLERY_CONTROL_HANDLER(id, func)
|
||
|
|
||
|
#define RIBBON_FONT_CONTROL_HANDLER(id, func) \
|
||
|
if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
|
||
|
{ \
|
||
|
bHandled = TRUE; \
|
||
|
lResult = func((UI_EXECUTIONVERB)HIWORD(wParam), LOWORD(wParam), (CHARFORMAT2*)lParam, bHandled); \
|
||
|
if(bHandled) \
|
||
|
return TRUE; \
|
||
|
}
|
||
|
|
||
|
#define RIBBON_COLOR_CONTROL_HANDLER(id, func) \
|
||
|
if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
|
||
|
{ \
|
||
|
bHandled = TRUE; \
|
||
|
lResult = func((UI_EXECUTIONVERB)HIWORD(wParam), LOWORD(wParam), (COLORREF)lParam, bHandled); \
|
||
|
if(bHandled) \
|
||
|
return TRUE; \
|
||
|
}
|
||
|
|
||
|
#define RIBBON_SPINNER_CONTROL_HANDLER(id, func) \
|
||
|
if(uMsg == WM_COMMAND && id == wParam) \
|
||
|
{ \
|
||
|
bHandled = TRUE; \
|
||
|
lResult = func((WORD)wParam, (LONG)lParam, bHandled); \
|
||
|
if(bHandled) \
|
||
|
return TRUE; \
|
||
|
}
|
||
|
|
||
|
#define RIBBON_FLOATSPINNER_CONTROL_HANDLER(id, func) \
|
||
|
if(uMsg == WM_COMMAND && id == wParam) \
|
||
|
{ \
|
||
|
bHandled = TRUE; \
|
||
|
lResult = func((WORD)wParam, (DOUBLE*)lParam, bHandled); \
|
||
|
if(bHandled) \
|
||
|
return TRUE; \
|
||
|
}
|
||
|
|
||
|
// Handler prototypes
|
||
|
/*
|
||
|
LRESULT OnRibbonGalleryCtrl(UI_EXECUTIONVERB verb, WORD wID, UINT uSel, BOOL& bHandled);
|
||
|
LRESULT OnRibbonComboCtrl(UI_EXECUTIONVERB verb, WORD wID, UINT uSel, BOOL& bHandled);
|
||
|
LRESULT OnRibbonFontCtrl(UI_EXECUTIONVERB verb, WORD wID, CHARFORMAT2* pcf, BOOL& bHandled);
|
||
|
LRESULT OnRibbonColorCtrl(UI_EXECUTIONVERB verb, WORD wID, COLORREF color, BOOL& bHandled);
|
||
|
LRESULT OnRibbonSpinnerCtrl(WORD wID, LONG lVal, BOOL& bHandled);
|
||
|
LRESULT OnRibbonFloatSpinnerCtrl(WORD wID, DOUBLE* pdVal, BOOL& bHandled);
|
||
|
*/
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Ribbon frame classes
|
||
|
|
||
|
// CRibbonFrameWindowImplBase
|
||
|
//
|
||
|
template <class T, class TFrameImpl>
|
||
|
class ATL_NO_VTABLE CRibbonFrameWindowImplBase : public TFrameImpl, public RibbonUI::CRibbonImpl<T>
|
||
|
{
|
||
|
typedef TFrameImpl baseFrame;
|
||
|
bool m_bUseCommandBarBitmaps;
|
||
|
bool m_bWin7Fix;
|
||
|
|
||
|
public:
|
||
|
// Construction
|
||
|
CRibbonFrameWindowImplBase(bool bUseCommandBarBitmaps = true) :
|
||
|
m_bUseCommandBarBitmaps(bUseCommandBarBitmaps), m_bWin7Fix(false)
|
||
|
{
|
||
|
__if_not_exists(T::m_CmdBar)
|
||
|
{
|
||
|
m_bUseCommandBarBitmaps = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Win7 Aero fix helpers
|
||
|
void ResetFrame()
|
||
|
{
|
||
|
const MARGINS margins = { 0 };
|
||
|
::DwmExtendFrameIntoClientArea(m_hWnd, &margins);
|
||
|
}
|
||
|
|
||
|
INT CalcWin7Fix()
|
||
|
{
|
||
|
ResetFrame();
|
||
|
RECT rc = { 0 };
|
||
|
::AdjustWindowRectEx(&rc, T::GetWndStyle(0), GetMenu() != NULL, T::GetWndExStyle(0));
|
||
|
return -rc.top;
|
||
|
}
|
||
|
|
||
|
bool NeedWin7Fix()
|
||
|
{
|
||
|
BOOL bComp = FALSE;
|
||
|
return m_bWin7Fix && RunTimeHelper::IsWin7() && SUCCEEDED(DwmIsCompositionEnabled(&bComp)) && bComp;
|
||
|
}
|
||
|
|
||
|
// Operations
|
||
|
bool UseCommandBarBitmaps(bool bUse)
|
||
|
{
|
||
|
__if_exists(T::m_CmdBar)
|
||
|
{
|
||
|
return m_bUseCommandBarBitmaps = bUse;
|
||
|
}
|
||
|
__if_not_exists(T::m_CmdBar)
|
||
|
{
|
||
|
bUse; // avoid level 4 warning
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool ShowRibbonUI(bool bShow, INT32 imodes = UI_MAKEAPPMODE(0), LPCWSTR sResName = L"APPLICATION_RIBBON")
|
||
|
{
|
||
|
if (!RunTimeHelper::IsRibbonUIAvailable())
|
||
|
return false;
|
||
|
|
||
|
ATLASSERT(GetIUIFrameworkPtr());
|
||
|
|
||
|
if (IsRibbonUI() == bShow)
|
||
|
return bShow;
|
||
|
|
||
|
bool bVisible = (IsWindowVisible() != FALSE);
|
||
|
if(bVisible && !bShow)
|
||
|
SetRedraw(FALSE);
|
||
|
|
||
|
if (bShow && ::IsWindow(m_hWndToolBar))
|
||
|
{
|
||
|
::ShowWindow(m_hWndToolBar, SW_HIDE);
|
||
|
UpdateLayout();
|
||
|
}
|
||
|
|
||
|
m_bWin7Fix = !bShow;
|
||
|
|
||
|
HRESULT hr = bShow ? CreateRibbon(sResName) : DestroyRibbon();
|
||
|
|
||
|
m_bWin7Fix = SUCCEEDED(hr) && !bShow;
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if(::IsWindow(m_hWndToolBar) && !bShow)
|
||
|
{
|
||
|
::ShowWindow(m_hWndToolBar, SW_SHOWNA);
|
||
|
UpdateLayout();
|
||
|
}
|
||
|
else if (bShow)
|
||
|
{
|
||
|
PostMessage(WM_SIZE);
|
||
|
SetRibbonModes(imodes);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(bVisible && !bShow)
|
||
|
{
|
||
|
SetRedraw(TRUE);
|
||
|
RedrawWindow(NULL, NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
|
||
|
}
|
||
|
|
||
|
return SUCCEEDED(hr) ? bShow : !bShow;
|
||
|
}
|
||
|
|
||
|
// Overrideables
|
||
|
HBITMAP OnRibbonQueryImage(UINT nCmdID, REFPROPERTYKEY key)
|
||
|
{
|
||
|
if ((key == UI_PKEY_SmallImage) && m_bUseCommandBarBitmaps)
|
||
|
{
|
||
|
if (HBITMAP hbm = GetCommandBarBitmap(nCmdID))
|
||
|
return (HBITMAP)::CopyImage(hbm, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
|
||
|
}
|
||
|
|
||
|
return DefRibbonQueryImage(nCmdID);
|
||
|
}
|
||
|
|
||
|
BEGIN_MSG_MAP(CRibbonFrameWindowImplBase)
|
||
|
if (!IsRibbonUI() && NeedWin7Fix())
|
||
|
{
|
||
|
MESSAGE_HANDLER(WM_SIZING, OnSizing)
|
||
|
MESSAGE_HANDLER(WM_SIZE, OnSize)
|
||
|
MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
|
||
|
MESSAGE_HANDLER(WM_NCCALCSIZE, OnNCCalcSize)
|
||
|
}
|
||
|
CHAIN_MSG_MAP(CRibbonUpdateUI<T>)
|
||
|
CHAIN_MSG_MAP(baseFrame)
|
||
|
END_MSG_MAP()
|
||
|
|
||
|
// Message handlers for Win7 Aero
|
||
|
LRESULT OnSizing(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
|
||
|
{
|
||
|
switch (wParam)
|
||
|
{
|
||
|
case WMSZ_TOP:
|
||
|
case WMSZ_TOPLEFT:
|
||
|
case WMSZ_TOPRIGHT:
|
||
|
SetWindowPos(NULL, (LPRECT)lParam, SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||
|
break;
|
||
|
default:
|
||
|
DefWindowProc();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return 1; // handled
|
||
|
}
|
||
|
|
||
|
LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
|
||
|
{
|
||
|
if (wParam != SIZE_MINIMIZED)
|
||
|
SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||
|
|
||
|
bHandled = FALSE;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
LRESULT OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
|
||
|
{
|
||
|
if(wParam != WA_INACTIVE)
|
||
|
SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||
|
|
||
|
bHandled = FALSE;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
LRESULT OnNCCalcSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
|
||
|
{
|
||
|
ATLASSERT(!IsRibbonUI() && NeedWin7Fix());
|
||
|
|
||
|
LRESULT lRet = DefWindowProc();
|
||
|
|
||
|
if(wParam)
|
||
|
{
|
||
|
LPNCCALCSIZE_PARAMS pParams = (LPNCCALCSIZE_PARAMS)lParam;
|
||
|
pParams->rgrc[0].top = pParams->rgrc[1].top + CalcWin7Fix();
|
||
|
}
|
||
|
|
||
|
return lRet;
|
||
|
}
|
||
|
|
||
|
// Overrides
|
||
|
void UpdateLayout(BOOL bResizeBars = TRUE)
|
||
|
{
|
||
|
RECT rect = { 0 };
|
||
|
GetClientRect(&rect);
|
||
|
|
||
|
if (IsRibbonUI() && !IsRibbonHidden())
|
||
|
{
|
||
|
rect.top += GetRibbonHeight();
|
||
|
}
|
||
|
else if (!IsRibbonUI() && NeedWin7Fix())
|
||
|
{
|
||
|
ResetFrame();
|
||
|
}
|
||
|
|
||
|
// position bars and offset their dimensions
|
||
|
UpdateBarsPosition(rect, bResizeBars);
|
||
|
|
||
|
// resize client window
|
||
|
if(m_hWndClient != NULL)
|
||
|
::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
|
||
|
rect.right - rect.left, rect.bottom - rect.top,
|
||
|
SWP_NOZORDER | SWP_NOACTIVATE);
|
||
|
}
|
||
|
|
||
|
// Implementation
|
||
|
HBITMAP GetCommandBarBitmap(UINT nCmdID)
|
||
|
{
|
||
|
__if_exists (T::m_CmdBar)
|
||
|
{
|
||
|
ATLASSERT(RunTimeHelper::IsVista());
|
||
|
T* pT =static_cast<T*>(this);
|
||
|
int nIndex = pT->m_CmdBar.m_arrCommand.Find((WORD&)nCmdID);
|
||
|
return (nIndex == -1) ? NULL : pT->m_CmdBar.m_arrVistaBitmap[nIndex];
|
||
|
}
|
||
|
__if_not_exists (T::m_CmdBar)
|
||
|
{
|
||
|
nCmdID; // avoid level 4 warning
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// CRibbonFrameWindowImpl
|
||
|
//
|
||
|
template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
|
||
|
class ATL_NO_VTABLE CRibbonFrameWindowImpl : public CRibbonFrameWindowImplBase<T, CFrameWindowImpl<T, TBase, TWinTraits>>
|
||
|
{ };
|
||
|
|
||
|
// CRibbonMDIFrameWindowImpl
|
||
|
//
|
||
|
template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CFrameWinTraits>
|
||
|
class ATL_NO_VTABLE CRibbonMDIFrameWindowImpl : public CRibbonFrameWindowImplBase<T, CMDIFrameWindowImpl<T, TBase, TWinTraits>>
|
||
|
{ };
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// CRibbonPersist helper for RibbonUI persistency
|
||
|
|
||
|
class CRibbonPersist
|
||
|
{
|
||
|
public:
|
||
|
CRibbonPersist(LPCWSTR sAppKey)
|
||
|
{
|
||
|
ATLASSERT(sAppKey && *sAppKey);
|
||
|
m_Key.Create(HKEY_CURRENT_USER, sAppKey);
|
||
|
ATLASSERT(m_Key.m_hKey);
|
||
|
}
|
||
|
|
||
|
CRegKeyEx m_Key;
|
||
|
|
||
|
LONG Save(bool bRibbonUI, HGLOBAL hgSettings = NULL)
|
||
|
{
|
||
|
CRegKeyEx key;
|
||
|
const DWORD dwUI = bRibbonUI;
|
||
|
|
||
|
LONG lRet = key.Create(m_Key, L"Ribbon");
|
||
|
if(lRet != ERROR_SUCCESS)
|
||
|
return lRet;
|
||
|
|
||
|
lRet = key.SetDWORDValue(L"UI", dwUI);
|
||
|
if(lRet != ERROR_SUCCESS)
|
||
|
return lRet;
|
||
|
|
||
|
if (hgSettings != NULL)
|
||
|
{
|
||
|
LPBYTE pVal = (LPBYTE)::GlobalLock(hgSettings);
|
||
|
if (pVal != NULL)
|
||
|
{
|
||
|
lRet = key.SetBinaryValue(L"Settings", pVal, (ULONG)::GlobalSize(hgSettings));
|
||
|
::GlobalUnlock(hgSettings);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lRet = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return lRet;
|
||
|
}
|
||
|
|
||
|
LONG Restore(bool& bRibbonUI, HGLOBAL& hgSettings)
|
||
|
{
|
||
|
ATLASSERT(hgSettings == NULL);
|
||
|
|
||
|
CRegKeyEx key;
|
||
|
|
||
|
LONG lRet = key.Open(m_Key, L"Ribbon");
|
||
|
if(lRet != ERROR_SUCCESS)
|
||
|
return lRet;
|
||
|
|
||
|
DWORD dwUI = 0xffff;
|
||
|
lRet = key.QueryDWORDValue(L"UI", dwUI);
|
||
|
if(lRet == ERROR_SUCCESS)
|
||
|
bRibbonUI = dwUI == 1;
|
||
|
else
|
||
|
return lRet;
|
||
|
|
||
|
ULONG ulSize = 0;
|
||
|
lRet = key.QueryBinaryValue(L"Settings", NULL, &ulSize);
|
||
|
if (lRet == ERROR_SUCCESS)
|
||
|
{
|
||
|
ATLASSERT(ulSize != 0);
|
||
|
|
||
|
hgSettings = ::GlobalAlloc(GHND, ulSize);
|
||
|
if (hgSettings != NULL)
|
||
|
{
|
||
|
LPBYTE pData = (LPBYTE)::GlobalLock(hgSettings);
|
||
|
if (pData != NULL)
|
||
|
{
|
||
|
lRet = key.QueryBinaryValue(L"Settings", pData, &ulSize);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lRet = GetLastError();
|
||
|
::GlobalFree(hgSettings);
|
||
|
hgSettings = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lRet = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
return lRet;
|
||
|
}
|
||
|
|
||
|
LONG Delete()
|
||
|
{
|
||
|
return m_Key.DeleteSubKey(L"Ribbon");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
} // namespace WTL
|
||
|
|
||
|
#endif // __ATLRIBBON_H__
|