⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skinmenu.cpp

📁 WMI接口测试Demo程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// SkinMenu.cpp: implementation of the CSkinMenu class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "SkinMenu.h"
#include "SkinMenuMgr.h"
#include "wclassdefines.h"
#include "winclasses.h"
#include "skinglobals.h"
#include "skinbase.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

ISkinMenuRender* CSkinMenu::s_pRenderer = NULL;

enum { REDRAWALL = -2 };

#ifndef SPI_GETMENUANIMATION
#define SPI_GETMENUANIMATION  0x1002
#endif

#ifndef SPI_GETMENUFADE
#define SPI_GETMENUFADE  0x1012
#endif

//////////////////////////////////////////////////////////////////////

struct colorMapping
{
	int nSrcColor;
	int nDestColor;
};

static colorMapping colors[] = 
{
//	{ COLOR_HIGHLIGHT, COLOR_HIGHLIGHT },
	{ COLOR_WINDOWTEXT, COLOR_WINDOWTEXT },
	{ COLOR_GRAYTEXT, COLOR_MENU },
	{ COLOR_HIGHLIGHTTEXT, COLOR_HIGHLIGHTTEXT },
	{ COLOR_3DHILIGHT, COLOR_MENU },
//	{ COLOR_3DDKSHADOW, COLOR_MENU },
	{ COLOR_3DSHADOW, COLOR_3DSHADOW },
	{ COLOR_3DFACE, COLOR_MENU },
	{ COLOR_MENU, COLOR_MENU },

};

CSkinMenu::CSkinMenu(CSkinGlobals* pGlobals, DWORD dwStyle, int nSBWidth) 
	: m_pGlobals(pGlobals), m_nSidebarWidth(nSBWidth), m_dwStyle(dwStyle)
{
	m_nSelIndex = REDRAWALL; // this ensures a full repaint when we first show
	m_hContextWnd = NULL;
	m_hMenu = NULL;

	// fix for animated menus
	m_bFirstRedraw = TRUE;

	m_bAnimatedMenus = FALSE;
	SystemParametersInfo(SPI_GETMENUANIMATION, 0, &m_bAnimatedMenus, 0);
}

CSkinMenu::~CSkinMenu()
{
}

BOOL CSkinMenu::IsMenuWnd(HWND hWnd)
{
	return CWinClasses::IsClass(hWnd, WC_MENU);
}

BOOL CSkinMenu::AttachWindow(HWND hWnd) 
{ 
	if (!IsMenuWnd(hWnd))
		return FALSE;

	if (HookWindow(hWnd))
	{
//		Invalidate();
//		PostMessage(WM_NCPAINT);

		return TRUE;
	}
	
	// else
	return FALSE;
}

BOOL CSkinMenu::DetachWindow() 
{ 
	return HookWindow((HWND)NULL); 
}

