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

📄 coolmenu.cpp

📁 (VC)又一个酒店管理系统, (VC)又一个酒店管理系统,(VC)又一个酒店管理系统
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*########################################################################
	Filename: 	coolmenu.cpp
	----------------------------------------------------
	Remarks:	...
	----------------------------------------------------
	
  ########################################################################*/

#include "stdafx.h"
#include "CoolMenu.h"

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

const TCHAR CoolMenu_oldProc[] = _T("CoolMenu_oldProc");

/*########################################################################
			  ------------------------------------------------
								Cool API 函数
			  ------------------------------------------------
  ########################################################################*/

HMODULE g_hUserDll = NULL;
#define WS_EX_LAYERED	0x00080000 //此扩展属性使窗口透明.
#define LWA_ALPHA		0x00000002

/*========================================================================
	功能:			创建相应的图像列表所需的图像
	-------------------------------------------------------------
	hbitmap:		原始位图句柄
	crBackColor:	背景色
	nstyle:			要创建的图像的风格,它们为下列值之一:
	----------------------------------------------------
		-	0:		创建禁止图像列表图像
		-	1:		创建正常图像列表图像
		-	2:		创建热图像列表图像
==========================================================================*/
HBITMAP CCoolMenu::CreateImage(HBITMAP hbitmap, int nstyle, BOOL bAlpha, COLORREF crBackColor, COLORREF crMarkColor)
{
	HBITMAP RetBmp = NULL;
    if (hbitmap == NULL)
    {  
		return NULL;
	}

	//源位图DC------------------------------------
    HDC BufferDC = CreateCompatibleDC(NULL);      
    if (BufferDC == NULL)
    {
		return NULL;
	}
    SelectObject(BufferDC, hbitmap);

	//目标DC--------------------------------------
    HDC DirectDC = CreateCompatibleDC(NULL);      
    if (DirectDC == NULL)
    {
		  DeleteDC(BufferDC);
		  return NULL;
	}

    // 获取源位图大小----------------------------
    BITMAP bm;
    GetObject(hbitmap, sizeof(bm), &bm);

	// 初始化BITMAPINFO信息----------------------
    BITMAPINFO bitmapinfo; 
    ZeroMemory(&bitmapinfo, sizeof(BITMAPINFO));
    bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bitmapinfo.bmiHeader.biWidth = bm.bmWidth;
    bitmapinfo.bmiHeader.biHeight = bm.bmHeight;
    bitmapinfo.bmiHeader.biPlanes = 1;
    bitmapinfo.bmiHeader.biBitCount = 32;
	
	//指向像素区指针--------
	BYTE *ptPixels;    
    HBITMAP DirectBitmap = CreateDIBSection(DirectDC, (BITMAPINFO*)&bitmapinfo, 
                                  DIB_RGB_COLORS, (void**)&ptPixels, NULL, 0);
	
	//背景颜色--------------
	BYTE	oldRed   = GetRValue(crBackColor);
	BYTE	oldGreen = GetGValue(crBackColor);
	BYTE	oldBlue  = GetBValue(crBackColor);

	//透明色----------------
	BYTE	markRed   = GetRValue(crMarkColor);
	BYTE	markGreen = GetGValue(crMarkColor);
	BYTE	markBlue  = GetBValue(crMarkColor);

	BYTE	temp = 0;

    if (DirectBitmap != NULL)
    {
        HGDIOBJ oldObject = SelectObject(DirectDC, DirectBitmap);
        BitBlt(DirectDC, 0, 0, bm.bmWidth, bm.bmHeight, BufferDC, 0, 0, SRCCOPY);

		register int nbitcount = (bm.bmWidth * bm.bmHeight * 4);
        for (register int i = 0; i < nbitcount;  i += 4)
        {
			//透明区(alpha == 0)----------------------------------
			if (	( bAlpha && ptPixels[i + 3] == 0) 
				||  (!bAlpha && ptPixels[i + 2] == markRed	//red
							   && ptPixels[i + 1] == markGreen	//green
							   && ptPixels[i + 0] == markBlue	//blue
					)
			   ) 
			{
				ptPixels[i + 2] = 255;	//red
				ptPixels[i + 1] = 0;	//green
				ptPixels[i + 0] = 255;	//blue
			}
			else 
			{
				//灰度化位图--------------------------------------
				if (nstyle == 0 )
				{
					temp = (BYTE)(ptPixels[i + 2] * 0.299 + ptPixels[i + 1] * 0.587 + ptPixels[i] * 0.114);
					temp = (BYTE)(255 - (255 - temp) * 0.8); 
					ptPixels[i + 2] = ptPixels[i + 1] = ptPixels[i] = temp;
				}

				//淡化位图----------------------------------------
				else if (nstyle == 2)
				{
					ptPixels[i + 2] = (BYTE)(255 - (255 - ptPixels[i + 2]) * 0.9); 
					ptPixels[i + 1] = (BYTE)(255 - (255 - ptPixels[i + 1]) * 0.9); 
					ptPixels[i    ] = (BYTE)(255 - (255 - ptPixels[i + 0]) * 0.9); 
				}

				//Alpha混合--------------------------------------
				if (bAlpha)
				{
					ptPixels[i + 2] = (oldRed * (255 - ptPixels[i + 3]) + ptPixels[i + 2] * ptPixels[i + 3]) / 255; // Alpha取值范围从0到255
					ptPixels[i + 1] = (oldGreen * (255 - ptPixels[i + 3]) + ptPixels[i + 1] * ptPixels[i + 3]) / 255; // Alpha取值范围从0到255
					ptPixels[i    ] = (oldBlue * (255 - ptPixels[i + 3]) + ptPixels[i    ] * ptPixels[i + 3]) / 255; // Alpha取值范围从0到255
				}
			}
        }

        SelectObject(DirectDC, oldObject);
        RetBmp = DirectBitmap;
    }
    // 释放DC--------------------
    DeleteDC(DirectDC);
    DeleteDC(BufferDC);
 
	return RetBmp;
}

