GfxPopupMenu.cpp
上传用户:guangzhiyw
上传日期:2007-01-09
资源大小:495k
文件大小:14k
源码类别:

ICQ/即时通讯

开发平台:

Visual C++

  1. // GfxPopupMenu.cpp: implementation of the CGfxPopupMenu class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "GfxPopupMenu.h"
  6. #ifdef _DEBUG
  7. #undef THIS_FILE
  8. static char THIS_FILE[]=__FILE__;
  9. #define new DEBUG_NEW
  10. #endif
  11. //////////////////////////////////////////////////////////////////////
  12. // Construction/Destruction
  13. //////////////////////////////////////////////////////////////////////
  14. CGfxPopupMenu::CGfxPopupMenu()
  15. {
  16. crMenuText = GetSysColor(COLOR_MENUTEXT);
  17. crMenuTextSel = GetSysColor(COLOR_HIGHLIGHTTEXT);
  18. cr3dFace = GetSysColor(COLOR_3DFACE);
  19. crMenu = GetSysColor(COLOR_MENU);
  20. crHighlight = GetSysColor(COLOR_HIGHLIGHT);
  21. cr3dHilight = GetSysColor(COLOR_3DHILIGHT);
  22. cr3dShadow = GetSysColor(COLOR_3DSHADOW);
  23. crGrayText = GetSysColor(COLOR_GRAYTEXT);
  24. m_clrBtnFace = GetSysColor(COLOR_BTNFACE);
  25. m_clrBtnHilight = GetSysColor(COLOR_BTNHILIGHT);
  26. m_clrBtnShadow = GetSysColor(COLOR_BTNSHADOW);
  27. iSpawnItem = 0;
  28. pSpawnItem = NULL;
  29. iImageItem = 0;
  30. pImageItem = NULL;
  31. szImage = CSize(20,20);
  32. hMenuFont = NULL;
  33. NONCLIENTMETRICS ncm;
  34. memset(&ncm, 0, sizeof(ncm));
  35. ncm.cbSize = sizeof(ncm);
  36. ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0);
  37. hGuiFont = ::CreateFontIndirect(&ncm.lfMenuFont);
  38. hMenuBoldFont = NULL;
  39. CreateBoldFont();
  40. }
  41. CGfxPopupMenu::~CGfxPopupMenu()
  42. {
  43. if (iSpawnItem > 0)
  44. {
  45. for (int t = 0; t < iSpawnItem; t++)
  46. if (pSpawnItem[t]) delete pSpawnItem[t];
  47. GlobalFree((HGLOBAL) pSpawnItem);
  48. }
  49. if (iImageItem > 0)
  50. {
  51. GlobalFree((HGLOBAL) pImageItem);
  52. }
  53. if (hMenuFont) ::DeleteObject((HGDIOBJ)hMenuFont);
  54. if (hMenuBoldFont) ::DeleteObject((HGDIOBJ)hMenuBoldFont);
  55. }
  56. void CGfxPopupMenu::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  57. {
  58. if (lpDrawItemStruct->CtlType == ODT_MENU)
  59. {
  60. UINT id = lpDrawItemStruct->itemID;
  61. UINT state = lpDrawItemStruct->itemState;
  62. bool bEnab = !(state & ODS_DISABLED);
  63. bool bSelect = (state & ODS_SELECTED) ? true : false;
  64. bool bChecked = (state & ODS_CHECKED) ? true : false;
  65. bool bBold = (state & ODS_DEFAULT) ? true : false;
  66. SpawnItem * pItem = (SpawnItem *) lpDrawItemStruct->itemData;
  67. if (pItem)
  68. {
  69. CDC * pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  70. CFont * pft;
  71. if (!bBold) pft = CFont::FromHandle((HFONT) hMenuFont ? hMenuFont : hGuiFont);
  72. else pft = CFont::FromHandle((HFONT) hMenuBoldFont ? hMenuBoldFont : hGuiFont);
  73. CFont * of = pDC->SelectObject(pft);
  74. CRect rc(lpDrawItemStruct->rcItem);
  75. CRect rcImage(rc), rcText(rc);
  76. rcImage.right = rcImage.left + rc.Height();
  77. rcImage.bottom = rc.bottom;
  78. if (pItem->iCmd == -3) // is a separator
  79. {
  80. CPen pnDk(PS_SOLID,1,cr3dShadow);
  81. CPen pnLt(PS_SOLID,1,cr3dHilight);
  82. CPen * opn = pDC->SelectObject(&pnDk);
  83. pDC->MoveTo(rc.left + 2, rc.top + 2);
  84. pDC->LineTo(rc.right - 2, rc.top + 2);
  85. pDC->SelectObject(&pnLt);
  86. pDC->MoveTo(rc.left + 2, rc.top + 3);
  87. pDC->LineTo(rc.right - 2, rc.top + 3);
  88. pDC->SelectObject(opn);
  89. }
  90. else if (pItem->iCmd == -4) // is a title item
  91. {
  92. CString cs(pItem->cText), cs1;
  93. CRect rcBdr(rcText);
  94. if (bSelect && bEnab)
  95. {
  96. rcText.top ++;
  97. rcText.left += 2;
  98. }
  99. pDC->FillSolidRect(rcText, crMenu);
  100. pDC->DrawText(cs, rcText, DT_VCENTER|DT_CENTER|DT_SINGLELINE);
  101. if (bSelect && bEnab) pDC->Draw3dRect(rcBdr,cr3dShadow,cr3dHilight);
  102. }
  103. else
  104. {
  105. rcText.left += rcImage.right + 1;
  106. int obk = pDC->SetBkMode(TRANSPARENT);
  107. COLORREF ocr;
  108. if (bSelect)
  109. {
  110. if (pItem->iImageIdx >= 0 || (state & ODS_CHECKED))
  111. pDC->FillSolidRect(rcText, crHighlight);
  112. else
  113. pDC->FillSolidRect(rc, crHighlight);
  114. ocr = pDC->SetTextColor(crMenuTextSel);
  115. }
  116. else
  117. {
  118. if (pItem->iImageIdx >= 0 || (state & ODS_CHECKED))
  119. pDC->FillSolidRect(rcText, crMenu);
  120. else
  121. pDC->FillSolidRect(rc/*rcText*/, crMenu);
  122. ocr = pDC->SetTextColor(crMenuText);
  123. }
  124. if (pItem->iImageIdx >= 0)
  125. {
  126. int ay = (rcImage.Height() - szImage.cy) / 2;
  127. int ax = (rcImage.Width()  - szImage.cx) / 2;
  128. if (bSelect && bEnab)
  129. pDC->Draw3dRect(rcImage,cr3dHilight,cr3dShadow);
  130. else
  131. {
  132. pDC->Draw3dRect(rcImage,crMenu,crMenu);
  133. }
  134. if (bEnab)
  135. {
  136. ilList.Draw(pDC, pItem->iImageIdx, CPoint(rcImage.left + ax, rcImage.top +ay), ILD_NORMAL);
  137. }
  138. else
  139. {
  140. HICON hIcon = ilList.ExtractIcon( pItem->iImageIdx );
  141. pDC->DrawState( CPoint(rcImage.left + ax, rcImage.top + ay ), szImage, (HICON)hIcon, DST_ICON | DSS_DISABLED, (CBrush *)NULL );
  142. }
  143. }
  144. else
  145. {
  146. if (bChecked)
  147. {
  148. int ay = (rcImage.Height() - szImage.cy) / 2;
  149. int ax = (rcImage.Width()  - szImage.cx) / 2;
  150. ilOther.Draw(pDC, 0, CPoint(rcImage.left + ax, rcImage.top + ay - 2), ILD_NORMAL);
  151. }
  152. }
  153. CString cs(pItem->cText), cs1;
  154. CSize sz;
  155. sz = pDC->GetTextExtent(cs);
  156. int ay1 = (rcText.Height() - sz.cy) / 2;
  157. rcText.top += ay1;
  158. rcText.left += 2;
  159. rcText.right -= 15;
  160. int tf = cs.Find('t');
  161. if (tf >= 0)
  162. {
  163. cs1 = cs.Right(cs.GetLength() - tf - 1);
  164. cs = cs.Left(tf);
  165. if (!bEnab)
  166. {
  167. if (!bSelect)
  168. {
  169. CRect rcText1(rcText);
  170. rcText1.InflateRect(-1,-1);
  171. pDC->SetTextColor(cr3dHilight);
  172. pDC->DrawText(cs, rcText1, DT_VCENTER|DT_LEFT);
  173. pDC->DrawText(cs1, rcText1, DT_VCENTER|DT_RIGHT);
  174. pDC->SetTextColor(crGrayText);
  175. pDC->DrawText(cs, rcText, DT_VCENTER|DT_LEFT);
  176. pDC->DrawText(cs1, rcText, DT_VCENTER|DT_RIGHT);
  177. }
  178. else
  179. {
  180. pDC->SetTextColor(crMenu);
  181. pDC->DrawText(cs, rcText, DT_VCENTER|DT_LEFT);
  182. pDC->DrawText(cs1, rcText, DT_VCENTER|DT_RIGHT);
  183. }
  184. }
  185. else
  186. {
  187. pDC->DrawText(cs, rcText, DT_VCENTER|DT_LEFT);
  188. pDC->DrawText(cs1, rcText, DT_VCENTER|DT_RIGHT);
  189. }
  190. }
  191. else 
  192. {
  193. if (!bEnab)
  194. {
  195. if (!bSelect)
  196. {
  197. CRect rcText1(rcText);
  198. rcText1.InflateRect(-1,-1);
  199. pDC->SetTextColor(cr3dHilight);
  200. pDC->DrawText(cs, rcText1, DT_VCENTER|DT_LEFT|DT_EXPANDTABS);
  201. pDC->SetTextColor(crGrayText);
  202. pDC->DrawText(cs, rcText, DT_VCENTER|DT_LEFT|DT_EXPANDTABS);
  203. }
  204. else
  205. {
  206. pDC->SetTextColor(crMenu);
  207. pDC->DrawText(cs, rcText, DT_VCENTER|DT_LEFT|DT_EXPANDTABS);
  208. }
  209. }
  210. else
  211. pDC->DrawText(cs, rcText, DT_VCENTER|DT_LEFT|DT_EXPANDTABS);
  212. }
  213. pDC->SetTextColor(ocr);
  214. pDC->SetBkMode(obk);
  215. }
  216. pDC->SelectObject(of);
  217. }
  218. }
  219. }
  220. void CGfxPopupMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  221. {
  222. bool res = false;
  223. if (lpMeasureItemStruct->CtlType == ODT_MENU)
  224. {
  225. UINT id = lpMeasureItemStruct->itemID;
  226. SpawnItem * pItem = (SpawnItem *) lpMeasureItemStruct->itemData;
  227. if (pItem)
  228. {
  229. if (pItem->iCmd == -3) // is a separator
  230. {
  231. lpMeasureItemStruct->itemWidth  = 10;
  232. lpMeasureItemStruct->itemHeight = 6;
  233. }
  234. else
  235. {
  236. CString cs(pItem->cText);
  237. if (!cs.IsEmpty())
  238. {
  239. CClientDC dc(AfxGetMainWnd());
  240. CFont * pft = CFont::FromHandle(hMenuFont ? hMenuFont : hGuiFont);
  241. CFont * of = dc.SelectObject(pft);
  242. CSize osz = dc.GetOutputTabbedTextExtent(cs,0,NULL);
  243. if (pItem->iCmd == -4)
  244. {
  245. CRect rci(0,0,0,0);
  246. dc.DrawText(cs, rci, DT_CALCRECT|DT_TOP|DT_VCENTER|DT_SINGLELINE);
  247. lpMeasureItemStruct->itemHeight = rci.Height();
  248. lpMeasureItemStruct->itemWidth = rci.Width();
  249. }
  250. else
  251. {
  252. lpMeasureItemStruct->itemHeight = szImage.cy + 5;
  253. if (osz.cy > (int) lpMeasureItemStruct->itemHeight) lpMeasureItemStruct->itemHeight = (int) osz.cy;
  254. lpMeasureItemStruct->itemWidth  = osz.cx + 2 + 15;
  255. lpMeasureItemStruct->itemWidth += lpMeasureItemStruct->itemHeight > (UINT) szImage.cx ? (UINT) lpMeasureItemStruct->itemHeight : (UINT) szImage.cx;
  256. }
  257. dc.SelectObject(of);
  258. }
  259. else
  260. {
  261. lpMeasureItemStruct->itemHeight = szImage.cy + 5;
  262. lpMeasureItemStruct->itemWidth  = 100;
  263. }
  264. }
  265. }
  266. }
  267. }
  268. bool CGfxPopupMenu::CreateBoldFont()
  269. {
  270. if (hMenuBoldFont) 
  271. ::DeleteObject((HGDIOBJ)hMenuBoldFont);
  272. LOGFONT lgFont;
  273. ::GetObject (hMenuFont ? hMenuFont : hGuiFont, sizeof (lgFont), &lgFont);
  274. lgFont.lfWeight = FW_BOLD;
  275. hMenuBoldFont = CreateFontIndirect (&lgFont);
  276. return !!hMenuBoldFont;
  277. }
  278. bool CGfxPopupMenu::AddToolBarResource(unsigned int resId)
  279. {
  280. // David 08/04/98 - start - put CMenuSpawn in DLL
  281. HINSTANCE hInst = AfxFindResourceHandle (MAKEINTRESOURCE(resId), RT_TOOLBAR);
  282. if (!hInst)
  283. return false;
  284. // David 08/04/98 - end - put CMenuSpawn in DLL
  285. HRSRC hRsrc = ::FindResource(/*AfxGetResourceHandle()*/hInst, MAKEINTRESOURCE(resId), RT_TOOLBAR);
  286. if (hRsrc == NULL) return false;
  287. HGLOBAL hGlb = ::LoadResource(/*AfxGetResourceHandle()*/hInst, hRsrc);
  288. if (hGlb == NULL) return false;
  289. ToolBarData* pTBData = (ToolBarData*) ::LockResource(hGlb);
  290. if (pTBData == NULL) return false;
  291. ASSERT(pTBData->wVersion == 1);
  292. CBitmap bmp;
  293. bmp.LoadBitmap(resId);
  294. int nBmpItems = ilList.Add(&bmp, RGB(192,192,192));
  295. bmp.DeleteObject();
  296. WORD* pItem = (WORD*)(pTBData+1);
  297. for(int i=0; i<pTBData->wItemCount; i++, pItem++)
  298. {
  299. if(*pItem != ID_SEPARATOR)
  300. AddImageItem(nBmpItems++, (WORD) *pItem);
  301. }
  302. // ** it seem that Windows doesn't free these resource (from Heitor Tome)
  303.     ::UnlockResource(hGlb);
  304.     ::FreeResource(hGlb);
  305. // **
  306. return true;
  307. }
  308. bool CGfxPopupMenu::LoadToolBarResource(unsigned int resId)
  309. {
  310. //David 08/04/98 - start - put CMenuSpawn in DLL
  311. HINSTANCE hInst = AfxFindResourceHandle (MAKEINTRESOURCE(resId), RT_TOOLBAR);
  312. if (!hInst)
  313. return false;
  314. //David 08/04/98 - end - put CMenuSpawn in DLL
  315. HRSRC hRsrc = ::FindResource(/*AfxGetResourceHandle()*/hInst, MAKEINTRESOURCE(resId), RT_TOOLBAR);
  316. if (hRsrc == NULL) return false;
  317. HGLOBAL hGlb = ::LoadResource(/*AfxGetResourceHandle()*/hInst, hRsrc);
  318. if (hGlb == NULL) return false;
  319. ToolBarData* pTBData = (ToolBarData*) ::LockResource(hGlb);
  320. if (pTBData == NULL) return false;
  321. ASSERT(pTBData->wVersion == 1);
  322. szImage.cx = (int) pTBData->wWidth;
  323. szImage.cy = (int) pTBData->wHeight;
  324. if (ilList.Create(szImage.cx, szImage.cy, ILC_COLOR4|ILC_MASK, pTBData->wItemCount, 0) == false)
  325. return false;
  326. ilList.SetBkColor(cr3dFace);
  327. CBitmap bmp;
  328. bmp.LoadBitmap(resId);
  329. ilList.Add(&bmp, RGB(192,192,192));
  330. bmp.DeleteObject();
  331. WORD* pItem = (WORD*)(pTBData+1);
  332. int nBmpItems = 0;
  333. for(int i=0; i<pTBData->wItemCount; i++, pItem++)
  334. {
  335. if(*pItem != ID_SEPARATOR)
  336. AddImageItem(nBmpItems++, (WORD) *pItem);
  337. }
  338. // ** it seem that Windows doesn't free these resource (from Heitor Tome)
  339.     ::UnlockResource(hGlb);
  340.     ::FreeResource(hGlb);
  341. // **
  342. return true;
  343. }
  344. void CGfxPopupMenu::AddImageItem(const int idx, WORD cmd)
  345. {
  346. if (iImageItem == 0)
  347. pImageItem = (ImageItem *) GlobalAlloc(GPTR, sizeof(ImageItem));
  348. else
  349. pImageItem = (ImageItem *) GlobalReAlloc((HGLOBAL) pImageItem, sizeof(ImageItem) * (iImageItem + 1), GMEM_MOVEABLE|GMEM_ZEROINIT);
  350. ASSERT(pImageItem);
  351. pImageItem[iImageItem].iCmd = (int) cmd;
  352. pImageItem[iImageItem].iImageIdx = idx;
  353. iImageItem ++;
  354. }
  355. void CGfxPopupMenu::RemapMenu(CMenu * pMenu)
  356. {
  357. static int iRecurse = 0;
  358. iRecurse ++;
  359. ASSERT(pMenu);
  360. int nItem = pMenu->GetMenuItemCount();
  361. while ((--nItem)>=0)
  362. {
  363. UINT itemId = pMenu->GetMenuItemID(nItem);
  364. if (itemId == (UINT) -1)
  365. {
  366. CMenu *pops = pMenu->GetSubMenu(nItem);
  367. if (pops) RemapMenu(pops);
  368. if (iRecurse > 0)
  369. {
  370. CString cs;
  371. pMenu->GetMenuString(nItem, cs, MF_BYPOSITION);
  372. if (cs != "")
  373. {
  374. SpawnItem * sp = AddSpawnItem(cs, (iRecurse == 1) ? -4 : -2);
  375. pMenu->ModifyMenu(nItem,MF_BYPOSITION|MF_OWNERDRAW, (UINT) -1, (LPCTSTR)sp);
  376. }
  377. }
  378. }
  379. else
  380. {
  381. if (itemId != 0)
  382. {
  383. UINT oldState = pMenu->GetMenuState(nItem,MF_BYPOSITION);
  384. if (!(oldState&MF_OWNERDRAW) && !(oldState&MF_BITMAP))
  385. {
  386. ASSERT(oldState != (UINT)-1);
  387. CString cs;
  388. pMenu->GetMenuString(nItem, cs, MF_BYPOSITION);
  389. SpawnItem * sp = AddSpawnItem(cs, itemId);
  390. pMenu->ModifyMenu(nItem,MF_BYPOSITION|MF_OWNERDRAW|oldState, (LPARAM)itemId, (LPCTSTR)sp);
  391. }
  392. }
  393. else
  394. {
  395. UINT oldState = pMenu->GetMenuState(nItem,MF_BYPOSITION);
  396. if (!(oldState&MF_OWNERDRAW) && !(oldState&MF_BITMAP))
  397. {
  398. ASSERT(oldState != (UINT)-1);
  399. SpawnItem * sp = AddSpawnItem("--", -3);
  400. pMenu->ModifyMenu(nItem,MF_BYPOSITION|MF_OWNERDRAW|oldState, (LPARAM)itemId, (LPCTSTR)sp);
  401. }
  402. }
  403. }
  404. }
  405. iRecurse --;
  406. }
  407. CGfxPopupMenu::SpawnItem * CGfxPopupMenu::AddSpawnItem(const char * txt, const int cmd)
  408. {
  409. if (iSpawnItem == 0)
  410. pSpawnItem = (SpawnItem **) GlobalAlloc(GPTR, sizeof(SpawnItem));
  411. else
  412. pSpawnItem = (SpawnItem **) GlobalReAlloc((HGLOBAL) pSpawnItem, sizeof(SpawnItem) * (iSpawnItem + 1), GMEM_MOVEABLE|GMEM_ZEROINIT);
  413. ASSERT(pSpawnItem);
  414. SpawnItem * p = new SpawnItem;
  415. ASSERT(p);
  416. pSpawnItem[iSpawnItem] = p;
  417. lstrcpy(p->cText, txt);
  418. p->iCmd = cmd;
  419. if (cmd >= 0) p->iImageIdx = FindImageItem(cmd);
  420. else p->iImageIdx = cmd;
  421. iSpawnItem ++;
  422. return p;
  423. }
  424. int CGfxPopupMenu::FindImageItem(const int cmd)
  425. {
  426. for (int t = 0; t < iImageItem; t++)
  427. if (pImageItem[t].iCmd == cmd) return pImageItem[t].iImageIdx;
  428. return -1;
  429. }
  430. void CGfxPopupMenu::EnableMenuItems(CMenu * pMenu, CWnd * pParent)
  431. {
  432. ASSERT(pMenu);
  433. ASSERT(pParent);
  434. int nItem = pMenu->GetMenuItemCount();
  435. CCmdUI state;
  436. state.m_pMenu = pMenu;
  437. state.m_nIndex = nItem-1;
  438. state.m_nIndexMax = nItem;
  439. while ((--nItem)>=0)
  440. {
  441. UINT itemId = pMenu->GetMenuItemID(nItem);
  442. if (itemId == (UINT) -1)
  443. {
  444. CMenu *pops = pMenu->GetSubMenu(nItem);
  445. if (pops) EnableMenuItems(pops, pParent);
  446. }
  447. else
  448. {
  449. if (itemId != 0)
  450. {
  451. state.m_nID = itemId;
  452. pParent->OnCmdMsg(itemId, CN_UPDATE_COMMAND_UI, &state, NULL);
  453. state.DoUpdate(pParent, true);
  454. }
  455. }
  456. state.m_nIndex = nItem-1;
  457. }
  458. }