WTL-Ribbon
1.在WTL项目中添加Ribbon的布局定义文件:RibbonMarkup.xml
< Application xmlns ="http://schemas.microsoft.com/windows/2009/Ribbon" >< Application.Commands >< Command Name ="TabHome" Symbol ="IDC_TabHome" Id ="30000" LabelTitle ="Home" />< Command Name ="GroupMain" Symbol ="IDC_GroupMain" Id ="30001" LabelTitle ="Main" />< Command Name ="Toggle" Symbol ="IDC_TOGGLE" Id ="30002" LabelTitle ="Toggle" >< Command.TooltipTitle > Toggle button</ Command.TooltipTitle >< Command.TooltipDescription > Click on Toggle SayHello Button.</ Command.TooltipDescription >< Command.LargeImages >< Image Source ="Button_Image.bmp" /></ Command.LargeImages ></ Command >< Command Name ="SayHello" Symbol ="IDC_SAY_HELLO" Id ="30003" LabelTitle ="Say hello" >< Command.TooltipTitle > SayHello button</ Command.TooltipTitle >< Command.TooltipDescription > Say hello to me!</ Command.TooltipDescription >< Command.LargeImages >< Image Source ="Button_Image.bmp" /></ Command.LargeImages ></ Command ></ Application.Commands >< Application.Views >< Ribbon >< Ribbon.Tabs >< Tab CommandName ="TabHome" >< Group CommandName ="GroupMain" SizeDefinition ="TwoButtons" >< ToggleButton CommandName ="Toggle" />< Button CommandName ="SayHello" /></ Group ></ Tab ></ Ribbon.Tabs ></ Ribbon ></ Application.Views ></ Application >2.选中RibbonMarkup.xml,右键点击Properties,在Property Pages对话框中修改属性:
Command Line : uicc.exe RibbonMarkup.xml RibbonMarkup.bml /header:RibbonRes.h /res:RibbonRes.rc
Outputs: RibbonMarkup.bml;RibbonRes.rc;RibbonRes.h
3.编译项目,已生成资源文件和符号定义头文件
4.Ribbon的实现:
#pragma once#include < atlbase.h >#include < atlcom.h >#include < InitGuid.h >#include < UIRibbon.h >#include < UIRibbonPropertyHelpers.h >#pragma comment(lib,"propsys.lib")#include "RibbonRes.h"CComPtr< IUIApplication > g_spIUIApplication;CComPtr< IUIFramework > g_spIUIFramework;enum{WM_USER_RIBBON_RESIZE = WM_USER+1,WM_USER_RIBBON_COMMAND};////User defined message crack//// void OnRibbonResize(UINT height)#define MSG_WM_USER_RIBBONRESIZE(func) /if (uMsg == WM_USER_RIBBON_RESIZE) /{ /SetMsgHandled(TRUE); /func((UINT)wParam); /lResult = 0; /if(IsMsgHandled()) /return TRUE; /}// void OnRibbonCommand(UINT cmdID)#define MSG_WM_USER_COMMAND(func) /if (uMsg == WM_USER_RIBBON_COMMAND) /{ /SetMsgHandled(TRUE); /func((UINT)wParam); /lResult = 0; /if(IsMsgHandled()) /return TRUE; /}[uuid("6760F7D7-2B58-481E-BB35-D701B8C9576E")]__interface IRibbonNotifyWindow : public IUnknown{HRESULT __stdcall SetNotifyWindow(HWND hNotifyWindow);};class CRibbonApp :public CComObjectRootEx< CComMultiThreadModel > ,public CComCoClass< CRibbonApp > ,public IRibbonNotifyWindow,public IUIApplication,public IUICommandHandler{public:BEGIN_COM_MAP(CRibbonApp)COM_INTERFACE_ENTRY(IUIApplication)COM_INTERFACE_ENTRY(IUICommandHandler)COM_INTERFACE_ENTRY(IRibbonNotifyWindow)END_COM_MAP()////IRibbonNotifyWindow methods//STDMETHOD(SetNotifyWindow)(HWND hNotifyWindow){m_NotifyWindow = hNotifyWindow;return S_OK;}////IUIApplication methods//STDMETHOD(OnViewChanged)(UINT32 viewId,UI_VIEWTYPE typeID,__in IUnknown *pView,UI_VIEWVERB verb,INT32 /*uReasonCode*/){HRESULT hr = E_NOTIMPL;if (typeID == UI_VIEWTYPE_RIBBON){switch(verb){case UI_VIEWVERB_CREATE:hr = S_OK;break;case UI_VIEWVERB_SIZE:{CComPtr< IUIRibbon > spUIRibbon;hr = pView->QueryInterface(IID_PPV_ARGS(&spUIRibbon));CHECKHR(hr);UINT32 height;spUIRibbon->GetHeight(&height);m_NotifyWindow.PostMessage(WM_USER_RIBBON_RESIZE,height);}break;case UI_VIEWVERB_DESTROY:hr = S_OK;break;}}return hr;}STDMETHOD(OnCreateUICommand)(UINT32 nCmdID,UI_COMMANDTYPE typeID,__out IUICommandHandler** ppCommandHandler){if ((nCmdID==IDC_TOGGLE) || (nCmdID==IDC_SAY_HELLO)){return QueryInterface(IID_PPV_ARGS(ppCommandHandler));}return E_NOTIMPL;}STDMETHOD(OnDestroyUICommand)(UINT32 commandId,UI_COMMANDTYPE typeID,__in IUICommandHandler* pCommandHandler){return E_NOTIMPL;}////IUICommandHandler methods//STDMETHODIMP Execute(UINT nCmdID,UI_EXECUTIONVERB verb,__in_opt const PROPERTYKEY* key,__in_opt const PROPVARIANT* pPropvarValue,__in_opt IUISimplePropertySet* pCommandExecutionProperties){HRESULT hr = S_OK;switch (verb){case UI_EXECUTIONVERB_EXECUTE:if (nCmdID == IDC_SAY_HELLO){m_NotifyWindow.PostMessage(WM_USER_RIBBON_COMMAND,IDC_SAY_HELLO);}else if (nCmdID == IDC_TOGGLE){PROPVARIANT var, varNew;hr = g_spIUIFramework->GetUICommandProperty(IDC_SAY_HELLO, UI_PKEY_Enabled, &var);CHECKHR(hr);hr = PropVariantToBoolean(var, &m_IsSayHelloEnabled);CHECKHR(hr);m_IsSayHelloEnabled = !m_IsSayHelloEnabled;hr = UIInitPropertyFromBoolean(UI_PKEY_Enabled, m_IsSayHelloEnabled, &varNew);CHECKHR(hr);hr = g_spIUIFramework->SetUICommandProperty(IDC_SAY_HELLO, UI_PKEY_Enabled, varNew);CHECKHR(hr);hr = g_spIUIFramework->InvalidateUICommand(IDC_TOGGLE, UI_INVALIDATIONS_PROPERTY, &UI_PKEY_Label);CHECKHR(hr);}break;}return hr;}STDMETHODIMP UpdateProperty(UINT nCmdID,__in REFPROPERTYKEY key,__in_opt const PROPVARIANT* ppropvarCurrentValue,__out PROPVARIANT* pPropvarNewValue){HRESULT hr = E_FAIL;if (key == UI_PKEY_Label){// Update the Label of ToggleButton controlif (nCmdID == IDC_TOGGLE){if (m_IsSayHelloEnabled){hr = UIInitPropertyFromString(UI_PKEY_Label,L"Disable", pPropvarNewValue);}else{hr = UIInitPropertyFromString(UI_PKEY_Label,L"Enable", pPropvarNewValue);}}}return hr;}private:CWindow m_NotifyWindow;BOOL m_IsSayHelloEnabled;};//Create and initialize ribbonHRESULT CreateRibbon(HWND hMainWnd){ATLASSERT(::IsWindow(hMainWnd));HRESULT hr = CRibbonApp::CreateInstance(&g_spIUIApplication);CHECKHR(hr);CComPtr< IRibbonNotifyWindow > spINotifyWindow;g_spIUIApplication.QueryInterface(&spINotifyWindow);ATLASSERT(spINotifyWindow != NULL);spINotifyWindow->SetNotifyWindow(hMainWnd);hr = g_spIUIFramework.CoCreateInstance(CLSID_UIRibbonFramework);CHECKHR(hr);hr = g_spIUIFramework->Initialize(hMainWnd, g_spIUIApplication);CHECKHR(hr);hr = g_spIUIFramework->LoadUI(::GetModuleHandle(NULL),_T("APPLICATION_RIBBON"));CHECKHR(hr);return hr;}//Destroy ribbonvoid DestroyRibbon(){g_spIUIFramework->Destroy();g_spIUIFramework = NULL;g_spIUIApplication = NULL;}//Get the height of ribbon controlUINT32 GetRibbonHeight(){ATLASSERT(g_spIUIFramework != NULL);CComPtr< IUIRibbon > spIUIRibbon;g_spIUIFramework->GetView(0,IID_PPV_ARGS(&spIUIRibbon));ATLASSERT(spIUIRibbon);UINT32 height;spIUIRibbon->GetHeight(&height);return height;}5.在主窗口中使用Ribbon:
#pragma once#include "MyView.h"#include "Ribbon.h"typedef CWinTraits< WS _OVERLAPPEDWINDOW |WS_CLIPCHILDREN > CMyWindowTraits;class CMyWindow :public CWindowImpl< CMyWindow , CWindow , CMyWindowTraits >{public:CMyWindow(){CWndClassInfo& wci = GetWndClassInfo();if (!wci.m_atom){wci.m_wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);}}public:DECLARE_WND_CLASS(_T("My WTL main window"))BEGIN_MSG_MAP_EX(CMyWindow)MSG_WM_CREATE(OnCreate)MSG_WM_DESTROY(OnDestroy)MSG_WM_SIZE(OnSize)//Ribbon messageMSG_WM_USER_RIBBONRESIZE(OnRibbonResize)MSG_WM_USER_COMMAND(OnRibbonCommand)END_MSG_MAP()int OnCreate(LPCREATESTRUCT /*lpCreateStruct*/){//Create and initialize ribbonHRESULT hr = CreateRibbon(m_hWnd);CHECKHR(hr);//Create view windowCRect rc;GetClientRect(&rc);rc.top += GetRibbonHeight();m_View.Create(m_hWnd,rc,NULL,WS_CHILD|WS_VISIBLE);return 0;}void OnSize(UINT /*nType*/, CSize /*size*/){if (m_View.m_hWnd){CRect rc;GetClientRect(&rc);rc.top += GetRibbonHeight();m_View.SetWindowPos(m_hWnd,&rc,SWP_NOZORDER | SWP_NOACTIVATE);}}void OnRibbonResize(UINT height){CRect rc;GetClientRect(&rc);rc.top += height;m_View.SetWindowPos(m_hWnd,&rc,SWP_NOZORDER | SWP_NOACTIVATE);}void OnRibbonCommand(UINT cmdID)