#ifndef SPI_GETDROPSHADOW
#define SPI_GETDROPSHADOW   0x1024
#endif

/*========================================================================
	说明:	用渐变色填充指定的矩形区域.
==========================================================================*/
void CCoolMenu::DrawGradsRect(CDC *pDC,  CRect &rect, COLORREF statColor, COLORREF endColor)
{//画梯度矩形,渐变的方式是从上到下再到上变化
	int r=GetRValue(statColor);
	int g=GetGValue(statColor);
	int b=GetBValue(statColor);//得到起始色的颜色分量

	//得到颜色分量的增量 
	float dr=(float)(2*(GetRValue(endColor)-GetRValue(statColor))/rect.Height());
	float dg=(float)(2*(GetGValue(endColor)-GetGValue(statColor))/rect.Height());
    float db=(float)(2*(GetBValue(endColor)-GetBValue(statColor))/rect.Height());
	//创建笔对象填充矩形
	for(int i=0;i<=rect.Height()/2;i++)
	{
        CPen pen(PS_SOLID,1,RGB(r+i*dr,g+i*dg,b+i*db)),*Oldpen;
		Oldpen=pDC->SelectObject(&pen);
		//画直线
		pDC->MoveTo(rect.left,rect.top+i);
		pDC->LineTo(rect.right,rect.top+i);
		pDC->MoveTo(rect.left,rect.bottom- i);
		pDC->LineTo(rect.right,rect.bottom-i);

		//恢复DC
		pDC->SelectObject(Oldpen);
		pen.DeleteObject();
	}
}

