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

书籍源码

开发平台:

Visual C++

  1. //*************************************************************************
  2. // BCMenu.cpp : implementation file
  3. // Version : 3.0
  4. // Date : January 2002
  5. // Author : Brent Corkum
  6. // Email :  corkum@rocscience.com
  7. // Latest Version : http://www.rocscience.com/~corkum/BCMenu.html
  8. // 
  9. // Bug Fixes and portions of code supplied by:
  10. //
  11. // Ben Ashley,Girish Bharadwaj,Jean-Edouard Lachand-Robert,
  12. // Robert Edward Caldecott,Kenny Goers,Leonardo Zide,
  13. // Stefan Kuhr,Reiner Jung,Martin Vladic,Kim Yoo Chul,
  14. // Oz Solomonovich,Tongzhe Cui,Stephane Clog,Warren Stevens,
  15. // Damir Valiulin
  16. //
  17. // You are free to use/modify this code but leave this header intact.
  18. // This class is public domain so you are free to use it any of
  19. // your applications (Freeware,Shareware,Commercial). All I ask is
  20. // that you let me know so that if you have a real winner I can
  21. // brag to my buddies that some of my code is in your app. I also
  22. // wouldn't mind if you sent me a copy of your application since I
  23. // like to play with new stuff.
  24. //*************************************************************************
  25. #include "stdafx.h"        // Standard windows header file
  26. #include "BCMenu.h"        // BCMenu class declaration
  27. #include <afxpriv.h>       //SK: makes A2W and other spiffy AFX macros work
  28. #ifdef _DEBUG
  29. #define new DEBUG_NEW
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #endif
  33. #define GAP 1
  34. #ifndef OBM_CHECK
  35. #define OBM_CHECK 32760 // from winuser.h
  36. #endif
  37. #if _MFC_VER <0x400
  38. #error This code does not work on Versions of MFC prior to 4.0
  39. #endif
  40. static CPINFO CPInfo;
  41. // how the menu's are drawn in win9x/NT/2000
  42. UINT BCMenu::original_drawmode=BCMENU_DRAWMODE_ORIGINAL;
  43. BOOL BCMenu::xp_select_disabled=FALSE;
  44. // how the menu's are drawn in winXP
  45. UINT BCMenu::xp_drawmode=BCMENU_DRAWMODE_XP;
  46. BOOL BCMenu::original_select_disabled=TRUE;
  47. enum Win32Type{
  48. Win32s,
  49. Windoze95,
  50. WinNT3,
  51. WinNT4orHigher
  52. };
  53. Win32Type IsShellType()
  54. {
  55. Win32Type  ShellType;
  56. DWORD winVer;
  57. OSVERSIONINFO *osvi;
  58. winVer=GetVersion();
  59. if(winVer<0x80000000){/*NT */
  60. ShellType=WinNT3;
  61. osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
  62. if (osvi!=NULL){
  63. memset(osvi,0,sizeof(OSVERSIONINFO));
  64. osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
  65. GetVersionEx(osvi);
  66. if (osvi->dwMajorVersion>=4L)
  67. ShellType=WinNT4orHigher;//yup, it is NT 4 or higher!
  68. free(osvi);
  69. }
  70. }
  71. else if  (LOBYTE(LOWORD(winVer))<4)
  72. ShellType=Win32s;/*Win32s*/
  73. else
  74. ShellType=Windoze95;/*Windoze95*/
  75. return ShellType;
  76. }
  77. static Win32Type g_Shell=IsShellType();
  78. void BCMenuData::SetAnsiString(LPCSTR szAnsiString)
  79. {
  80. USES_CONVERSION;
  81. SetWideString(A2W(szAnsiString));  //SK:  see MFC Tech Note 059
  82. }
  83. CString BCMenuData::GetString(void)//returns the menu text in ANSI or UNICODE
  84. //depending on the MFC-Version we are using
  85. {
  86. CString strText;
  87. if (m_szMenuText)
  88.     {
  89. #ifdef UNICODE
  90. strText = m_szMenuText;
  91. #else
  92. USES_CONVERSION;
  93. strText=W2A(m_szMenuText);     //SK:  see MFC Tech Note 059
  94. #endif    
  95.     }
  96. return strText;
  97. }
  98. CTypedPtrArray<CPtrArray, HMENU> BCMenu::m_AllSubMenus;  // Stores list of all sub-menus
  99. /*
  100. ===============================================================================
  101. BCMenu::BCMenu()
  102. BCMenu::~BCMenu()
  103. -----------------
  104. Constructor and Destructor.
  105. ===============================================================================
  106. */
  107. BCMenu::BCMenu()
  108. {
  109. m_bDynIcons = FALSE;     // O.S. - no dynamic icons by default
  110. disable_old_style=FALSE;
  111. m_iconX = 16;            // Icon sizes default to 16 x 16
  112. m_iconY = 15;            // ...
  113. m_selectcheck = -1;
  114. m_unselectcheck = -1;
  115. checkmaps=NULL;
  116. checkmapsshare=FALSE;
  117. // set the color used for the transparent background in all bitmaps
  118. m_bitmapBackground=RGB(192,192,192); //gray
  119. m_bitmapBackgroundFlag=FALSE;
  120. GetCPInfo(CP_ACP,&CPInfo);
  121. }
  122. BCMenu::~BCMenu()
  123. {
  124. DestroyMenu();
  125. }
  126. BOOL BCMenu::IsNewShell ()
  127. {
  128. return (Windoze95==g_Shell || WinNT4orHigher==g_Shell);
  129. }
  130. BCMenuData::~BCMenuData()
  131. {
  132. if(bitmap)
  133. delete(bitmap);
  134. delete[] m_szMenuText; //Need not check for NULL because ANSI X3J16 allows "delete NULL"
  135. }
  136. void BCMenuData::SetWideString(const wchar_t *szWideString)
  137. {
  138. delete[] m_szMenuText;//Need not check for NULL because ANSI X3J16 allows "delete NULL"
  139. if (szWideString)
  140.     {
  141. m_szMenuText = new wchar_t[sizeof(wchar_t)*(wcslen(szWideString)+1)];
  142. if (m_szMenuText)
  143. wcscpy(m_szMenuText,szWideString);
  144.     }
  145. else
  146. m_szMenuText=NULL;//set to NULL so we need not bother about dangling non-NULL Ptrs
  147. }
  148. BOOL BCMenu::IsMenu(CMenu *submenu)
  149. {
  150. int m;
  151. int numSubMenus = m_AllSubMenus.GetUpperBound();
  152. for(m=0;m<=numSubMenus;++m){
  153. if(submenu->m_hMenu==m_AllSubMenus[m])return(TRUE);
  154. }
  155. return(FALSE);
  156. }
  157. BOOL BCMenu::IsMenu(HMENU submenu)
  158. {
  159. int m;
  160. int numSubMenus = m_AllSubMenus.GetUpperBound();
  161. for(m=0;m<=numSubMenus;++m){
  162. if(submenu==m_AllSubMenus[m])return(TRUE);
  163. }
  164. return(FALSE);
  165. }
  166. BOOL BCMenu::DestroyMenu()
  167. {
  168. // Destroy Sub menus:
  169. int m,n;
  170. int numAllSubMenus = m_AllSubMenus.GetUpperBound();
  171. for(n = numAllSubMenus; n>= 0; n--){
  172. if(m_AllSubMenus[n]==this->m_hMenu)m_AllSubMenus.RemoveAt(n);
  173. }
  174. int numSubMenus = m_SubMenus.GetUpperBound();
  175. for(m = numSubMenus; m >= 0; m--){
  176. numAllSubMenus = m_AllSubMenus.GetUpperBound();
  177. for(n = numAllSubMenus; n>= 0; n--){
  178. if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
  179. }
  180. delete((BCMenu *)FromHandle(m_SubMenus[m]));
  181. }
  182. m_SubMenus.RemoveAll();
  183. // Destroy menu data
  184. int numItems = m_MenuList.GetUpperBound();
  185. for(m = 0; m <= numItems; m++)delete(m_MenuList[m]);
  186. m_MenuList.RemoveAll();
  187. if(checkmaps&&!checkmapsshare){
  188. delete checkmaps;
  189. checkmaps=NULL;
  190. }
  191. // Call base-class implementation last:
  192. return(CMenu::DestroyMenu());
  193. };
  194. int BCMenu::GetMenuDrawMode(void)
  195. {
  196. COLORREF m_newclrBack=GetSysColor((IsNewShell())?COLOR_3DFACE:COLOR_MENU);
  197. COLORREF m_clrBack=GetSysColor(COLOR_MENU);
  198. BOOL XPflag = m_newclrBack==m_clrBack ? FALSE : TRUE;
  199. if(XPflag)return(xp_drawmode);
  200. return(original_drawmode);
  201. }
  202. /*
  203. ==========================================================================
  204. void BCMenu::DrawItem(LPDRAWITEMSTRUCT)
  205. ---------------------------------------
  206.   Called by the framework when a particular item needs to be drawn.  We
  207.   overide this to draw the menu item in a custom-fashion, including icons
  208.   and the 3D rectangle bar.
  209.   ==========================================================================
  210. */
  211. void BCMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
  212. {
  213. ASSERT(lpDIS != NULL);
  214. COLORREF m_newclrBack=GetSysColor((IsNewShell())?COLOR_3DFACE:COLOR_MENU);
  215. COLORREF m_clrBack=GetSysColor(COLOR_MENU);
  216. BOOL XPflag = m_newclrBack==m_clrBack ? FALSE : TRUE;
  217. CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  218. if(pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)DrawItem_Win9xNT2000(lpDIS);
  219. else{
  220. if(XPflag){
  221. if(xp_drawmode==BCMENU_DRAWMODE_XP) DrawItem_WinXP(lpDIS);
  222. else DrawItem_Win9xNT2000(lpDIS);
  223. }
  224. else{
  225. if(original_drawmode==BCMENU_DRAWMODE_XP) DrawItem_WinXP(lpDIS);
  226. else DrawItem_Win9xNT2000(lpDIS);
  227. }
  228. }
  229. }
  230. void BCMenu::DrawItem_Win9xNT2000 (LPDRAWITEMSTRUCT lpDIS)
  231. {
  232. ASSERT(lpDIS != NULL);
  233. CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  234. CRect rect;
  235. UINT state = (((BCMenuData*)(lpDIS->itemData))->nFlags);
  236. CBrush m_brBackground;
  237. m_brBackground.CreateSolidBrush(GetSysColor((IsNewShell())?COLOR_3DFACE:COLOR_MENU));
  238. // remove the selected bit if it's grayed out
  239. if(lpDIS->itemState & ODS_GRAYED&&!original_select_disabled){
  240. if(lpDIS->itemState & ODS_SELECTED)lpDIS->itemState=lpDIS->itemState & ~ODS_SELECTED;
  241. }
  242. if(state & MF_SEPARATOR){
  243. rect.CopyRect(&lpDIS->rcItem);
  244. pDC->FillRect (rect,&m_brBackground);
  245. rect.top += (rect.Height()>>1);
  246. pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
  247. }
  248. else{
  249. CRect rect2;
  250. BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
  251. BOOL checkflag=FALSE;
  252. COLORREF crText = GetSysColor(COLOR_MENUTEXT);
  253. COLORREF m_clrBack=GetSysColor((IsNewShell())?COLOR_3DFACE:COLOR_MENU);
  254. CBrush m_brSelect;
  255. CPen m_penBack;
  256. int x0,y0,dy;
  257. int nIconNormal=-1,xoffset=-1;
  258. CImageList *bitmap=NULL;
  259. CFont m_fontMenu;
  260. LOGFONT m_lf;
  261. // set some colors and the font
  262. m_penBack.CreatePen (PS_SOLID,0,GetSysColor((IsNewShell())?COLOR_3DFACE:COLOR_MENU));
  263. m_brSelect.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
  264. ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
  265. NONCLIENTMETRICS nm;
  266. nm.cbSize = sizeof (NONCLIENTMETRICS);
  267. VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); 
  268. m_lf =  nm.lfMenuFont;
  269. m_fontMenu.CreateFontIndirect (&m_lf);
  270. // draw the colored rectangle portion
  271. rect.CopyRect(&lpDIS->rcItem);
  272. rect2=rect;
  273. // draw the up/down/focused/disabled state
  274. UINT state = lpDIS->itemState;
  275. CString strText;
  276. LOGFONT lf;
  277. lf = m_lf;
  278. CFont dispFont;
  279. CFont *pFont=NULL;
  280. if(lpDIS->itemData != NULL){
  281. nIconNormal = (((BCMenuData*)(lpDIS->itemData))->menuIconNormal);
  282. xoffset = (((BCMenuData*)(lpDIS->itemData))->xoffset);
  283. bitmap = (((BCMenuData*)(lpDIS->itemData))->bitmap);
  284. strText = ((BCMenuData*) (lpDIS->itemData))->GetString();
  285. if(state&ODS_CHECKED && nIconNormal<0){
  286. if(state&ODS_SELECTED && m_selectcheck>0)checkflag=TRUE;
  287. else if(m_unselectcheck>0) checkflag=TRUE;
  288. }
  289. else if(nIconNormal != -1){
  290. standardflag=TRUE;
  291. if(state&ODS_SELECTED && !(state&ODS_GRAYED))selectedflag=TRUE;
  292. else if(state&ODS_GRAYED) disableflag=TRUE;
  293. }
  294. }
  295. else{
  296. strText.Empty();
  297. }
  298. if(state&ODS_SELECTED){ // draw the down edges
  299. CPen *pOldPen = pDC->SelectObject (&m_penBack);
  300. // You need only Text highlight and thats what you get
  301. if(checkflag||standardflag||selectedflag||disableflag||state&ODS_CHECKED)
  302. rect2.SetRect(rect.left+m_iconX+4+GAP,rect.top,rect.right,rect.bottom);
  303. pDC->FillRect (rect2,&m_brSelect);
  304. pDC->SelectObject (pOldPen);
  305. if((HFONT)dispFont != NULL)dispFont.DeleteObject ();
  306. dispFont.CreateFontIndirect (&lf);
  307. crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
  308. }
  309. else {
  310. CPen *pOldPen = pDC->SelectObject (&m_penBack);
  311. pDC->FillRect (rect,&m_brBackground);
  312. pDC->SelectObject (pOldPen);
  313. // draw the up edges
  314. pDC->Draw3dRect (rect,m_clrBack,m_clrBack);
  315. if ((HFONT)dispFont != NULL) dispFont.DeleteObject ();
  316. dispFont.CreateFontIndirect (&lf); //Normal
  317. }
  318. // draw the text if there is any
  319. //We have to paint the text only if the image is nonexistant
  320. dy = (rect.Height()-4-m_iconY)/2;
  321. dy = dy<0 ? 0 : dy;
  322. if(checkflag||standardflag||selectedflag||disableflag){
  323. rect2.SetRect(rect.left+1,rect.top+1+dy,rect.left+m_iconX+3,
  324. rect.top+m_iconY+3+dy);
  325. pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
  326. if(checkflag && checkmaps){
  327. pDC->FillRect (rect2,&m_brBackground);
  328. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  329. rect.top+m_iconY+4+dy);
  330. pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
  331. CPoint ptImage(rect.left+2,rect.top+2+dy);
  332. if(state&ODS_SELECTED)checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
  333. else checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
  334. }
  335. else if(disableflag){
  336. if(!selectedflag){
  337. CBitmap bitmapstandard;
  338. GetBitmapFromImageList(pDC,bitmap,xoffset,bitmapstandard);
  339. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  340.                         rect.top+m_iconY+4+dy);
  341. pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
  342. if(disable_old_style)
  343. DitherBlt(lpDIS->hDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
  344. (HBITMAP)(bitmapstandard),0,0,m_clrBack);
  345. else
  346. DitherBlt2(pDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
  347. bitmapstandard,0,0,m_clrBack);
  348. bitmapstandard.DeleteObject();
  349. }
  350. }
  351. else if(selectedflag){
  352. pDC->FillRect (rect2,&m_brBackground);
  353. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  354. rect.top+m_iconY+4+dy);
  355. if (IsNewShell()){
  356. if(state&ODS_CHECKED)
  357. pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),
  358. GetSysColor(COLOR_3DHILIGHT));
  359. else
  360. pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DHILIGHT),
  361. GetSysColor(COLOR_3DSHADOW));
  362. }
  363. CPoint ptImage(rect.left+2,rect.top+2+dy);
  364. if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
  365. }
  366. else{
  367. if(state&ODS_CHECKED){
  368. CBrush brush;
  369. COLORREF col =GetSysColor(COLOR_3DLIGHT);
  370. brush.CreateSolidBrush(col);
  371. pDC->FillRect(rect2,&brush);
  372. brush.DeleteObject();
  373. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  374.                         rect.top+m_iconY+4+dy);
  375. if (IsNewShell())
  376. pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),
  377. GetSysColor(COLOR_3DHILIGHT));
  378. }
  379. else{
  380. pDC->FillRect (rect2,&m_brBackground);
  381. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  382.                         rect.top+m_iconY+4+dy);
  383. pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
  384. }
  385. CPoint ptImage(rect.left+2,rect.top+2+dy);
  386. if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
  387. }
  388. }
  389. if(nIconNormal<0 && state&ODS_CHECKED && !checkflag){
  390. rect2.SetRect(rect.left+1,rect.top+2+dy,rect.left+m_iconX+1,
  391. rect.top+m_iconY+2+dy);
  392. CMenuItemInfo info;
  393. info.fMask = MIIM_CHECKMARKS;
  394. ::GetMenuItemInfo((HMENU)lpDIS->hwndItem,lpDIS->itemID,
  395. MF_BYCOMMAND, &info);
  396. if(state&ODS_CHECKED || info.hbmpUnchecked) {
  397. Draw3DCheckmark(pDC, rect2, state&ODS_SELECTED,
  398. state&ODS_CHECKED ? info.hbmpChecked :
  399. info.hbmpUnchecked);
  400. }
  401. }
  402. //This is needed always so that we can have the space for check marks
  403. x0=rect.left;y0=rect.top;
  404. rect.left = rect.left + m_iconX + 8 + GAP; 
  405. if(!strText.IsEmpty()){
  406. CRect rectt(rect.left,rect.top-1,rect.right,rect.bottom-1);
  407. //   Find tabs
  408. CString leftStr,rightStr;
  409. leftStr.Empty();rightStr.Empty();
  410. int tablocr=strText.ReverseFind(_T('t'));
  411. if(tablocr!=-1){
  412. rightStr=strText.Mid(tablocr+1);
  413. leftStr=strText.Left(strText.Find(_T('t')));
  414. rectt.right-=m_iconX;
  415. }
  416. else leftStr=strText;
  417. int iOldMode = pDC->GetBkMode();
  418. pDC->SetBkMode( TRANSPARENT);
  419. // Draw the text in the correct colour:
  420. UINT nFormat  = DT_LEFT|DT_SINGLELINE|DT_VCENTER;
  421. UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
  422. if(!(lpDIS->itemState & ODS_GRAYED)){
  423. pDC->SetTextColor(crText);
  424. pDC->DrawText (leftStr,rectt,nFormat);
  425. if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
  426. }
  427. else{
  428. // Draw the disabled text
  429. if(!(state & ODS_SELECTED)){
  430. RECT offset = *rectt;
  431. offset.left+=1;
  432. offset.right+=1;
  433. offset.top+=1;
  434. offset.bottom+=1;
  435. pDC->SetTextColor(GetSysColor(COLOR_BTNHILIGHT));
  436. pDC->DrawText(leftStr,&offset, nFormat);
  437. if(tablocr!=-1) pDC->DrawText (rightStr,&offset,nFormatr);
  438. pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
  439. pDC->DrawText(leftStr,rectt, nFormat);
  440. if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
  441. }
  442. else{
  443. // And the standard Grey text:
  444. pDC->SetTextColor(m_clrBack);
  445. pDC->DrawText(leftStr,rectt, nFormat);
  446. if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
  447. }
  448. }
  449. pFont = pDC->SelectObject (&dispFont);
  450. pDC->SetBkMode( iOldMode );
  451. pDC->SelectObject (pFont); //set it to the old font
  452. }
  453. m_penBack.DeleteObject();
  454. m_fontMenu.DeleteObject();
  455. m_brSelect.DeleteObject();
  456. dispFont.DeleteObject ();
  457. }
  458. m_brBackground.DeleteObject();
  459. }
  460. COLORREF BCMenu::LightenColor(COLORREF col,double factor)
  461. {
  462. if(factor>0.0&&factor<=1.0){
  463. BYTE red,green,blue,lightred,lightgreen,lightblue;
  464. red = GetRValue(col);
  465. green = GetGValue(col);
  466. blue = GetBValue(col);
  467. lightred = (BYTE)((factor*(255-red)) + red);
  468. lightgreen = (BYTE)((factor*(255-green)) + green);
  469. lightblue = (BYTE)((factor*(255-blue)) + blue);
  470. col = RGB(lightred,lightgreen,lightblue);
  471. }
  472. return(col);
  473. }
  474. void BCMenu::DrawItem_WinXP (LPDRAWITEMSTRUCT lpDIS)
  475. {
  476. ASSERT(lpDIS != NULL);
  477. CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  478. #ifdef BCMENU_USE_MEMDC
  479. BCMenuMemDC *pMemDC=NULL;
  480. #endif
  481. CRect rect,rect2;
  482. UINT state = (((BCMenuData*)(lpDIS->itemData))->nFlags);
  483. COLORREF m_newclrBack=GetSysColor((IsNewShell())?COLOR_3DFACE:COLOR_MENU);
  484. COLORREF m_clrBack=GetSysColor(COLOR_MENU);
  485. BOOL XPflag = m_newclrBack==m_clrBack ? FALSE : TRUE;
  486. if(!XPflag){
  487. m_newclrBack=LightenColor(m_newclrBack,0.35);
  488. m_clrBack=RGB(255,255,255);
  489. }
  490. CBrush m_newbrBackground,m_brBackground;
  491. m_brBackground.CreateSolidBrush(m_clrBack);
  492. m_newbrBackground.CreateSolidBrush(m_newclrBack);
  493. // remove the selected bit if it's grayed out
  494. if(lpDIS->itemState & ODS_GRAYED&&!xp_select_disabled){
  495. if(lpDIS->itemState & ODS_SELECTED)lpDIS->itemState=lpDIS->itemState & ~ODS_SELECTED;
  496. #ifdef BCMENU_USE_MEMDC
  497. pMemDC=new BCMenuMemDC(pDC,&lpDIS->rcItem);
  498. pDC = pMemDC;
  499. #endif
  500. }
  501. if(state & MF_SEPARATOR){
  502. rect.CopyRect(&lpDIS->rcItem);
  503. pDC->FillRect (rect,&m_brBackground);
  504. rect2.SetRect(rect.left,rect.top,rect.left+m_iconX+4+GAP,rect.bottom);
  505. rect.top+=rect.Height()>>1;
  506. rect.left = rect2.right+4;
  507. pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
  508. pDC->FillRect (rect2,&m_newbrBackground);
  509. pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
  510. }
  511. else{
  512. BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
  513. BOOL checkflag=FALSE;
  514. COLORREF crText = GetSysColor(COLOR_MENUTEXT);
  515. COLORREF crSelect = GetSysColor(COLOR_HIGHLIGHT);
  516. COLORREF crSelectFill;
  517. if(!XPflag)crSelectFill=LightenColor(crSelect,0.85);
  518. else crSelectFill=LightenColor(crSelect,0.7);
  519. CBrush m_brSelect;
  520. CPen m_penBack;
  521. int x0,y0,dy;
  522. int nIconNormal=-1,xoffset=-1;
  523. CImageList *bitmap=NULL;
  524. CFont m_fontMenu;
  525. LOGFONT m_lf;
  526. // set some colors and the font
  527. m_penBack.CreatePen (PS_SOLID,0,m_clrBack);
  528. m_brSelect.CreateSolidBrush(crSelectFill);
  529. ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
  530. NONCLIENTMETRICS nm;
  531. nm.cbSize = sizeof (NONCLIENTMETRICS);
  532. VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); 
  533. m_lf =  nm.lfMenuFont;
  534. m_fontMenu.CreateFontIndirect (&m_lf);
  535. // draw the colored rectangle portion
  536. rect.CopyRect(&lpDIS->rcItem);
  537. rect2=rect;
  538. // draw the up/down/focused/disabled state
  539. UINT state = lpDIS->itemState;
  540. CString strText;
  541. LOGFONT lf;
  542. lf = m_lf;
  543. CFont dispFont;
  544. CFont *pFont=NULL;
  545. if(lpDIS->itemData != NULL){
  546. nIconNormal = (((BCMenuData*)(lpDIS->itemData))->menuIconNormal);
  547. xoffset = (((BCMenuData*)(lpDIS->itemData))->xoffset);
  548. bitmap = (((BCMenuData*)(lpDIS->itemData))->bitmap);
  549. strText = ((BCMenuData*) (lpDIS->itemData))->GetString();
  550. if(state&ODS_CHECKED && nIconNormal<0){
  551. if(state&ODS_SELECTED && m_selectcheck>0)checkflag=TRUE;
  552. else if(m_unselectcheck>0) checkflag=TRUE;
  553. }
  554. else if(nIconNormal != -1){
  555. standardflag=TRUE;
  556. if(state&ODS_SELECTED && !(state&ODS_GRAYED))selectedflag=TRUE;
  557. else if(state&ODS_GRAYED) disableflag=TRUE;
  558. }
  559. }
  560. else{
  561. strText.Empty();
  562. }
  563. if(state&ODS_SELECTED){ // draw the down edges
  564. CPen *pOldPen = pDC->SelectObject (&m_penBack);
  565. pDC->FillRect (rect,&m_brSelect);
  566. pDC->Draw3dRect (rect,crSelect,crSelect);
  567. pDC->SelectObject (pOldPen);
  568. if((HFONT)dispFont != NULL)dispFont.DeleteObject ();
  569. dispFont.CreateFontIndirect (&lf);
  570. }
  571. else {
  572. rect2.SetRect(rect.left,rect.top,rect.left+m_iconX+4+GAP,rect.bottom);
  573. CPen *pOldPen = pDC->SelectObject (&m_penBack);
  574. pDC->FillRect (rect,&m_brBackground);
  575. pDC->FillRect (rect2,&m_newbrBackground);
  576. pDC->SelectObject (pOldPen);
  577. // draw the up edges
  578. pDC->Draw3dRect (rect,m_clrBack,m_clrBack);
  579. pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
  580. if ((HFONT)dispFont != NULL) dispFont.DeleteObject ();
  581. dispFont.CreateFontIndirect (&lf); //Normal
  582. }
  583. // draw the text if there is any
  584. //We have to paint the text only if the image is nonexistant
  585. dy = (rect.Height()-4-m_iconY)/2;
  586. dy = dy<0 ? 0 : dy;
  587. if(checkflag||standardflag||selectedflag||disableflag){
  588. rect2.SetRect(rect.left+1,rect.top+1+dy,rect.left+m_iconX+3,
  589. rect.top+m_iconY+3+dy);
  590. pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
  591. if(checkflag && checkmaps){
  592. pDC->FillRect (rect2,&m_newbrBackground);
  593. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  594. rect.top+m_iconY+4+dy);
  595. pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
  596. CPoint ptImage(rect.left+3,rect.top+2+dy);
  597. if(state&ODS_SELECTED)checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
  598. else checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
  599. }
  600. else if(disableflag){
  601. if(!selectedflag){
  602. CBitmap bitmapstandard;
  603. GetBitmapFromImageList(pDC,bitmap,xoffset,bitmapstandard);
  604. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  605.                         rect.top+m_iconY+4+dy);
  606. pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
  607. COLORREF transparentcol=m_newclrBack;
  608. if(state&ODS_SELECTED)transparentcol=crSelectFill;
  609. if(disable_old_style)
  610. DitherBlt(lpDIS->hDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
  611. (HBITMAP)(bitmapstandard),0,0,transparentcol);
  612. else
  613. DitherBlt2(pDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
  614. bitmapstandard,0,0,transparentcol);
  615. if(state&ODS_SELECTED)pDC->Draw3dRect (rect,crSelect,crSelect);
  616. bitmapstandard.DeleteObject();
  617. }
  618. }
  619. else if(selectedflag){
  620. pDC->FillRect (rect2,&m_brSelect);
  621. if (IsNewShell() && state&ODS_CHECKED){
  622. rect2.SetRect(rect.left,rect.top,rect.left+m_iconX+GAP+3,rect.bottom);
  623. pDC->Draw3dRect(rect2,crSelect,crSelect);
  624. }
  625. CPoint ptImage(rect.left+3,rect.top+2+dy);
  626. if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
  627. }
  628. else{
  629. if(state&ODS_CHECKED){
  630. if(!XPflag)rect2.SetRect(rect.left+1,rect.top,rect.left+m_iconX+GAP+3,rect.bottom);
  631. else rect2.SetRect(rect.left+1,rect.top,rect.left+m_iconX+GAP+3,rect.bottom-1);
  632. CBrush brushin;
  633. brushin.CreateSolidBrush(LightenColor(crSelect,0.85));
  634. pDC->FillRect(rect2,&brushin);
  635. brushin.DeleteObject();
  636. pDC->Draw3dRect(rect2,crSelect,crSelect);
  637. }
  638. else{
  639. pDC->FillRect (rect2,&m_newbrBackground);
  640. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  641.                         rect.top+m_iconY+4+dy);
  642. pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
  643. }
  644. CPoint ptImage(rect.left+3,rect.top+2+dy);
  645. if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
  646. }
  647. }
  648. if(nIconNormal<0 && state&ODS_CHECKED && !checkflag){
  649. CMenuItemInfo info;
  650. info.fMask = MIIM_CHECKMARKS;
  651. ::GetMenuItemInfo((HMENU)lpDIS->hwndItem,lpDIS->itemID,
  652. MF_BYCOMMAND, &info);
  653. if(state&ODS_CHECKED || info.hbmpUnchecked) {
  654. if(XPflag)rect2.SetRect(rect.left+2,rect.top+2+dy,rect.left+m_iconX+2,rect.top+m_iconY+3+dy);
  655. else rect2.SetRect(rect.left+2,rect.top+2+dy,rect.left+m_iconX+2,rect.top+m_iconY+2+dy);
  656. DrawXPCheckmark(pDC, rect2,state&ODS_CHECKED ? info.hbmpChecked :
  657. info.hbmpUnchecked,crSelect);
  658. }
  659. }
  660. //This is needed always so that we can have the space for check marks
  661. x0=rect.left;y0=rect.top;
  662. rect.left = rect.left + m_iconX + 8 + GAP; 
  663. if(!strText.IsEmpty()){
  664. CRect rectt(rect.left,rect.top-1,rect.right,rect.bottom-1);
  665. //   Find tabs
  666. CString leftStr,rightStr;
  667. leftStr.Empty();rightStr.Empty();
  668. int tablocr=strText.ReverseFind(_T('t'));
  669. if(tablocr!=-1){
  670. rightStr=strText.Mid(tablocr+1);
  671. leftStr=strText.Left(strText.Find(_T('t')));
  672. rectt.right-=m_iconX;
  673. }
  674. else leftStr=strText;
  675. int iOldMode = pDC->GetBkMode();
  676. pDC->SetBkMode( TRANSPARENT);
  677. // Draw the text in the correct colour:
  678. pFont = pDC->SelectObject (&dispFont);
  679. UINT nFormat  = DT_LEFT|DT_SINGLELINE|DT_VCENTER;
  680. UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
  681. if(!(lpDIS->itemState & ODS_GRAYED)){
  682. pDC->SetTextColor(crText);
  683. pDC->DrawText (leftStr,rectt,nFormat);
  684. if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
  685. }
  686. else{
  687. RECT offset = *rectt;
  688. offset.left+=1;
  689. offset.right+=1;
  690. offset.top+=1;
  691. offset.bottom+=1;
  692. if(!XPflag){
  693. COLORREF graycol=GetSysColor(COLOR_GRAYTEXT);
  694. graycol = LightenColor(graycol,0.55);
  695. pDC->SetTextColor(graycol);
  696. }
  697. else pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
  698. pDC->DrawText(leftStr,rectt, nFormat);
  699. if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
  700. }
  701. pDC->SetBkMode( iOldMode );
  702. pDC->SelectObject (pFont); //set it to the old font
  703. }
  704. m_penBack.DeleteObject();
  705. m_fontMenu.DeleteObject();
  706. m_brSelect.DeleteObject();
  707. dispFont.DeleteObject ();
  708. }
  709. m_brBackground.DeleteObject();
  710. m_newbrBackground.DeleteObject();
  711. #ifdef BCMENU_USE_MEMDC
  712. if(pMemDC)delete pMemDC;
  713. #endif
  714. }
  715. BOOL BCMenu::GetBitmapFromImageList(CDC* pDC,CImageList *imglist,int nIndex,CBitmap &bmp)
  716. {
  717. HICON hIcon = imglist->ExtractIcon(nIndex);
  718. CDC dc;
  719. dc.CreateCompatibleDC(pDC);
  720. bmp.CreateCompatibleBitmap(pDC,m_iconX,m_iconY);
  721. CBitmap* pOldBmp = dc.SelectObject(&bmp);
  722. CBrush brush ;
  723. brush.CreateSolidBrush(GetSysColor(COLOR_MENU));
  724. ::DrawIconEx(
  725. dc.GetSafeHdc(),
  726. 0,
  727. 0,
  728. hIcon,
  729. m_iconX,
  730. m_iconY,
  731. 0,
  732. (HBRUSH)brush,
  733. DI_NORMAL
  734. );
  735. dc.SelectObject( pOldBmp );
  736. dc.DeleteDC();
  737. // the icon is not longer needed
  738. DestroyIcon(hIcon);
  739. return(TRUE);
  740. }
  741. /*
  742. ==========================================================================
  743. void BCMenu::MeasureItem(LPMEASUREITEMSTRUCT)
  744. ---------------------------------------------
  745.   Called by the framework when it wants to know what the width and height
  746.   of our item will be.  To accomplish this we provide the width of the
  747.   icon plus the width of the menu text, and then the height of the icon.
  748.   
  749. ==========================================================================
  750. */
  751. void BCMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
  752. {
  753. UINT state = (((BCMenuData*)(lpMIS->itemData))->nFlags);
  754. if(state & MF_SEPARATOR){
  755. lpMIS->itemWidth = 0;
  756. lpMIS->itemHeight = GetSystemMetrics(SM_CYMENU)>>1;
  757. }
  758. else{
  759. CFont m_fontMenu;
  760. LOGFONT m_lf;
  761. ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
  762. NONCLIENTMETRICS nm;
  763. nm.cbSize = sizeof (NONCLIENTMETRICS);
  764. VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
  765. nm.cbSize,&nm,0)); 
  766. m_lf =  nm.lfMenuFont;
  767. m_fontMenu.CreateFontIndirect (&m_lf);
  768. // Obtain the width of the text:
  769. CWnd *pWnd = AfxGetMainWnd();            // Get main window
  770. CDC *pDC = pWnd->GetDC();              // Get device context
  771. CFont* pFont=NULL;    // Select menu font in...
  772. if (IsNewShell())
  773. pFont = pDC->SelectObject (&m_fontMenu);// Select menu font in...
  774.         
  775. //Get pointer to text SK
  776. const wchar_t *lpstrText = ((BCMenuData*)(lpMIS->itemData))->GetWideString();//SK: we use const to prevent misuse
  777.         
  778. SIZE size;
  779. if (Win32s!=g_Shell)
  780. VERIFY(::GetTextExtentPoint32W(pDC->m_hDC,lpstrText,
  781. wcslen(lpstrText),&size)); //SK should also work on 95
  782. #ifndef UNICODE //can't be UNICODE for Win32s
  783. else{//it's Win32suckx
  784. RECT rect;
  785. rect.left=rect.top=0;
  786. size.cy=DrawText(pDC->m_hDC,(LPCTSTR)lpstrText,
  787. wcslen(lpstrText),&rect,
  788. DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_CALCRECT);
  789. //+3 makes at least three pixels space to the menu border
  790. size.cx=rect.right-rect.left+3;
  791. size.cx += 3*(size.cx/wcslen(lpstrText));
  792. }
  793. #endif    
  794. CSize t = CSize(size);
  795. if(IsNewShell())
  796. pDC->SelectObject (pFont);  // Select old font in
  797. AfxGetMainWnd()->ReleaseDC(pDC);  // Release the DC
  798. // Set width and height:
  799. lpMIS->itemWidth = m_iconX + t.cx + m_iconX + GAP;
  800. int temp = GetSystemMetrics(SM_CYMENU);
  801. lpMIS->itemHeight = temp>m_iconY+4 ? temp : m_iconY+4;
  802. m_fontMenu.DeleteObject();
  803. }
  804. }
  805. void BCMenu::SetIconSize (int width, int height)
  806. {
  807. m_iconX = width;
  808. m_iconY = height;
  809. }
  810. BOOL BCMenu::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,
  811.                            int nIconNormal)
  812. {
  813. USES_CONVERSION;
  814. return AppendODMenuW(A2W(lpstrText),nFlags,nID,nIconNormal);//SK: See MFC Tech Note 059
  815. }
  816. BOOL BCMenu::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,
  817.                            int nIconNormal)
  818. {
  819. // Add the MF_OWNERDRAW flag if not specified:
  820. if(!nID){
  821. if(nFlags&MF_BYPOSITION)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  822. else nFlags=MF_SEPARATOR|MF_OWNERDRAW;
  823. }
  824. else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
  825. if(nFlags & MF_POPUP){
  826. m_AllSubMenus.Add((HMENU)nID);
  827. m_SubMenus.Add((HMENU)nID);
  828. }
  829. BCMenuData *mdata = new BCMenuData;
  830. m_MenuList.Add(mdata);
  831. mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
  832. mdata->menuIconNormal = nIconNormal;
  833. mdata->xoffset=-1;
  834. if(nIconNormal>=0){
  835. mdata->xoffset=0;
  836. LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
  837. if(mdata->bitmap)mdata->bitmap->DeleteImageList();
  838. else mdata->bitmap=new(CImageList);
  839. mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  840. if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
  841. mdata->bitmap->DeleteImageList();
  842. delete mdata->bitmap;
  843. mdata->bitmap=NULL;
  844. mdata->menuIconNormal = nIconNormal = -1;
  845. mdata->xoffset = -1;
  846. }
  847. }
  848. mdata->nFlags = nFlags;
  849. mdata->nID = nID;
  850. return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
  851. }
  852. BOOL BCMenu::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,
  853.                            CImageList *il,int xoffset)
  854. {
  855. USES_CONVERSION;
  856. return AppendODMenuW(A2W(lpstrText),nFlags,nID,il,xoffset);
  857. }
  858. BOOL BCMenu::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,
  859.                            CImageList *il,int xoffset)
  860. {
  861. // Add the MF_OWNERDRAW flag if not specified:
  862. if(!nID){
  863. if(nFlags&MF_BYPOSITION)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  864. else nFlags=MF_SEPARATOR|MF_OWNERDRAW;
  865. }
  866. else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
  867. if(nFlags & MF_POPUP){
  868. m_AllSubMenus.Add((HMENU)nID);
  869. m_SubMenus.Add((HMENU)nID);
  870. }
  871. BCMenuData *mdata = new BCMenuData;
  872. m_MenuList.Add(mdata);
  873. mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
  874. if(il){
  875. mdata->menuIconNormal = 0;
  876. mdata->xoffset=0;
  877. if(mdata->bitmap)mdata->bitmap->DeleteImageList();
  878. else mdata->bitmap=new(CImageList);
  879. ImageListDuplicate(il,xoffset,mdata->bitmap);
  880. }
  881. else{
  882. mdata->menuIconNormal = -1;
  883. mdata->xoffset = -1;
  884. }
  885. mdata->nFlags = nFlags;
  886. mdata->nID = nID;
  887. return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
  888. }
  889. BOOL BCMenu::InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,
  890.                            int nIconNormal)
  891. {
  892. USES_CONVERSION;
  893. return InsertODMenuW(nPosition,A2W(lpstrText),nFlags,nID,nIconNormal);
  894. }
  895. BOOL BCMenu::InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,
  896.                            int nIconNormal)
  897. {
  898. if(!(nFlags & MF_BYPOSITION)){
  899. int iPosition =0;
  900. BCMenu* pMenu = FindMenuOption(nPosition,iPosition);
  901. if(pMenu){
  902. return(pMenu->InsertODMenuW(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,nIconNormal));
  903. }
  904. else return(FALSE);
  905. }
  906. if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  907. else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
  908. if(nFlags & MF_POPUP){
  909. m_AllSubMenus.Add((HMENU)nID);
  910. m_SubMenus.InsertAt(nPosition,(HMENU)nID);
  911. }
  912. //Stephane Clog suggested adding this, believe it or not it's in the help 
  913. if(nPosition==(UINT)-1)nPosition=GetMenuItemCount();
  914. BCMenuData *mdata = new BCMenuData;
  915. m_MenuList.InsertAt(nPosition,mdata);
  916. mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
  917. mdata->menuIconNormal = nIconNormal;
  918. mdata->xoffset=-1;
  919. if(nIconNormal>=0){
  920. mdata->xoffset=0;
  921. LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
  922. if(mdata->bitmap)mdata->bitmap->DeleteImageList();
  923. else mdata->bitmap=new(CImageList);
  924. mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  925. if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
  926. mdata->bitmap->DeleteImageList();
  927. delete mdata->bitmap;
  928. mdata->bitmap=NULL;
  929. mdata->menuIconNormal = nIconNormal = -1;
  930. mdata->xoffset = -1;
  931. }
  932. }
  933. mdata->nFlags = nFlags;
  934. mdata->nID = nID;
  935. return(CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata));
  936. }
  937. BOOL BCMenu::InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,
  938.                            CImageList *il,int xoffset)
  939. {
  940. USES_CONVERSION;
  941. return InsertODMenuW(nPosition,A2W(lpstrText),nFlags,nID,il,xoffset);
  942. }
  943. BOOL BCMenu::InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,
  944.                            CImageList *il,int xoffset)
  945. {
  946. if(!(nFlags & MF_BYPOSITION)){
  947. int iPosition =0;
  948. BCMenu* pMenu = FindMenuOption(nPosition,iPosition);
  949. if(pMenu){
  950. return(pMenu->InsertODMenuW(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,il,xoffset));
  951. }
  952. else return(FALSE);
  953. }
  954. if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  955. else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
  956. if(nFlags & MF_POPUP){
  957. m_AllSubMenus.Add((HMENU)nID);
  958. m_SubMenus.InsertAt(nPosition,(HMENU)nID);
  959. }
  960. //Stephane Clog suggested adding this, believe it or not it's in the help 
  961. if(nPosition==(UINT)-1)nPosition=GetMenuItemCount();
  962. BCMenuData *mdata = new BCMenuData;
  963. m_MenuList.InsertAt(nPosition,mdata);
  964. mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
  965. if(il){
  966. mdata->menuIconNormal = 0;
  967. mdata->xoffset=0;
  968. if(mdata->bitmap)mdata->bitmap->DeleteImageList();
  969. else mdata->bitmap=new(CImageList);
  970. ImageListDuplicate(il,xoffset,mdata->bitmap);
  971. }
  972. else{
  973. mdata->menuIconNormal = -1;
  974. mdata->xoffset = -1;
  975. }
  976. mdata->nFlags = nFlags;
  977. mdata->nID = nID;
  978. return(CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata));
  979. }
  980. BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,int nIconNormal)
  981. {
  982. USES_CONVERSION;
  983. return ModifyODMenuW(A2W(lpstrText),nID,nIconNormal);//SK: see MFC Tech Note 059
  984. }
  985. BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,int nIconNormal)
  986. {
  987. int nLoc;
  988. BCMenuData *mdata;
  989. CArray<BCMenu*,BCMenu*>bcsubs;
  990. CArray<int,int&>bclocs;
  991. // Find the old BCMenuData structure:
  992. BCMenu *psubmenu = FindMenuOption(nID,nLoc);
  993. do{
  994. if(psubmenu && nLoc>=0)mdata = psubmenu->m_MenuList[nLoc];
  995. else{
  996. // Create a new BCMenuData structure:
  997. mdata = new BCMenuData;
  998. m_MenuList.Add(mdata);
  999. }
  1000. ASSERT(mdata);
  1001. if(lpstrText)
  1002. mdata->SetWideString(lpstrText);  //SK: modified for dynamic allocation
  1003. mdata->menuIconNormal = nIconNormal;
  1004. mdata->xoffset=-1;
  1005. if(nIconNormal>=0){
  1006. mdata->xoffset=0;
  1007. LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
  1008. if(mdata->bitmap)mdata->bitmap->DeleteImageList();
  1009. else mdata->bitmap=new CImageList;
  1010. mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  1011. if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
  1012. mdata->bitmap->DeleteImageList();
  1013. delete mdata->bitmap;
  1014. mdata->bitmap=NULL;
  1015. mdata->menuIconNormal = nIconNormal = -1;
  1016. mdata->xoffset = -1;
  1017. }
  1018. }
  1019. mdata->nFlags &= ~(MF_BYPOSITION);
  1020. mdata->nFlags |= MF_OWNERDRAW;
  1021. mdata->nID = nID;
  1022. bcsubs.Add(psubmenu);
  1023. bclocs.Add(nLoc);
  1024. if(psubmenu && nLoc>=0)psubmenu = FindAnotherMenuOption(nID,nLoc,bcsubs,bclocs);
  1025. else psubmenu=NULL;
  1026. }while(psubmenu);
  1027. return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
  1028. }
  1029. BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,CImageList *il,int xoffset)
  1030. {
  1031. USES_CONVERSION;
  1032. return ModifyODMenuW(A2W(lpstrText),nID,il,xoffset);
  1033. }
  1034. BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,CImageList *il,int xoffset)
  1035. {
  1036. int nLoc;
  1037. BCMenuData *mdata;
  1038. CArray<BCMenu*,BCMenu*>bcsubs;
  1039. CArray<int,int&>bclocs;
  1040. // Find the old BCMenuData structure:
  1041. BCMenu *psubmenu = FindMenuOption(nID,nLoc);
  1042. do{
  1043. if(psubmenu && nLoc>=0)mdata = psubmenu->m_MenuList[nLoc];
  1044. else{
  1045. // Create a new BCMenuData structure:
  1046. mdata = new BCMenuData;
  1047. m_MenuList.Add(mdata);
  1048. }
  1049. ASSERT(mdata);
  1050. if(lpstrText)
  1051. mdata->SetWideString(lpstrText);  //SK: modified for dynamic allocation
  1052. if(il){
  1053. mdata->menuIconNormal = 0;
  1054. mdata->xoffset=0;
  1055. if(mdata->bitmap)mdata->bitmap->DeleteImageList();
  1056. else mdata->bitmap=new(CImageList);
  1057. ImageListDuplicate(il,xoffset,mdata->bitmap);
  1058. }
  1059. else{
  1060. mdata->menuIconNormal = -1;
  1061. mdata->xoffset = -1;
  1062. }
  1063. mdata->nFlags &= ~(MF_BYPOSITION);
  1064. mdata->nFlags |= MF_OWNERDRAW;
  1065. mdata->nID = nID;
  1066. bcsubs.Add(psubmenu);
  1067. bclocs.Add(nLoc);
  1068. if(psubmenu && nLoc>=0)psubmenu = FindAnotherMenuOption(nID,nLoc,bcsubs,bclocs);
  1069. else psubmenu=NULL;
  1070. }while(psubmenu);
  1071. return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
  1072. }
  1073. BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,CBitmap *bmp)
  1074. {
  1075. USES_CONVERSION;
  1076. return ModifyODMenuW(A2W(lpstrText),nID,bmp);
  1077. }
  1078. BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,CBitmap *bmp)
  1079. {
  1080. if(bmp){
  1081. CImageList temp;
  1082. temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  1083. if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
  1084. else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
  1085. return ModifyODMenuW(lpstrText,nID,&temp,0);
  1086. }
  1087. return ModifyODMenuW(lpstrText,nID,NULL,0);
  1088. }
  1089. // courtesy of Warren Stevens
  1090. BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,COLORREF fill,COLORREF border,int hatchstyle)
  1091. {
  1092. USES_CONVERSION;
  1093. return ModifyODMenuW(A2W(lpstrText),nID,fill,border,hatchstyle);
  1094. }
  1095. BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,COLORREF fill,COLORREF border,int hatchstyle)
  1096. {
  1097. CWnd *pWnd = AfxGetMainWnd();            // Get main window
  1098. CDC *pDC = pWnd->GetDC();              // Get device context
  1099. CSize bitmap_size(m_iconX,m_iconY);
  1100. CBitmap bmp;
  1101. ColorBitmap(pDC,bmp,bitmap_size,fill,border,hatchstyle);
  1102. return ModifyODMenuW(lpstrText,nID,&bmp);
  1103. }
  1104. BOOL BCMenu::ModifyODMenuA(const char *lpstrText,const char *OptionText,
  1105.                            int nIconNormal)
  1106. {
  1107. USES_CONVERSION;
  1108. return ModifyODMenuW(A2W(lpstrText),A2W(OptionText),nIconNormal);//SK: see MFC  Tech Note 059
  1109. }
  1110. BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,wchar_t *OptionText,
  1111.                            int nIconNormal)
  1112. {
  1113. BCMenuData *mdata;
  1114. // Find the old BCMenuData structure:
  1115. CString junk=OptionText;
  1116. mdata=FindMenuOption(OptionText);
  1117. if(mdata){
  1118. if(lpstrText)
  1119. mdata->SetWideString(lpstrText);//SK: modified for dynamic allocation
  1120. mdata->menuIconNormal = nIconNormal;
  1121. mdata->xoffset=-1;
  1122. if(nIconNormal>=0){
  1123. mdata->xoffset=0;
  1124. if(mdata->bitmap)mdata->bitmap->DeleteImageList();
  1125. else mdata->bitmap=new(CImageList);
  1126. mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  1127. if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
  1128. mdata->bitmap->DeleteImageList();
  1129. delete mdata->bitmap;
  1130. mdata->bitmap=NULL;
  1131. mdata->menuIconNormal = nIconNormal = -1;
  1132. mdata->xoffset = -1;
  1133. }
  1134. }
  1135. return(TRUE);
  1136. }
  1137. return(FALSE);
  1138. }
  1139. BCMenuData *BCMenu::NewODMenu(UINT pos,UINT nFlags,UINT nID,CString string)
  1140. {
  1141. BCMenuData *mdata;
  1142. mdata = new BCMenuData;
  1143. mdata->menuIconNormal = -1;
  1144. mdata->xoffset=-1;
  1145. #ifdef UNICODE
  1146. mdata->SetWideString((LPCTSTR)string);//SK: modified for dynamic allocation
  1147. #else
  1148. mdata->SetAnsiString(string);
  1149. #endif
  1150. mdata->nFlags = nFlags;
  1151. mdata->nID = nID;
  1152. // if(nFlags & MF_POPUP)m_AllSubMenus.Add((HMENU)nID);
  1153. if (nFlags&MF_OWNERDRAW){
  1154. ASSERT(!(nFlags&MF_STRING));
  1155. ModifyMenu(pos,nFlags,nID,(LPCTSTR)mdata);
  1156. }
  1157. else if (nFlags&MF_STRING){
  1158. ASSERT(!(nFlags&MF_OWNERDRAW));
  1159. ModifyMenu(pos,nFlags,nID,mdata->GetString());
  1160. }
  1161. else{
  1162. ASSERT(nFlags&MF_SEPARATOR);
  1163. ModifyMenu(pos,nFlags,nID);
  1164. }
  1165. return(mdata);
  1166. };
  1167. BOOL BCMenu::LoadToolbars(const UINT *arID,int n)
  1168. {
  1169. ASSERT(arID);
  1170. BOOL returnflag=TRUE;
  1171. for(int i=0;i<n;++i){
  1172. if(!LoadToolbar(arID[i]))returnflag=FALSE;
  1173. }
  1174. return(returnflag);
  1175. }
  1176. BOOL BCMenu::LoadToolbar(UINT nToolBar)
  1177. {
  1178. UINT nID,nStyle;
  1179. BOOL returnflag=FALSE;
  1180. CToolBar bar;
  1181. int xoffset=-1,xset;
  1182. bar.Create(AfxGetMainWnd());
  1183. if(bar.LoadToolBar(nToolBar)){
  1184. CImageList imglist;
  1185. imglist.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  1186. if(AddBitmapToImageList(&imglist,nToolBar)){
  1187. returnflag=TRUE;
  1188. for(int i=0;i<bar.GetCount();++i){
  1189. nID = bar.GetItemID(i); 
  1190. if(nID && GetMenuState(nID, MF_BYCOMMAND)
  1191. !=0xFFFFFFFF){
  1192. xoffset=bar.CommandToIndex(nID);
  1193. if(xoffset>=0){
  1194. bar.GetButtonInfo(xoffset,nID,nStyle,xset);
  1195. if(xset>0)xoffset=xset;
  1196. }
  1197. ModifyODMenu(NULL,nID,&imglist,xoffset);
  1198. }
  1199. }
  1200. }
  1201. }
  1202. return(returnflag);
  1203. }
  1204. BOOL BCMenu::LoadFromToolBar(UINT nID,UINT nToolBar,int& xoffset)
  1205. {
  1206. int xset,offset;
  1207. UINT nStyle;
  1208. BOOL returnflag=FALSE;
  1209. CToolBar bar;
  1210. bar.Create(AfxGetMainWnd());
  1211. if(bar.LoadToolBar(nToolBar)){
  1212. offset=bar.CommandToIndex(nID);
  1213. if(offset>=0){
  1214. bar.GetButtonInfo(offset,nID,nStyle,xset);
  1215. if(xset>0)xoffset=xset;
  1216. returnflag=TRUE;
  1217. }
  1218. }
  1219. return(returnflag);
  1220. }
  1221. // O.S.
  1222. BCMenuData *BCMenu::FindMenuItem(UINT nID)
  1223. {
  1224. BCMenuData *pData = NULL;
  1225. int i;
  1226. for(i = 0; i <= m_MenuList.GetUpperBound(); i++){
  1227. if (m_MenuList[i]->nID == nID){
  1228. pData = m_MenuList[i];
  1229. break;
  1230. }
  1231. }
  1232. if (!pData){
  1233. int loc;
  1234. BCMenu *pMenu = FindMenuOption(nID, loc);
  1235. ASSERT(pMenu != this);
  1236. if (loc >= 0){
  1237. return pMenu->FindMenuItem(nID);
  1238. }
  1239. }
  1240. return pData;
  1241. }
  1242. BCMenu *BCMenu::FindAnotherMenuOption(int nId,int& nLoc,CArray<BCMenu*,BCMenu*>&bcsubs,
  1243.   CArray<int,int&>&bclocs)
  1244. {
  1245. int i,numsubs,j;
  1246. BCMenu *psubmenu,*pgoodmenu;
  1247. BOOL foundflag;
  1248. for(i=0;i<(int)(GetMenuItemCount());++i){
  1249. #ifdef _CPPRTTI 
  1250. psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
  1251. #else
  1252. psubmenu=(BCMenu *)GetSubMenu(i);
  1253. #endif
  1254. if(psubmenu){
  1255. pgoodmenu=psubmenu->FindAnotherMenuOption(nId,nLoc,bcsubs,bclocs);
  1256. if(pgoodmenu)return(pgoodmenu);
  1257. }
  1258. else if(nId==(int)GetMenuItemID(i)){
  1259. numsubs=bcsubs.GetSize();
  1260. foundflag=TRUE;
  1261. for(j=0;j<numsubs;++j){
  1262. if(bcsubs[j]==this&&bclocs[j]==i){
  1263. foundflag=FALSE;
  1264. break;
  1265. }
  1266. }
  1267. if(foundflag){
  1268. nLoc=i;
  1269. return(this);
  1270. }
  1271. }
  1272. }
  1273. nLoc = -1;
  1274. return(NULL);
  1275. }
  1276. BCMenu *BCMenu::FindMenuOption(int nId,int& nLoc)
  1277. {
  1278. int i;
  1279. BCMenu *psubmenu,*pgoodmenu;
  1280. for(i=0;i<(int)(GetMenuItemCount());++i){
  1281. #ifdef _CPPRTTI 
  1282. psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
  1283. #else
  1284. psubmenu=(BCMenu *)GetSubMenu(i);
  1285. #endif
  1286. if(psubmenu){
  1287. pgoodmenu=psubmenu->FindMenuOption(nId,nLoc);
  1288. if(pgoodmenu)return(pgoodmenu);
  1289. }
  1290. else if(nId==(int)GetMenuItemID(i)){
  1291. nLoc=i;
  1292. return(this);
  1293. }
  1294. }
  1295. nLoc = -1;
  1296. return(NULL);
  1297. }
  1298. BCMenuData *BCMenu::FindMenuOption(wchar_t *lpstrText)
  1299. {
  1300. int i,j;
  1301. BCMenu *psubmenu;
  1302. BCMenuData *pmenulist;
  1303. for(i=0;i<(int)(GetMenuItemCount());++i){
  1304. #ifdef _CPPRTTI 
  1305. psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
  1306. #else
  1307. psubmenu=(BCMenu *)GetSubMenu(i);
  1308. #endif
  1309. if(psubmenu){
  1310. pmenulist=psubmenu->FindMenuOption(lpstrText);
  1311. if(pmenulist)return(pmenulist);
  1312. }
  1313. else{
  1314. const wchar_t *szWide;//SK: we use const to prevent misuse of this Ptr
  1315. for(j=0;j<=m_MenuList.GetUpperBound();++j){     
  1316. szWide = m_MenuList[j]->GetWideString ();
  1317. if(szWide && !wcscmp(lpstrText,szWide))//SK: modified for dynamic allocation
  1318. return(m_MenuList[j]);
  1319. }
  1320. }
  1321. }
  1322. return(NULL);
  1323. }
  1324. BOOL BCMenu::LoadMenu(int nResource)
  1325. {
  1326. return(BCMenu::LoadMenu(MAKEINTRESOURCE(nResource)));
  1327. };
  1328. BOOL BCMenu::LoadMenu(LPCTSTR lpszResourceName)
  1329. {
  1330. TRACE(_T(
  1331. "IMPORTANT:Use BCMenu::DestroyMenu to destroy Loaded Menu'sn"));
  1332. ASSERT_VALID(this);
  1333. ASSERT(lpszResourceName != NULL);
  1334. // Find the Menu Resource:
  1335. HINSTANCE m_hInst = AfxFindResourceHandle(lpszResourceName,RT_MENU);
  1336. HRSRC hRsrc = ::FindResource(m_hInst,lpszResourceName,RT_MENU);
  1337. if(hRsrc == NULL)return FALSE;
  1338. // Load the Menu Resource:
  1339. HGLOBAL hGlobal = LoadResource(m_hInst, hRsrc);
  1340. if(hGlobal == NULL)return FALSE;
  1341. // Attempt to create us as a menu...
  1342. if(!CMenu::CreateMenu())return FALSE;
  1343. // Get Item template Header, and calculate offset of MENUITEMTEMPLATES
  1344. MENUITEMTEMPLATEHEADER *pTpHdr=
  1345. (MENUITEMTEMPLATEHEADER*)LockResource(hGlobal);
  1346. BYTE* pTp=(BYTE*)pTpHdr + 
  1347. (sizeof(MENUITEMTEMPLATEHEADER) + pTpHdr->offset);
  1348. // Variables needed during processing of Menu Item Templates:
  1349. int j=0;
  1350. WORD    dwFlags = 0;              // Flags of the Menu Item
  1351. WORD    dwID  = 0;              // ID of the Menu Item
  1352. UINT    uFlags;                  // Actual Flags.
  1353. wchar_t *szCaption=NULL;
  1354. int      nLen   = 0;                // Length of caption
  1355. CTypedPtrArray<CPtrArray, BCMenu*>  m_Stack;    // Popup menu stack
  1356. CArray<BOOL,BOOL>  m_StackEnd;    // Popup menu stack
  1357. m_Stack.Add(this);                  // Add it to this...
  1358. m_StackEnd.Add(FALSE);
  1359. do{
  1360. // Obtain Flags and (if necessary), the ID...
  1361. memcpy(&dwFlags, pTp, sizeof(WORD));pTp+=sizeof(WORD);// Obtain Flags
  1362. if(!(dwFlags & MF_POPUP)){
  1363. memcpy(&dwID, pTp, sizeof(WORD)); // Obtain ID
  1364. pTp+=sizeof(WORD);
  1365. }
  1366. else dwID = 0;
  1367. uFlags = (UINT)dwFlags; // Remove MF_END from the flags that will
  1368. if(uFlags & MF_END) // be passed to the Append(OD)Menu functions.
  1369. uFlags -= MF_END;
  1370. // Obtain Caption (and length)
  1371. nLen = 0;
  1372. szCaption=new wchar_t[wcslen((wchar_t *)pTp)+1];
  1373. wcscpy(szCaption,(wchar_t *)pTp);
  1374. pTp=&pTp[(wcslen((wchar_t *)pTp)+1)*sizeof(wchar_t)];//modified SK
  1375. // Handle popup menus first....
  1376. //WideCharToMultiByte
  1377. if(dwFlags & MF_POPUP){
  1378. if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
  1379. BCMenu* pSubMenu = new BCMenu;
  1380. pSubMenu->m_unselectcheck=m_unselectcheck;
  1381. pSubMenu->m_selectcheck=m_selectcheck;
  1382. pSubMenu->checkmaps=checkmaps;
  1383. pSubMenu->checkmapsshare=TRUE;
  1384. pSubMenu->CreatePopupMenu();
  1385. // Append it to the top of the stack:
  1386. m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption,uFlags,
  1387. (UINT)pSubMenu->m_hMenu, -1);
  1388. m_Stack.Add(pSubMenu);
  1389. m_StackEnd.Add(FALSE);
  1390. }
  1391. else {
  1392. m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption, uFlags,
  1393. dwID, -1);
  1394. if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
  1395. j = m_Stack.GetUpperBound();
  1396. while(j>=0 && m_StackEnd.GetAt(j)){
  1397. m_Stack[m_Stack.GetUpperBound()]->InsertSpaces();
  1398. m_Stack.RemoveAt(j);
  1399. m_StackEnd.RemoveAt(j);
  1400. --j;
  1401. }
  1402. }
  1403. delete[] szCaption;
  1404. }while(m_Stack.GetUpperBound() != -1);
  1405. for(int i=0;i<(int)GetMenuItemCount();++i){
  1406. CString str=m_MenuList[i]->GetString();
  1407. if(GetSubMenu(i)){
  1408. m_MenuList[i]->nFlags=MF_POPUP|MF_BYPOSITION;
  1409. ModifyMenu(i,MF_POPUP|MF_BYPOSITION,
  1410. (UINT)GetSubMenu(i)->m_hMenu,str);
  1411. }
  1412. else{
  1413. m_MenuList[i]->nFlags=MF_STRING|MF_BYPOSITION;
  1414. ModifyMenu(i,MF_STRING|MF_BYPOSITION,m_MenuList[i]->nID,str);
  1415. }
  1416. }
  1417. return(TRUE);
  1418. }
  1419. void BCMenu::InsertSpaces(void)
  1420. {
  1421. int i,j,numitems,maxlength;
  1422. CString string,newstring;
  1423. CSize t;
  1424. CFont m_fontMenu;
  1425. LOGFONT m_lf;
  1426. ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
  1427. NONCLIENTMETRICS nm;
  1428. nm.cbSize = sizeof (NONCLIENTMETRICS);
  1429. VERIFY (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); 
  1430. m_lf =  nm.lfMenuFont;
  1431. m_fontMenu.CreateFontIndirect (&m_lf);
  1432. CWnd *pWnd = AfxGetMainWnd();  
  1433. CDC *pDC = pWnd->GetDC();
  1434. CFont* pFont = pDC->SelectObject (&m_fontMenu);
  1435. numitems=GetMenuItemCount();
  1436. maxlength = -1;
  1437. for(i=0;i<numitems;++i){
  1438. string=m_MenuList[i]->GetString();
  1439. j=string.Find((char)9);
  1440. newstring.Empty();
  1441. if(j!=-1)newstring=string.Left(j);
  1442. else newstring=string;
  1443. newstring+=_T(" ");//SK: modified for Unicode correctness. 
  1444. LPCTSTR lpstrText = (LPCTSTR)newstring;
  1445. t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
  1446. if(t.cx>maxlength)maxlength = t.cx;
  1447. }
  1448. for(i=0;i<numitems;++i){
  1449. string=m_MenuList[i]->GetString();
  1450. j=string.Find((char)9);
  1451. if(j!=-1){
  1452. newstring.Empty();
  1453. newstring=string.Left(j);
  1454. LPCTSTR lpstrText = (LPCTSTR)(newstring);
  1455. t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
  1456. while(t.cx<maxlength){
  1457. newstring+=_T(' ');//SK: modified for Unicode correctness
  1458. LPCTSTR lpstrText = (LPCTSTR)(newstring);
  1459. t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
  1460. }
  1461. newstring+=string.Mid(j);
  1462. #ifdef UNICODE      
  1463. m_MenuList[i]->SetWideString(newstring);//SK: modified for dynamic allocation
  1464. #else
  1465. m_MenuList[i]->SetAnsiString(newstring);
  1466. #endif
  1467. }
  1468. }
  1469. pDC->SelectObject (pFont);              // Select old font in
  1470. AfxGetMainWnd()->ReleaseDC(pDC);       // Release the DC
  1471. m_fontMenu.DeleteObject();
  1472. }
  1473. void BCMenu::LoadCheckmarkBitmap(int unselect, int select)
  1474. {
  1475. if(unselect>0 && select>0){
  1476. m_selectcheck=select;
  1477. m_unselectcheck=unselect;
  1478. if(checkmaps)checkmaps->DeleteImageList();
  1479. else checkmaps=new(CImageList);
  1480. checkmaps->Create(m_iconX,m_iconY,ILC_MASK,2,1);
  1481. BOOL flag1=AddBitmapToImageList(checkmaps,unselect);
  1482. BOOL flag2=AddBitmapToImageList(checkmaps,select);
  1483. if(!flag1||!flag2){
  1484. checkmaps->DeleteImageList();
  1485. delete checkmaps;
  1486. checkmaps=NULL;
  1487. }
  1488. }
  1489. }
  1490. //--------------------------------------------------------------------------
  1491. //[18.06.99 rj]
  1492. BOOL BCMenu::GetMenuText(UINT id, CString& string, UINT nFlags/*= MF_BYPOSITION*/)
  1493. {
  1494. BOOL returnflag=FALSE;
  1495. if(MF_BYPOSITION&nFlags){
  1496. UINT numMenuItems = m_MenuList.GetUpperBound();
  1497. if(id<=numMenuItems){
  1498. string=m_MenuList[id]->GetString();
  1499. returnflag=TRUE;
  1500. }
  1501. }
  1502. else{
  1503. int uiLoc;
  1504. BCMenu* pMenu = FindMenuOption(id,uiLoc);
  1505. if(NULL!=pMenu) returnflag = pMenu->GetMenuText(uiLoc,string);
  1506. }
  1507. return(returnflag);
  1508. }
  1509. void BCMenu::DrawRadioDot(CDC *pDC,int x,int y,COLORREF color)
  1510. {
  1511. CRect rcDot(x,y,x+6,y+6);
  1512. CBrush brush;
  1513. CPen pen;
  1514. brush.CreateSolidBrush(color);
  1515. pen.CreatePen(PS_SOLID,0,color);
  1516. CBrush *pOldBrush=pDC->SelectObject(&brush);
  1517. CPen *pOldPen=pDC->SelectObject(&pen);
  1518. pDC->Ellipse(&rcDot);
  1519. pDC->SelectObject(pOldBrush);
  1520. pDC->SelectObject(pOldPen);
  1521. pen.DeleteObject();
  1522. brush.DeleteObject();
  1523. }
  1524. void BCMenu::DrawCheckMark(CDC* pDC,int x,int y,COLORREF color)
  1525. {
  1526. CPen m_penBack;
  1527. m_penBack.CreatePen (PS_SOLID,0,color);
  1528. CPen *pOldPen = pDC->SelectObject (&m_penBack);
  1529. pDC->MoveTo(x,y+2);
  1530. pDC->LineTo(x,y+5);
  1531. pDC->MoveTo(x+1,y+3);
  1532. pDC->LineTo(x+1,y+6);
  1533. pDC->MoveTo(x+2,y+4);
  1534. pDC->LineTo(x+2,y+7);
  1535. pDC->MoveTo(x+3,y+3);
  1536. pDC->LineTo(x+3,y+6);
  1537. pDC->MoveTo(x+4,y+2);
  1538. pDC->LineTo(x+4,y+5);
  1539. pDC->MoveTo(x+5,y+1);
  1540. pDC->LineTo(x+5,y+4);
  1541. pDC->MoveTo(x+6,y);
  1542. pDC->LineTo(x+6,y+3);
  1543. pDC->SelectObject (pOldPen);
  1544. m_penBack.DeleteObject();
  1545. }
  1546. BCMenuData *BCMenu::FindMenuList(UINT nID)
  1547. {
  1548. for(int i=0;i<=m_MenuList.GetUpperBound();++i){
  1549. if(m_MenuList[i]->nID==nID && !m_MenuList[i]->syncflag){
  1550. m_MenuList[i]->syncflag=1;
  1551. return(m_MenuList[i]);
  1552. }
  1553. }
  1554. return(NULL);
  1555. }
  1556. void BCMenu::InitializeMenuList(int value)
  1557. {
  1558. for(int i=0;i<=m_MenuList.GetUpperBound();++i)
  1559. m_MenuList[i]->syncflag=value;
  1560. }
  1561. void BCMenu::DeleteMenuList(void)
  1562. {
  1563. for(int i=0;i<=m_MenuList.GetUpperBound();++i){
  1564. if(!m_MenuList[i]->syncflag){
  1565. delete m_MenuList[i];
  1566. }
  1567. }
  1568. }
  1569. void BCMenu::SynchronizeMenu(void)
  1570. {
  1571. CTypedPtrArray<CPtrArray, BCMenuData*> temp;
  1572. BCMenuData *mdata;
  1573. CString string;
  1574. UINT submenu,nID=0,state,j;
  1575. InitializeMenuList(0);
  1576. for(j=0;j<GetMenuItemCount();++j){
  1577. mdata=NULL;
  1578. state=GetMenuState(j,MF_BYPOSITION);
  1579. if(state&MF_POPUP){
  1580. submenu=(UINT)GetSubMenu(j)->m_hMenu;
  1581. mdata=FindMenuList(submenu);
  1582. GetMenuString(j,string,MF_BYPOSITION);
  1583. if(!mdata)mdata=NewODMenu(j,
  1584. (state&0xFF)|MF_BYPOSITION|MF_POPUP|MF_OWNERDRAW,submenu,string);
  1585. else if(string.GetLength()>0)
  1586. #ifdef UNICODE
  1587. mdata->SetWideString(string);  //SK: modified for dynamic allocation
  1588. #else
  1589. mdata->SetAnsiString(string);
  1590. #endif
  1591. }
  1592. else if(state&MF_SEPARATOR){
  1593. mdata=FindMenuList(0);
  1594. if(!mdata)mdata=NewODMenu(j,
  1595. state|MF_BYPOSITION|MF_SEPARATOR|MF_OWNERDRAW,0,_T(""));//SK: modified for Unicode correctness
  1596. else ModifyMenu(j,mdata->nFlags,nID,(LPCTSTR)mdata);
  1597. }
  1598. else{
  1599. nID=GetMenuItemID(j);
  1600. mdata=FindMenuList(nID);
  1601. GetMenuString(j,string,MF_BYPOSITION);
  1602. if(!mdata)mdata=NewODMenu(j,state|MF_BYPOSITION|MF_OWNERDRAW,
  1603. nID,string);
  1604. else{
  1605. mdata->nFlags=state|MF_BYPOSITION|MF_OWNERDRAW;
  1606. if(string.GetLength()>0)
  1607. #ifdef UNICODE
  1608. mdata->SetWideString(string);//SK: modified for dynamic allocation
  1609. #else
  1610. mdata->SetAnsiString(string);
  1611. #endif
  1612. ModifyMenu(j,mdata->nFlags,nID,(LPCTSTR)mdata);
  1613. }
  1614. }
  1615. if(mdata)temp.Add(mdata);
  1616. }
  1617. DeleteMenuList();
  1618. m_MenuList.RemoveAll();
  1619. m_MenuList.Append(temp);
  1620. temp.RemoveAll(); 
  1621. }
  1622. void BCMenu::UpdateMenu(CMenu *pmenu)
  1623. {
  1624. #ifdef _CPPRTTI 
  1625. BCMenu *psubmenu = dynamic_cast<BCMenu *>(pmenu);
  1626. #else
  1627. BCMenu *psubmenu = (BCMenu *)pmenu;
  1628. #endif
  1629. if(psubmenu)psubmenu->SynchronizeMenu();
  1630. }
  1631. LRESULT BCMenu::FindKeyboardShortcut(UINT nChar, UINT nFlags,
  1632.                                      CMenu *pMenu)
  1633. {
  1634. #ifdef _CPPRTTI 
  1635. BCMenu *pBCMenu = dynamic_cast<BCMenu *>(pMenu);
  1636. #else
  1637. BCMenu *pBCMenu = (BCMenu *)pMenu;
  1638. #endif
  1639. if(pBCMenu && nFlags&MF_POPUP){
  1640. CString key(_T('&'),2);//SK: modified for Unicode correctness
  1641. key.SetAt(1,(TCHAR)nChar);
  1642. key.MakeLower();
  1643. CString menutext;
  1644. int menusize = (int)pBCMenu->GetMenuItemCount();
  1645. if(menusize!=(pBCMenu->m_MenuList.GetUpperBound()+1))
  1646. pBCMenu->SynchronizeMenu();
  1647. for(int i=0;i<menusize;++i){
  1648. if(pBCMenu->GetMenuText(i,menutext)){
  1649. menutext.MakeLower();
  1650. if(menutext.Find(key)>=0)return(MAKELRESULT(i,2));
  1651. }
  1652. }
  1653. }
  1654. return(0);
  1655. }
  1656. void BCMenu::DitherBlt (HDC hdcDest, int nXDest, int nYDest, int nWidth, 
  1657.                         int nHeight, HBITMAP hbm, int nXSrc, int nYSrc,
  1658. COLORREF bgcolor)
  1659. {
  1660. ASSERT(hdcDest && hbm);
  1661. ASSERT(nWidth > 0 && nHeight > 0);
  1662. // Create a generic DC for all BitBlts
  1663. HDC hDC = CreateCompatibleDC(hdcDest);
  1664. ASSERT(hDC);
  1665. if (hDC)
  1666. {
  1667. // Create a DC for the monochrome DIB section
  1668. HDC bwDC = CreateCompatibleDC(hDC);
  1669. ASSERT(bwDC);
  1670. if (bwDC)
  1671. {
  1672. // Create the monochrome DIB section with a black and white palette
  1673. struct {
  1674. BITMAPINFOHEADER bmiHeader; 
  1675. RGBQUAD      bmiColors[2]; 
  1676. } RGBBWBITMAPINFO = {
  1677. {    // a BITMAPINFOHEADER
  1678. sizeof(BITMAPINFOHEADER),  // biSize 
  1679. nWidth,         // biWidth; 
  1680. nHeight,        // biHeight; 
  1681. 1,            // biPlanes; 
  1682. 1,            // biBitCount 
  1683. BI_RGB,         // biCompression; 
  1684. 0,            // biSizeImage; 
  1685. 0,            // biXPelsPerMeter; 
  1686. 0,            // biYPelsPerMeter; 
  1687. 0,            // biClrUsed; 
  1688. 0            // biClrImportant; 
  1689. },    
  1690. {
  1691. { 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 }
  1692. };
  1693. VOID *pbitsBW;
  1694. HBITMAP hbmBW = CreateDIBSection(bwDC,
  1695. (LPBITMAPINFO)&RGBBWBITMAPINFO, DIB_RGB_COLORS, &pbitsBW, NULL, 0);
  1696. ASSERT(hbmBW);
  1697. if (hbmBW)
  1698. {
  1699. // Attach the monochrome DIB section and the bitmap to the DCs
  1700. HBITMAP olddib = (HBITMAP)SelectObject(bwDC, hbmBW);
  1701. HBITMAP hdcolddib = (HBITMAP)SelectObject(hDC, hbm);
  1702. // BitBlt the bitmap into the monochrome DIB section
  1703. BitBlt(bwDC, 0, 0, nWidth, nHeight, hDC, nXSrc, nYSrc, SRCCOPY);
  1704. // Paint the destination rectangle in gray
  1705. FillRect(hdcDest, CRect(nXDest, nYDest, nXDest + nWidth, nYDest +
  1706. nHeight), GetSysColorBrush(bgcolor));
  1707. //SK: looks better on the old shell
  1708. // BitBlt the black bits in the monochrome bitmap into COLOR_3DHILIGHT
  1709. // bits in the destination DC
  1710. // The magic ROP comes from the Charles Petzold's book
  1711. HBRUSH hb = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT));
  1712. HBRUSH oldBrush = (HBRUSH)SelectObject(hdcDest, hb);
  1713. BitBlt(hdcDest,nXDest+1,nYDest+1,nWidth,nHeight,bwDC,0,0,0xB8074A);
  1714. // BitBlt the black bits in the monochrome bitmap into COLOR_3DSHADOW
  1715. // bits in the destination DC
  1716. hb = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
  1717. DeleteObject(SelectObject(hdcDest, hb));
  1718. BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight,bwDC,0,0,0xB8074A);
  1719. DeleteObject(SelectObject(hdcDest, oldBrush));
  1720. VERIFY(DeleteObject(SelectObject(bwDC, olddib)));
  1721. SelectObject(hDC, hdcolddib);
  1722. }
  1723. VERIFY(DeleteDC(bwDC));
  1724. }
  1725. VERIFY(DeleteDC(hDC));
  1726. }
  1727. }
  1728. BOOL BCMenu::AddBitmapToImageList(CImageList *bmplist,UINT nResourceID)
  1729. {
  1730. // O.S.
  1731. if (m_bDynIcons){
  1732. bmplist->Add((HICON)nResourceID);
  1733. return TRUE;
  1734. }
  1735. BOOL bReturn=FALSE;
  1736. HBITMAP hbmp=LoadSysColorBitmap(nResourceID);
  1737. if(hbmp){
  1738. CBitmap bmp;
  1739. bmp.Attach(hbmp);
  1740. if(m_bitmapBackgroundFlag){
  1741. if(bmplist->Add(&bmp,m_bitmapBackground)>=0)bReturn=TRUE;
  1742. }
  1743. else{
  1744. if(bmplist->Add(&bmp,GetSysColor(COLOR_3DFACE))>=0)bReturn=TRUE;
  1745. }
  1746. bmp.Detach();
  1747. DeleteObject(hbmp);
  1748. }
  1749. else{
  1750. CBitmap mybmp;
  1751. if(mybmp.LoadBitmap(nResourceID)){
  1752. if(m_bitmapBackgroundFlag){
  1753. if(bmplist->Add(&mybmp,m_bitmapBackground)>=0)bReturn=TRUE;
  1754. }
  1755. else{
  1756. if(bmplist->Add(&mybmp,GetSysColor(COLOR_3DFACE))>=0)bReturn=TRUE;
  1757. }
  1758. }
  1759. }
  1760. return(bReturn);
  1761. }
  1762. void BCMenu::SetBitmapBackground(COLORREF color)
  1763. {
  1764. m_bitmapBackground=color;
  1765. m_bitmapBackgroundFlag=TRUE;
  1766. }
  1767. void BCMenu::UnSetBitmapBackground(void)
  1768. {
  1769. m_bitmapBackgroundFlag=FALSE;
  1770. }
  1771. // Given a toolbar, append all the options from it to this menu
  1772. // Passed a ptr to the toolbar object and the toolbar ID
  1773. // Author : Robert Edward Caldecott
  1774. void BCMenu::AddFromToolBar(CToolBar* pToolBar, int nResourceID)
  1775. {
  1776. for (int i = 0; i < pToolBar->GetCount(); i++) {
  1777. UINT nID = pToolBar->GetItemID(i);
  1778. // See if this toolbar option
  1779. // appears as a command on this
  1780. // menu or is a separator
  1781. if (nID == 0 || GetMenuState(nID, MF_BYCOMMAND) == 0xFFFFFFFF)
  1782. continue; // Item doesn't exist
  1783. UINT nStyle;
  1784. int nImage;
  1785. // Get the toolbar button info
  1786. pToolBar->GetButtonInfo(i, nID, nStyle, nImage);
  1787. // OK, we have the command ID of the toolbar
  1788. // option, and the tollbar bitmap offset
  1789. int nLoc;
  1790. BCMenuData* pData;
  1791. BCMenu *pSubMenu = FindMenuOption(nID, nLoc);
  1792. if (pSubMenu && nLoc >= 0)pData = pSubMenu->m_MenuList[nLoc];
  1793. else {
  1794. // Create a new BCMenuData structure
  1795. pData = new BCMenuData;
  1796. m_MenuList.Add(pData);
  1797. }
  1798. // Set some default structure members
  1799. pData->menuIconNormal = nResourceID;
  1800. pData->nID = nID;
  1801. pData->nFlags =  MF_BYCOMMAND | MF_OWNERDRAW;
  1802. pData->xoffset = nImage;
  1803. if (pData->bitmap)pData->bitmap->DeleteImageList();
  1804. else pData->bitmap = new CImageList;
  1805. pData->bitmap->Create(m_iconX, m_iconY,ILC_COLORDDB|ILC_MASK, 1, 1);
  1806. if(!AddBitmapToImageList(pData->bitmap, nResourceID)){
  1807. pData->bitmap->DeleteImageList();
  1808. delete pData->bitmap;
  1809. pData->bitmap=NULL;
  1810. pData->menuIconNormal = -1;
  1811. pData->xoffset = -1;
  1812. }
  1813. // Modify our menu
  1814. ModifyMenu(nID,pData->nFlags,nID,(LPCTSTR)pData);
  1815. }
  1816. }
  1817. BOOL BCMenu::Draw3DCheckmark(CDC *dc, const CRect& rc,
  1818.                              BOOL bSelected, HBITMAP hbmCheck)
  1819. {
  1820. CRect rcDest = rc;
  1821. CBrush brush;
  1822. COLORREF col=GetSysColor((bSelected||!IsNewShell())?COLOR_MENU:COLOR_3DLIGHT);//SK: Looks better on the old shell
  1823. brush.CreateSolidBrush(col);
  1824. dc->FillRect(rcDest,&brush);
  1825. brush.DeleteObject();
  1826. if (IsNewShell()) //SK: looks better on the old shell
  1827. dc->DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT);
  1828. if (!hbmCheck)DrawCheckMark(dc,rc.left+4,rc.top+4,GetSysColor(COLOR_MENUTEXT));
  1829. else DrawRadioDot(dc,rc.left+5,rc.top+4,GetSysColor(COLOR_MENUTEXT));
  1830. return TRUE;
  1831. }
  1832. BOOL BCMenu::DrawXPCheckmark(CDC *dc, const CRect& rc, HBITMAP hbmCheck,COLORREF &colorout)
  1833. {
  1834. CBrush brushin;
  1835. brushin.CreateSolidBrush(LightenColor(colorout,0.85));
  1836. dc->FillRect(rc,&brushin);
  1837. brushin.DeleteObject();
  1838. dc->Draw3dRect (rc,colorout,colorout);
  1839. if (!hbmCheck)DrawCheckMark(dc,rc.left+5,rc.top+4,GetSysColor(COLOR_MENUTEXT));
  1840. else DrawRadioDot(dc,rc.left+5,rc.top+4,GetSysColor(COLOR_MENUTEXT));
  1841. return TRUE;
  1842. }
  1843. void BCMenu::DitherBlt2(CDC *drawdc, int nXDest, int nYDest, int nWidth, 
  1844.                         int nHeight, CBitmap &bmp, int nXSrc, int nYSrc,
  1845. COLORREF bgcolor)
  1846. {
  1847. // create a monochrome memory DC
  1848. CDC ddc;
  1849. ddc.CreateCompatibleDC(0);
  1850. CBitmap bwbmp;
  1851. bwbmp.CreateCompatibleBitmap(&ddc, nWidth, nHeight);
  1852. CBitmap * pddcOldBmp = ddc.SelectObject(&bwbmp);
  1853. CDC dc;
  1854. dc.CreateCompatibleDC(0);
  1855. CBitmap * pdcOldBmp = dc.SelectObject(&bmp);
  1856. // build a mask
  1857. ddc.PatBlt(0, 0, nWidth, nHeight, WHITENESS);
  1858. dc.SetBkColor(GetSysColor(COLOR_BTNFACE));
  1859. ddc.BitBlt(0, 0, nWidth, nHeight, &dc, nXSrc,nYSrc, SRCCOPY);
  1860. dc.SetBkColor(GetSysColor(COLOR_BTNHILIGHT));
  1861. ddc.BitBlt(0, 0, nWidth, nHeight, &dc, nXSrc,nYSrc, SRCPAINT);
  1862. // Copy the image from the toolbar into the memory DC
  1863. // and draw it (grayed) back into the toolbar.
  1864. dc.FillSolidRect(0,0, nWidth, nHeight, bgcolor);
  1865. //SK: Looks better on the old shell
  1866. dc.SetBkColor(RGB(0, 0, 0));
  1867. dc.SetTextColor(RGB(255, 255, 255));
  1868. CBrush brShadow, brHilight;
  1869. brHilight.CreateSolidBrush(GetSysColor(COLOR_BTNHILIGHT));
  1870. brShadow.CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
  1871. CBrush * pOldBrush = dc.SelectObject(&brHilight);
  1872. dc.BitBlt(0,0, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
  1873. drawdc->BitBlt(nXDest+1,nYDest+1,nWidth, nHeight, &dc,0,0,SRCCOPY);
  1874. dc.BitBlt(1,1, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
  1875. dc.SelectObject(&brShadow);
  1876. dc.BitBlt(0,0, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
  1877. drawdc->BitBlt(nXDest,nYDest,nWidth, nHeight, &dc,0,0,SRCCOPY);
  1878. // reset DCs
  1879. ddc.SelectObject(pddcOldBmp);
  1880. ddc.DeleteDC();
  1881. dc.SelectObject(pOldBrush);
  1882. dc.SelectObject(pdcOldBmp);
  1883. dc.DeleteDC();
  1884. brShadow.DeleteObject();
  1885. brHilight.DeleteObject();
  1886. bwbmp.DeleteObject();
  1887. }
  1888. void BCMenu::SetDisableOldStyle(void)
  1889. {
  1890. disable_old_style=TRUE;
  1891. }
  1892. void BCMenu::UnSetDisableOldStyle(void)
  1893. {
  1894. disable_old_style=FALSE;
  1895. }
  1896. BOOL BCMenu::GetDisableOldStyle(void)
  1897. {
  1898. return(disable_old_style);
  1899. }
  1900. WORD BCMenu::NumBitmapColors(LPBITMAPINFOHEADER lpBitmap)
  1901. {
  1902. if ( lpBitmap->biClrUsed != 0)
  1903. return (WORD)lpBitmap->biClrUsed;
  1904. switch (lpBitmap->biBitCount){
  1905. case 1:
  1906. return 2;
  1907. case 4:
  1908. return 16;
  1909. case 8:
  1910. return 256;
  1911. default:
  1912. return 0;
  1913. }
  1914. return 0;
  1915. }
  1916. HBITMAP BCMenu::LoadSysColorBitmap(int nResourceId)
  1917. {
  1918. HINSTANCE hInst = 
  1919. AfxFindResourceHandle(MAKEINTRESOURCE(nResourceId),RT_BITMAP);
  1920. HRSRC hRsrc = 
  1921. ::FindResource(hInst,MAKEINTRESOURCE(nResourceId),RT_BITMAP);
  1922. if (hRsrc == NULL)return NULL;
  1923. // determine how many colors in the bitmap
  1924. HGLOBAL hglb;
  1925. if ((hglb = LoadResource(hInst, hRsrc)) == NULL)
  1926. return NULL;
  1927. LPBITMAPINFOHEADER lpBitmap = (LPBITMAPINFOHEADER)LockResource(hglb);
  1928. if (lpBitmap == NULL)return NULL;
  1929. WORD numcol = NumBitmapColors(lpBitmap);
  1930. ::FreeResource(hglb);
  1931. if(numcol!=16)return(NULL);
  1932. return AfxLoadSysColorBitmap(hInst, hRsrc, FALSE);
  1933. }
  1934. BOOL BCMenu::RemoveMenu(UINT uiId,UINT nFlags)
  1935. {
  1936. if(MF_BYPOSITION&nFlags){
  1937. UINT uint = GetMenuState(uiId,MF_BYPOSITION);
  1938. if(uint&MF_SEPARATOR && !(uint&MF_POPUP)){
  1939. delete m_MenuList.GetAt(uiId);
  1940. m_MenuList.RemoveAt(uiId);
  1941. }
  1942. else{
  1943. BCMenu* pSubMenu = (BCMenu*) GetSubMenu(uiId);
  1944. if(NULL==pSubMenu){
  1945. UINT uiCommandId = GetMenuItemID(uiId);
  1946. for(int i=0;i<m_MenuList.GetSize(); i++){
  1947. if(m_MenuList[i]->nID==uiCommandId){
  1948. delete m_MenuList.GetAt(i);
  1949. m_MenuList.RemoveAt(i);
  1950. break;
  1951. }
  1952. }
  1953. }
  1954. else{
  1955. int numSubMenus = m_SubMenus.GetUpperBound();
  1956. for(int m = numSubMenus; m >= 0; m--){
  1957. if(m_SubMenus[m]==pSubMenu->m_hMenu){
  1958. int numAllSubMenus = m_AllSubMenus.GetUpperBound();
  1959. for(int n = numAllSubMenus; n>= 0; n--){
  1960. if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
  1961. }
  1962. m_SubMenus.RemoveAt(m);
  1963. }
  1964. }
  1965. int num = pSubMenu->GetMenuItemCount();
  1966. for(int i=num-1;i>=0;--i)pSubMenu->RemoveMenu(i,MF_BYPOSITION);
  1967. for(i=m_MenuList.GetUpperBound();i>=0;i--){
  1968. if(m_MenuList[i]->nID==(UINT)pSubMenu->m_hMenu){
  1969. delete m_MenuList.GetAt(i);
  1970. m_MenuList.RemoveAt(i);
  1971. break;
  1972. }
  1973. }
  1974. delete pSubMenu;
  1975. }
  1976. }
  1977. }
  1978. else{
  1979. int iPosition =0;
  1980. BCMenu* pMenu = FindMenuOption(uiId,iPosition);
  1981. // bug fix RIA 14th September 2000 
  1982. // failed to return correct value on call to remove menu as the item was 
  1983. // removed twice. The second time its not found 
  1984. // so a value of 0 was being returned 
  1985. if(pMenu) return pMenu->RemoveMenu(iPosition,MF_BYPOSITION); // added return 
  1986. }
  1987. return CMenu::RemoveMenu(uiId,nFlags);
  1988. }
  1989. BOOL BCMenu::DeleteMenu(UINT uiId,UINT nFlags)
  1990. {
  1991. if(MF_BYPOSITION&nFlags){
  1992. UINT uint = GetMenuState(uiId,MF_BYPOSITION);
  1993. if(uint&MF_SEPARATOR && !(uint&MF_POPUP)){
  1994. delete m_MenuList.GetAt(uiId);
  1995. m_MenuList.RemoveAt(uiId);
  1996. }
  1997. else{
  1998. BCMenu* pSubMenu = (BCMenu*) GetSubMenu(uiId);
  1999. if(NULL==pSubMenu){
  2000. UINT uiCommandId = GetMenuItemID(uiId);
  2001. for(int i=0;i<m_MenuList.GetSize(); i++){
  2002. if(m_MenuList[i]->nID==uiCommandId){
  2003. delete m_MenuList.GetAt(i);
  2004. m_MenuList.RemoveAt(i);
  2005. break;
  2006. }
  2007. }
  2008. }
  2009. else{
  2010. int numSubMenus = m_SubMenus.GetUpperBound();
  2011. for(int m = numSubMenus; m >= 0; m--){
  2012. if(m_SubMenus[m]==pSubMenu->m_hMenu){
  2013. int numAllSubMenus = m_AllSubMenus.GetUpperBound();
  2014. for(int n = numAllSubMenus; n>= 0; n--){
  2015. if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
  2016. }
  2017. m_SubMenus.RemoveAt(m);
  2018. }
  2019. }
  2020. int num = pSubMenu->GetMenuItemCount();
  2021. for(int i=num-1;i>=0;--i)pSubMenu->DeleteMenu(i,MF_BYPOSITION);
  2022. for(i=m_MenuList.GetUpperBound();i>=0;i--){
  2023. if(m_MenuList[i]->nID==(UINT)pSubMenu->m_hMenu){
  2024. delete m_MenuList.GetAt(i);
  2025. m_MenuList.RemoveAt(i);
  2026. break;
  2027. }
  2028. }
  2029. delete pSubMenu;
  2030. }
  2031. }
  2032. }
  2033. else{
  2034. int iPosition =0;
  2035. BCMenu* pMenu = FindMenuOption(uiId,iPosition);
  2036. if(pMenu)pMenu->DeleteMenu(iPosition,MF_BYPOSITION);
  2037. }
  2038. return CMenu::DeleteMenu(uiId,nFlags);
  2039. }
  2040. BOOL BCMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,int nIconNormal)
  2041. {
  2042. USES_CONVERSION;
  2043. return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),nIconNormal);
  2044. }
  2045. BOOL BCMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,int nIconNormal)
  2046. {
  2047. return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,nIconNormal);
  2048. }
  2049. BOOL BCMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CImageList *il,int xoffset)
  2050. {
  2051. USES_CONVERSION;
  2052. return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),il,xoffset);
  2053. }
  2054. BOOL BCMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CImageList *il,int xoffset)
  2055. {
  2056. return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,il,xoffset);
  2057. }
  2058. BOOL BCMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CBitmap *bmp)
  2059. {
  2060. USES_CONVERSION;
  2061. return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),bmp);
  2062. }
  2063. BOOL BCMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CBitmap *bmp)
  2064. {
  2065. if(bmp){
  2066. CImageList temp;
  2067. temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  2068. if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
  2069. else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
  2070. return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,&temp,0);
  2071. }
  2072. return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,NULL,0);
  2073. }
  2074. BOOL BCMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,int nIconNormal)
  2075. {
  2076. USES_CONVERSION;
  2077. return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),nIconNormal);
  2078. }
  2079. BOOL BCMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,int nIconNormal)
  2080. {
  2081. return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,nIconNormal);
  2082. }
  2083. BOOL BCMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CImageList *il,int xoffset)
  2084. {
  2085. USES_CONVERSION;
  2086. return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),il,xoffset);
  2087. }
  2088. BOOL BCMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CImageList *il,int xoffset)
  2089. {
  2090. return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,il,xoffset);
  2091. }
  2092. BOOL BCMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CBitmap *bmp)
  2093. {
  2094. USES_CONVERSION;
  2095. return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),bmp);
  2096. }
  2097. BOOL BCMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CBitmap *bmp)
  2098. {
  2099. if(bmp){
  2100. CImageList temp;
  2101. temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  2102. if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
  2103. else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
  2104. return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,&temp,0);
  2105. }
  2106. return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,NULL,0);
  2107. }
  2108. //--------------------------------------------------------------------------
  2109. //[21.06.99 rj]
  2110. BCMenu* BCMenu::AppendODPopupMenuW(wchar_t *lpstrText)
  2111. {
  2112. BCMenu* pSubMenu = new BCMenu;
  2113. pSubMenu->m_unselectcheck=m_unselectcheck;
  2114. pSubMenu->m_selectcheck=m_selectcheck;
  2115. pSubMenu->checkmaps=checkmaps;
  2116. pSubMenu->checkmapsshare=TRUE;
  2117. pSubMenu->CreatePopupMenu();
  2118. AppendODMenuW(lpstrText,MF_POPUP,(UINT)pSubMenu->m_hMenu, -1);
  2119. return pSubMenu;
  2120. }
  2121. //--------------------------------------------------------------------------
  2122. //[21.06.99 rj]
  2123. BCMenu* BCMenu::AppendODPopupMenuA(LPCSTR lpstrText)
  2124. {
  2125. USES_CONVERSION;
  2126. return AppendODPopupMenuW(A2W(lpstrText));
  2127. }
  2128. BOOL BCMenu::ImageListDuplicate(CImageList *il,int xoffset,CImageList *newlist)
  2129. {
  2130. if (il == NULL||newlist==NULL||xoffset<0) return FALSE;
  2131. HICON hIcon = il->ExtractIcon(xoffset);
  2132. int cx, cy;
  2133. ImageList_GetIconSize(il->m_hImageList, &cx, &cy);
  2134. newlist->Create(cx,cy,ILC_COLORDDB|ILC_MASK,1,1);
  2135. newlist->Add(hIcon);
  2136. ::DestroyIcon(hIcon);
  2137. return TRUE;
  2138. }
  2139. // 2001-07-12, Damir Valiulin:
  2140. //          Added GetSubMenu (LPCTSTR lpszSubMenuName) function
  2141. //
  2142. CMenu* BCMenu::GetSubMenu(int nPos)
  2143. {
  2144. return CMenu::GetSubMenu (nPos);
  2145. }
  2146. CMenu* BCMenu::GetSubMenu(LPCTSTR lpszSubMenuName)
  2147. {
  2148. int num = GetMenuItemCount ();
  2149. CString name;
  2150. for (int i=0; i<num; i++)
  2151. {
  2152. GetMenuString (i, name, MF_BYPOSITION);
  2153. if (name.Compare (lpszSubMenuName) == 0)
  2154. {
  2155. return CMenu::GetSubMenu (i);
  2156. }
  2157. }
  2158. return NULL;
  2159. }
  2160. // Tongzhe Cui, Functions to remove a popup menu based on its name. Seperators
  2161. // before and after the popup menu can also be removed if they exist.
  2162. int BCMenu::GetMenuPosition(char* pText)
  2163. {
  2164. USES_CONVERSION;
  2165. return GetMenuPosition(A2W(pText));
  2166. }
  2167. int BCMenu::GetMenuPosition(wchar_t* pText)
  2168. {
  2169. int i,j;
  2170. BCMenu* psubmenu;
  2171. for(i=0;i<(int)(GetMenuItemCount());++i)
  2172. {
  2173. psubmenu=(BCMenu *)GetSubMenu(i);
  2174. if(!psubmenu)
  2175. {
  2176. const wchar_t *szWide;//SK: we use const to prevent misuse of this Ptr
  2177. for(j=0;j<=m_MenuList.GetUpperBound();++j)
  2178. {     
  2179. szWide = m_MenuList[j]->GetWideString ();
  2180. if(szWide && !wcscmp(pText,szWide))//SK: modified for dynamic allocation
  2181. return j;
  2182. }
  2183. }
  2184. }
  2185. // means no found;
  2186. return -1;
  2187. }
  2188. int BCMenu::RemoveMenu(char* pText, BC_Seperator sPos)
  2189. {
  2190. USES_CONVERSION;
  2191. return RemoveMenu(A2W(pText), sPos);
  2192. }
  2193. int BCMenu::RemoveMenu(wchar_t* pText, BC_Seperator sPos)
  2194. {
  2195. int nPos = GetMenuPosition(pText);
  2196. if(nPos != -1)
  2197. {
  2198. RemoveMenu(nPos, MF_BYPOSITION);
  2199. }
  2200. if(sPos == BCMENU_HEAD)
  2201. {
  2202. ASSERT(nPos - 1 >= 0);
  2203. RemoveMenu(nPos-1, MF_BYPOSITION);
  2204. }
  2205. else if(sPos == BCMENU_TAIL)
  2206. {
  2207. RemoveMenu(nPos-1, MF_BYPOSITION);
  2208. }
  2209. else if(sPos == BCMENU_BOTH)
  2210. {
  2211. // remove the end first;
  2212. RemoveMenu(nPos-1, MF_BYPOSITION);
  2213. // remove the head;
  2214. ASSERT(nPos - 1 >= 0);
  2215. RemoveMenu(nPos-1, MF_BYPOSITION);
  2216. }
  2217. return nPos;
  2218. }
  2219. // Larry Antram
  2220. BOOL BCMenu::SetMenuText(UINT id, CString string, UINT nFlags/*= MF_BYPOSITION*/ )
  2221. {
  2222. BOOL returnflag=FALSE;
  2223. if(MF_BYPOSITION&nFlags)
  2224. {
  2225. UINT numMenuItems = m_MenuList.GetUpperBound();
  2226. if(id<=numMenuItems){
  2227. #ifdef UNICODE
  2228. m_MenuList[id]->SetWideString((LPCTSTR)string);
  2229. #else
  2230. m_MenuList[id]->SetAnsiString(string);
  2231. #endif
  2232. returnflag=TRUE;
  2233. }
  2234. }
  2235. else{
  2236. int uiLoc;
  2237. BCMenu* pMenu = FindMenuOption(id,uiLoc);
  2238. if(NULL!=pMenu) returnflag = pMenu->SetMenuText(uiLoc,string);
  2239. }
  2240. return(returnflag);
  2241. }
  2242. // courtesy of Warren Stevens
  2243. void BCMenu::ColorBitmap(CDC* pDC,CBitmap& bmp,CSize size,COLORREF fill,COLORREF border,int hatchstyle)
  2244. {
  2245. CDC bmpdc;
  2246. bmpdc.CreateCompatibleDC(pDC);
  2247. bmp.CreateCompatibleBitmap(pDC, size.cx, size.cy);
  2248. CPen border_pen(PS_SOLID, 1, border);
  2249. CBrush fill_brush;
  2250. if(hatchstyle!=-1) { fill_brush.CreateHatchBrush(hatchstyle, fill); }
  2251. else      { fill_brush.CreateSolidBrush(fill);             }
  2252. CBitmap* pOldBitmap = bmpdc.SelectObject(&bmp);
  2253. CPen*    pOldPen    = bmpdc.SelectObject(&border_pen);
  2254. CBrush*  pOldBrush  = bmpdc.SelectObject(&fill_brush);
  2255. bmpdc.Rectangle(0,0, size.cx, size.cy);
  2256. if(NULL!=pOldBrush)  { bmpdc.SelectObject(pOldBrush);  }
  2257. if(NULL!=pOldPen)    { bmpdc.SelectObject(pOldPen);    }
  2258. if(NULL!=pOldBitmap) { bmpdc.SelectObject(pOldBitmap); }
  2259. }
  2260. //*************************************************************************