1 // Win32++ Version 7.3
\r
2 // Released: 30th November 2011
\r
6 // url: https://sourceforge.net/projects/win32-framework
\r
9 // Copyright (c) 2005-2011 David Nash
\r
11 // Permission is hereby granted, free of charge, to
\r
12 // any person obtaining a copy of this software and
\r
13 // associated documentation files (the "Software"),
\r
14 // to deal in the Software without restriction, including
\r
15 // without limitation the rights to use, copy, modify,
\r
16 // merge, publish, distribute, sublicense, and/or sell
\r
17 // copies of the Software, and to permit persons to whom
\r
18 // the Software is furnished to do so, subject to the
\r
19 // following conditions:
\r
21 // The above copyright notice and this permission notice
\r
22 // shall be included in all copies or substantial portions
\r
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
\r
26 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
\r
27 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
\r
28 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
\r
29 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
\r
30 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
31 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
32 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
\r
33 // OR OTHER DEALINGS IN THE SOFTWARE.
\r
35 ////////////////////////////////////////////////////////
\r
38 ///////////////////////////////////////////////////////
\r
40 // Declaration of the following classes:
\r
41 // CRibbon and CRibbonFrame
\r
44 #ifndef _WIN32XX_RIBBON_H_
\r
45 #define _WIN32XX_RIBBON_H_
\r
48 // Notes: 1) The Windows 7 SDK must be installed and its directories added to the IDE
\r
49 // 2) The ribbon only works on OS Windows 7 and above
\r
51 //#include <strsafe.h>
\r
52 #include <UIRibbon.h> // Contained within the Windows 7 SDK
\r
53 #include <UIRibbonPropertyHelpers.h>
\r
57 // Defines the callback entry-point methods for the Ribbon framework.
\r
58 class CRibbon : public IUICommandHandler, public IUIApplication
\r
61 CRibbon() : m_cRef(1), m_pRibbonFramework(NULL) {}
\r
64 // IUnknown methods.
\r
65 STDMETHOD_(ULONG, AddRef());
\r
66 STDMETHOD_(ULONG, Release());
\r
67 STDMETHOD(QueryInterface(REFIID iid, void** ppv));
\r
69 // IUIApplication methods
\r
70 STDMETHOD(OnCreateUICommand)(UINT nCmdID, __in UI_COMMANDTYPE typeID,
\r
71 __deref_out IUICommandHandler** ppCommandHandler);
\r
73 STDMETHOD(OnDestroyUICommand)(UINT32 commandId, __in UI_COMMANDTYPE typeID,
\r
74 __in_opt IUICommandHandler* commandHandler);
\r
76 STDMETHOD(OnViewChanged)(UINT viewId, __in UI_VIEWTYPE typeId, __in IUnknown* pView,
\r
77 UI_VIEWVERB verb, INT uReasonCode);
\r
79 // IUICommandHandle methods
\r
80 STDMETHODIMP Execute(UINT nCmdID, UI_EXECUTIONVERB verb, __in_opt const PROPERTYKEY* key, __in_opt const PROPVARIANT* ppropvarValue,
\r
81 __in_opt IUISimplePropertySet* pCommandExecutionProperties);
\r
83 STDMETHODIMP UpdateProperty(UINT nCmdID, __in REFPROPERTYKEY key, __in_opt const PROPVARIANT* ppropvarCurrentValue,
\r
84 __out PROPVARIANT* ppropvarNewValue);
\r
86 bool virtual CreateRibbon(CWnd* pWnd);
\r
87 void virtual DestroyRibbon();
\r
88 IUIFramework* GetRibbonFramework() { return m_pRibbonFramework; }
\r
91 IUIFramework* m_pRibbonFramework;
\r
92 LONG m_cRef; // Reference count.
\r
97 class CRibbonFrame : public CFrame, public CRibbon
\r
100 // A nested class for the MRU item properties
\r
101 class CRecentFiles : public IUISimplePropertySet
\r
104 CRecentFiles(PWSTR wszFullPath);
\r
105 ~CRecentFiles() {}
\r
107 // IUnknown methods.
\r
108 STDMETHODIMP_(ULONG) AddRef();
\r
109 STDMETHODIMP_(ULONG) Release();
\r
110 STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
\r
112 // IUISimplePropertySet methods
\r
113 STDMETHODIMP GetValue(__in REFPROPERTYKEY key, __out PROPVARIANT *value);
\r
116 LONG m_cRef; // Reference count.
\r
117 WCHAR m_wszDisplayName[MAX_PATH];
\r
118 WCHAR m_wszFullPath[MAX_PATH];
\r
121 typedef Shared_Ptr<CRecentFiles> RecentFilesPtr;
\r
123 CRibbonFrame() : m_uRibbonHeight(0) {}
\r
124 virtual ~CRibbonFrame() {}
\r
125 virtual CRect GetViewRect() const;
\r
126 virtual void OnCreate();
\r
127 virtual void OnDestroy();
\r
128 virtual STDMETHODIMP OnViewChanged(UINT32 viewId, UI_VIEWTYPE typeId, IUnknown* pView, UI_VIEWVERB verb, INT32 uReasonCode);
\r
129 virtual HRESULT PopulateRibbonRecentItems(__deref_out PROPVARIANT* pvarValue);
\r
130 virtual void UpdateMRUMenu();
\r
132 UINT GetRibbonHeight() const { return m_uRibbonHeight; }
\r
135 std::vector<RecentFilesPtr> m_vRecentFiles;
\r
136 void SetRibbonHeight(UINT uRibbonHeight) { m_uRibbonHeight = uRibbonHeight; }
\r
137 UINT m_uRibbonHeight;
\r
143 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
148 //////////////////////////////////////////////
\r
149 // Definitions for the CRibbon class
\r
152 inline CRibbon::~CRibbon()
\r
154 // Reference count must be 1 or we have a leak!
\r
155 assert(m_cRef == 1);
\r
158 // IUnknown method implementations.
\r
159 inline STDMETHODIMP_(ULONG) CRibbon::AddRef()
\r
161 return InterlockedIncrement(&m_cRef);
\r
164 inline STDMETHODIMP_(ULONG) CRibbon::Release()
\r
166 LONG cRef = InterlockedDecrement(&m_cRef);
\r
170 inline STDMETHODIMP CRibbon::Execute(UINT nCmdID, UI_EXECUTIONVERB verb, __in_opt const PROPERTYKEY* key, __in_opt const PROPVARIANT* ppropvarValue,
\r
171 __in_opt IUISimplePropertySet* pCommandExecutionProperties)
\r
173 UNREFERENCED_PARAMETER (nCmdID);
\r
174 UNREFERENCED_PARAMETER (verb);
\r
175 UNREFERENCED_PARAMETER (key);
\r
176 UNREFERENCED_PARAMETER (ppropvarValue);
\r
177 UNREFERENCED_PARAMETER (pCommandExecutionProperties);
\r
182 inline STDMETHODIMP CRibbon::QueryInterface(REFIID iid, void** ppv)
\r
184 if (iid == __uuidof(IUnknown))
\r
186 *ppv = static_cast<IUnknown*>(static_cast<IUIApplication*>(this));
\r
188 else if (iid == __uuidof(IUICommandHandler))
\r
190 *ppv = static_cast<IUICommandHandler*>(this);
\r
192 else if (iid == __uuidof(IUIApplication))
\r
194 *ppv = static_cast<IUIApplication*>(this);
\r
199 return E_NOINTERFACE;
\r
206 // Called by the Ribbon framework for each command specified in markup, to bind the Command to an IUICommandHandler.
\r
207 inline STDMETHODIMP CRibbon::OnCreateUICommand(UINT nCmdID, __in UI_COMMANDTYPE typeID,
\r
208 __deref_out IUICommandHandler** ppCommandHandler)
\r
210 UNREFERENCED_PARAMETER(typeID);
\r
211 UNREFERENCED_PARAMETER(nCmdID);
\r
213 // By default we use the single command handler provided as part of CRibbon.
\r
214 // Override this function to account for multiple command handlers.
\r
216 return QueryInterface(IID_PPV_ARGS(ppCommandHandler));
\r
219 // Called when the state of the Ribbon changes, for example, created, destroyed, or resized.
\r
220 inline STDMETHODIMP CRibbon::OnViewChanged(UINT viewId, __in UI_VIEWTYPE typeId, __in IUnknown* pView,
\r
221 UI_VIEWVERB verb, INT uReasonCode)
\r
223 UNREFERENCED_PARAMETER(viewId);
\r
224 UNREFERENCED_PARAMETER(typeId);
\r
225 UNREFERENCED_PARAMETER(pView);
\r
226 UNREFERENCED_PARAMETER(verb);
\r
227 UNREFERENCED_PARAMETER(uReasonCode);
\r
233 // Called by the Ribbon framework for each command at the time of ribbon destruction.
\r
234 inline STDMETHODIMP CRibbon::OnDestroyUICommand(UINT32 nCmdID, __in UI_COMMANDTYPE typeID,
\r
235 __in_opt IUICommandHandler* commandHandler)
\r
237 UNREFERENCED_PARAMETER(commandHandler);
\r
238 UNREFERENCED_PARAMETER(typeID);
\r
239 UNREFERENCED_PARAMETER(nCmdID);
\r
244 // Called by the Ribbon framework when a command property (PKEY) needs to be updated.
\r
245 inline STDMETHODIMP CRibbon::UpdateProperty(UINT nCmdID, __in REFPROPERTYKEY key, __in_opt const PROPVARIANT* ppropvarCurrentValue,
\r
246 __out PROPVARIANT* ppropvarNewValue)
\r
248 UNREFERENCED_PARAMETER(nCmdID);
\r
249 UNREFERENCED_PARAMETER(key);
\r
250 UNREFERENCED_PARAMETER(ppropvarCurrentValue);
\r
251 UNREFERENCED_PARAMETER(ppropvarNewValue);
\r
256 inline bool CRibbon::CreateRibbon(CWnd* pWnd)
\r
258 ::CoInitialize(NULL);
\r
260 // Instantiate the Ribbon framework object.
\r
261 ::CoCreateInstance(CLSID_UIRibbonFramework, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pRibbonFramework));
\r
263 // Connect the host application to the Ribbon framework.
\r
264 HRESULT hr = m_pRibbonFramework->Initialize(pWnd->GetHwnd(), this);
\r
270 // Load the binary markup. APPLICATION_RIBBON is the default name generated by uicc.
\r
271 hr = m_pRibbonFramework->LoadUI(GetModuleHandle(NULL), L"APPLICATION_RIBBON");
\r
280 inline void CRibbon::DestroyRibbon()
\r
282 if (m_pRibbonFramework)
\r
284 m_pRibbonFramework->Destroy();
\r
285 m_pRibbonFramework->Release();
\r
286 m_pRibbonFramework = NULL;
\r
291 //////////////////////////////////////////////
\r
292 // Definitions for the CRibbonFrame class
\r
295 inline CRect CRibbonFrame::GetViewRect() const
\r
297 // Get the frame's client area
\r
298 CRect rcFrame = GetClientRect();
\r
300 // Get the statusbar's window area
\r
302 if (GetStatusBar().IsWindowVisible() || !IsWindowVisible())
\r
303 rcStatus = GetStatusBar().GetWindowRect();
\r
305 // Get the top rebar or toolbar's window area
\r
307 if (IsReBarSupported() && m_bUseReBar)
\r
308 rcTop = GetReBar().GetWindowRect();
\r
310 if (m_bUseToolBar && GetToolBar().IsWindowVisible())
\r
311 rcTop = GetToolBar().GetWindowRect();
\r
313 // Return client size less the rebar and status windows
\r
314 int top = rcFrame.top + rcTop.Height() + m_uRibbonHeight;
\r
315 int left = rcFrame.left;
\r
316 int right = rcFrame.right;
\r
317 int bottom = rcFrame.Height() - (rcStatus.Height());
\r
318 if ((bottom <= top) ||( right <= left))
\r
319 top = left = right = bottom = 0;
\r
321 CRect rcView(left, top, right, bottom);
\r
325 inline void CRibbonFrame::OnCreate()
\r
327 // OnCreate is called automatically during window creation when a
\r
328 // WM_CREATE message received.
\r
330 // Tasks such as setting the icon, creating child windows, or anything
\r
331 // associated with creating windows are normally performed here.
\r
333 if (GetWinVersion() >= 2601) // WinVersion >= Windows 7
\r
335 m_bUseReBar = FALSE; // Don't use rebars
\r
336 m_bUseToolBar = FALSE; // Don't use a toolbar
\r
338 CFrame::OnCreate();
\r
340 if (CreateRibbon(this))
\r
341 TRACE(_T("Ribbon Created Succesfully\n"));
\r
343 throw CWinException(_T("Failed to create ribbon"));
\r
347 CFrame::OnCreate();
\r
351 inline void CRibbonFrame::OnDestroy()
\r
354 CFrame::OnDestroy();
\r
357 inline STDMETHODIMP CRibbonFrame::OnViewChanged(UINT32 viewId, UI_VIEWTYPE typeId, IUnknown* pView, UI_VIEWVERB verb, INT32 uReasonCode)
\r
359 UNREFERENCED_PARAMETER(viewId);
\r
360 UNREFERENCED_PARAMETER(uReasonCode);
\r
362 HRESULT hr = E_NOTIMPL;
\r
364 // Checks to see if the view that was changed was a Ribbon view.
\r
365 if (UI_VIEWTYPE_RIBBON == typeId)
\r
369 // The view was newly created.
\r
370 case UI_VIEWVERB_CREATE:
\r
374 // The view has been resized. For the Ribbon view, the application should
\r
375 // call GetHeight to determine the height of the ribbon.
\r
376 case UI_VIEWVERB_SIZE:
\r
378 IUIRibbon* pRibbon = NULL;
\r
379 UINT uRibbonHeight;
\r
381 hr = pView->QueryInterface(IID_PPV_ARGS(&pRibbon));
\r
384 // Call to the framework to determine the desired height of the Ribbon.
\r
385 hr = pRibbon->GetHeight(&uRibbonHeight);
\r
386 SetRibbonHeight(uRibbonHeight);
\r
387 pRibbon->Release();
\r
390 // Use the ribbon height to position controls in the client area of the window.
\r
394 // The view was destroyed.
\r
395 case UI_VIEWVERB_DESTROY:
\r
404 inline HRESULT CRibbonFrame::PopulateRibbonRecentItems(__deref_out PROPVARIANT* pvarValue)
\r
406 LONG iCurrentFile = 0;
\r
407 std::vector<CString> FileNames = GetMRUEntries();
\r
408 std::vector<CString>::iterator iter;
\r
409 int iFileCount = FileNames.size();
\r
410 HRESULT hr = E_FAIL;
\r
411 SAFEARRAY* psa = SafeArrayCreateVector(VT_UNKNOWN, 0, iFileCount);
\r
412 m_vRecentFiles.clear();
\r
416 for (iter = FileNames.begin(); iter < FileNames.end(); ++iter)
\r
418 CString strCurrentFile = (*iter);
\r
419 WCHAR wszCurrentFile[MAX_PATH] = {0L};
\r
420 lstrcpynW(wszCurrentFile, T2W(strCurrentFile), MAX_PATH);
\r
422 CRecentFiles* pRecentFiles = new CRecentFiles(wszCurrentFile);
\r
423 m_vRecentFiles.push_back(RecentFilesPtr(pRecentFiles));
\r
424 hr = SafeArrayPutElement(psa, &iCurrentFile, static_cast<void*>(pRecentFiles));
\r
428 SAFEARRAYBOUND sab = {iCurrentFile,0};
\r
429 SafeArrayRedim(psa, &sab);
\r
430 hr = UIInitPropertyFromIUnknownArray(UI_PKEY_RecentItems, psa, pvarValue);
\r
432 SafeArrayDestroy(psa); // Calls release for each element in the array
\r
438 inline void CRibbonFrame::UpdateMRUMenu()
\r
440 // Suppress UpdateMRUMenu when ribbon is used
\r
441 if (0 != GetRibbonFramework()) return;
\r
443 CFrame::UpdateMRUMenu();
\r
447 ////////////////////////////////////////////////////////
\r
448 // Declaration of the nested CRecentFiles class
\r
450 inline CRibbonFrame::CRecentFiles::CRecentFiles(PWSTR wszFullPath) : m_cRef(1)
\r
453 DWORD_PTR dwPtr = NULL;
\r
454 m_wszFullPath[0] = L'\0';
\r
455 m_wszDisplayName[0] = L'\0';
\r
457 if (NULL != lstrcpynW(m_wszFullPath, wszFullPath, MAX_PATH))
\r
459 dwPtr = ::SHGetFileInfoW(wszFullPath, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME | SHGFI_USEFILEATTRIBUTES);
\r
463 lstrcpynW(m_wszDisplayName, sfi.szDisplayName, MAX_PATH);
\r
465 else // Provide a reasonable fallback.
\r
467 lstrcpynW(m_wszDisplayName, m_wszFullPath, MAX_PATH);
\r
472 inline STDMETHODIMP_(ULONG) CRibbonFrame::CRecentFiles::AddRef()
\r
474 return InterlockedIncrement(&m_cRef);
\r
477 inline STDMETHODIMP_(ULONG) CRibbonFrame::CRecentFiles::Release()
\r
479 return InterlockedDecrement(&m_cRef);
\r
482 inline STDMETHODIMP CRibbonFrame::CRecentFiles::QueryInterface(REFIID iid, void** ppv)
\r
489 if (iid == __uuidof(IUnknown))
\r
491 *ppv = static_cast<IUnknown*>(this);
\r
493 else if (iid == __uuidof(IUISimplePropertySet))
\r
495 *ppv = static_cast<IUISimplePropertySet*>(this);
\r
500 return E_NOINTERFACE;
\r
507 // IUISimplePropertySet methods.
\r
508 inline STDMETHODIMP CRibbonFrame::CRecentFiles::GetValue(__in REFPROPERTYKEY key, __out PROPVARIANT *ppropvar)
\r
510 HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
\r
512 if (key == UI_PKEY_Label)
\r
514 hr = UIInitPropertyFromString(key, m_wszDisplayName, ppropvar);
\r
516 else if (key == UI_PKEY_LabelDescription)
\r
518 hr = UIInitPropertyFromString(key, m_wszDisplayName, ppropvar);
\r
524 } // namespace Win32xx
\r
526 #endif // _WIN32XX_RIBBON_H_
\r