499 lines
11 KiB
C++
499 lines
11 KiB
C++
// Windows Template Library - WTL version 10.0
|
|
// Copyright (C) Microsoft Corporation, WTL Team. 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
|
|
// Microsoft Public License (http://opensource.org/licenses/MS-PL)
|
|
// which can be found in the file MS-PL.txt at the root folder.
|
|
|
|
#ifndef __ATLDWM_H__
|
|
#define __ATLDWM_H__
|
|
|
|
#pragma once
|
|
|
|
#ifndef __ATLAPP_H__
|
|
#error atldwm.h requires atlapp.h to be included first
|
|
#endif
|
|
|
|
#ifndef __ATLWIN_H__
|
|
#error atldwm.h requires atlwin.h to be included first
|
|
#endif
|
|
|
|
#if (_WIN32_WINNT < 0x0600)
|
|
#error atldwm.h requires _WIN32_WINNT >= 0x0600
|
|
#endif
|
|
|
|
#ifndef _DWMAPI_H_
|
|
#include <dwmapi.h>
|
|
#endif
|
|
#pragma comment(lib, "dwmapi.lib")
|
|
|
|
// Note: To create an application that also runs on older versions of Windows,
|
|
// use delay load of dwmapi.dll and ensure that no calls to the DWM API are
|
|
// Delay load is NOT AUTOMATIC for VC++ 7, you have to link to delayimp.lib,
|
|
// and add dwmapi.dll in the Linker.Input.Delay Loaded DLLs section of the
|
|
// project properties.
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Classes in this file:
|
|
//
|
|
// CDwm
|
|
// CDwmImpl<T, TBase>
|
|
// CDwmWindowT<TBase> - CDwmWindow
|
|
// CDwmThumbnailT<t_bManaged, TBase>
|
|
// CDwmThumbnail
|
|
// CDwmThumbnailHandle
|
|
// CAeroControlImpl
|
|
|
|
|
|
namespace WTL
|
|
{
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CDwm - wrapper for DWM handle
|
|
|
|
class CDwm
|
|
{
|
|
public:
|
|
// Data members
|
|
static int m_nIsDwmSupported;
|
|
|
|
// Constructor
|
|
CDwm()
|
|
{
|
|
IsDwmSupported();
|
|
}
|
|
|
|
// Dwm support helper
|
|
static bool IsDwmSupported()
|
|
{
|
|
if(m_nIsDwmSupported == -1)
|
|
{
|
|
CStaticDataInitCriticalSectionLock lock;
|
|
if(FAILED(lock.Lock()))
|
|
{
|
|
ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CDwm::IsDwmSupported.\n"));
|
|
ATLASSERT(FALSE);
|
|
return false;
|
|
}
|
|
|
|
if(m_nIsDwmSupported == -1)
|
|
{
|
|
HMODULE hDwmDLL = ::LoadLibrary(_T("dwmapi.dll"));
|
|
m_nIsDwmSupported = (hDwmDLL != NULL) ? 1 : 0;
|
|
if(hDwmDLL != NULL)
|
|
::FreeLibrary(hDwmDLL);
|
|
}
|
|
|
|
lock.Unlock();
|
|
}
|
|
|
|
ATLASSERT(m_nIsDwmSupported != -1);
|
|
return (m_nIsDwmSupported == 1);
|
|
}
|
|
|
|
// Operations
|
|
BOOL DwmIsCompositionEnabled() const
|
|
{
|
|
if(!IsDwmSupported())
|
|
return FALSE;
|
|
|
|
BOOL bRes = FALSE;
|
|
return (SUCCEEDED(::DwmIsCompositionEnabled(&bRes)) && bRes) ? TRUE : FALSE;
|
|
}
|
|
|
|
BOOL DwmEnableComposition(UINT fEnable)
|
|
{
|
|
if(!IsDwmSupported())
|
|
return FALSE;
|
|
|
|
return SUCCEEDED(::DwmEnableComposition(fEnable)) ? TRUE : FALSE;
|
|
}
|
|
|
|
BOOL DwmEnableMMCSS(BOOL fEnableMMCSS)
|
|
{
|
|
if(!IsDwmSupported())
|
|
return FALSE;
|
|
|
|
return SUCCEEDED(::DwmEnableMMCSS(fEnableMMCSS)) ? TRUE : FALSE;
|
|
}
|
|
|
|
HRESULT DwmGetColorizationColor(DWORD* pcrColorization, BOOL* pfOpaqueBlend)
|
|
{
|
|
if(!IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
return ::DwmGetColorizationColor(pcrColorization, pfOpaqueBlend);
|
|
}
|
|
|
|
HRESULT DwmFlush()
|
|
{
|
|
if(!IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
return ::DwmFlush();
|
|
}
|
|
};
|
|
|
|
__declspec(selectany) int CDwm::m_nIsDwmSupported = -1;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CDwmImpl - DWM window support
|
|
|
|
template <class T, class TBase = CDwm>
|
|
class CDwmImpl : public TBase
|
|
{
|
|
public:
|
|
HRESULT DwmEnableBlurBehindWindow(const DWM_BLURBEHIND* pBB)
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
T* pT = static_cast<T*>(this);
|
|
ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
return ::DwmEnableBlurBehindWindow(pT->m_hWnd, pBB);
|
|
}
|
|
|
|
HRESULT DwmExtendFrameIntoClientArea(const MARGINS* pMargins)
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
T* pT = static_cast<T*>(this);
|
|
ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
return ::DwmExtendFrameIntoClientArea(pT->m_hWnd, pMargins);
|
|
}
|
|
|
|
HRESULT DwmExtendFrameIntoEntireClientArea()
|
|
{
|
|
MARGINS margins = { -1 };
|
|
return DwmExtendFrameIntoClientArea(&margins);
|
|
}
|
|
|
|
HRESULT DwmGetCompositionTimingInfo(DWM_TIMING_INFO* pTimingInfo)
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
T* pT = static_cast<T*>(this);
|
|
ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
return ::DwmGetCompositionTimingInfo(pT->m_hWnd, pTimingInfo);
|
|
}
|
|
|
|
HRESULT DwmGetWindowAttribute(DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute)
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
T* pT = static_cast<T*>(this);
|
|
ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
return ::DwmGetWindowAttribute(pT->m_hWnd, dwAttribute, pvAttribute, cbAttribute);
|
|
}
|
|
|
|
HRESULT DwmModifyPreviousDxFrameDuration(INT cRefreshes, BOOL fRelative)
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
T* pT = static_cast<T*>(this);
|
|
ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
return ::DwmModifyPreviousDxFrameDuration(pT->m_hWnd, cRefreshes, fRelative);
|
|
}
|
|
|
|
HRESULT DwmSetDxFrameDuration(INT cRefreshes)
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
T* pT = static_cast<T*>(this);
|
|
ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
return ::DwmSetDxFrameDuration(pT->m_hWnd, cRefreshes);
|
|
}
|
|
|
|
HRESULT DwmSetPresentParameters(DWM_PRESENT_PARAMETERS* pPresentParams)
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
T* pT = static_cast<T*>(this);
|
|
ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
return ::DwmSetPresentParameters(pT->m_hWnd, pPresentParams);
|
|
}
|
|
|
|
HRESULT DwmSetWindowAttribute(DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute)
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
T* pT = static_cast<T*>(this);
|
|
ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
return ::DwmSetWindowAttribute(pT->m_hWnd, dwAttribute, pvAttribute, cbAttribute);
|
|
}
|
|
|
|
HRESULT DwmAttachMilContent()
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
T* pT = static_cast<T*>(this);
|
|
ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
return ::DwmAttachMilContent(pT->m_hWnd);
|
|
}
|
|
|
|
HRESULT DwmDetachMilContent()
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
T* pT = static_cast<T*>(this);
|
|
ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
return ::DwmDetachMilContent(pT->m_hWnd);
|
|
}
|
|
};
|
|
|
|
template <class TBase>
|
|
class CDwmWindowT : public TBase, public CDwmImpl<CDwmWindowT< TBase > >
|
|
{
|
|
public:
|
|
CDwmWindowT(HWND hWnd = NULL) : TBase(hWnd)
|
|
{ }
|
|
|
|
CDwmWindowT< TBase >& operator =(HWND hWnd)
|
|
{
|
|
this->m_hWnd = hWnd;
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
typedef CDwmWindowT<ATL::CWindow> CDwmWindow;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CDwmThumbnail - provides DWM thumbnail support
|
|
|
|
template <bool t_bManaged, class TBase = CDwm>
|
|
class CDwmThumbnailT : public TBase
|
|
{
|
|
public:
|
|
// Data members
|
|
HTHUMBNAIL m_hThumbnail;
|
|
|
|
// Constructor
|
|
CDwmThumbnailT(HTHUMBNAIL hThumbnail = NULL) : m_hThumbnail(hThumbnail)
|
|
{ }
|
|
|
|
~CDwmThumbnailT()
|
|
{
|
|
if(t_bManaged && (m_hThumbnail != NULL))
|
|
Unregister();
|
|
}
|
|
|
|
// Operations
|
|
CDwmThumbnailT<t_bManaged, TBase>& operator =(HTHUMBNAIL hThumbnail)
|
|
{
|
|
Attach(hThumbnail);
|
|
return *this;
|
|
}
|
|
|
|
void Attach(HTHUMBNAIL hThumbnailNew)
|
|
{
|
|
if(t_bManaged && (m_hThumbnail != NULL) && (m_hThumbnail != hThumbnailNew))
|
|
Unregister();
|
|
m_hThumbnail = hThumbnailNew;
|
|
}
|
|
|
|
HTHUMBNAIL Detach()
|
|
{
|
|
HTHUMBNAIL hThumbnail = m_hThumbnail;
|
|
m_hThumbnail = NULL;
|
|
return hThumbnail;
|
|
}
|
|
|
|
HRESULT Register(HWND hwndDestination, HWND hwndSource)
|
|
{
|
|
ATLASSERT(::IsWindow(hwndDestination));
|
|
ATLASSERT(::IsWindow(hwndSource));
|
|
ATLASSERT(m_hThumbnail==NULL);
|
|
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
return ::DwmRegisterThumbnail(hwndDestination, hwndSource, &m_hThumbnail);
|
|
}
|
|
|
|
HRESULT Unregister()
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
if(m_hThumbnail == NULL)
|
|
return S_FALSE;
|
|
|
|
HRESULT Hr = ::DwmUnregisterThumbnail(m_hThumbnail);
|
|
if(SUCCEEDED(Hr))
|
|
m_hThumbnail = NULL;
|
|
|
|
return Hr;
|
|
}
|
|
|
|
operator HTHUMBNAIL() const { return m_hThumbnail; }
|
|
|
|
bool IsNull() const { return (m_hThumbnail == NULL); }
|
|
|
|
HRESULT UpdateProperties(const DWM_THUMBNAIL_PROPERTIES* ptnProperties)
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
ATLASSERT(m_hThumbnail != NULL);
|
|
return ::DwmUpdateThumbnailProperties(m_hThumbnail, ptnProperties);
|
|
}
|
|
|
|
// Attributes
|
|
HRESULT QuerySourceSize(PSIZE pSize)
|
|
{
|
|
if(!this->IsDwmSupported())
|
|
return E_NOTIMPL;
|
|
|
|
ATLASSERT(m_hThumbnail != NULL);
|
|
return ::DwmQueryThumbnailSourceSize(m_hThumbnail, pSize);
|
|
}
|
|
};
|
|
|
|
typedef CDwmThumbnailT<true, CDwm> CDwmThumbnail;
|
|
typedef CDwmThumbnailT<false, CDwm> CDwmThumbnailHandle;
|
|
|
|
|
|
#ifdef __ATLTHEME_H__
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CAeroControlImpl - Base class for controls on Glass
|
|
|
|
template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
|
|
class CAeroControlImpl : public CThemeImpl<T>,
|
|
public CBufferedPaintImpl<T>,
|
|
public ATL::CWindowImpl<T, TBase, TWinTraits>
|
|
{
|
|
public:
|
|
typedef CThemeImpl<T> _themeClass;
|
|
typedef CBufferedPaintImpl<T> _baseClass;
|
|
typedef ATL::CWindowImpl<T, TBase, TWinTraits> _windowClass;
|
|
|
|
CAeroControlImpl()
|
|
{
|
|
this->m_PaintParams.dwFlags = BPPF_ERASE;
|
|
}
|
|
|
|
static LPCWSTR GetThemeName()
|
|
{
|
|
#ifdef _UNICODE
|
|
return TBase::GetWndClassName();
|
|
#else
|
|
ATLASSERT(!_T("Return UNICODE string of window classname / theme class"));
|
|
return NULL;
|
|
#endif // _UNICODE
|
|
}
|
|
|
|
// Message map and handlers
|
|
BEGIN_MSG_MAP(CAeroControlImpl)
|
|
MESSAGE_HANDLER(WM_CREATE, OnCreate)
|
|
MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
|
|
CHAIN_MSG_MAP(_themeClass)
|
|
CHAIN_MSG_MAP(_baseClass)
|
|
END_MSG_MAP()
|
|
|
|
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
|
|
{
|
|
T* pT = static_cast<T*>(this);
|
|
pT->Init();
|
|
|
|
bHandled = FALSE;
|
|
return 0;
|
|
}
|
|
|
|
LRESULT OnActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
|
|
{
|
|
if(this->IsThemingSupported())
|
|
this->Invalidate(FALSE);
|
|
|
|
bHandled = FALSE;
|
|
return 0;
|
|
}
|
|
|
|
// Operations
|
|
BOOL SubclassWindow(HWND hWnd)
|
|
{
|
|
ATLASSERT(this->m_hWnd == NULL);
|
|
ATLASSERT(::IsWindow(hWnd));
|
|
BOOL bRet = _windowClass::SubclassWindow(hWnd);
|
|
if(bRet)
|
|
{
|
|
T* pT = static_cast<T*>(this);
|
|
pT->Init();
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// Implementation
|
|
LRESULT DefWindowProc()
|
|
{
|
|
const ATL::_ATL_MSG* pMsg = this->m_pCurrentMsg;
|
|
LRESULT lRes = 0;
|
|
if(pMsg != NULL)
|
|
lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
|
|
|
|
return lRes;
|
|
}
|
|
|
|
LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
T* pT = static_cast<T*>(this);
|
|
LRESULT lRes = 0;
|
|
if(::DwmDefWindowProc(pT->m_hWnd, uMsg, wParam, lParam, &lRes) != FALSE)
|
|
return lRes;
|
|
|
|
return _windowClass::DefWindowProc(uMsg, wParam, lParam);
|
|
}
|
|
|
|
void DoBufferedPaint(HDC hDC, RECT& rcPaint)
|
|
{
|
|
T* pT = static_cast<T*>(this);
|
|
HDC hDCPaint = NULL;
|
|
RECT rcClient = {};
|
|
this->GetClientRect(&rcClient);
|
|
this->m_BufferedPaint.Begin(hDC, &rcClient, this->m_dwFormat, &this->m_PaintParams, &hDCPaint);
|
|
ATLASSERT(hDCPaint != NULL);
|
|
pT->DoAeroPaint(hDCPaint, rcClient, rcPaint);
|
|
this->m_BufferedPaint.End();
|
|
}
|
|
|
|
void DoPaint(HDC /*hdc*/, RECT& /*rcClient*/)
|
|
{
|
|
DefWindowProc();
|
|
}
|
|
|
|
// Overridables
|
|
void Init()
|
|
{
|
|
T* pT = static_cast<T*>(this);
|
|
(void)pT; // avoid level 4 warning
|
|
this->SetThemeClassList(pT->GetThemeName());
|
|
if(this->m_lpstrThemeClassList != NULL)
|
|
this->OpenThemeData();
|
|
}
|
|
|
|
void DoAeroPaint(HDC hDC, RECT& /*rcClient*/, RECT& rcPaint)
|
|
{
|
|
DefWindowProc(WM_PAINT, (WPARAM) hDC, 0L);
|
|
this->m_BufferedPaint.MakeOpaque(&rcPaint);
|
|
}
|
|
};
|
|
|
|
#endif // __ATLTHEME_H__
|
|
|
|
} // namespace WTL
|
|
|
|
#endif // __ATLDWM_H__
|