/*===================用指定的位图填充菜单背景=======================*/
void CCoolMenu::DrawBackGroundBmp(CDC*pDC,CRect rect,BOOL bFill)
{ 
	if(!bFill)
	{//若不填充则直接返回
       return ;
	}
	else//注意:位图的大小要大于rect的大小
	{//若填充则用指定的位图填充
        if(nBackGroundbmpID!=NULL)
		{//若位图不为空
			/*-------------------加载位图-----------------------*/
			CBitmap m_BkGndBmp;
            m_BkGndBmp.LoadBitmap(nBackGroundbmpID);//加载位图
			if(m_BkGndBmp.m_hObject!=NULL)
			{//加载位图成功
			   CDC MemDC;//定义内存DC来保存背景位图
	           MemDC.CreateCompatibleDC(pDC);//创建一个于pDC兼容的DC
	           MemDC.SelectObject(&m_BkGndBmp);//将位图对象选入内存中
	           pDC->BitBlt(0,0,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY);
			}
		}
	}

}


/*########################################################################
			  ------------------------------------------------
						菜单子类化类 CCoolMenuHook
			  ------------------------------------------------
		用于截获拥有此菜单窗口的与菜单相关的消息,以便进行相应的处理.
  ########################################################################*/

LRESULT CCoolMenuHook::WindowProc(UINT uMesssage, WPARAM wparam, LPARAM lparam)
{
	switch (uMesssage) 
	{
	case WM_DRAWITEM:
		CCoolMenu::DrawItem(LPDRAWITEMSTRUCT(lparam));
		break;
	case WM_MEASUREITEM:
		CCoolMenu::MeasureItem(LPMEASUREITEMSTRUCT(lparam));
		break;
	case WM_NCDESTROY:
		CCoolMenu::UnSubClass();
		break;
	default:
		break;
	}
	
	return CSubclassWnd::WindowProc(uMesssage, wparam, lparam);
}

/*========================================================================
	功能:	设置菜单项的名称,并把快捷键提示信息从菜单名中分离出来.
==========================================================================*/
void CCoolMenu::CCoolMenuItem::SetItemName(CString sname)
{
	//快捷键提示信息一般在'\t'字符之后.如"Open(&O)\tCtrl+O";
	int n = sname.Find('\t');
	if(n != -1)
	{
		strText = sname.Left(n);
		strKeyName = sname.Right(sname.GetLength() - n - 1);
	}
	else
	{
		strText = sname;
		strKeyName = "";
	}
}

/*########################################################################
					  ----------------------------------
								    构建菜单	
					  ----------------------------------
  ########################################################################*/

CUIntArray CCoolMenu::m_uIDArray;		//菜单项ID数组
//菜单图标图像列表-------------------------------
CImageList CCoolMenu::m_iImageList;
CImageList CCoolMenu::m_iHotImageList;
CImageList CCoolMenu::m_iDisabledImageList;
CString CCoolMenu::m_sLogoText;		//LOGO字符串
CCoolMenuHook CCoolMenu::m_MenuHook;

CSize CCoolMenu::m_szMenuLogo = CSize(0, 0);		//主菜单左LOGO图像栏大小
CSize CCoolMenu::m_szMenuIcon = CSize(16, 16);		//图标大小
UINT CCoolMenu::nBackGroundbmpID=0;         //要填充菜单背景的位图ID
UINT CCoolMenu::m_uLogoBmpID = 0;			//主菜单左LOGO图像ID
UINT CCoolMenu::m_uBitmapID = 0;			//图像列表图像资源ID
DWORD CCoolMenu::m_dwStyle = 0;
CRect CCoolMenu::m_rcMenuItem = CRect(0, 0, 0, 0);

COLORREF CCoolMenu::m_crLogoColor        = RGB(0, 0, 255);			//LOGO图像的背景颜色
COLORREF CCoolMenu::m_crTextColor        = ::GetSysColor(COLOR_MENUTEXT);//字体颜色
COLORREF CCoolMenu::m_crMenuColor        = ::GetSysColor(COLOR_MENU);	//菜单颜色
COLORREF CCoolMenu::m_crIconBarColor     = ::GetSysColor(COLOR_MENU);	//图标栏背景颜色
COLORREF CCoolMenu::m_crLightBarColor    = RGB(234, 240, 250);		//光标条颜色
COLORREF CCoolMenu::m_crLightBarStartColor = RGB(234, 240, 250);
COLORREF CCoolMenu::m_crLightBarEndColor = RGB(196, 212, 239);
COLORREF CCoolMenu::m_crMarkColor        = RGB(255, 0, 255);			//
COLORREF CCoolMenu::m_crHighLightColor   = ::GetSysColor(COLOR_HIGHLIGHTTEXT);

