You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

924 lines
22 KiB
C++

2 years ago
// XTPHookManager.cpp : implementation of the CXTPHookManager class.
//
// This file is a part of the XTREME TOOLKIT PRO MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "XTPHookManager.h"
#include "XTPColorManager.h"
#include "XTPDrawHelpers.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define FALSE_EXIT 2
CXTPHookManagerHookAble::CXTPHookManagerHookAble()
{
m_bAutoDestroy = FALSE;
}
CXTPHookManagerHookAble::~CXTPHookManagerHookAble()
{
}
class CXTPHookManager::CHookSink : public CArray<CXTPHookManagerHookAble*, CXTPHookManagerHookAble*>
{
friend class CXTPHookManager;
public:
CHookSink(HWND hWnd);
~CHookSink();
public:
void UnsubclassWnd();
int Find(CXTPHookManagerHookAble* pItem)
{
for (int i = 0; i < GetSize(); i++)
{
if (pItem == GetAt(i))
return i;
}
return -1;
}
void RemoveHook(CXTPHookManagerHookAble* pHook)
{
int nIndex = Find(pHook);
if (nIndex != -1)
{
RemoveAt(nIndex);
if (pHook->m_bAutoDestroy)
delete pHook;
if (GetSize() == 0)
{
UnsubclassWnd();
XTPHookManager()->m_mapHooks.RemoveKey(m_hWnd);
delete this;
}
}
}
public:
BOOL OnHookMessage(HWND hWnd, UINT nMessage, WPARAM& wParam, LPARAM& lParam, LRESULT& lResult);
protected:
WNDPROC m_pOldWndProc;
HWND m_hWnd;
BOOL m_bUnicode;
BOOL m_bLastMessage;
#ifdef _AFXDLL
AFX_MODULE_STATE* m_pModuleState;
#endif
};
#if (_MSC_VER <= 1200) && !defined(_WIN64)
#define GetWindowLongPtrW GetWindowLongW
#define GetWindowLongPtrA GetWindowLongA
#define SetWindowLongPtrW SetWindowLongW
#define SetWindowLongPtrA SetWindowLongA
#endif
CXTPHookManager::CHookSink::CHookSink(HWND hWnd)
{
#ifdef _AFXDLL
m_pModuleState = 0;
#endif
m_bUnicode = IsWindowUnicode(hWnd);
m_hWnd = hWnd;
m_bLastMessage = FALSE;
if (m_bUnicode)
{
m_pOldWndProc = (WNDPROC)GetWindowLongPtrW(hWnd, GWLP_WNDPROC);
SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)CXTPHookManager::HookWndProc);
}
else
{
m_pOldWndProc = (WNDPROC)GetWindowLongPtrA(hWnd, GWLP_WNDPROC);
SetWindowLongPtrA(hWnd, GWLP_WNDPROC, (LONG_PTR)CXTPHookManager::HookWndProc);
}
}
UINT CXTPHookManager::m_nMsgSinkRemoved = RegisterWindowMessage(_T("WM_HOOKMANAGER_SINKREMOVED"));
void CXTPHookManager::CHookSink::UnsubclassWnd()
{
if (!m_bLastMessage)
{
if (::SendMessage(m_hWnd, CXTPHookManager::m_nMsgSinkRemoved, (WPARAM)(LONG_PTR)CXTPHookManager::HookWndProc, (LPARAM)(LONG_PTR)m_pOldWndProc))
return;
}
if (m_bUnicode)
SetWindowLongPtrW(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pOldWndProc);
else
SetWindowLongPtrA(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pOldWndProc);
}
CXTPHookManager::CHookSink::~CHookSink()
{
for (int i = (int)GetSize() - 1; i >= 0; i--)
{
CXTPHookManagerHookAble* pHookAble = GetAt(i);
if (pHookAble->m_bAutoDestroy)
{
delete pHookAble;
}
}
}
BOOL CXTPHookManager::CHookSink::OnHookMessage(HWND hWnd, UINT nMessage, WPARAM& wParam, LPARAM& lParam, LRESULT& lResult)
{
if (nMessage == CXTPHookManager::m_nMsgSinkRemoved && (LONG_PTR)wParam == (LONG_PTR)m_pOldWndProc)
{
m_pOldWndProc = (WNDPROC)lParam;
lResult = TRUE;
return TRUE;
}
int nCount = (int)GetSize();
for (int i = nCount - 1; i >= 0; i--)
{
int nResult = GetAt(i)->OnHookMessage(hWnd, nMessage, wParam, lParam, lResult);
if (nResult == TRUE)
return TRUE;
if (nResult == FALSE_EXIT)
return FALSE;
}
return FALSE;
}
CXTPHookManager::CXTPHookManager()
{
}
CXTPHookManager* AFX_CDECL XTPHookManager()
{
static CXTPHookManager s_managerInstance;
return &s_managerInstance;
}
CXTPHookManager::~CXTPHookManager()
{
RemoveAll();
}
LRESULT CXTPHookManager::Default(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
CHookSink* pSink = Lookup(hWnd);
ASSERT(pSink);
if (!pSink)
return 0;
WNDPROC wndProc = pSink->m_pOldWndProc;
LRESULT lResult = ::CallWindowProc(wndProc, hWnd, message, wParam, lParam);
return lResult;
}
LRESULT CXTPHookManager::Default(WPARAM wParam, LPARAM lParam)
{
MSG& curMsg = AfxGetThreadState()->m_lastSentMsg;
return Default(curMsg.hwnd, curMsg.message, wParam, lParam);
}
LRESULT CXTPHookManager::Default()
{
MSG& curMsg = AfxGetThreadState()->m_lastSentMsg;
return Default(curMsg.hwnd, curMsg.message, curMsg.wParam, curMsg.lParam);;
}
LRESULT CALLBACK CXTPHookManager::HookWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
MSG& curMsg = AfxGetThreadState()->m_lastSentMsg;
MSG oldMsg = curMsg;
curMsg.hwnd = hWnd;
curMsg.message = message;
curMsg.wParam = wParam;
curMsg.lParam = lParam;
// Get hook object for this window. Get from hook map
CHookSink* pSink = XTPHookManager()->Lookup(hWnd);
ASSERT(pSink);
if (!pSink)
return 0;
LRESULT lResult = 0;
WNDPROC wndProc = pSink->m_pOldWndProc;
{
SAFE_MANAGE_STATE(pSink->m_pModuleState);
// Window is being destroyed: unhook all hooks (for this window)
// and pass message to orginal window proc
if (message == WM_NCDESTROY)
{
XTPHookManager()->RemoveAll(hWnd, TRUE);
}
// pass to message hook
else
{
if (pSink->OnHookMessage(hWnd, message, wParam, lParam, lResult))
{
curMsg = oldMsg;
return lResult;
}
}
}
lResult = ::CallWindowProc(wndProc, hWnd, message, wParam, lParam);
curMsg = oldMsg;
return lResult;
}
void CXTPHookManager::SetHook(HWND hWnd, CXTPHookManagerHookAble* pHook)
{
CHookSink* pSink = Lookup(hWnd);
if (pSink)
{
if (pSink->Find(pHook) == -1)
{
pSink->Add(pHook);
}
}
else
{
pSink = new CHookSink(hWnd);
pSink->Add(pHook);
m_mapHooks[hWnd] = pSink;
}
#ifdef _AFXDLL
pSink->m_pModuleState = AfxGetModuleState();
#endif
}
void CXTPHookManager::RemoveAll()
{
HWND hWnd;
POSITION pos = m_mapHooks.GetStartPosition();
CHookSink* pSink;
while (pos)
{
m_mapHooks.GetNextAssoc(pos, hWnd, (void*&)pSink);
pSink->UnsubclassWnd();
delete pSink;
}
m_mapHooks.RemoveAll();
}
void CXTPHookManager::RemoveAll(HWND hWnd)
{
RemoveAll(hWnd, FALSE);
}
void CXTPHookManager::RemoveAll(HWND hWnd, BOOL bLastMessage)
{
CHookSink* pSink = Lookup(hWnd);
if (pSink)
{
pSink->m_bLastMessage = bLastMessage;
pSink->UnsubclassWnd();
m_mapHooks.RemoveKey(hWnd);
delete pSink;
}
}
void CXTPHookManager::RemoveAll(CXTPHookManagerHookAble* pHook)
{
ASSERT(pHook);
HWND hWnd;
CHookSink* pSink = NULL;
POSITION pos = m_mapHooks.GetStartPosition();
while (pos)
{
m_mapHooks.GetNextAssoc(pos, hWnd, (void*&)pSink);
pSink->RemoveHook(pHook);
}
}
CXTPHookManager::CHookSink* CXTPHookManager::Lookup(HWND hWnd)
{
CHookSink* pSink;
if (m_mapHooks.Lookup(hWnd, (void*&)pSink))
return pSink;
return NULL;
}
void CXTPHookManager::RemoveHook(HWND hWnd, CXTPHookManagerHookAble* pHook)
{
ASSERT(hWnd);
CHookSink* pSink = Lookup(hWnd);
if (pSink)
{
pSink->RemoveHook(pHook);
}
}
//////////////////////////////////////////////////////////////////////////
// CXTPShadowManager
class CXTPShadowManager::CShadowWnd : public CWnd, public CXTPHookManagerHookAble
{
public:
//-------------------------------------------------------------------------
// Summary:
// Constructs a CShadowWnd object.
//-------------------------------------------------------------------------
CShadowWnd(CXTPShadowManager* pShadowManager);
~CShadowWnd();
public:
BOOL Create(BOOL bHoriz, CRect rcWindow);
void LongShadow(CShadowList* pList);
BOOL ExcludeRect(CRect rcExclude);
private:
DECLARE_MESSAGE_MAP()
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnPaint();
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg LRESULT OnNcHitTest(CPoint point);
private:
virtual int OnHookMessage(HWND hWnd, UINT nMessage, WPARAM& wParam, LPARAM& lParam, LRESULT& lResult);
UINT Factor(int& nRed, int& nGreen, int& nBlue, double dFactor);
private:
BOOL m_bHoriz;
BOOL m_bExcluded;
CWnd* m_pShadowsOwner;
int m_nLevel;
BOOL m_bControlPopup;
CXTPShadowManager* m_pShadowsManager;
friend class CXTPShadowManager;
};
//===========================================================================
// Summary:
// Shadow list
//===========================================================================
class CXTPShadowManager::CShadowList : public CList<CShadowWnd*, CShadowWnd*>
{
public:
void AddShadow(CShadowWnd* pShadow)
{
pShadow->LongShadow(this);
AddTail(pShadow);
}
void RemoveShadow(CShadowWnd* pShadow)
{
POSITION pos = Find(pShadow);
ASSERT(pos);
RemoveAt(pos);
}
};
CXTPShadowManager::CXTPShadowManager()
{
m_pfnUpdateLayeredWindow = NULL;
HMODULE hLib = GetModuleHandle(_T("USER32"));
if (hLib)
{
m_pfnUpdateLayeredWindow = (LPFNUPDATELAYEREDWINDOW) GetProcAddress(hLib, "UpdateLayeredWindow");
}
m_bAlphaShadow = IsAlphaShadow();
m_nShadowOptions = 0;
m_clrShadowFactor = 0;
m_bUseSystemSaveBitsStyle = TRUE;
m_pShadows = new CShadowList();
}
CXTPShadowManager::~CXTPShadowManager()
{
ASSERT(m_pShadows->IsEmpty());
SAFE_DELETE(m_pShadows);
}
BOOL CXTPShadowManager::IsAlphaShadow()
{
#ifdef NOALPHASHADOW
return FALSE;
#endif
if (XTPColorManager()->IsLowResolution())
return FALSE;
return (m_pfnUpdateLayeredWindow != NULL);
}
#ifndef SPI_GETDROPSHADOW
#define SPI_GETDROPSHADOW 0x1024
#endif
void CXTPShadowManager::SetShadow(CWnd* pShadowOwner, const CRect& rcExclude, int nLevel)
{
if (!(GetShadowOptions() & xtpShadowOfficeAlpha))
{
if (!m_bAlphaShadow)
return;
BOOL bDropShadow = FALSE;
SystemParametersInfo(SPI_GETDROPSHADOW, 0, &bDropShadow, 0);
if (!bDropShadow)
return;
}
CXTPWindowRect rc(pShadowOwner);
CreateShadow(TRUE, rc, rcExclude, pShadowOwner, FALSE, nLevel);
CreateShadow(FALSE, rc, rcExclude, pShadowOwner, FALSE, nLevel);
HRGN hRgn = CreateRectRgn(0, 0, 0, 0);
if (pShadowOwner->GetWindowRgn(hRgn) == COMPLEXREGION)
{
CreateShadow(2, rc, rcExclude, pShadowOwner, FALSE, nLevel);
}
DeleteObject(hRgn);
}
void CXTPShadowManager::SetShadow(CRect rcWindow, CWnd* pShadowOwner)
{
if ((GetShadowOptions() & (xtpShadowOfficeAlpha | xtpShadowShowPopupControl)) ==
(xtpShadowOfficeAlpha | xtpShadowShowPopupControl))
{
CreateShadow(TRUE, rcWindow, CXTPEmptyRect(), pShadowOwner, TRUE, 0);
CreateShadow(FALSE, rcWindow, CXTPEmptyRect(), pShadowOwner, TRUE, 0);
}
}
POSITION CXTPShadowManager::GetHeadPosition(CWnd* pShadowOwner) const
{
POSITION pos = m_pShadows->GetHeadPosition();
while (pos)
{
CShadowWnd* pShadow = m_pShadows->GetAt(pos);
if (pShadow->m_pShadowsOwner == pShadowOwner)
return pos;
m_pShadows->GetNext(pos);
}
return NULL;
}
CWnd* CXTPShadowManager::GetNext(POSITION& pos) const
{
CShadowWnd* pShadowResult = m_pShadows->GetNext(pos);
while (pos)
{
CShadowWnd* pShadow = m_pShadows->GetAt(pos);
if (pShadow->m_pShadowsOwner == pShadowResult->m_pShadowsOwner)
break;
m_pShadows->GetNext(pos);
}
return pShadowResult;
}
void CXTPShadowManager::RemoveShadow(CWnd* pShadowOwner)
{
POSITION pos = m_pShadows->GetHeadPosition();
while (pos)
{
CShadowWnd* pShadow = m_pShadows->GetNext(pos);
if (pShadowOwner == pShadow->m_pShadowsOwner)
{
XTPHookManager()->RemoveHook(pShadow->m_pShadowsOwner->GetSafeHwnd(), pShadow);
DestroyShadow(pShadow);
}
}
}
void CXTPShadowManager::OffsetShadow(CWnd* pShadowOwner, CSize szOffset)
{
BOOL bLayoutRTL = pShadowOwner->GetExStyle() & WS_EX_LAYOUTRTL;
POSITION pos = m_pShadows->GetHeadPosition();
while (pos)
{
CShadowWnd* pShadow = m_pShadows->GetNext(pos);
if (pShadowOwner == pShadow->m_pShadowsOwner && pShadow->GetSafeHwnd() && !pShadow->m_bControlPopup)
{
if (pShadow->m_bExcluded)
{
pShadow->SetWindowRgn(NULL, FALSE);
pShadow->m_bExcluded = FALSE;
}
CXTPWindowRect rc(pShadow);
if (bLayoutRTL)
{
if (pShadow->m_bHoriz == 1)
{
pShadow->SetWindowPos(0, rc.left - szOffset.cx , rc.top + szOffset.cy,
rc.Width() + szOffset.cx, rc.Height(), SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
else if (pShadow->m_bHoriz == 2)
{
pShadow->SetWindowPos(0, rc.left, rc.top + szOffset.cy,
rc.Width(), rc.Height(), SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
else
{
pShadow->SetWindowPos(0, rc.left, rc.top,
rc.Width(), rc.Height() + szOffset.cy, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
}
else
{
if (pShadow->m_bHoriz == 1)
{
pShadow->SetWindowPos(0, rc.left, rc.top + szOffset.cy,
rc.Width() + szOffset.cx, rc.Height(), SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
else if (pShadow->m_bHoriz == 2)
{
pShadow->SetWindowPos(0, rc.left + szOffset.cx , rc.top + szOffset.cy,
rc.Width(), rc.Height(), SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
else
{
pShadow->SetWindowPos(0, rc.left + szOffset.cx, rc.top,
rc.Width(), rc.Height() + szOffset.cy, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
}
}
}
}
CXTPShadowManager::CShadowWnd* CXTPShadowManager::CreateShadow(BOOL bHoriz, CRect rc, CRect rcExclude, CWnd* pShadowOwner, BOOL bControlPopup, int nLevel)
{
CShadowWnd* pShadow = new CShadowWnd(this);
pShadow->m_pShadowsOwner = pShadowOwner;
pShadow->m_bControlPopup = bControlPopup;
pShadow->m_nLevel = nLevel;
pShadow->Create(bHoriz, rc);
m_pShadows->AddShadow(pShadow);
if (m_nShadowOptions & xtpShadowShowPopupControl)
{
pShadow->ExcludeRect(rcExclude);
}
POSITION pos = m_pShadows->GetHeadPosition();
while (pos)
{
CShadowWnd* pShadowPrev = m_pShadows->GetNext(pos);
if (pShadowPrev->m_pShadowsOwner && (bHoriz != 2 || pShadowPrev->m_pShadowsOwner != pShadowOwner) && pShadowPrev->m_nLevel == nLevel)
{
pShadow->ExcludeRect(CXTPWindowRect(pShadowPrev->m_pShadowsOwner));
}
}
pShadow->SetWindowPos(pShadowOwner->GetExStyle() & WS_EX_TOPMOST ? &CWnd::wndTopMost : &CWnd::wndTop,
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
XTPHookManager()->SetHook(pShadowOwner->m_hWnd, pShadow);
return pShadow;
}
void CXTPShadowManager::DestroyShadow(CShadowWnd* pWnd)
{
if (pWnd->GetSafeHwnd()) pWnd->ShowWindow(SW_HIDE);
pWnd->m_pShadowsOwner = 0;
m_pShadows->RemoveShadow(pWnd);
pWnd->DestroyWindow();
delete pWnd;
}
CXTPShadowManager::CShadowWnd::CShadowWnd(CXTPShadowManager* pShadowManager)
{
m_pShadowsOwner = 0;
m_bHoriz = FALSE;
m_bExcluded = FALSE;
m_nLevel = 0;
m_pShadowsManager = pShadowManager;
CMDTARGET_ADDREF(m_pShadowsManager);
}
CXTPShadowManager::CShadowWnd::~CShadowWnd()
{
CMDTARGET_RELEASE(m_pShadowsManager);
}
int CXTPShadowManager::CShadowWnd::OnHookMessage(HWND hWnd, UINT nMessage, WPARAM& wParam, LPARAM& /*lParam*/, LRESULT& /*lResult*/)
{
if (nMessage == WM_SHOWWINDOW && wParam == FALSE)
{
ShowWindow(SW_HIDE);
}
if (nMessage == WM_SHOWWINDOW && wParam == TRUE)
{
ShowWindow(SW_SHOWNA);
}
if (nMessage == WM_DESTROY)
{
XTPHookManager()->RemoveHook(hWnd, this);
m_pShadowsManager->DestroyShadow(this);
}
return 0;
}
BOOL CXTPShadowManager::CShadowWnd::Create(BOOL bHoriz, CRect rcWindow)
{
CWnd* pSite = m_pShadowsOwner->GetParent();
ASSERT(pSite);
if (m_hWnd == 0)
{
int nFlags = WS_EX_TOOLWINDOW;
if (m_pShadowsManager->m_bAlphaShadow) nFlags |= 0x80000;
UINT nClassStyle = m_pShadowsManager->m_bUseSystemSaveBitsStyle ? CS_SAVEBITS | CS_OWNDC : 0;
CString strClass = ::AfxRegisterWndClass(nClassStyle, AfxGetApp()->LoadStandardCursor(IDC_ARROW));
if (!CreateEx(nFlags, strClass, 0, WS_POPUP, CXTPEmptyRect(), pSite, 0))
return FALSE;
}
SetWindowRgn(NULL, FALSE);
int nWidth = m_pShadowsManager->m_bAlphaShadow ? 4 : 2;
m_bHoriz = bHoriz;
CRect rcShadow;
if (bHoriz == 2)
rcShadow.SetRect(rcWindow.right - 1, rcWindow.bottom - 1, rcWindow.right, rcWindow.bottom);
else if (bHoriz == 1)
rcShadow.SetRect(rcWindow.left + nWidth, rcWindow.bottom, rcWindow.right + nWidth, rcWindow.bottom + nWidth);
else
rcShadow.SetRect(rcWindow.right, rcWindow.top + nWidth, rcWindow.right + nWidth, rcWindow.bottom);
MoveWindow(rcShadow, FALSE);
return TRUE;
}
BEGIN_MESSAGE_MAP(CXTPShadowManager::CShadowWnd, CWnd)
{ WM_ERASEBKGND, 0, 0, 0, AfxSig_bD, (AFX_PMSG)(AFX_PMSGW) (static_cast< BOOL (AFX_MSG_CALL CWnd::*)(CDC*) > (CXTPShadowManager::CShadowWnd::OnEraseBkgnd)) },
{ WM_PAINT, 0, 0, 0, AfxSig_vv, (AFX_PMSG)(AFX_PMSGW) (static_cast< void (AFX_MSG_CALL CWnd::*)(void) > (CXTPShadowManager::CShadowWnd::OnPaint)) },
{ WM_SIZE, 0, 0, 0, AfxSig_vwii, (AFX_PMSG)(AFX_PMSGW) (static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, int, int) > (CXTPShadowManager::CShadowWnd::OnSize)) },
{ WM_NCHITTEST, 0, 0, 0, AfxSig_wp, (AFX_PMSG)(AFX_PMSGW) (static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(CPoint) > (CXTPShadowManager::CShadowWnd::OnNcHitTest)) },
END_MESSAGE_MAP()
LRESULT CXTPShadowManager::CShadowWnd::OnNcHitTest(CPoint /*point*/)
{
return (LRESULT)HTTRANSPARENT;
}
void CXTPShadowManager::CShadowWnd::OnPaint()
{
CPaintDC dc(this);
CXTPClientRect rcClient(this);
dc.FillSolidRect(rcClient, m_pShadowsManager->m_bAlphaShadow ? 0 : GetXtremeColor(COLOR_3DSHADOW));
}
BOOL CXTPShadowManager::CShadowWnd::OnEraseBkgnd(CDC* /*pDC*/)
{
return TRUE;
}
BOOL CXTPShadowManager::CShadowWnd::ExcludeRect(CRect rcExclude)
{
CXTPWindowRect rcWindow(this);
CRect rcIntersect;
if (rcIntersect.IntersectRect(rcWindow, rcExclude))
{
CXTPClientRect rcClient(this);
HRGN hrgnClip = ::CreateRectRgnIndirect(&rcClient);
rcIntersect.OffsetRect(-rcWindow.TopLeft());
HRGN hrgnIntersect = ::CreateRectRgnIndirect(&rcIntersect);
CombineRgn(hrgnClip, hrgnClip, hrgnIntersect, RGN_DIFF);
DeleteObject(hrgnIntersect);
if (!SetWindowRgn(hrgnClip, FALSE))
DeleteObject(hrgnClip);
m_bExcluded = TRUE;
}
return TRUE;
}
void CXTPShadowManager::CShadowWnd::LongShadow(CShadowList* pList)
{
CXTPWindowRect rcWindow(this);
POSITION pos = pList->GetHeadPosition();
while (pos)
{
CShadowWnd* pWnd = pList->GetNext(pos);
if (m_bHoriz == !pWnd->m_bHoriz)
{
CXTPWindowRect rc(pWnd);
if (m_bHoriz == FALSE)
{
if (rcWindow.top == rc.bottom -1 && rcWindow.right < rc.right && rcWindow.right > rc.left)
{
rcWindow.top -= 2 * rc.Height();
MoveWindow(rcWindow, FALSE);
}
}
else
{
if (rcWindow.left == rc.right - 1 && rcWindow.top > rc.top && rcWindow.bottom < rc.bottom)
{
rcWindow.left -= 2 * rc.Width() + 1;
MoveWindow(rcWindow, FALSE);
}
}
}
}
}
UINT CXTPShadowManager::CShadowWnd::Factor(int& nRed, int& nGreen, int& nBlue, double dFactor)
{
return (int(nRed * dFactor) << 16) + (int(nGreen * dFactor) << 8) + (int(nBlue * dFactor));
}
void CXTPShadowManager::CShadowWnd::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
if (!cx || !cy || !m_pShadowsManager->m_bAlphaShadow ||
!m_pShadowsManager->m_pfnUpdateLayeredWindow || !m_pShadowsOwner)
return;
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255;
bf.AlphaFormat = 0x01;
POINT pt = {0, 0};
int x, y;
HBITMAP hbitmap;
BITMAPINFO bmi;
CClientDC cDC(this);
CDC dc;
dc.CreateCompatibleDC(&cDC);
// zero the memory for the bitmap info
ZeroMemory(&bmi, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = cx;
bmi.bmiHeader.biHeight = cy;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32; // four 8-bit components
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = cx * cy * 4;
UINT* pvBits = NULL;
// create our DIB section and select the bitmap into the dc
hbitmap = CreateDIBSection(cDC, &bmi, DIB_RGB_COLORS, (void**)&pvBits, NULL, 0x0);
if (pvBits == NULL || hbitmap == NULL)
return;
COLORREF clrFactor = m_pShadowsManager->m_clrShadowFactor;
int nRed = GetRValue(clrFactor), nGreen = GetGValue(clrFactor), nBlue = GetBValue(clrFactor);
int nFactor = m_pShadowsManager->m_nShadowOptions & xtpShadowOfficeAlpha ? 1 : 2;
if (m_bHoriz == 2)
{
pvBits[0] = (UINT) 4 * 0x0F000000 * nFactor
+ Factor(nRed, nGreen, nBlue, 1);
}
else if (m_bHoriz == 0)
{
ASSERT(cx == 4);
for (x = 0; x < 4; x++) for (y = 0; y < 4; y++)
{
pvBits[3 - x + (cy - 1 - y) * cx] = (UINT) 3 * (x + 1) * (y + 1) * 0x1000000 * nFactor
+ Factor(nRed, nGreen, nBlue, double((x + 1) * (y + 1))/20);
}
for (x = 3; x >= 0; x--)
{
UINT nColor = 0x0F000000 * nFactor * (4 - x) + Factor(nRed, nGreen, nBlue, double(4 - x)/4);
for (y = 0; y < cy - 4; y++) pvBits[x + y * cx] = nColor;
}
}
else
{
ASSERT(cy == 4);
for (x = 0; x < 4; x++) for (y = 0; y < 4; y++)
{
pvBits[x + y * cx] = (UINT) 3 * (x + 1) * (y + 1) * 0x1000000 * nFactor
+ Factor(nRed, nGreen, nBlue, double((x + 1) * (y + 1))/20);
}
for (y = 0; y < 4; y++)
{
UINT nColor = 0x0F000000 * nFactor * (y + 1) + Factor(nRed, nGreen, nBlue, double(y + 1)/4);
for (x = 4; x < cx - 4; x++) pvBits[x + y * cx] = nColor;
}
for (x = 0; x < 4; x++) for (y = 0; y < 4; y++)
{
pvBits[cx - 1 - x + y * cx] = (UINT)3 * (x + 1) * (y + 1) * 0x1000000 * nFactor
+ Factor(nRed, nGreen, nBlue, double((x + 1) * (y + 1))/20);
}
}
HBITMAP hOld = (HBITMAP)SelectObject(dc, hbitmap);
SIZE sz = {cx, cy};
m_pShadowsManager->m_pfnUpdateLayeredWindow((HWND)GetSafeHwnd(), (HDC)0, 0, &sz, dc.GetSafeHdc(), &pt, 0, &bf, 0x02);
SelectObject(dc, hOld);
DeleteObject(hbitmap);
dc.DeleteDC();
}