📄 coolmenu.cpp
字号:
/*########################################################################
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 + -