GfxPopupMenu.cpp
上传用户:aokegd
上传日期:2009-12-14
资源大小:1276k
文件大小:15k
源码类别:

书籍源码

开发平台:

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