2025-11-28 00:35:46 +09:00

410 lines
11 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
#include "../stdafx.h"
#include "../MainFrm.h"
#include <UIRibbon.h>
#include <UIRibbonPropertyHelpers.h>
#include "../RibbonRes/ribbonres.h"
#include "../HTMLEdDoc.h"
#include "../HTMLEdView.h"
#include "../HTMLEdit.h"
#include "Ribbon.h"
#include "font.h"
#include "MRU.h"
/////////////////////////////////////////////////////////////////////////////
// CRibbonBar
BEGIN_MESSAGE_MAP(CRibbonBar, CToolBar)
//{{AFX_MSG_MAP(CRibbonBar)
ON_WM_NCCALCSIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CSize CRibbonBar::CalcFixedLayout(BOOL fStretch, BOOL fHortz)
{
CSize size = CToolBar::CalcFixedLayout(fStretch, fHortz);
size.cy = m_ulRibbonHeight;
return size;
}
// This is the Ribbon implementation that is done by an application.
// Applications have to implement IUIApplication and IUICommandHandler to set up communication with the Windows Ribbon.
class CApplication
: public IUIApplication
, public IUICommandHandler
{
public:
// Static method to create an instance of the object.
__checkReturn static HRESULT CreateInstance(__in CMainFrame* pFrame, __deref_out_opt CApplication **ppApplication)
{
if (!pFrame || !ppApplication)
{
return E_POINTER;
}
*ppApplication = NULL;
HRESULT hr = S_OK;
CApplication* pApplication = new CApplication();
if (pApplication != NULL)
{
pApplication->m_pMainFrame = pFrame;
// pApplication->m_cRef is 1.
*ppApplication = pApplication;
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
// IUnknown methods.
STDMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) Release()
{
LONG cRef = InterlockedDecrement(&m_cRef);
if (cRef == 0)
{
delete this;
}
return cRef;
}
STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
{
if (!ppv)
{
return E_POINTER;
}
if (iid == __uuidof(IUnknown))
{
*ppv = static_cast<IUnknown*>(static_cast<IUIApplication*>(this));
}
else if (iid == __uuidof(IUIApplication))
{
*ppv = static_cast<IUIApplication*>(this);
}
else if (iid == __uuidof(IUICommandHandler))
{
*ppv = static_cast<IUICommandHandler*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
// IUIApplication methods.
STDMETHODIMP OnViewChanged(UINT32 /*nViewID*/,
__in UI_VIEWTYPE /*typeID*/,
__in IUnknown* pView,
UI_VIEWVERB verb,
INT32 /*uReasonCode*/)
{
HRESULT hr;
// The Ribbon size has changed.
if (verb == UI_VIEWVERB_SIZE)
{
IUIRibbon* pRibbon;
pView->QueryInterface(IID_PPV_ARGS(&pRibbon));
if (!pRibbon)
{
return E_FAIL;
}
UINT ulRibbonHeight;
// Get the Ribbon height.
hr = pRibbon->GetHeight(&ulRibbonHeight);
pRibbon->Release();
if (FAILED(hr))
{
return hr;
}
// Update the Ribbon bar so that the main frame can recalculate the child layout.
m_pMainFrame->m_RibbonBar.SetRibbonHeight(ulRibbonHeight);
m_pMainFrame->RecalcLayout();
}
return S_OK;
}
STDMETHODIMP OnCreateUICommand(UINT32 /*nCmdID*/,
__in UI_COMMANDTYPE /*typeID*/,
__deref_out IUICommandHandler** ppCommandHandler)
{
// This application uses one command handler for all ribbon commands.
return QueryInterface(IID_PPV_ARGS(ppCommandHandler));
}
STDMETHODIMP OnDestroyUICommand(UINT32 /*commandId*/,
__in UI_COMMANDTYPE /*typeID*/,
__in_opt IUICommandHandler* /*commandHandler*/)
{
return E_NOTIMPL;
}
// IUICommandHandler methods.
// User action callback, with transient execution parameters.
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(nCmdID)
{
case IDC_FONT:
{
if (key != NULL && ppropvarValue != NULL)
{
IPropertyStore* pPropertyStore = NULL;
UIPropertyToInterface(*key, *ppropvarValue, &pPropertyStore);
if (pPropertyStore)
{
// Set font to the HTML editor.
hr = SetFont(m_pMainFrame, pPropertyStore);
pPropertyStore->Release();
}
}
break;
}
case IDC_MRULIST:
{
if (key != NULL && UI_PKEY_SelectedItem == *key)
{
UINT uSelectedMRUItem = 0xffffffff;
if (ppropvarValue != NULL && SUCCEEDED(UIPropertyToUInt32(*key, *ppropvarValue, &uSelectedMRUItem)))
{
ASSERT(uSelectedMRUItem < RECENT_FILE_COUNT);
::SendMessage(*m_pMainFrame, WM_COMMAND, uSelectedMRUItem + ID_FILE_MRU_FILE1, 0);
}
}
break;
}
default:
::SendMessage(*m_pMainFrame, WM_COMMAND, nCmdID, 0);
}
return hr;
}
STDMETHODIMP UpdateProperty(UINT32 nCmdID,
__in REFPROPERTYKEY key,
__in_opt const PROPVARIANT *currentValue,
__out PROPVARIANT *newValue)
{
HRESULT hr = E_NOTIMPL;
if(UI_PKEY_Enabled == key)
{
return UIInitPropertyFromBoolean(UI_PKEY_Enabled, GetStatus(nCmdID), newValue);
}
switch(nCmdID)
{
case IDC_MRULIST:
if (UI_PKEY_Label == key)
{
WCHAR label[MAX_PATH];
LoadStringW(AfxGetResourceHandle(), IDS_RECENTFILES, label, _countof(label));
hr = UIInitPropertyFromString(UI_PKEY_Label, label, newValue);
}
else if (UI_PKEY_RecentItems == key)
{
hr = PopulateRibbonRecentItems(theApp.GetRecentFileList(), newValue);
}
break;
case IDC_FONT:
if (UI_PKEY_FontProperties == key && currentValue != NULL)
{
IPropertyStore* pPropertyStore;
UIPropertyToInterface(UI_PKEY_FontProperties, *currentValue, &pPropertyStore);
if (pPropertyStore)
{
// Update the Ribbon font control.
hr = UpdateFont(m_pMainFrame, pPropertyStore);
pPropertyStore->Release();
}
}
break;
case IDC_VIEWSOURCE:
if (UI_PKEY_BooleanValue == key)
{
hr = UIInitPropertyFromBoolean(UI_PKEY_BooleanValue, !(GetStatus(nCmdID) & OLECMDF_LATCHED), newValue);
}
break;
default:
if (UI_PKEY_BooleanValue == key)
{
hr = UIInitPropertyFromBoolean(UI_PKEY_BooleanValue, GetStatus(nCmdID) & OLECMDF_LATCHED, newValue);
}
break;
}
return hr;
}
private:
CApplication()
: m_cRef(1)
, m_pMainFrame(NULL)
{
}
BOOL GetStatus(UINT32 nCmdID)
{
CHTMLEdView *pView = (CHTMLEdView*)m_pMainFrame->GetActiveView();
if (!pView)
return 0;
return pView->GetCommandStatus(nCmdID);
}
private:
LONG m_cRef; // Reference count.
CMainFrame* m_pMainFrame;
};
__checkReturn HRESULT InitRibbon(__in CMainFrame* pMainFrame, __deref_out_opt IUnknown** ppFramework)
{
if (ppFramework == NULL)
{
return E_POINTER;
}
// Create the IUIFramework instance.
IUIFramework* pFramework = NULL;
HRESULT hr = ::CoCreateInstance(CLSID_UIRibbonFramework, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFramework));
if (FAILED(hr))
{
return hr;
}
// Instantiate the CApplication object.
CApplication* pAppObject = NULL;
IUIApplication* pApplication = NULL;
hr = CApplication::CreateInstance(pMainFrame, &pAppObject);
if (FAILED(hr))
{
goto done;
}
#pragma warning( disable : 6011) // pAppObject cannot be NULL.
hr = pAppObject->QueryInterface(IID_PPV_ARGS(&pApplication));
#pragma warning( default : 6011)
if (FAILED(hr))
{
goto done;
}
hr = pFramework->Initialize(*pMainFrame, pApplication);
if (FAILED(hr))
{
goto done;
}
hr = pFramework->LoadUI(GetModuleHandle(NULL), L"APPLICATION_RIBBON");
if (FAILED(hr))
{
goto done;
}
// Return IUIFramework interface to the caller.
hr = pFramework->QueryInterface(ppFramework);
done:
if (pApplication)
{
pApplication->Release();
}
if (pAppObject)
{
pAppObject->Release();
}
if (pFramework)
{
pFramework->Release();
}
return hr;
}
void DestroyRibbon(__in IUnknown* pFramework)
{
IUIFramework* pUIFramework;
pFramework->QueryInterface(IID_PPV_ARGS(&pUIFramework));
ASSERT(pFramework != NULL);
// Destroy the Ribbon.
pUIFramework->Destroy();
pUIFramework->Release();
}
HRESULT SetModes(__in IUnknown* pFramework, UINT modes)
{
IUIFramework* pUIFramework;
pFramework->QueryInterface(IID_PPV_ARGS(&pUIFramework));
if (pUIFramework == NULL)
{
return E_FAIL;
}
// Change the modes.
HRESULT hr = pUIFramework->SetModes(modes);
pUIFramework->Release();
return hr;
}
HRESULT RibbonInvalidate(__in IUnknown* pFramework)
{
IUIFramework* pUIFramework;
pFramework->QueryInterface(IID_PPV_ARGS(&pUIFramework));
if (pUIFramework == NULL)
{
return E_FAIL;
}
// Invalidate the Font control properties.
HRESULT hr = pUIFramework->InvalidateUICommand(IDC_FONT, UI_INVALIDATIONS_PROPERTY, &UI_PKEY_FontProperties);
// Invalidate the control values, for example, the checked value of toggle buttons and enabled state.
hr = pUIFramework->InvalidateUICommand(0, UI_INVALIDATIONS_STATE|UI_INVALIDATIONS_VALUE, NULL);
UNREFERENCED_PARAMETER(hr);
pUIFramework->Release();
return S_OK;
}