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

ScreenShot00102

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 control
            if (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 ribbon
HRESULT 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 ribbon
void DestroyRibbon()
{
    g_spIUIFramework->Destroy();
    g_spIUIFramework = NULL;
    g_spIUIApplication = NULL;
}
//Get the height of ribbon control
UINT32 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 message
        MSG_WM_USER_RIBBONRESIZE(OnRibbonResize)
        MSG_WM_USER_COMMAND(OnRibbonCommand)
    END_MSG_MAP()
    int OnCreate(LPCREATESTRUCT /*lpCreateStruct*/)
    {
        //Create and initialize ribbon
        HRESULT hr = CreateRibbon(m_hWnd);
        CHECKHR(hr);
        //Create view window
        CRect 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)
    {
        if (cmdID == IDC_SAY_HELLO)
        {
            MessageBox(_T("MyButton button is clicked!"),_T("WTL ribbon message"));
        }
    }
    
    void OnDestroy()
    {
        //Destroy ribbon
        DestroyRibbon();
        PostQuitMessage(0);
    }
private:
    CMyView m_View;
};

6.实现效果:

ScreenShot00103

posted on 2010-10-03 21:45  wudong  阅读(2450)  评论(0编辑  收藏  举报

导航