CCoolMenu::CCoolMenu()
{

}

CCoolMenu::~CCoolMenu()
{
	ClearData();
}

/*========================================================================
	功能:	清除相关数据
==========================================================================*/
void CCoolMenu::ClearData()
{
	POSITION pos = m_obMenuList.GetHeadPosition();
	while (pos)
	{
		LPCOOLMENU lpMenu = (LPCOOLMENU)m_obMenuList.GetNext(pos);
		if (lpMenu != NULL)
		{
			delete lpMenu;
			lpMenu = NULL;
		}
	}
	m_obMenuList.RemoveAll();
}

void CCoolMenu::UnSubClass()
{
	m_MenuHook.HookWindow(HWND(NULL));
	m_uIDArray.RemoveAll();
	m_iImageList.DeleteImageList();
	m_iHotImageList.DeleteImageList();
	m_iDisabledImageList.DeleteImageList();
}

/*========================================================================
	功能:	初始化自绘菜单
	-----------------------------------------------
	nlevel: 当前菜单项级别,它们只能是以下值:
	-----------------------------------------
	-	MDS_TOP_MENU:		顶级菜单项
	-	MDS_TOP_SUBMENU:	主菜单项
	-	MDS_TOP_ENDSUBMENU:	主菜单的最后一项
	-	MDS_SUBMENU:		其他子菜单项
==========================================================================*/
BOOL CCoolMenu::ModifyStyle(HMENU hMenu, int nlevel)
{
	CMenu *pMenu = CMenu::FromHandle(hMenu);
	if (pMenu == NULL) return FALSE;
	UINT n = pMenu->GetMenuItemCount();
	for(UINT i = 0; i < n; i ++)
	{
		LPCOOLMENU lpMenu = new COOLMENU;

		lpMenu->nMenuLevel = nlevel;
		lpMenu->nMenuID = pMenu->GetMenuItemID(i);
		CString strText;
		pMenu->GetMenuString(i, strText, MF_BYPOSITION);
		lpMenu->SetItemName(strText);
		lpMenu->hMenu = pMenu->GetSafeHmenu();

		pMenu->ModifyMenu(	i, 
							MF_BYPOSITION | MF_OWNERDRAW,
							lpMenu->nMenuID, 
							LPCTSTR(lpMenu));
		m_obMenuList.AddTail((CObject *)lpMenu);//保存到对象列表中

		CMenu *pSubMenu = pMenu->GetSubMenu(i);

		if (nlevel == MDS_TOP_MENU)
		{
			if (lpMenu->nMenuID < 0 )
			{
				lpMenu->nMenuID = -2;
			}
			if(pSubMenu)
			{
				ModifyStyle(pSubMenu->GetSafeHmenu(),MDS_TOP_SUBMENU);
			}
		}
		else if (nlevel == MDS_TOP_SUBMENU)
		{
			if (i == n-1) lpMenu->nMenuLevel = MDS_TOP_ENDSUBMENU;

			if (pSubMenu != NULL)
			{
				lpMenu->nMenuID = -1;
				ModifyStyle(pSubMenu->GetSafeHmenu(),MDS_SUBMENU);
			}
		}
		else  
		{
			if (pSubMenu != NULL)
			{
				lpMenu->nMenuID = -1;
			}
			if (pSubMenu)
			{
				ModifyStyle(pSubMenu->GetSafeHmenu(),MDS_SUBMENU );
			}
		}
	}//End For
	
	return TRUE;
}

/*========================================================================
	功能:		载入菜单资源
	--------------------------------------------

⌨️ 快捷键说明

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