// 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 { 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 { 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(); }