253 lines
6.1 KiB
C++
253 lines
6.1 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;
|
|
}
|