LRESULT CSkinMenu::WindowProc(CWnd* pRealWnd, UINT msg, WPARAM wp, LPARAM lp)
{
	ASSERT_VALID(pRealWnd);

	UINT uRes = 0;
	LRESULT lr = 0;

	int nOS = CSkinBase::GetOS();

	switch (msg) 
	{
	case WM_NCPAINT: 
		// the very first WM_NCPAINT appears to be responsible for
		// doing any menu animation. since our std OnNcPaint does not
		// deal with animation we must leave it to the default handler.
		// fortunately, the default handler calls WM_PRINT to implement
		// the animation.
		if (!m_bAnimatedMenus || !m_bFirstRedraw)
		{
			CWindowDC dc(pRealWnd);
			OnNcPaint(&dc);
			return 0;
		}
		break; 
		
	case WM_PRINT: 
		if (nOS != SBOS_95 && nOS != SBOS_NT4)
		{
			lr = CSubclassWnd::WindowProc(pRealWnd, msg, wp, lp);
			OnNcPaint(CDC::FromHandle((HDC)wp));
			return lr;
		}
		break; 
		
	case WM_PRINTCLIENT:
		if (nOS != SBOS_95 && nOS != SBOS_NT4)
		{
			OnPrintClient(CDC::FromHandle((HDC)wp), lp);
			return 0;
		}
		break; 
		
	case WM_PAINT:
		if (nOS != SBOS_95 && nOS != SBOS_NT4)
		{
			CPaintDC dc(pRealWnd);
//			OnPaint(&dc);
			SendMessage(WM_PRINTCLIENT, (WPARAM)(HDC)dc, PRF_CLIENT | PRF_CHECKVISIBLE);
			return 0;
		}
		break; 
		
		// handle keyboard navigation
	case WM_KEYDOWN:
		if (nOS != SBOS_95 && nOS != SBOS_NT4)
		{
			switch (wp)
			{
			case VK_UP:
			case VK_DOWN:
			case VK_RIGHT:
				// left is much trickier because if the currently selected item
				// has a popup menu then left will close that submenu, and if
				// we prevent the default redrawing then the submenu is not correctly
				// removed from the screen.
				// so we must always do the default drawing and follow it up with our own.
			case VK_LEFT:
				if (!m_hMenu)
				{
					if (wp != VK_LEFT) 
						SetRedraw(FALSE);

					lr = Default();

					if (wp != VK_LEFT) 
						SetRedraw(TRUE);

//					TRACE ("Invalidating entire menu in response to a cursor keypress\n");

					m_nSelIndex = -1; // reset current selection because its too risky to 
										// try to figure it out for ourselves
					Invalidate(FALSE);
					UpdateWindow(*this);

					m_bFirstRedraw = FALSE;
				}
				else // have menu handle
				{
					int nPrevSel = GetCurSel();

					if (wp != VK_LEFT) 
						SetRedraw(FALSE);

					lr = Default();

					if (wp != VK_LEFT) 
						SetRedraw(TRUE);

					// if we have the handle of the menu then 
					// we can do a selective redraw else we must redraw all
					m_nSelIndex = GetCurSel();

					if (m_nSelIndex != nPrevSel)
					{
						CRect rInvalid;
						GetInvalidRect(m_nSelIndex, nPrevSel, rInvalid);

//						TRACE ("Invalidating menu items %d & %d in response to a cursor keypress\n", m_nSelIndex, nPrevSel);

						InvalidateRect(*this, rInvalid, FALSE);
						UpdateWindow(*this);

						m_bFirstRedraw = FALSE;
					}
				}
				return lr;
			}
		}
		break;

	case 0x1e5: 
		if (nOS != SBOS_95 && nOS != SBOS_NT4)
		{
			if (m_nSelIndex != (int)wp)
			{
				// attempt to do a partial redraw where possible
				// this needs more thought
				CRect rInvalid;
				
				if (m_hMenu)
					GetInvalidRect((int)wp, m_nSelIndex, rInvalid);
				else
					GetClientRect(rInvalid);
				
				// prevent redrawing during default message processing
				// because otherwise the item is redrawn oven ours.
				SetRedraw(FALSE);
				lr = Default();
				SetRedraw(TRUE);
				
				m_nSelIndex = (int)wp;
				
				pRealWnd->InvalidateRect(rInvalid, FALSE);

				if (!m_bFirstRedraw)
					pRealWnd->UpdateWindow();
			}

			// special fix for animated menus
			if (m_bAnimatedMenus && m_bFirstRedraw)
			{
				CWindowDC dc(pRealWnd);
				OnNcPaint(&dc);
			}

			m_bFirstRedraw = FALSE;
			return lr;
		}
		break;

	case WM_NCCALCSIZE:
		if (Sidebar())
		{
			lr = Default();
			
			LPRECT pRect = wp ? &((LPNCCALCSIZE_PARAMS)lp)->rgrc[0] : (LPRECT)lp;
			pRect->left += m_nSidebarWidth;
			
			return lr;
		}
		break;
		
	case WM_WINDOWPOSCHANGING:
		{
			WINDOWPOS* pWP = (WINDOWPOS*)lp;
			
			// adjust width for sidebar
			if (Sidebar() && !(pWP->flags & SWP_NOSIZE))
				pWP->cx += m_nSidebarWidth;

			// if we have a parent menu we may need to adjust our
			// pos to avoid client repainting issues
			if (m_pParentMenu && !(pWP->flags & SWP_NOMOVE))
			{
				// if we are on the right side of our parent
				// then we need to adjust ourselves to avoid the client rect
				CRect rParentWindow;
				::GetWindowRect(*m_pParentMenu, rParentWindow);

				if (pWP->x > rParentWindow.left) // right
				{
					CRect rParentClient;
					::GetClientRect(*m_pParentMenu, rParentClient);

					m_pParentMenu->GetHookedWnd()->ClientToScreen(rParentClient);

					pWP->x = rParentClient.right;
				}
			}
		}
		break;
		
	case WM_ERASEBKGND: 
		if (nOS != SBOS_95 && nOS != SBOS_NT4)
			return TRUE; 
		break;
		
	default:
		break;
	}

	// We don't handle it: pass along
	return CSubclassWnd::WindowProc(pRealWnd, msg, wp, lp);
}

CDC* CSkinMenu::ReplaceSystemColors(CDC* pDCSrc, CDC* pDCDest, LPRECT pRect, LPRECT pClip)
{
	int nOS = CSkinBase::GetOS();

	if (nOS == SBOS_95 || nOS == SBOS_NT4)
		return pDCSrc;

	// replace the system colors with skin colors
	CMap<COLORREF, COLORREF, int, int&> mapColors;

	// 1. replace the actual background color with COLOR_MENU
	const COLORREF COLORMENU = GetColor(COLOR_MENU);

	COLORREF crSrc, crDest = COLORMENU;

	if (m_nSelIndex != 0)
		crSrc = pDCSrc->GetPixel(pRect->right, pRect->top);
	else
		crSrc = pDCSrc->GetPixel(pRect->right, pRect->bottom);

	// see if user wants to render bkgnd
	if (crSrc != -1)
	{
		if (s_pRenderer && s_pRenderer->DrawMenuClientBkgnd(pDCDest, pRect, pClip))
		{
			// transparent blt
			CSkinBase::BitBlt(pDCDest, pRect->left, pRect->top, 
						pRect->right - pRect->left, 
						pRect->bottom - pRect->top, pDCSrc, 0, 0, SRCCOPY, crSrc);

			// swap dest and src
			SwapDCs(pDCSrc, pDCDest);
		}
		// else simple color replacement
		else if (ReplaceColor(pDCSrc, crSrc, pDCDest, crDest, pRect, pClip))
		{		
			// swap dest and src
			SwapDCs(pDCSrc, pDCDest);
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -