252 lines
13 KiB
C++
252 lines
13 KiB
C++
// OXShdWnd.cpp : implementation file
|
||
//
|
||
|
||
#include "stdafx.h"
|
||
#include "OXShdWnd.h"
|
||
|
||
#ifdef _DEBUG
|
||
#define new DEBUG_NEW
|
||
#undef THIS_FILE
|
||
static char THIS_FILE[] = __FILE__;
|
||
#endif
|
||
|
||
|
||
const int m_giFirst = 5;
|
||
const int m_giSecond = 5;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// COXShdWnd
|
||
|
||
COXShdWnd::COXShdWnd()
|
||
{
|
||
m_pCastingWindow = NULL;
|
||
}
|
||
|
||
COXShdWnd::~COXShdWnd()
|
||
{
|
||
}
|
||
|
||
|
||
BEGIN_MESSAGE_MAP(COXShdWnd, CWnd)
|
||
//{{AFX_MSG_MAP(COXShdWnd)
|
||
ON_WM_WINDOWPOSCHANGED()
|
||
ON_WM_ERASEBKGND()
|
||
//}}AFX_MSG_MAP
|
||
END_MESSAGE_MAP()
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// COXShdWnd message handlers
|
||
|
||
//DEL void COXShdWnd::OnPaint()
|
||
//DEL {
|
||
//DEL CPaintDC dc(this); // device context for painting
|
||
//DEL
|
||
//DEL CRect rect;
|
||
//DEL GetWindowRect(rect);
|
||
//DEL
|
||
//DEL DrawShadow(dc.m_hDC, rect, NULL);
|
||
//DEL }
|
||
|
||
COLORREF COXShdWnd::DarkenColor(long lScale, COLORREF lColor)
|
||
{
|
||
long R = MulDiv(GetRValue(lColor), (255 - lScale), 255);
|
||
long G = MulDiv(GetGValue(lColor), (255 - lScale), 255);
|
||
long B = MulDiv(GetBValue(lColor), (255 - lScale), 255);
|
||
|
||
return RGB(R, G, B);
|
||
}
|
||
|
||
// Wrapper function for ::GetPixel(...) that facilitates the shadow buffering
|
||
COLORREF COXShdWnd::GetShadowPixel(HDC hDC, int iXPos, int iYPos, bool bUseSavedShadow)
|
||
{
|
||
if (bUseSavedShadow)
|
||
return 0; // we don't need this pixel
|
||
|
||
return ::GetPixel(hDC, iXPos, iYPos);
|
||
};
|
||
|
||
// Wrapper function for ::SetPixelV(...) that facilitates the shadow buffering
|
||
void COXShdWnd::SetShadowPixel(HDC hDC, int iXPos, int iYPos, COLORREF clr, bool bSaveShadow, bool bUseSavedShadow, OXSHADOWARRAY* pShadowArray, int& iIndex)
|
||
{
|
||
if (bUseSavedShadow)
|
||
::SetPixelV(hDC, iXPos, iYPos, pShadowArray->GetAt(iIndex++));
|
||
else
|
||
::SetPixelV(hDC, iXPos, iYPos, clr);
|
||
|
||
if (bSaveShadow)
|
||
pShadowArray->Add(clr);
|
||
|
||
// AddPixelToMap(iXPos, iYPos, clr);
|
||
};
|
||
|
||
// Draws a menu shadow for the given rectangle
|
||
void COXShdWnd::DrawShadow(HDC hDC, LPRECT lpRect, OXSHADOWARRAY* pShadowArray)
|
||
{
|
||
|
||
int iArrayIndex = 0;
|
||
bool bSaveShadow, bUseSavedShadow;
|
||
if (pShadowArray == NULL)
|
||
{
|
||
// We don't need to use the shadow array
|
||
bSaveShadow = false;
|
||
bUseSavedShadow = false;
|
||
}
|
||
else if (pShadowArray->GetSize() == 0)
|
||
{
|
||
// Save the shadow in the array
|
||
bSaveShadow = true;
|
||
bUseSavedShadow = false;
|
||
}
|
||
else
|
||
{
|
||
// Use the shadow from the array
|
||
bSaveShadow = false;
|
||
bUseSavedShadow = true;
|
||
}
|
||
|
||
CRect rectWindow(lpRect);
|
||
|
||
// Draw the shadow - get the pixels from the desktop, darken them
|
||
// and place them on the popup window
|
||
HDC hDesktopDC = ::GetWindowDC(::GetDesktopWindow());
|
||
|
||
// copy desktop to mem DC and work with that for Get/Set pixel (Vista bug)
|
||
CDC* pDC = CDC::FromHandle(hDesktopDC);
|
||
|
||
CDC dcMem;
|
||
dcMem.CreateCompatibleDC(pDC);
|
||
CBitmap bitmap;
|
||
bitmap.CreateCompatibleBitmap(pDC, rectWindow.Width(), rectWindow.Height());
|
||
CBitmap *pOldBitmap = dcMem.SelectObject(&bitmap);
|
||
|
||
// working with a mem bitmap at 0,0 for GetPixel
|
||
dcMem.BitBlt(0,0, rectWindow.Width(), rectWindow.Height(), pDC, rectWindow.left, rectWindow.top, SRCCOPY);
|
||
|
||
int x, y;
|
||
CPoint pt;
|
||
COLORREF clr;
|
||
|
||
int iLeft = 4;
|
||
int iTop = 4;
|
||
int iRight = rectWindow.Width();
|
||
int iBottom = rectWindow.Height();
|
||
|
||
// Right shadow
|
||
for (x = 1; x <= 4; x++)
|
||
{
|
||
// Copy the top right pixels
|
||
for (y = 1; y <= 4; y++)
|
||
{
|
||
pt.x = iRight - x;
|
||
pt.y = iTop + y - 4 - 1;
|
||
clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
|
||
SetShadowPixel(hDC, pt.x, pt.y, clr, bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
|
||
}
|
||
|
||
// Top right corner
|
||
for (y = 4; y >= 1; y--)
|
||
{
|
||
pt.x = iRight - x;
|
||
pt.y = iTop + y - 1;
|
||
clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
|
||
SetShadowPixel(hDC, pt.x, pt.y, DarkenColor(3 * x * y, clr), bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
|
||
}
|
||
|
||
// Vertical line
|
||
for (y = iTop + 4; y <= iBottom - 4 - 1; y++)
|
||
{
|
||
pt.x = iRight - x;
|
||
pt.y = y;
|
||
clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
|
||
SetShadowPixel(hDC, pt.x, pt.y, DarkenColor(15 * x, clr), bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
|
||
}
|
||
|
||
// Bottom right corner
|
||
for (y = 1; y <= 4; y++)
|
||
{
|
||
pt.x = iRight - x;
|
||
pt.y = iBottom - y;
|
||
clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
|
||
SetShadowPixel(hDC, pt.x, pt.y, DarkenColor(3 * x * y, clr), bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
|
||
}
|
||
}
|
||
|
||
// Bottom shadow
|
||
for (y = 1; y <= 4; y++)
|
||
{
|
||
// Copy the bottom left pixels
|
||
for (x = 1; x <= 4; x++)
|
||
{
|
||
pt.x = iLeft - x;
|
||
pt.y = iBottom - y;
|
||
clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
|
||
SetShadowPixel(hDC, pt.x, pt.y, clr, bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
|
||
}
|
||
|
||
// Bottom left corner
|
||
for (x = 1; x <= 4; x++)
|
||
{
|
||
pt.x = iLeft - x + 4;
|
||
pt.y = iBottom - y;
|
||
clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
|
||
SetShadowPixel(hDC, pt.x, pt.y, DarkenColor(3 * (5 - x) * y, clr), bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
|
||
}
|
||
|
||
// Horizontal line
|
||
for (x = iLeft + 4; x <= iRight - 5; x++)
|
||
{
|
||
pt.x = x;
|
||
pt.y = iBottom - y;
|
||
clr = GetShadowPixel(dcMem.m_hDC, pt.x, pt.y, bUseSavedShadow);
|
||
SetShadowPixel(hDC, pt.x, pt.y, DarkenColor(15 * y, clr), bSaveShadow, bUseSavedShadow, pShadowArray, iArrayIndex);
|
||
}
|
||
}
|
||
// done with bitmap here
|
||
dcMem.SelectObject(pOldBitmap);
|
||
|
||
|
||
::ReleaseDC(0, hDesktopDC);
|
||
|
||
|
||
}
|
||
|
||
void COXShdWnd::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
|
||
{
|
||
CWnd::OnWindowPosChanged(lpwndpos);
|
||
|
||
// TODO: Add your message handler code here
|
||
//Invalidate();
|
||
|
||
|
||
}
|
||
|
||
BOOL COXShdWnd::OnEraseBkgnd(CDC* pDC)
|
||
{
|
||
// handle pending WM_PAINT messages
|
||
MSG msg;
|
||
while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
|
||
{
|
||
// if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT))
|
||
// return FALSE;
|
||
ASSERT(msg.message == WM_PAINT);
|
||
DispatchMessage(&msg);
|
||
}
|
||
|
||
CRect rect;
|
||
GetWindowRect(rect);
|
||
|
||
DrawShadow(pDC->m_hDC, rect, NULL);
|
||
|
||
// if (m_pCastingWindow != NULL)
|
||
// ::SetWindowPos(m_hWnd, m_pCastingWindow->m_hWnd, 0, 0, 0, 0,
|
||
// SWP_NOSENDCHANGING | SWP_NOMOVE | SWP_NOSIZE);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
void COXShdWnd::SetCastingWindow(CWnd* pWnd)
|
||
{
|
||
m_pCastingWindow = pWnd;
|
||
}
|