?? 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 函數(shù)
------------------------------------------------
########################################################################*/
HMODULE g_hUserDll = NULL;
#define WS_EX_LAYERED 0x00080000 //此擴(kuò)展屬性使窗口透明.
#define LWA_ALPHA 0x00000002
/*========================================================================
功能: 創(chuàng)建相應(yīng)的圖像列表所需的圖像
-------------------------------------------------------------
hbitmap: 原始位圖句柄
crBackColor: 背景色
nstyle: 要創(chuàng)建的圖像的風(fēng)格,它們?yōu)橄铝兄抵?
----------------------------------------------------
- 0: 創(chuàng)建禁止圖像列表圖像
- 1: 創(chuàng)建正常圖像列表圖像
- 2: 創(chuàng)建熱圖像列表圖像
==========================================================================*/
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);
//目標(biāo)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;
//指向像素區(qū)指針--------
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)
{
//透明區(qū)(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
/*========================================================================
說明: 用漸變色填充指定的矩形區(qū)域.
==========================================================================*/
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());
//創(chuàng)建筆對象填充矩形
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);
//恢復(fù)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;//定義內(nèi)存DC來保存背景位圖
MemDC.CreateCompatibleDC(pDC);//創(chuàng)建一個于pDC兼容的DC
MemDC.SelectObject(&m_BkGndBmp);//將位圖對象選入內(nèi)存中
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY);
}
}
}
}
/*########################################################################
------------------------------------------------
菜單子類化類 CCoolMenuHook
------------------------------------------------
用于截獲擁有此菜單窗口的與菜單相關(guān)的消息,以便進(jìn)行相應(yīng)的處理.
########################################################################*/
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);
}
/*========================================================================
功能: 設(shè)置菜單項(xiàng)的名稱,并把快捷鍵提示信息從菜單名中分離出來.
==========================================================================*/
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 = "";
}
}
/*########################################################################
----------------------------------
構(gòu)建菜單
----------------------------------
########################################################################*/
CUIntArray CCoolMenu::m_uIDArray; //菜單項(xiàng)ID數(shù)組
//菜單圖標(biāo)圖像列表-------------------------------
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); //圖標(biāo)大小
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); //圖標(biāo)欄背景顏色
COLORREF CCoolMenu::m_crLightBarColor = RGB(234, 240, 250); //光標(biāo)條顏色
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();
}
/*========================================================================
功能: 清除相關(guān)數(shù)據(jù)
==========================================================================*/
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: 當(dāng)前菜單項(xiàng)級別,它們只能是以下值:
-----------------------------------------
- MDS_TOP_MENU: 頂級菜單項(xiàng)
- MDS_TOP_SUBMENU: 主菜單項(xiàng)
- MDS_TOP_ENDSUBMENU: 主菜單的最后一項(xiàng)
- MDS_SUBMENU: 其他子菜單項(xiàng)
==========================================================================*/
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;
}
/*========================================================================
功能: 載入菜單資源
--------------------------------------------
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -