CoolMenu.cpp
上传用户:sunh8215
上传日期:2010-02-13
资源大小:1616k
文件大小:48k
源码类别:

酒店行业

开发平台:

Visual C++

  1. /*########################################################################
  2. Filename:  coolmenu.cpp
  3. ----------------------------------------------------
  4. Remarks: ...
  5. ----------------------------------------------------
  6.   ########################################################################*/
  7. #include "stdafx.h"
  8. #include "CoolMenu.h"
  9. #ifdef _DEBUG
  10. #undef THIS_FILE
  11. static char THIS_FILE[]=__FILE__;
  12. #define new DEBUG_NEW
  13. #endif 
  14. const TCHAR CoolMenu_oldProc[] = _T("CoolMenu_oldProc");
  15. /*########################################################################
  16.   ------------------------------------------------
  17. Cool API 函数
  18.   ------------------------------------------------
  19.   ########################################################################*/
  20. HMODULE g_hUserDll = NULL;
  21. #define WS_EX_LAYERED 0x00080000 //此扩展属性使窗口透明.
  22. #define LWA_ALPHA 0x00000002
  23. /*========================================================================
  24. 功能: 创建相应的图像列表所需的图像
  25. -------------------------------------------------------------
  26. hbitmap: 原始位图句柄
  27. crBackColor: 背景色
  28. nstyle: 要创建的图像的风格,它们为下列值之一:
  29. ----------------------------------------------------
  30. - 0: 创建禁止图像列表图像
  31. - 1: 创建正常图像列表图像
  32. - 2: 创建热图像列表图像
  33. ==========================================================================*/
  34. HBITMAP CCoolMenu::CreateImage(HBITMAP hbitmap, int nstyle, BOOL bAlpha, COLORREF crBackColor, COLORREF crMarkColor)
  35. {
  36. HBITMAP RetBmp = NULL;
  37.     if (hbitmap == NULL)
  38.     {  
  39. return NULL;
  40. }
  41. //源位图DC------------------------------------
  42.     HDC BufferDC = CreateCompatibleDC(NULL);      
  43.     if (BufferDC == NULL)
  44.     {
  45. return NULL;
  46. }
  47.     SelectObject(BufferDC, hbitmap);
  48. //目标DC--------------------------------------
  49.     HDC DirectDC = CreateCompatibleDC(NULL);      
  50.     if (DirectDC == NULL)
  51.     {
  52.   DeleteDC(BufferDC);
  53.   return NULL;
  54. }
  55.     // 获取源位图大小----------------------------
  56.     BITMAP bm;
  57.     GetObject(hbitmap, sizeof(bm), &bm);
  58. // 初始化BITMAPINFO信息----------------------
  59.     BITMAPINFO bitmapinfo; 
  60.     ZeroMemory(&bitmapinfo, sizeof(BITMAPINFO));
  61.     bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  62.     bitmapinfo.bmiHeader.biWidth = bm.bmWidth;
  63.     bitmapinfo.bmiHeader.biHeight = bm.bmHeight;
  64.     bitmapinfo.bmiHeader.biPlanes = 1;
  65.     bitmapinfo.bmiHeader.biBitCount = 32;
  66. //指向像素区指针--------
  67. BYTE *ptPixels;    
  68.     HBITMAP DirectBitmap = CreateDIBSection(DirectDC, (BITMAPINFO*)&bitmapinfo, 
  69.                                   DIB_RGB_COLORS, (void**)&ptPixels, NULL, 0);
  70. //背景颜色--------------
  71. BYTE oldRed   = GetRValue(crBackColor);
  72. BYTE oldGreen = GetGValue(crBackColor);
  73. BYTE oldBlue  = GetBValue(crBackColor);
  74. //透明色----------------
  75. BYTE markRed   = GetRValue(crMarkColor);
  76. BYTE markGreen = GetGValue(crMarkColor);
  77. BYTE markBlue  = GetBValue(crMarkColor);
  78. BYTE temp = 0;
  79.     if (DirectBitmap != NULL)
  80.     {
  81.         HGDIOBJ oldObject = SelectObject(DirectDC, DirectBitmap);
  82.         BitBlt(DirectDC, 0, 0, bm.bmWidth, bm.bmHeight, BufferDC, 0, 0, SRCCOPY);
  83. register int nbitcount = (bm.bmWidth * bm.bmHeight * 4);
  84.         for (register int i = 0; i < nbitcount;  i += 4)
  85.         {
  86. //透明区(alpha == 0)----------------------------------
  87. if ( ( bAlpha && ptPixels[i + 3] == 0) 
  88. ||  (!bAlpha && ptPixels[i + 2] == markRed //red
  89.    && ptPixels[i + 1] == markGreen //green
  90.    && ptPixels[i + 0] == markBlue //blue
  91. )
  92.    ) 
  93. {
  94. ptPixels[i + 2] = 255; //red
  95. ptPixels[i + 1] = 0; //green
  96. ptPixels[i + 0] = 255; //blue
  97. }
  98. else 
  99. {
  100. //灰度化位图--------------------------------------
  101. if (nstyle == 0 )
  102. {
  103. temp = (BYTE)(ptPixels[i + 2] * 0.299 + ptPixels[i + 1] * 0.587 + ptPixels[i] * 0.114);
  104. temp = (BYTE)(255 - (255 - temp) * 0.8); 
  105. ptPixels[i + 2] = ptPixels[i + 1] = ptPixels[i] = temp;
  106. }
  107. //淡化位图----------------------------------------
  108. else if (nstyle == 2)
  109. {
  110. ptPixels[i + 2] = (BYTE)(255 - (255 - ptPixels[i + 2]) * 0.9); 
  111. ptPixels[i + 1] = (BYTE)(255 - (255 - ptPixels[i + 1]) * 0.9); 
  112. ptPixels[i    ] = (BYTE)(255 - (255 - ptPixels[i + 0]) * 0.9); 
  113. }
  114. //Alpha混合--------------------------------------
  115. if (bAlpha)
  116. {
  117. ptPixels[i + 2] = (oldRed * (255 - ptPixels[i + 3]) + ptPixels[i + 2] * ptPixels[i + 3]) / 255; // Alpha取值范围从0到255
  118. ptPixels[i + 1] = (oldGreen * (255 - ptPixels[i + 3]) + ptPixels[i + 1] * ptPixels[i + 3]) / 255; // Alpha取值范围从0到255
  119. ptPixels[i    ] = (oldBlue * (255 - ptPixels[i + 3]) + ptPixels[i    ] * ptPixels[i + 3]) / 255; // Alpha取值范围从0到255
  120. }
  121. }
  122.         }
  123.         SelectObject(DirectDC, oldObject);
  124.         RetBmp = DirectBitmap;
  125.     }
  126.     // 释放DC--------------------
  127.     DeleteDC(DirectDC);
  128.     DeleteDC(BufferDC);
  129.  
  130. return RetBmp;
  131. }
  132. #ifndef SPI_GETDROPSHADOW
  133. #define SPI_GETDROPSHADOW   0x1024
  134. #endif
  135. /*========================================================================
  136. 说明: 用渐变色填充指定的矩形区域.
  137. ==========================================================================*/
  138. void CCoolMenu::DrawGradsRect(CDC *pDC,  CRect &rect, COLORREF statColor, COLORREF endColor)
  139. {//画梯度矩形,渐变的方式是从上到下再到上变化
  140. int r=GetRValue(statColor);
  141. int g=GetGValue(statColor);
  142. int b=GetBValue(statColor);//得到起始色的颜色分量
  143. //得到颜色分量的增量 
  144. float dr=(float)(2*(GetRValue(endColor)-GetRValue(statColor))/rect.Height());
  145. float dg=(float)(2*(GetGValue(endColor)-GetGValue(statColor))/rect.Height());
  146.     float db=(float)(2*(GetBValue(endColor)-GetBValue(statColor))/rect.Height());
  147. //创建笔对象填充矩形
  148. for(int i=0;i<=rect.Height()/2;i++)
  149. {
  150.         CPen pen(PS_SOLID,1,RGB(r+i*dr,g+i*dg,b+i*db)),*Oldpen;
  151. Oldpen=pDC->SelectObject(&pen);
  152. //画直线
  153. pDC->MoveTo(rect.left,rect.top+i);
  154. pDC->LineTo(rect.right,rect.top+i);
  155. pDC->MoveTo(rect.left,rect.bottom- i);
  156. pDC->LineTo(rect.right,rect.bottom-i);
  157. //恢复DC
  158. pDC->SelectObject(Oldpen);
  159. pen.DeleteObject();
  160. }
  161. }
  162. /*===================用指定的位图填充菜单背景=======================*/
  163. void CCoolMenu::DrawBackGroundBmp(CDC*pDC,CRect rect,BOOL bFill)
  164. if(!bFill)
  165. {//若不填充则直接返回
  166.        return ;
  167. }
  168. else//注意:位图的大小要大于rect的大小
  169. {//若填充则用指定的位图填充
  170.         if(nBackGroundbmpID!=NULL)
  171. {//若位图不为空
  172. /*-------------------加载位图-----------------------*/
  173. CBitmap m_BkGndBmp;
  174.             m_BkGndBmp.LoadBitmap(nBackGroundbmpID);//加载位图
  175. if(m_BkGndBmp.m_hObject!=NULL)
  176. {//加载位图成功
  177.    CDC MemDC;//定义内存DC来保存背景位图
  178.            MemDC.CreateCompatibleDC(pDC);//创建一个于pDC兼容的DC
  179.            MemDC.SelectObject(&m_BkGndBmp);//将位图对象选入内存中
  180.            pDC->BitBlt(0,0,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY);
  181. }
  182. }
  183. }
  184. }
  185. /*########################################################################
  186.   ------------------------------------------------
  187. 菜单子类化类 CCoolMenuHook
  188.   ------------------------------------------------
  189. 用于截获拥有此菜单窗口的与菜单相关的消息,以便进行相应的处理.
  190.   ########################################################################*/
  191. LRESULT CCoolMenuHook::WindowProc(UINT uMesssage, WPARAM wparam, LPARAM lparam)
  192. {
  193. switch (uMesssage) 
  194. {
  195. case WM_DRAWITEM:
  196. CCoolMenu::DrawItem(LPDRAWITEMSTRUCT(lparam));
  197. break;
  198. case WM_MEASUREITEM:
  199. CCoolMenu::MeasureItem(LPMEASUREITEMSTRUCT(lparam));
  200. break;
  201. case WM_NCDESTROY:
  202. CCoolMenu::UnSubClass();
  203. break;
  204. default:
  205. break;
  206. }
  207. return CSubclassWnd::WindowProc(uMesssage, wparam, lparam);
  208. }
  209. /*========================================================================
  210. 功能: 设置菜单项的名称,并把快捷键提示信息从菜单名中分离出来.
  211. ==========================================================================*/
  212. void CCoolMenu::CCoolMenuItem::SetItemName(CString sname)
  213. {
  214. //快捷键提示信息一般在't'字符之后.如"Open(&O)tCtrl+O";
  215. int n = sname.Find('t');
  216. if(n != -1)
  217. {
  218. strText = sname.Left(n);
  219. strKeyName = sname.Right(sname.GetLength() - n - 1);
  220. }
  221. else
  222. {
  223. strText = sname;
  224. strKeyName = "";
  225. }
  226. }
  227. /*########################################################################
  228.   ----------------------------------
  229.     构建菜单
  230.   ----------------------------------
  231.   ########################################################################*/
  232. CUIntArray CCoolMenu::m_uIDArray; //菜单项ID数组
  233. //菜单图标图像列表-------------------------------
  234. CImageList CCoolMenu::m_iImageList;
  235. CImageList CCoolMenu::m_iHotImageList;
  236. CImageList CCoolMenu::m_iDisabledImageList;
  237. CString CCoolMenu::m_sLogoText; //LOGO字符串
  238. CCoolMenuHook CCoolMenu::m_MenuHook;
  239. CSize CCoolMenu::m_szMenuLogo = CSize(0, 0); //主菜单左LOGO图像栏大小
  240. CSize CCoolMenu::m_szMenuIcon = CSize(16, 16); //图标大小
  241. UINT CCoolMenu::nBackGroundbmpID=0;         //要填充菜单背景的位图ID
  242. UINT CCoolMenu::m_uLogoBmpID = 0; //主菜单左LOGO图像ID
  243. UINT CCoolMenu::m_uBitmapID = 0; //图像列表图像资源ID
  244. DWORD CCoolMenu::m_dwStyle = 0;
  245. CRect CCoolMenu::m_rcMenuItem = CRect(0, 0, 0, 0);
  246. COLORREF CCoolMenu::m_crLogoColor        = RGB(0, 0, 255); //LOGO图像的背景颜色
  247. COLORREF CCoolMenu::m_crTextColor        = ::GetSysColor(COLOR_MENUTEXT);//字体颜色
  248. COLORREF CCoolMenu::m_crMenuColor        = ::GetSysColor(COLOR_MENU); //菜单颜色
  249. COLORREF CCoolMenu::m_crIconBarColor     = ::GetSysColor(COLOR_MENU); //图标栏背景颜色
  250. COLORREF CCoolMenu::m_crLightBarColor    = RGB(234, 240, 250); //光标条颜色
  251. COLORREF CCoolMenu::m_crLightBarStartColor = RGB(234, 240, 250);
  252. COLORREF CCoolMenu::m_crLightBarEndColor = RGB(196, 212, 239);
  253. COLORREF CCoolMenu::m_crMarkColor        = RGB(255, 0, 255); //
  254. COLORREF CCoolMenu::m_crHighLightColor   = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
  255. CCoolMenu::CCoolMenu()
  256. {
  257. }
  258. CCoolMenu::~CCoolMenu()
  259. {
  260. ClearData();
  261. }
  262. /*========================================================================
  263. 功能: 清除相关数据
  264. ==========================================================================*/
  265. void CCoolMenu::ClearData()
  266. {
  267. POSITION pos = m_obMenuList.GetHeadPosition();
  268. while (pos)
  269. {
  270. LPCOOLMENU lpMenu = (LPCOOLMENU)m_obMenuList.GetNext(pos);
  271. if (lpMenu != NULL)
  272. {
  273. delete lpMenu;
  274. lpMenu = NULL;
  275. }
  276. }
  277. m_obMenuList.RemoveAll();
  278. }
  279. void CCoolMenu::UnSubClass()
  280. {
  281. m_MenuHook.HookWindow(HWND(NULL));
  282. m_uIDArray.RemoveAll();
  283. m_iImageList.DeleteImageList();
  284. m_iHotImageList.DeleteImageList();
  285. m_iDisabledImageList.DeleteImageList();
  286. }
  287. /*========================================================================
  288. 功能: 初始化自绘菜单
  289. -----------------------------------------------
  290. nlevel: 当前菜单项级别,它们只能是以下值:
  291. -----------------------------------------
  292. - MDS_TOP_MENU: 顶级菜单项
  293. - MDS_TOP_SUBMENU: 主菜单项
  294. - MDS_TOP_ENDSUBMENU: 主菜单的最后一项
  295. - MDS_SUBMENU: 其他子菜单项
  296. ==========================================================================*/
  297. BOOL CCoolMenu::ModifyStyle(HMENU hMenu, int nlevel)
  298. {
  299. CMenu *pMenu = CMenu::FromHandle(hMenu);
  300. if (pMenu == NULL) return FALSE;
  301. UINT n = pMenu->GetMenuItemCount();
  302. for(UINT i = 0; i < n; i ++)
  303. {
  304. LPCOOLMENU lpMenu = new COOLMENU;
  305. lpMenu->nMenuLevel = nlevel;
  306. lpMenu->nMenuID = pMenu->GetMenuItemID(i);
  307. CString strText;
  308. pMenu->GetMenuString(i, strText, MF_BYPOSITION);
  309. lpMenu->SetItemName(strText);
  310. lpMenu->hMenu = pMenu->GetSafeHmenu();
  311. pMenu->ModifyMenu( i, 
  312. MF_BYPOSITION | MF_OWNERDRAW,
  313. lpMenu->nMenuID, 
  314. LPCTSTR(lpMenu));
  315. m_obMenuList.AddTail((CObject *)lpMenu);//保存到对象列表中
  316. CMenu *pSubMenu = pMenu->GetSubMenu(i);
  317. if (nlevel == MDS_TOP_MENU)
  318. {
  319. if (lpMenu->nMenuID < 0 )
  320. {
  321. lpMenu->nMenuID = -2;
  322. }
  323. if(pSubMenu)
  324. {
  325. ModifyStyle(pSubMenu->GetSafeHmenu(),MDS_TOP_SUBMENU);
  326. }
  327. }
  328. else if (nlevel == MDS_TOP_SUBMENU)
  329. {
  330. if (i == n-1) lpMenu->nMenuLevel = MDS_TOP_ENDSUBMENU;
  331. if (pSubMenu != NULL)
  332. {
  333. lpMenu->nMenuID = -1;
  334. ModifyStyle(pSubMenu->GetSafeHmenu(),MDS_SUBMENU);
  335. }
  336. }
  337. else  
  338. {
  339. if (pSubMenu != NULL)
  340. {
  341. lpMenu->nMenuID = -1;
  342. }
  343. if (pSubMenu)
  344. {
  345. ModifyStyle(pSubMenu->GetSafeHmenu(),MDS_SUBMENU );
  346. }
  347. }
  348. }//End For
  349. return TRUE;
  350. }
  351. /*========================================================================
  352. 功能: 载入菜单资源
  353. --------------------------------------------
  354. uMenuID: 菜单资源ID
  355. uToolBarID: 工具栏资源ID,用来提取图标资源
  356. ==========================================================================*/
  357. BOOL CCoolMenu::LoadMenu(UINT uMenuID, UINT uToolBarID)
  358. {
  359. ClearData();
  360. BOOL bRet = CMenu::LoadMenu(uMenuID);
  361. if (bRet)
  362. {
  363. //依次设置菜单为自绘风格并设置相关信息-------------
  364. ModifyStyle(GetSafeHmenu(), MDS_TOP_MENU);
  365. //从工具栏中添加图标资源---------------------------
  366. SetImageList(uToolBarID);
  367. }
  368. return bRet;
  369. }
  370. /*========================================================================
  371. 功能: 将Windows菜单句柄连接到CCoolMenu对象.
  372. ------------------------------------------------
  373. hMenu: 要连接的菜单名柄
  374. uToolBarID: 对应工具栏资源ID,用来提取图标资源
  375. ==========================================================================*/
  376. BOOL CCoolMenu::Attach(HMENU hMenu, UINT uToolBarID)
  377. {
  378. ClearData();
  379. BOOL bRet = CMenu::Attach(hMenu);
  380. if (bRet)
  381. {
  382. //依次设置菜单为自绘风格并设置相关信息-------------
  383. ModifyStyle(GetSafeHmenu(), MDS_TOP_MENU);
  384. //从工具栏中添加图标资源---------------------------
  385. SetImageList(uToolBarID);
  386. }
  387. return bRet;
  388. }
  389. /*========================================================================
  390. 功能: 断开与菜单句柄的连接并清除相关数据
  391. ==========================================================================*/
  392. HMENU CCoolMenu::Detach()
  393. {
  394. ClearData();
  395. return CMenu::Detach();
  396. }
  397. /*========================================================================
  398. 功能: 添加菜单项
  399. -------------------------------------------
  400. uID: 菜单ID
  401. strText: 菜单文本
  402. nlevel: 菜单级别,请参考相关函数
  403. ==========================================================================*/
  404. void CCoolMenu::AppendMenu(UINT uFlags, UINT uNewMenuItemID, CString strNewMenuItem, int nlevel)
  405. {
  406. LPCOOLMENU lpMenu = new COOLMENU;
  407. lpMenu->nMenuID = uNewMenuItemID;
  408. lpMenu->strText = strNewMenuItem;
  409. lpMenu->nMenuLevel = nlevel;
  410. CMenu::AppendMenu(MF_BYPOSITION | MF_OWNERDRAW | uFlags, lpMenu->nMenuID, LPCTSTR(lpMenu));
  411. m_obMenuList.AddTail((CObject *)lpMenu);
  412. }
  413. /*========================================================================
  414. 功能: 子类化指定窗口
  415. ==========================================================================*/
  416. void CCoolMenu::SubClass(HWND hwnd)
  417. {
  418. m_MenuHook.HookWindow(hwnd);
  419. }
  420. /*########################################################################
  421. -----------------------
  422. 绘制菜单
  423. -----------------------
  424.   ########################################################################*/
  425. /*========================================================================
  426. 功能: 计算菜单大小
  427. --------------------------------------------
  428. lpMIS: LPMEASUREITEMSTRUCT结构体
  429. ==========================================================================*/
  430. void CCoolMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
  431. {
  432. LPCOOLMENU lpMenu = (LPCOOLMENU)(lpMIS->itemData);
  433. //分隔条---------------------------------
  434. if(lpMenu->nMenuID == 0)
  435. {
  436. lpMIS->itemHeight = 5;
  437. lpMIS->itemWidth = 50;
  438. return;
  439. }
  440. //非分隔条-------------------------------
  441. lpMIS->itemWidth = 50; // default width
  442. lpMIS->itemHeight = 19;
  443. CString strText = lpMenu->strText + lpMenu->strKeyName;
  444. int nLen = strText.GetLength();
  445. if (nLen > 0)
  446. {
  447. //计算绘制菜单文本所需宽度-------------------
  448. CFont fontMenu;
  449. LOGFONT lf;
  450. ZeroMemory(&lf, sizeof(LOGFONT));
  451. NONCLIENTMETRICS nm;
  452. nm.cbSize = sizeof(NONCLIENTMETRICS);
  453. VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nm.cbSize, &nm, 0)); 
  454. lf = nm.lfMenuFont;
  455. fontMenu.CreateFontIndirect(&lf);
  456. CDC *pDC = AfxGetMainWnd()->GetDC();
  457. CFont *old = pDC->SelectObject(&fontMenu);
  458. CSize sz = pDC->GetTextExtent(lpMenu->strText);  
  459. pDC->SelectObject(&old);
  460. AfxGetMainWnd()->ReleaseDC(pDC);
  461. fontMenu.DeleteObject();
  462. //调整有快捷键提示的菜单的宽度,使宽度适中-------------
  463. if (lpMenu->strKeyName != "") sz.cx += (62 - (strText.GetLength() % 8) * (sz.cx/strText.GetLength()));
  464. if(lpMenu->nMenuID == -2)
  465. {
  466. //顶级菜单宽度---------------------------
  467. lpMIS->itemWidth = sz.cx - 6;
  468. }
  469. else if (lpMenu->nMenuLevel <= MDS_TOP_SUBMENU)
  470. {
  471. //主菜单项宽度---------------------------
  472. lpMIS->itemWidth = sz.cx + m_szMenuLogo.cx + m_szMenuIcon.cx + MENU_SPACE * 5;
  473. }
  474. else 
  475. {
  476. //普通菜单宽度---------------------------
  477. lpMIS->itemWidth = sz.cx  + m_szMenuIcon.cx + MENU_SPACE * 5;
  478. }
  479. }
  480. }
  481. /*========================================================================
  482. 功能: 获取菜单命令ID对应的图标序列号
  483. ----------------------------------------------
  484. uID: 菜单命令ID
  485. ==========================================================================*/
  486. int CCoolMenu::GetIndex(UINT uID)
  487. {
  488. for(int i = 0; i < m_uIDArray.GetSize(); i ++)
  489. {
  490. if(uID == m_uIDArray[i])
  491. {
  492. if (i >= m_iImageList.GetImageCount()) return -1;
  493. return i;
  494. }
  495. }
  496. return -1;
  497. }
  498. /*========================================================================
  499. 功能: 绘制菜单
  500. ------------------------------------------------
  501. lpDIS: 自绘信息结构体
  502. ==========================================================================*/
  503. void CCoolMenu::DrawItem(LPDRAWITEMSTRUCT lpDIS)
  504. {
  505. LPCOOLMENU lpMenu = (LPCOOLMENU)(lpDIS->itemData);
  506. if(!AfxIsValidAddress(lpMenu, sizeof(COOLMENU))) return ;
  507. CDC *pdc = CDC::FromHandle(lpDIS->hDC);
  508. const CRect rect = lpDIS->rcItem;
  509. //#ifdef _DEBUG
  510. //    CMemoryState oldmem,newmem,diff;
  511. // oldmem.Checkpoint();
  512. //#endif
  513. //建立内存上下文---------------------------------------
  514. CDC *pDC = new CDC();
  515. //#ifdef _DEBUG
  516. // newmem.Checkpoint();
  517. // if(diff.Difference(oldmem,newmem))
  518. // {
  519. // ASSERT(0);
  520. // }
  521. //#endif
  522. pDC->CreateCompatibleDC(pdc);
  523. CBitmap *bitmap, *oldbitmap;
  524. bitmap = new CBitmap;
  525. bitmap->CreateCompatibleBitmap(pdc,rect.right, rect.bottom);//improtant
  526. oldbitmap = pDC->SelectObject(bitmap);
  527. //把菜单字体选入内存设备上下文-----------------------------
  528. CFont fontMenu, *oldfont;
  529. LOGFONT lf;
  530. ZeroMemory(&lf, sizeof(LOGFONT));
  531. NONCLIENTMETRICS nm;
  532. nm.cbSize = sizeof(NONCLIENTMETRICS);
  533. VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nm.cbSize, &nm, 0)); 
  534. lf = nm.lfMenuFont;
  535. // lf.lfUnderline=true; 
  536. fontMenu.CreateFontIndirect(&lf);
  537. oldfont = pDC->SelectObject(&fontMenu);
  538. pDC->SetBkColor(m_crMenuColor);
  539. pDC->SetBkMode(TRANSPARENT);
  540. pDC->SelectStockObject(NULL_BRUSH);
  541.     //用位图填充菜单背景
  542. // CRect rect2;
  543. // rect2.left+=m_szMenuLogo.cx;
  544. //    DrawBackGroundBmp(pdc,rect2,true);
  545. //当当前菜单为主菜单时,空出左边用于绘制LOGO图片----------
  546. int nMenuLogoBarcx = 0; //左边LOGO栏宽度
  547. if (lpMenu->nMenuLevel <= MDS_TOP_SUBMENU) nMenuLogoBarcx = m_szMenuLogo.cx;
  548. //绘制LOGO图片----------------------------
  549. if (nMenuLogoBarcx > 0 && (lpDIS->itemAction & ODA_DRAWENTIRE) 
  550. && lpMenu->nMenuLevel != MDS_TOP_SUBMENU)
  551. {
  552. DrawLogoBar(pdc, CRect(0, 0, m_szMenuLogo.cx, rect.bottom));
  553. }
  554. //取得菜单状态----------------------------
  555. BOOL bIsSelected = (lpDIS->itemState & ODS_SELECTED);
  556. BOOL bIsChecked  = (lpDIS->itemState & ODS_CHECKED);
  557. BOOL bIsGrayed   = (lpDIS->itemState & ODS_GRAYED);
  558. BOOL bIsHotLight  = (lpDIS->itemState & ODS_HOTLIGHT );
  559. //擦除背景---------------------------------
  560. CRect rc = rect;
  561. rc.left += nMenuLogoBarcx;
  562. if (lpMenu->nMenuID == -2)//顶级菜单-------
  563. {
  564. CBrush Brush(::GetSysColor(COLOR_3DFACE));//即是非弹出菜单
  565. pDC->FillRect(rc, &Brush);
  566. }
  567. else//非顶级菜单---------------------------
  568. {
  569. CBrush Brush(m_crMenuColor);
  570. pDC->FillRect(rc, &Brush);
  571. }
  572. //绘制Office XP风格的图标栏灰色背景------------
  573. if (lpMenu->nMenuID != -2 && (GetStyle() & CMS_ICONBAR != 0) && nMenuLogoBarcx == 0)
  574. {
  575. rc.right = rc.left + m_szMenuIcon.cx + MENU_SPACE*2 - 1;
  576. pDC->FillSolidRect(rc,m_crIconBarColor);
  577. }
  578. //绘制分隔条-----------------------------------
  579. if(lpMenu->nMenuID == 0)
  580. {
  581. rc = rect;
  582. rc.top += rect.Height()/2; //居矩形区域中间
  583. rc.bottom = rc.top + 2; //高两个象素
  584. rc.left += (nMenuLogoBarcx + MENU_SPACE); //空出左边LOGO栏区
  585. if ((GetStyle() & CMS_ICONBAR != 0) && nMenuLogoBarcx == 0) 
  586. {
  587. //在XP风格下空出左边图标栏区域----------
  588. rc.left += (m_szMenuIcon.cx + MENU_SPACE);
  589. }
  590. pDC->Draw3dRect(rc, ::GetSysColor(COLOR_GRAYTEXT), RGB(240, 240, 240));
  591. }
  592. else
  593. {
  594. //显示菜单文字-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  595. //禁止菜单========================================================
  596. if(bIsGrayed) 
  597. {
  598. rc = rect;
  599. rc.left += nMenuLogoBarcx; //空出左边LOGO栏区域
  600. // 菜单被选择----------------------------------
  601. if(bIsSelected) 
  602. {
  603. // DrawLightBar(pDC, rc, FALSE);
  604. }
  605. //菜单文本----------------------------
  606. if(lpMenu->strText.GetLength() > 0)
  607. {
  608. rc.left += (m_szMenuIcon.cx + MENU_SPACE*3 + 1); 
  609. rc.top += 2;
  610. rc.right -= 11;//调节快捷方式的宽度"ctrl+o"
  611. //绘制立体字---------------------------
  612. pDC->SetTextColor(::GetSysColor(COLOR_3DLIGHT));
  613. pDC->DrawText(lpMenu->strText, &rc, DT_EXPANDTABS | DT_VCENTER | DT_SINGLELINE);
  614. pDC->DrawText(lpMenu->strKeyName, &rc, DT_EXPANDTABS | DT_VCENTER | DT_SINGLELINE | DT_RIGHT);
  615. pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
  616. rc.InflateRect(1,1,-1,-1);
  617. pDC->DrawText(lpMenu->strText, &rc, DT_EXPANDTABS | DT_VCENTER | DT_SINGLELINE);
  618. pDC->DrawText(lpMenu->strKeyName, &rc, DT_EXPANDTABS | DT_VCENTER | DT_SINGLELINE | DT_RIGHT);
  619. }
  620. }
  621. //非禁止菜单==========================================================
  622. else 
  623. {
  624. //顶层菜单------------------------------------------
  625. if (lpMenu->nMenuID == -2) 
  626. {
  627. rc = rect;
  628. rc.right -= 4;
  629. m_rcMenuItem = rect;
  630. //选择状态----------------------------
  631. if (bIsSelected) 
  632. {
  633. DrawMenuBar(pDC, rect);
  634. pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
  635. m_rcMenuItem = rect;
  636. CRect rcFram; 
  637. AfxGetMainWnd()->GetWindowRect(&rcFram);
  638. m_rcMenuItem.OffsetRect(rcFram.TopLeft());
  639. }
  640. //焦点状态----------------------------
  641. else if (bIsHotLight)  
  642. {
  643. DrawLightBar(pDC, rc);
  644. pDC->SetTextColor(m_crHighLightColor);
  645. m_rcMenuItem.SetRectEmpty();
  646. }
  647. //正常状态----------------------------
  648. else 
  649. {
  650. pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
  651. m_rcMenuItem.SetRectEmpty();
  652. }
  653. //菜单文本----------------------------
  654. if(lpMenu->strText.GetLength() > 0)
  655. {
  656. pDC->DrawText(lpMenu->strText, &rc, DT_EXPANDTABS | DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  657. }
  658. }
  659. //非顶层菜单,是弹出菜单或者一个菜单项目---------------
  660. else 
  661. {
  662. rc = rect;
  663. rc.left += nMenuLogoBarcx;
  664. //选择状态-----------------------------
  665. if(bIsSelected)
  666. {
  667. DrawLightBar(pDC, rc);
  668. pDC->SetTextColor(m_crHighLightColor);
  669. }
  670. //非选择状态---------------------------
  671. else
  672. {
  673. pDC->SetTextColor(m_crTextColor);
  674. }
  675. //菜单文本----------------------------
  676. if(lpMenu->strText.GetLength() > 0)
  677. {
  678. rc.left += (m_szMenuIcon.cx + MENU_SPACE*3);
  679. rc.right -= 12;
  680. pDC->DrawText(lpMenu->strText, &rc, DT_EXPANDTABS |
  681. DT_VCENTER | DT_SINGLELINE);
  682. pDC->DrawText(lpMenu->strKeyName, &rc, DT_EXPANDTABS | 
  683. DT_VCENTER | DT_SINGLELINE | DT_RIGHT);
  684. }
  685. }
  686. }
  687. //<<绘制图标或Check标志-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  688. rc = rect;
  689. rc.left += (nMenuLogoBarcx + MENU_SPACE -1);
  690. rc.top += ((rect.Height() - m_szMenuIcon.cy)/2 + 1);
  691. rc.right = rc.left + m_szMenuIcon.cx;
  692. rc.bottom = rc.top + m_szMenuIcon.cy;
  693. int nIndex = GetIndex(lpMenu->nMenuID);
  694. //如果有图标------------------------------------------
  695. if(nIndex >= 0) 
  696. {
  697. //画图标Check框-----------------------------------
  698. if(bIsChecked)
  699. {
  700. CRect rcc = rect;
  701. rcc.left += nMenuLogoBarcx;
  702. rcc.right = rcc.left + rect.Height() + 1;
  703. if (bIsSelected)
  704. {
  705. // rcc.InflateRect(-1,-1);
  706. // pDC->FillSolidRect(rcc,m_crMenuColor);
  707. // pDC->Draw3dRect(rcc, RGB(255,255,255), TOP_COLOR);
  708. }
  709. else 
  710. {
  711. pDC->FillSolidRect(rcc,RGB(235,235,235));
  712. pDC->Draw3dRect(rc, RGB(160,170,210), RGB(160,170,210));
  713. }
  714. }
  715. //绘制图标-------------------------------------
  716. if (bIsGrayed)
  717. {
  718. m_iDisabledImageList.Draw(pDC, nIndex, CPoint(rc.left, rc.top), ILD_TRANSPARENT);
  719. }
  720. else if(bIsSelected)
  721. {
  722. m_iHotImageList.Draw(pDC, nIndex, CPoint(rc.left, rc.top), ILD_TRANSPARENT);
  723. }
  724. else
  725. {
  726. m_iImageList.Draw(pDC, nIndex, CPoint(rc.left, rc.top), ILD_TRANSPARENT);
  727. }
  728. }
  729. //如果没有图标---------------------------------------
  730. else 
  731. {
  732. // 绘制Check标志-------------------------
  733. if(bIsChecked)
  734. {
  735. rc.InflateRect(-1, 0, 0, -1);
  736. if(bIsSelected)
  737. {
  738. pDC->FillSolidRect(rc,RGB(255,255,255));
  739. pDC->Draw3dRect(rc, RGB(160,170,210), RGB(160,170,210));
  740. }
  741. else
  742. {
  743. pDC->FillSolidRect(rc,RGB(235,235,235));
  744. pDC->Draw3dRect(rc, RGB(160,170,210), RGB(160,170,210));
  745. }
  746. //画勾号----------------------------
  747. pDC->MoveTo(rc.left + 4,  rc.top + 6);
  748. pDC->LineTo(rc.left + 6,  rc.top + 8);
  749. pDC->LineTo(rc.left + 11, rc.top + 3);
  750. pDC->MoveTo(rc.left + 4,  rc.top + 7);
  751. pDC->LineTo(rc.left + 6,  rc.top + 9);
  752. pDC->LineTo(rc.left + 11, rc.top + 4);
  753. }
  754. }
  755. //---------结束绘制图标或Check标志>>>
  756. }
  757. //扫尾工作-------------------------------------------
  758. pdc->BitBlt(rect.left + nMenuLogoBarcx, rect.top, rect.Width() - nMenuLogoBarcx, rect.Height(), 
  759. pDC, rect.left + nMenuLogoBarcx, rect.top, SRCCOPY);
  760. pDC->SelectObject(&oldfont);
  761. pDC->SelectObject(oldbitmap);
  762. if (pDC != NULL) delete pDC;
  763. if (bitmap != NULL) delete bitmap;
  764. }
  765. void CCoolMenu::DrawMenuBar(CDC *pDC, CRect rect)
  766. {
  767. rect.right -= 4;
  768. // pDC->FillSolidRect(rect, m_crIconBarColor);
  769. pDC->Draw3dRect(rect, ::GetSysColor(COLOR_3DDKSHADOW), ::GetSysColor(COLOR_3DDKSHADOW));
  770. //Draw shadow----------------------------------------->>
  771. COLORREF oldcolor = ::GetSysColor(COLOR_3DFACE);
  772. BYTE AlphaArray[] ={90,210, 222, 240};
  773. for (int i = 0; i < 4; i++)
  774. {
  775. BYTE newR = GetRValue(oldcolor) * AlphaArray[i] / 255;  
  776. BYTE newG = GetGValue(oldcolor) * AlphaArray[i] / 255;  
  777. BYTE newB = GetBValue(oldcolor) * AlphaArray[i] / 255;  
  778. CPen pen(0, 1, RGB(newR, newG, newB));
  779. CPen *oldpen = pDC->SelectObject(&pen);
  780. pDC->MoveTo(rect.right + i, rect.top + i + 3);
  781. pDC->LineTo(rect.right + i, rect.bottom );
  782. pDC->SelectObject(oldpen);
  783. }
  784. }
  785. /*========================================================================
  786. 功能: 绘制光标条
  787. -----------------------------------------
  788. rect: 绘制范围
  789. ==========================================================================*/
  790. void CCoolMenu::DrawLightBar(CDC *pDC, CRect rect, BOOL bfill)
  791. {
  792. if (bfill)
  793. {
  794. //绘制渐变色----------------------------------------
  795. FillGradient(pDC, rect, m_crLightBarStartColor, m_crLightBarEndColor);
  796. // DrawGradsRect(pDC,rect,m_crLightBarStartColor,m_crLightBarEndColor);
  797. }
  798. pDC->Draw3dRect(rect, m_crLightBarColor, m_crLightBarColor);
  799. }
  800. /*========================================================================
  801. 功能: 绘制LOGO栏
  802. --------------------------------------------
  803. pDC: 设备上下文
  804. rect: 绘制范围
  805. ==========================================================================*/
  806. void CCoolMenu::DrawLogoBar(CDC *pDC, CRect rect)
  807. {
  808. if (m_szMenuLogo.cx > 0)
  809. {
  810. //如果设置了LOGO图片------------------------------------
  811. if(m_uLogoBmpID != NULL)
  812. {
  813. CDC memDC;
  814. memDC.CreateCompatibleDC(pDC);
  815. CBitmap bitmap, *oldbitmap;
  816. bitmap.LoadBitmap(m_uLogoBmpID);
  817. if (bitmap.GetSafeHandle() != NULL)
  818. {
  819. oldbitmap = memDC.SelectObject(&bitmap);
  820. pDC->BitBlt(rect.left, rect.bottom-m_szMenuLogo.cy, m_szMenuLogo.cx, m_szMenuLogo.cy,
  821. &memDC, 0, 0, SRCCOPY);
  822. memDC.SelectObject(oldbitmap);
  823. bitmap.DeleteObject();
  824. memDC.DeleteDC();
  825. //如果图片比要填充的矩形小,则继续用此图片填充剩下的矩形,直到填满为止----------
  826. if(rect.Height() > m_szMenuLogo.cy) DrawLogoBar(pDC, CRect(0, 0, rect.right, (rect.Height() - m_szMenuLogo.cy)));
  827. }
  828. }
  829. //如果没有设置LOGO图片,则以渐变色和LOGO字串绘制LOGO栏--
  830. else 
  831. {
  832. //绘制渐变色--------------------------------
  833. FillGradient(pDC, rect, RGB(90, 90, 90), m_crLogoColor);
  834. //绘制LOGO字串---------------------------------
  835. CFont vertFont;
  836. vertFont.CreateFont(14, 0, 900, 900, FW_BOLD,
  837. 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
  838. CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
  839. DEFAULT_PITCH, "Arial");
  840. CFont *pOldFont = pDC->SelectObject(&vertFont);
  841. pDC->SetTextColor(RGB(255, 255, 255));
  842. pDC->SetBkMode(TRANSPARENT);
  843. pDC->TextOut(rect.left+3, rect.bottom-4, m_sLogoText);
  844. pDC->SelectObject(pOldFont);
  845. vertFont.DeleteObject();
  846. }
  847. }
  848. }
  849. /*########################################################################
  850. -----------------------
  851. 设置菜单LOGO栏
  852. -----------------------
  853.   ########################################################################*/
  854. /*========================================================================
  855. 功能: 设置LOGO字串及背景渐变色
  856. ==========================================================================*/
  857. void CCoolMenu::SetLogoText(CString strText, COLORREF color)
  858. {
  859. m_sLogoText  = strText;
  860. m_crLogoColor = color;
  861. m_szMenuLogo.cx = 20;
  862. }
  863. /*========================================================================
  864. 功能: 设置LOGO图片
  865. --------------------------------------------
  866. uID: LOGO图片ID
  867. width: LOGO栏宽度,如果为0,则把图片的宽度作为LGOG栏宽度
  868. ==========================================================================*/
  869. BOOL CCoolMenu::SetLogoImage(UINT uBitmapID, int nwidth)
  870. {
  871. if (uBitmapID == NULL) 
  872. {
  873. m_uLogoBmpID = 0;
  874. return FALSE;
  875. }
  876. CBitmap bitmap;
  877. bitmap.LoadBitmap(uBitmapID);
  878. if(bitmap.GetSafeHandle() != NULL)
  879. {
  880. BITMAP bm;
  881. bitmap.GetBitmap(&bm);
  882. if (nwidth == 0) m_szMenuLogo.cx = bm.bmWidth;
  883. else m_szMenuLogo.cx = nwidth;
  884. m_szMenuLogo.cy = bm.bmHeight;
  885. m_uLogoBmpID = uBitmapID;
  886. bitmap.DeleteObject();
  887. }
  888. else
  889. {
  890. m_uLogoBmpID = 0;
  891. m_szMenuLogo = CSize(0, 0);
  892. }
  893. return TRUE;
  894. }
  895. /*########################################################################
  896. -----------------------
  897. 设置菜单图像列表
  898. -----------------------
  899.   ########################################################################*/
  900. /*========================================================================
  901. 功能: 设置菜单图像列表.
  902. ------------------------------------------------------------
  903. uToolBarID: 对应用来提取命令ID工具栏资源的ID.
  904. uBitmapID: 图像资源ID.
  905. bAlpha: 是否有alpha通道.
  906. ==========================================================================*/
  907. int CCoolMenu::SetImageList(UINT uToolBarID, UINT uBitmapID, BOOL bAlpha)
  908. {
  909. if (uToolBarID != NULL)
  910. {
  911. if (uBitmapID == NULL)
  912. {
  913. m_uBitmapID = uToolBarID;
  914. m_crMarkColor = RGB(192, 192, 192);
  915. }
  916. else
  917. {
  918. m_uBitmapID = uBitmapID;
  919. m_crMarkColor = RGB(255, 0, 255);
  920. }
  921. if (bAlpha) 
  922. {
  923. m_dwStyle |= CMS_32IMAGELIST;
  924. }
  925. else 
  926. {
  927. m_dwStyle &= ~CMS_32IMAGELIST;
  928. }
  929. InitImageList();
  930. m_uIDArray.RemoveAll();
  931. return GetIDFromToolBar(uToolBarID, &m_uIDArray);
  932. }
  933. return -1;
  934. }
  935. /*========================================================================
  936. 功能: 初始化图像列表
  937. ==========================================================================*/
  938. BOOL CCoolMenu::InitImageList()
  939. {
  940. CBitmap bitmap, tempbitmap;
  941. CSize szIcon(16, 16);
  942. bitmap.LoadBitmap(m_uBitmapID);
  943. if (bitmap.GetSafeHandle() == NULL)
  944. {
  945. return FALSE;
  946. }
  947. m_iImageList.DeleteImageList();
  948. m_iHotImageList.DeleteImageList();
  949. m_iDisabledImageList.DeleteImageList();
  950. m_iImageList.Create(szIcon.cx, szIcon.cy, ILC_COLOR24 | ILC_MASK, 16, 16);
  951. m_iHotImageList.Create(szIcon.cx, szIcon.cy, ILC_COLOR24 | ILC_MASK, 16, 16);
  952. m_iDisabledImageList.Create(szIcon.cx, szIcon.cy, ILC_COLOR24 |ILC_MASK, 16, 16);
  953. BOOL bAlpha = ((GetStyle() & CMS_32IMAGELIST) == CMS_32IMAGELIST);
  954. //创建正常图像列表----------------------------------------
  955. HBITMAP bm = NULL;
  956. if ((GetStyle() & CMS_ICONBAR) == 0)
  957. {
  958. bm =CCoolMenu::CreateImage(HBITMAP(bitmap), 1, bAlpha, m_crMenuColor, m_crMarkColor);
  959. }
  960. else
  961. {
  962. bm = CCoolMenu::CreateImage(HBITMAP(bitmap), 1, bAlpha, m_crIconBarColor, m_crMarkColor);
  963. }
  964. tempbitmap.Attach(bm);
  965. m_iImageList.Add(&tempbitmap, RGB(255, 0, 255));
  966. //创建禁止图像列表----------------------------------------
  967. tempbitmap.DeleteObject();
  968. if (GetStyle() & CMS_ICONBAR == 0)
  969. {
  970. bm = CCoolMenu::CreateImage(HBITMAP(bitmap), 0, bAlpha, m_crMenuColor, m_crMarkColor);
  971. }
  972. else
  973. {
  974. bm = CCoolMenu::CreateImage(HBITMAP(bitmap), 0, bAlpha, m_crIconBarColor, m_crMarkColor);
  975. }
  976. tempbitmap.Attach(bm);
  977. m_iDisabledImageList.Add(&tempbitmap, RGB(255, 0, 255));
  978. //创建热图像列表----------------------------------------
  979. tempbitmap.DeleteObject();
  980. bm = CCoolMenu::CreateImage(HBITMAP(bitmap), 2, bAlpha, m_crLightBarStartColor, m_crMarkColor);
  981. tempbitmap.Attach(bm);
  982. m_iHotImageList.Add(&tempbitmap, RGB(255, 0, 255));
  983. bitmap.DeleteObject();
  984. return TRUE;
  985. }
  986. /*========================================================================
  987. 功能: 从工具栏资源中提取命令ID
  988. ---------------------------------------------
  989. uToolBarID: 工具栏资源ID
  990. uIDArray: 用于存贮ID列表的数组指针
  991. ==========================================================================*/
  992. int CCoolMenu::GetIDFromToolBar(UINT uToolBarID, CUIntArray *uIDArray)
  993. {
  994. if (uToolBarID <= 0 || uIDArray == NULL) return -1;
  995. struct CToolBarData
  996. {
  997. WORD wVersion;
  998. WORD wWidth;
  999. WORD wHeight;
  1000. WORD wItemCount;
  1001. WORD* items()
  1002. {
  1003. return (WORD*)(this + 1); 
  1004. }
  1005. };
  1006. ASSERT(MAKEINTRESOURCE(uToolBarID) != NULL);
  1007. HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(uToolBarID), RT_TOOLBAR);
  1008. HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(uToolBarID), RT_TOOLBAR);
  1009. if (hRsrc == NULL)
  1010. {
  1011. return -1;
  1012. }
  1013. HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
  1014. if (hGlobal == NULL)
  1015. {
  1016. return -1;
  1017. }
  1018. CToolBarData* pData = (CToolBarData*)LockResource(hGlobal);
  1019. if (pData == NULL)
  1020. {
  1021. return -1;
  1022. }
  1023. ASSERT(pData->wVersion == 1);
  1024. UINT uID;
  1025. for (int i = 0; i < pData->wItemCount; i++)
  1026. {
  1027. uID = pData->items()[i];
  1028. if (uID != ID_SEPARATOR)
  1029. {
  1030. uIDArray->Add(uID);
  1031. }
  1032. }
  1033. UnlockResource(hGlobal);
  1034. FreeResource(hGlobal);
  1035. return uIDArray->GetSize();
  1036. }
  1037. /*########################################################################
  1038.   ------------------------------------------------
  1039. class CMenuWndHook
  1040.   ------------------------------------------------
  1041.   ########################################################################*/
  1042. CMap <HWND, HWND, CMenuWndHook*, CMenuWndHook*> CMenuWndHook::m_WndMenuMap;
  1043. HHOOK CMenuWndHook::m_hMenuHook = NULL;
  1044. COLORREF CMenuWndHook::m_crFrame[4] = {::GetSysColor(COLOR_3DDKSHADOW), ::GetSysColor(COLOR_3DDKSHADOW), ::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_WINDOW)};
  1045. CMenuWndHook::CMenuWndHook (HWND hWnd)
  1046. : m_hWnd(hWnd), m_rcMenu(0, 0, 0, 0), m_ptMenu(-0xFFFF, -0xFFFF)
  1047. {
  1048. }
  1049. CMenuWndHook::~CMenuWndHook ()
  1050. {
  1051.     WNDPROC oldWndProc = (WNDPROC)::GetProp(m_hWnd, CoolMenu_oldProc);
  1052.     if (oldWndProc != NULL)
  1053.     {
  1054.         ::SetWindowLong(m_hWnd, GWL_WNDPROC, (DWORD)(ULONG)oldWndProc);
  1055.         ::RemoveProp(m_hWnd, CoolMenu_oldProc);
  1056.     }
  1057.     m_WndMenuMap.RemoveKey(m_hWnd);
  1058. }
  1059. void CMenuWndHook::InstallHook()
  1060. {
  1061.     if (m_hMenuHook == NULL )
  1062.     {
  1063.         m_hMenuHook = ::SetWindowsHookEx(WH_CALLWNDPROC, WindowHook, 
  1064. AfxGetApp()->m_hInstance, ::GetCurrentThreadId());
  1065.     }
  1066. }
  1067. void CMenuWndHook::UnInstallHook()
  1068. {
  1069.     POSITION pos = m_WndMenuMap.GetStartPosition();
  1070.     while (pos != NULL)
  1071.     {
  1072.         HWND hwnd;
  1073.         CMenuWndHook* pMenuWndHook;
  1074.         m_WndMenuMap.GetNextAssoc(pos, hwnd, pMenuWndHook);
  1075.         delete pMenuWndHook;
  1076. pMenuWndHook = NULL;
  1077.     }
  1078.     m_WndMenuMap.RemoveAll();
  1079.     if (m_hMenuHook != NULL)
  1080.     {
  1081.         ::UnhookWindowsHookEx(m_hMenuHook);
  1082.     }
  1083. }
  1084. CMenuWndHook* CMenuWndHook::GetWndHook(HWND hwnd)
  1085. {
  1086.     CMenuWndHook* pWnd = NULL;
  1087.     if (m_WndMenuMap.Lookup(hwnd, pWnd))
  1088.     {
  1089.         return pWnd;
  1090.     }
  1091.     return NULL;
  1092. }
  1093. CMenuWndHook* CMenuWndHook::AddWndHook(HWND hwnd)
  1094. {
  1095. CMenuWndHook* pWnd = NULL;
  1096. if (m_WndMenuMap.Lookup(hwnd, pWnd))
  1097. {
  1098.    return pWnd;
  1099. }
  1100. pWnd = new CMenuWndHook(hwnd);
  1101. if (pWnd != NULL)
  1102. {
  1103. m_WndMenuMap.SetAt(hwnd, pWnd);
  1104. }
  1105. return pWnd;
  1106. }
  1107. /*########################################################################
  1108.   ------------------------------------------------
  1109.   消息过程
  1110.   ------------------------------------------------
  1111.   ########################################################################*/
  1112. LRESULT CALLBACK CMenuWndHook::WindowHook(int code, WPARAM wParam, LPARAM lParam)
  1113. {
  1114.     CWPSTRUCT* pStruct = (CWPSTRUCT*)lParam;
  1115.     while (code == HC_ACTION)
  1116.     {
  1117.         HWND hWnd = pStruct->hwnd;
  1118.         if (pStruct->message != WM_CREATE && pStruct->message != 0x01E2)
  1119.         {
  1120.             break;
  1121.         }
  1122.         // 是否为菜单类 ----------------------------------------
  1123.         TCHAR strClassName[10];
  1124.         int Count = ::GetClassName (hWnd, strClassName, sizeof(strClassName) / sizeof(strClassName[0]));
  1125.         if (Count != 6 || _tcscmp(strClassName, _T("#32768")) != 0 )
  1126.         {
  1127.             break;
  1128.         }
  1129. // 是否已经被子类化 ------------------------------------
  1130.         if (::GetProp(pStruct->hwnd, CoolMenu_oldProc) != NULL )
  1131.         {
  1132.             break;
  1133.         }
  1134.         VERIFY(AddWndHook(pStruct->hwnd) != NULL);
  1135.         // 取得原来的窗口过程 ----------------------------------
  1136.         WNDPROC oldWndProc = (WNDPROC)(long)::GetWindowLong(pStruct->hwnd, GWL_WNDPROC);
  1137.         if (oldWndProc == NULL)
  1138.         {
  1139.             break;
  1140.         }
  1141.         ASSERT(oldWndProc != CoolMenuProc);
  1142.         // 保存到窗口的属性中 ----------------------------------
  1143.         if (!SetProp(pStruct->hwnd, CoolMenu_oldProc, oldWndProc) )
  1144.         {
  1145.             break;
  1146.         }
  1147.         // 子类化 ----------------------------------------------
  1148.         if (!SetWindowLong(pStruct->hwnd, GWL_WNDPROC,(DWORD)(ULONG)CoolMenuProc) )
  1149.         {
  1150.             ::RemoveProp(pStruct->hwnd, CoolMenu_oldProc);
  1151.             break;
  1152.         }
  1153.         break;
  1154.     }
  1155.     return CallNextHookEx (m_hMenuHook, code, wParam, lParam);
  1156. }
  1157. LRESULT CALLBACK CMenuWndHook::CoolMenuProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1158. {
  1159. WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, CoolMenu_oldProc);
  1160.     CMenuWndHook* pWnd = NULL;
  1161.     switch (uMsg)
  1162.     {
  1163. case WM_NCCALCSIZE:
  1164. {
  1165. LRESULT lResult = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
  1166. if ((pWnd = GetWndHook(hWnd)) != NULL)
  1167. {
  1168. pWnd->OnNcCalcsize((NCCALCSIZE_PARAMS*)lParam);
  1169. }
  1170. return lResult;
  1171. }
  1172. break;
  1173. case WM_WINDOWPOSCHANGING:
  1174. {
  1175. if ((pWnd = GetWndHook(hWnd)) != NULL)
  1176. {
  1177. pWnd->OnWindowPosChanging((LPWINDOWPOS)lParam);
  1178. }
  1179. }
  1180. break;
  1181. case WM_PRINT:
  1182. {
  1183. LRESULT lResult = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
  1184. if ((pWnd = GetWndHook(hWnd)) != NULL)
  1185. {
  1186. pWnd->OnPrint(CDC::FromHandle((HDC)wParam));
  1187. }
  1188. return lResult;
  1189. }
  1190. break;
  1191. case WM_NCPAINT:
  1192. {
  1193. if ((pWnd = GetWndHook(hWnd)) != NULL)
  1194. {
  1195. pWnd->OnNcPaint();
  1196. return 0;
  1197. }
  1198. }
  1199. break;
  1200. case WM_SHOWWINDOW:
  1201. {
  1202. if ((pWnd = GetWndHook(hWnd)) != NULL)
  1203. {
  1204. pWnd->OnShowWindow(wParam != NULL);
  1205. }
  1206. }
  1207. break;
  1208. case WM_NCDESTROY:
  1209. {
  1210. if ((pWnd = GetWndHook(hWnd)) != NULL)
  1211. {
  1212. pWnd->OnNcDestroy();
  1213. }
  1214. }
  1215. break;
  1216.     }
  1217.     return CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
  1218. }
  1219. /*########################################################################
  1220.   ------------------------------------------------
  1221. 消息处理函数
  1222.   ------------------------------------------------
  1223.   ########################################################################*/
  1224. void CMenuWndHook::OnWindowPosChanging(WINDOWPOS *pWindowPos)
  1225. {
  1226. if (!IsShadowEnabled())
  1227. {
  1228. pWindowPos->cx += 4;
  1229. pWindowPos->cy += 4;
  1230. }
  1231. pWindowPos->cx -= 2;
  1232. pWindowPos->cy -= 2;
  1233.     pWindowPos->y--;
  1234.     m_ptMenu.x = pWindowPos->x;
  1235.     m_ptMenu.y = pWindowPos->y;
  1236. if (!IsWindowVisible(m_hWnd))
  1237.     {
  1238. CRect rc;
  1239. GetClientRect(m_hWnd, &rc);
  1240.         if (m_bmpBack.m_hObject != NULL )
  1241.         {
  1242.             m_bmpBack.DeleteObject();
  1243.         }
  1244.         m_bmpBack.Attach(GetScreenBitmap(CRect(m_ptMenu.x, m_ptMenu.y, rc.right + m_ptMenu.x + 10,
  1245. rc.bottom + m_ptMenu.y + 10)));
  1246.     }
  1247. }
  1248. void CMenuWndHook::OnNcPaint()
  1249. {
  1250.     CWindowDC dc(CWnd::FromHandle(m_hWnd));
  1251. OnPrint(&dc);
  1252. }
  1253. void CMenuWndHook::OnPrint(CDC *pDC)
  1254. {
  1255. CRect rc;
  1256. GetWindowRect(m_hWnd, &rc);
  1257.     rc.OffsetRect(-rc.TopLeft());
  1258.     if (rc != m_rcMenu)
  1259.     {
  1260.         m_rcMenu = rc;
  1261. if (!IsShadowEnabled())
  1262. {
  1263. CDC cMemDC;
  1264. cMemDC.CreateCompatibleDC (pDC);
  1265. HGDIOBJ hOldBitmap = ::SelectObject (cMemDC.m_hDC, m_bmpBack);
  1266. pDC->BitBlt (0, rc.bottom - 4, rc.Width() - 4, 4, &cMemDC, 0, rc.bottom - 4, SRCCOPY);
  1267. pDC->BitBlt (rc.right - 4, 0, 4, rc.Height(), &cMemDC, rc.right - 4, 0, SRCCOPY);
  1268. DrawShadow(pDC, rc);
  1269. rc.right -= 4;
  1270. rc.bottom -= 4;
  1271. }
  1272. pDC->Draw3dRect(rc, m_crFrame[0], m_crFrame[1]);
  1273. rc.DeflateRect (1, 1);
  1274. pDC->Draw3dRect(rc, m_crFrame[2], m_crFrame[3]);
  1275. #if defined(_ANYOU_COOLMENU_H)
  1276. if (CCoolMenu::m_rcMenuItem.bottom == (m_ptMenu.y + 1) && CCoolMenu::m_rcMenuItem.Width() > 0)
  1277. {
  1278. CPen pen(0, 1, ::GetSysColor(COLOR_3DFACE));
  1279. CPen *oldpen = pDC->SelectObject(&pen);
  1280. pDC->MoveTo(m_rcMenu.left + 1, m_rcMenu.top);
  1281. pDC->LineTo(CCoolMenu::m_rcMenuItem.Width() - 5, m_rcMenu.top);
  1282. pDC->SelectObject(oldpen);
  1283. }
  1284. #endif
  1285.     }
  1286. }
  1287. void CMenuWndHook::OnNcDestroy()
  1288. {
  1289. delete this;
  1290. }
  1291. void CMenuWndHook::OnShowWindow(BOOL bShow)
  1292. {
  1293.     if (!bShow)
  1294.     {
  1295.         delete this;
  1296.     }
  1297. }
  1298. void CMenuWndHook::OnNcCalcsize(NCCALCSIZE_PARAMS* lpncsp)
  1299. {
  1300. if (!IsShadowEnabled())
  1301. {
  1302.  lpncsp->rgrc[0].right -= 4;
  1303.  lpncsp->rgrc[0].bottom -= 4;
  1304. }
  1305. lpncsp->rgrc[0].top -= 1;
  1306. lpncsp->rgrc[0].left -= 1;
  1307. lpncsp->rgrc[0].right += 1;
  1308. lpncsp->rgrc[0].bottom += 1;
  1309. }
  1310. CCoolMenuTheme::CCoolMenuTheme()
  1311. {
  1312. }
  1313. CCoolMenuTheme::~CCoolMenuTheme()
  1314. {
  1315. }
  1316. /*========================================================================
  1317. 功能: 设置菜单预置风格
  1318. ----------------------------------------------------------
  1319. dwstyle: 风格名,只能是以下值之一:
  1320. -------------------------------------------
  1321. - MENU_STYLE_DEFAULT: 默认风格
  1322. - MENU_STYLE_XP: Office XP 风格
  1323. - MENU_STYLE_XP2: 另一种 Office XP 风格
  1324. - MENU_STYLE_SNOW: 白色风格
  1325. - MENU_STYLE_GREEN: 绿色风格
  1326. - MENU_STYLE_BLUE: 蓝色风格
  1327. - ... ...
  1328. ----------------------------------------------------------
  1329. 说明: 可以在这个函数里添加代码,添加更多的自定义
  1330. 风格,以便在使用菜单时,可以很快地切换成想要的菜单
  1331. 风格。
  1332. ==========================================================================*/
  1333. void CCoolMenuTheme::SetTheme(DWORD dwstyle)
  1334. {
  1335. if (dwstyle == MENU_STYLE_DEFAULT)
  1336. {
  1337. CCoolMenu::SetStyle(CCoolMenu::GetStyle() & ~CMS_ICONBAR);
  1338. CCoolMenu::SetMenuColor(::GetSysColor(COLOR_MENU));
  1339. CCoolMenu::SetIconBarColor(::GetSysColor(COLOR_3DFACE));
  1340. CCoolMenu::SetLightBarColor(RGB(10, 36, 106));
  1341. CCoolMenu::SetLightBarStartColor(RGB(10, 36, 106));
  1342. CCoolMenu::SetLightBarEndColor(RGB(10, 36, 106));
  1343. CCoolMenu::SetTextColor(::GetSysColor(COLOR_MENUTEXT));
  1344. CCoolMenu::SetHighLightColor(RGB(255, 255, 255));
  1345. CMenuWndHook::m_crFrame[0] = RGB(148, 150, 148);
  1346. CMenuWndHook::m_crFrame[1] = RGB(48, 50, 48);
  1347. CMenuWndHook::m_crFrame[2] = RGB(255, 255, 255);
  1348. CMenuWndHook::m_crFrame[3] = RGB(180, 180, 180);
  1349. }
  1350. else if (dwstyle == MENU_STYLE_XP)
  1351. {
  1352. CCoolMenu::SetStyle(CCoolMenu::GetStyle() | CMS_ICONBAR);
  1353. CCoolMenu::SetMenuColor(RGB(255,255,255));
  1354. CCoolMenu::SetIconBarColor(::GetSysColor(COLOR_3DFACE));
  1355. CCoolMenu::SetLightBarColor(RGB(155,155,185));
  1356. CCoolMenu::SetLightBarStartColor(RGB(234, 240, 250));
  1357. CCoolMenu::SetLightBarEndColor(RGB(196, 212, 239));
  1358. CCoolMenu::SetTextColor(::GetSysColor(COLOR_MENUTEXT));
  1359. CCoolMenu::SetHighLightColor(RGB(20, 20, 50));
  1360. CMenuWndHook::m_crFrame[0] = RGB(48, 50, 48);
  1361. CMenuWndHook::m_crFrame[1] = RGB(48, 50, 48);
  1362. CMenuWndHook::m_crFrame[2] = RGB(255, 255, 255);
  1363. CMenuWndHook::m_crFrame[3] = RGB(255, 255, 255);
  1364. }
  1365. else if (dwstyle == MENU_STYLE_SNOW)
  1366. {
  1367. CCoolMenu::SetStyle(CCoolMenu::GetStyle() & ~CMS_ICONBAR);
  1368. CCoolMenu::SetMenuColor(RGB(255,255,255));
  1369. CCoolMenu::SetIconBarColor(::GetSysColor(COLOR_3DFACE));
  1370. CCoolMenu::SetLightBarColor(RGB(155,155,185));
  1371. CCoolMenu::SetLightBarStartColor(RGB(234, 240, 250));
  1372. CCoolMenu::SetLightBarEndColor(RGB(196, 212, 239));
  1373. CCoolMenu::SetTextColor(RGB(0, 0, 0));
  1374. CCoolMenu::SetHighLightColor(RGB(0, 0, 0));
  1375. CMenuWndHook::m_crFrame[0] = RGB(48, 50, 48);
  1376. CMenuWndHook::m_crFrame[1] = RGB(48, 50, 48);
  1377. CMenuWndHook::m_crFrame[2] = RGB(255, 255, 255);
  1378. CMenuWndHook::m_crFrame[3] = RGB(255, 255, 255);
  1379. }
  1380. else if (dwstyle == MENU_STYLE_GREEN)
  1381. {
  1382. CCoolMenu::SetStyle(CCoolMenu::GetStyle() & ~CMS_ICONBAR);
  1383. CCoolMenu::SetMenuColor(RGB(220,235,220));
  1384. CCoolMenu::SetIconBarColor(::GetSysColor(COLOR_3DFACE));
  1385. CCoolMenu::SetLightBarColor(RGB(155,185,155));
  1386. CCoolMenu::SetLightBarStartColor(RGB(240, 250, 234));
  1387. CCoolMenu::SetLightBarEndColor(RGB(212, 239, 196));
  1388. CCoolMenu::SetTextColor(RGB(10, 80, 10));
  1389. CCoolMenu::SetHighLightColor(RGB(20, 20, 50));
  1390. CMenuWndHook::m_crFrame[0] = RGB(128, 150, 128);
  1391. CMenuWndHook::m_crFrame[1] = RGB(48, 50, 48);
  1392. CMenuWndHook::m_crFrame[2] = RGB(255, 255, 255);
  1393. CMenuWndHook::m_crFrame[3] = RGB(168, 210, 168);
  1394. }
  1395. else if (dwstyle == MENU_STYLE_BLUE)
  1396. {
  1397. CCoolMenu::SetStyle(CCoolMenu::GetStyle() & ~CMS_ICONBAR);
  1398. CCoolMenu::SetMenuColor(RGB(225,225,235));
  1399. CCoolMenu::SetIconBarColor(::GetSysColor(COLOR_3DFACE));
  1400. CCoolMenu::SetLightBarColor(RGB(155,155,185));
  1401. CCoolMenu::SetLightBarStartColor(RGB(234, 240, 250));
  1402. CCoolMenu::SetLightBarEndColor(RGB(196, 212, 239));
  1403. CCoolMenu::SetTextColor(RGB(10, 10, 80));
  1404. CCoolMenu::SetHighLightColor(RGB(20, 20, 50));
  1405. CMenuWndHook::m_crFrame[0] = RGB(120, 120, 158);
  1406. CMenuWndHook::m_crFrame[1] = RGB(48, 50, 48);
  1407. CMenuWndHook::m_crFrame[2] = RGB(255, 255, 255);
  1408. CMenuWndHook::m_crFrame[3] = RGB(168, 168, 210);
  1409. }
  1410. else if (dwstyle == MENU_STYLE_XP2)
  1411. {
  1412. CCoolMenu::SetStyle(CCoolMenu::GetStyle() | CMS_ICONBAR);
  1413. CCoolMenu::SetMenuColor(::GetSysColor(COLOR_3DFACE));
  1414. CCoolMenu::SetIconBarColor(RGB(255,255,255));
  1415. CCoolMenu::SetLightBarColor(RGB(155,155,185));
  1416. CCoolMenu::SetLightBarStartColor(RGB(234, 240, 250));
  1417. CCoolMenu::SetLightBarEndColor(RGB(196, 212, 239));
  1418. CCoolMenu::SetTextColor(::GetSysColor(COLOR_MENUTEXT));
  1419. CCoolMenu::SetHighLightColor(RGB(20, 20, 50));
  1420. CMenuWndHook::m_crFrame[0] = RGB(48, 50, 48);
  1421. CMenuWndHook::m_crFrame[1] = RGB(48, 50, 48);
  1422. CMenuWndHook::m_crFrame[2] = RGB(255, 255, 255);
  1423. CMenuWndHook::m_crFrame[3] = RGB(255, 255, 255);
  1424. }
  1425. CCoolMenu::InitImageList();
  1426. }