BCMenu.cpp
上传用户:dengkfang
上传日期:2008-12-30
资源大小:5233k
文件大小:89k
源码类别:

CA认证

开发平台:

Visual C++

  1. //*************************************************************************
  2. // BCMenu.cpp : implementation file
  3. // Version : 3.034
  4. // Date : May 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,David Kinder,Marc Loiry
  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 <afxpriv.h>       //SK: makes A2W and other spiffy AFX macros work
  27. #ifdef _DEBUG
  28. #define new DEBUG_NEW
  29. #undef THIS_FILE
  30. static char THIS_FILE[] = __FILE__;
  31. #endif
  32. #define BCMENU_GAP 1
  33. #ifndef OBM_CHECK
  34. #define OBM_CHECK 32760 // from winuser.h
  35. #endif
  36. #if _MFC_VER <0x400
  37. #error This code does not work on Versions of MFC prior to 4.0
  38. #endif
  39. static CPINFO CPInfo;
  40. // how the menu's are drawn in win9x/NT/2000
  41. UINT BCMenu::original_drawmode=BCMENU_DRAWMODE_ORIGINAL;
  42. BOOL BCMenu::original_select_disabled=TRUE;
  43. // how the menu's are drawn in winXP
  44. UINT BCMenu::xp_drawmode=BCMENU_DRAWMODE_XP;
  45. BOOL BCMenu::xp_select_disabled=FALSE;
  46. BOOL BCMenu::xp_draw_3D_bitmaps=TRUE;
  47. BOOL BCMenu::hicolor_bitmaps=FALSE;
  48. // Variable to set how accelerators are justified. The default mode (TRUE) right
  49. // justifies them to the right of the longes string in the menu. FALSE
  50. // just right justifies them.
  51. BOOL BCMenu::xp_space_accelerators=TRUE;
  52. BOOL BCMenu::original_space_accelerators=TRUE;
  53. CImageList BCMenu::m_AllImages;
  54. CArray<int,int&> BCMenu::m_AllImagesID;
  55. int BCMenu::m_iconX = 16;
  56. int BCMenu::m_iconY = 15;
  57. enum Win32Type{
  58. Win32s,
  59. WinNT3,
  60. Win95,
  61. Win98,
  62. WinME,
  63. WinNT4,
  64. Win2000,
  65. WinXP
  66. };
  67. Win32Type IsShellType()
  68. {
  69. Win32Type  ShellType;
  70. DWORD winVer;
  71. OSVERSIONINFO *osvi;
  72. winVer=GetVersion();
  73. if(winVer<0x80000000){/*NT */
  74. ShellType=WinNT3;
  75. osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
  76. if (osvi!=NULL){
  77. memset(osvi,0,sizeof(OSVERSIONINFO));
  78. osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
  79. GetVersionEx(osvi);
  80. if(osvi->dwMajorVersion==4L)ShellType=WinNT4;
  81. else if(osvi->dwMajorVersion==5L&&osvi->dwMinorVersion==0L)ShellType=Win2000;
  82. else if(osvi->dwMajorVersion==5L&&osvi->dwMinorVersion==1L)ShellType=WinXP;
  83. free(osvi);
  84. }
  85. }
  86. else if  (LOBYTE(LOWORD(winVer))<4)
  87. ShellType=Win32s;
  88. else{
  89. ShellType=Win95;
  90. osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
  91. if (osvi!=NULL){
  92. memset(osvi,0,sizeof(OSVERSIONINFO));
  93. osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
  94. GetVersionEx(osvi);
  95. if(osvi->dwMajorVersion==4L&&osvi->dwMinorVersion==10L)ShellType=Win98;
  96. else if(osvi->dwMajorVersion==4L&&osvi->dwMinorVersion==90L)ShellType=WinME;
  97. free(osvi);
  98. }
  99. }
  100. return ShellType;
  101. }
  102. static Win32Type g_Shell=IsShellType();
  103. void BCMenuData::SetAnsiString(LPCSTR szAnsiString)
  104. {
  105. USES_CONVERSION;
  106. SetWideString(A2W(szAnsiString));  //SK:  see MFC Tech Note 059
  107. }
  108. CString BCMenuData::GetString(void)//returns the menu text in ANSI or UNICODE
  109. //depending on the MFC-Version we are using
  110. {
  111. CString strText;
  112. if (m_szMenuText)
  113.     {
  114. #ifdef UNICODE
  115. strText = m_szMenuText;
  116. #else
  117. USES_CONVERSION;
  118. strText=W2A(m_szMenuText);     //SK:  see MFC Tech Note 059
  119. #endif    
  120.     }
  121. return strText;
  122. }
  123. CTypedPtrArray<CPtrArray, HMENU> BCMenu::m_AllSubMenus;  // Stores list of all sub-menus
  124. IMPLEMENT_DYNAMIC( BCMenu, CMenu )
  125. /*
  126. ===============================================================================
  127. BCMenu::BCMenu()
  128. BCMenu::~BCMenu()
  129. -----------------
  130. Constructor and Destructor.
  131. ===============================================================================
  132. */
  133. BCMenu::BCMenu()
  134. {
  135. m_bDynIcons = FALSE;     // O.S. - no dynamic icons by default
  136. disable_old_style=FALSE;
  137. m_selectcheck = -1;
  138. m_unselectcheck = -1;
  139. checkmaps=NULL;
  140. checkmapsshare=FALSE;
  141. // set the color used for the transparent background in all bitmaps
  142. m_bitmapBackground=RGB(192,192,192); //gray
  143. m_bitmapBackgroundFlag=FALSE;
  144. GetCPInfo(CP_ACP,&CPInfo);
  145. m_loadmenu=FALSE;
  146. }
  147. BCMenu::~BCMenu()
  148. {
  149. DestroyMenu();
  150. }
  151. BOOL BCMenu::IsNewShell ()
  152. {
  153. return (g_Shell>=Win95);
  154. }
  155. BOOL BCMenu::IsWinXPLuna()
  156. {
  157. if(g_Shell==WinXP){
  158. if(IsWindowsClassicTheme())return(FALSE);
  159. else return(TRUE);
  160. }
  161. return(FALSE);
  162. }
  163. BOOL BCMenu::IsLunaMenuStyle()
  164. {
  165. if(IsWinXPLuna()){
  166. if(xp_drawmode==BCMENU_DRAWMODE_XP)return(TRUE);
  167. }
  168. else{
  169. if(original_drawmode==BCMENU_DRAWMODE_XP)return(TRUE);
  170. }
  171. return(FALSE);
  172. }
  173. BCMenuData::~BCMenuData()
  174. {
  175. if(bitmap)
  176. delete(bitmap);
  177. delete[] m_szMenuText; //Need not check for NULL because ANSI X3J16 allows "delete NULL"
  178. }
  179. void BCMenuData::SetWideString(const wchar_t *szWideString)
  180. {
  181. delete[] m_szMenuText;//Need not check for NULL because ANSI X3J16 allows "delete NULL"
  182. if (szWideString)
  183.     {
  184. m_szMenuText = new wchar_t[sizeof(wchar_t)*(wcslen(szWideString)+1)];
  185. if (m_szMenuText)
  186. wcscpy(m_szMenuText,szWideString);
  187.     }
  188. else
  189. m_szMenuText=NULL;//set to NULL so we need not bother about dangling non-NULL Ptrs
  190. }
  191. BOOL BCMenu::IsMenu(CMenu *submenu)
  192. {
  193. int m;
  194. int numSubMenus = m_AllSubMenus.GetUpperBound();
  195. for(m=0;m<=numSubMenus;++m){
  196. if(submenu->m_hMenu==m_AllSubMenus[m])return(TRUE);
  197. }
  198. return(FALSE);
  199. }
  200. BOOL BCMenu::IsMenu(HMENU submenu)
  201. {
  202. int m;
  203. int numSubMenus = m_AllSubMenus.GetUpperBound();
  204. for(m=0;m<=numSubMenus;++m){
  205. if(submenu==m_AllSubMenus[m])return(TRUE);
  206. }
  207. return(FALSE);
  208. }
  209. BOOL BCMenu::DestroyMenu()
  210. {
  211. // Destroy Sub menus:
  212. int m,n;
  213. int numAllSubMenus = m_AllSubMenus.GetUpperBound();
  214. for(n = numAllSubMenus; n>= 0; n--){
  215. if(m_AllSubMenus[n]==this->m_hMenu)m_AllSubMenus.RemoveAt(n);
  216. }
  217. int numSubMenus = m_SubMenus.GetUpperBound();
  218. for(m = numSubMenus; m >= 0; m--){
  219. numAllSubMenus = m_AllSubMenus.GetUpperBound();
  220. for(n = numAllSubMenus; n>= 0; n--){
  221. if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
  222. }
  223. CMenu *ptr=FromHandle(m_SubMenus[m]);
  224. if(ptr){
  225. BOOL flag=ptr->IsKindOf(RUNTIME_CLASS( BCMenu ));
  226. if(flag)delete((BCMenu *)ptr);
  227. }
  228. }
  229. m_SubMenus.RemoveAll();
  230. // Destroy menu data
  231. int numItems = m_MenuList.GetUpperBound();
  232. for(m = 0; m <= numItems; m++)delete(m_MenuList[m]);
  233. m_MenuList.RemoveAll();
  234. if(checkmaps&&!checkmapsshare){
  235. delete checkmaps;
  236. checkmaps=NULL;
  237. }
  238. // Call base-class implementation last:
  239. return(CMenu::DestroyMenu());
  240. };
  241. int BCMenu::GetMenuDrawMode(void)
  242. {
  243. if(IsWinXPLuna())return(xp_drawmode);
  244. return(original_drawmode);
  245. }
  246. BOOL BCMenu::GetSelectDisableMode(void)
  247. {
  248. if(IsLunaMenuStyle())return(xp_select_disabled);
  249. return(original_select_disabled);
  250. }
  251. /*
  252. ==========================================================================
  253. void BCMenu::DrawItem(LPDRAWITEMSTRUCT)
  254. ---------------------------------------
  255.   Called by the framework when a particular item needs to be drawn.  We
  256.   overide this to draw the menu item in a custom-fashion, including icons
  257.   and the 3D rectangle bar.
  258.   ==========================================================================
  259. */
  260. void BCMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
  261. {
  262. ASSERT(lpDIS != NULL);
  263. CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  264. if(pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)DrawItem_Win9xNT2000(lpDIS);
  265. else{
  266. if(IsWinXPLuna()){
  267. if(xp_drawmode==BCMENU_DRAWMODE_XP) DrawItem_WinXP(lpDIS);
  268. else DrawItem_Win9xNT2000(lpDIS);
  269. }
  270. else{
  271. if(original_drawmode==BCMENU_DRAWMODE_XP) DrawItem_WinXP(lpDIS);
  272. else DrawItem_Win9xNT2000(lpDIS);
  273. }
  274. }
  275. }
  276. void BCMenu::DrawItem_Win9xNT2000 (LPDRAWITEMSTRUCT lpDIS)
  277. {
  278. ASSERT(lpDIS != NULL);
  279. CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  280. CRect rect;
  281. UINT state = (((BCMenuData*)(lpDIS->itemData))->nFlags);
  282. CBrush m_brBackground;
  283. COLORREF m_clrBack;
  284. if(IsWinXPLuna())m_clrBack=GetSysColor(COLOR_3DFACE);
  285. else m_clrBack=GetSysColor(COLOR_MENU);
  286. m_brBackground.CreateSolidBrush(m_clrBack);
  287. // remove the selected bit if it's grayed out
  288. if(lpDIS->itemState & ODS_GRAYED&&!original_select_disabled){
  289. if(lpDIS->itemState & ODS_SELECTED)lpDIS->itemState=lpDIS->itemState & ~ODS_SELECTED;
  290. }
  291. if(state & MF_SEPARATOR){
  292. rect.CopyRect(&lpDIS->rcItem);
  293. pDC->FillRect (rect,&m_brBackground);
  294. rect.top += (rect.Height()>>1);
  295. pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
  296. }
  297. else{
  298. CRect rect2;
  299. BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
  300. BOOL checkflag=FALSE;
  301. COLORREF crText = GetSysColor(COLOR_MENUTEXT);
  302. CBrush m_brSelect;
  303. CPen m_penBack;
  304. int x0,y0,dy;
  305. int nIconNormal=-1,xoffset=-1,global_offset=-1;
  306. CImageList *bitmap=NULL;
  307. // set some colors
  308. m_penBack.CreatePen (PS_SOLID,0,m_clrBack);
  309. m_brSelect.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
  310. // draw the colored rectangle portion
  311. rect.CopyRect(&lpDIS->rcItem);
  312. rect2=rect;
  313. // draw the up/down/focused/disabled state
  314. UINT state = lpDIS->itemState;
  315. CString strText;
  316. if(lpDIS->itemData != NULL){
  317. nIconNormal = (((BCMenuData*)(lpDIS->itemData))->menuIconNormal);
  318. xoffset = (((BCMenuData*)(lpDIS->itemData))->xoffset);
  319. global_offset = (((BCMenuData*)(lpDIS->itemData))->global_offset);
  320. bitmap = (((BCMenuData*)(lpDIS->itemData))->bitmap);
  321. strText = ((BCMenuData*) (lpDIS->itemData))->GetString();
  322. if(nIconNormal<0&&global_offset>=0){
  323. xoffset=global_offset;
  324. nIconNormal=0;
  325. bitmap = &m_AllImages;
  326. }
  327. if(state&ODS_CHECKED && nIconNormal<0){
  328. if(state&ODS_SELECTED && m_selectcheck>0)checkflag=TRUE;
  329. else if(m_unselectcheck>0) checkflag=TRUE;
  330. }
  331. else if(nIconNormal != -1){
  332. standardflag=TRUE;
  333. if(state&ODS_SELECTED && !(state&ODS_GRAYED))selectedflag=TRUE;
  334. else if(state&ODS_GRAYED) disableflag=TRUE;
  335. }
  336. }
  337. else{
  338. strText.Empty();
  339. }
  340. if(state&ODS_SELECTED){ // draw the down edges
  341. CPen *pOldPen = pDC->SelectObject (&m_penBack);
  342. // You need only Text highlight and thats what you get
  343. if(checkflag||standardflag||selectedflag||disableflag||state&ODS_CHECKED)
  344. rect2.SetRect(rect.left+m_iconX+4+BCMENU_GAP,rect.top,rect.right,rect.bottom);
  345. pDC->FillRect (rect2,&m_brSelect);
  346. pDC->SelectObject (pOldPen);
  347. crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
  348. }
  349. else {
  350. CPen *pOldPen = pDC->SelectObject (&m_penBack);
  351. pDC->FillRect (rect,&m_brBackground);
  352. pDC->SelectObject (pOldPen);
  353. // draw the up edges
  354. pDC->Draw3dRect (rect,m_clrBack,m_clrBack);
  355. }
  356. // draw the text if there is any
  357. //We have to paint the text only if the image is nonexistant
  358. dy = (rect.Height()-4-m_iconY)/2;
  359. dy = dy<0 ? 0 : dy;
  360. if(checkflag||standardflag||selectedflag||disableflag){
  361. rect2.SetRect(rect.left+1,rect.top+1+dy,rect.left+m_iconX+3,
  362. rect.top+m_iconY+3+dy);
  363. pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
  364. if(checkflag && checkmaps){
  365. pDC->FillRect (rect2,&m_brBackground);
  366. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  367. rect.top+m_iconY+4+dy);
  368. pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
  369. CPoint ptImage(rect.left+2,rect.top+2+dy);
  370. if(state&ODS_SELECTED)checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
  371. else checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
  372. }
  373. else if(disableflag){
  374. if(!selectedflag){
  375. CBitmap bitmapstandard;
  376. GetBitmapFromImageList(pDC,bitmap,xoffset,bitmapstandard);
  377. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  378.                         rect.top+m_iconY+4+dy);
  379. pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
  380. if(disable_old_style)
  381. DitherBlt(lpDIS->hDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
  382. (HBITMAP)(bitmapstandard),0,0,m_clrBack);
  383. else{
  384. if(hicolor_bitmaps)
  385. DitherBlt3(pDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
  386. bitmapstandard,m_clrBack);
  387. else
  388. DitherBlt2(pDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
  389. bitmapstandard,0,0,m_clrBack);
  390. }
  391. bitmapstandard.DeleteObject();
  392. }
  393. }
  394. else if(selectedflag){
  395. pDC->FillRect (rect2,&m_brBackground);
  396. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  397. rect.top+m_iconY+4+dy);
  398. if (IsNewShell()){
  399. if(state&ODS_CHECKED)
  400. pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),
  401. GetSysColor(COLOR_3DHILIGHT));
  402. else
  403. pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DHILIGHT),
  404. GetSysColor(COLOR_3DSHADOW));
  405. }
  406. CPoint ptImage(rect.left+2,rect.top+2+dy);
  407. if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
  408. }
  409. else{
  410. if(state&ODS_CHECKED){
  411. CBrush brush;
  412. COLORREF col = m_clrBack;
  413. col = LightenColor(col,0.6);
  414. brush.CreateSolidBrush(col);
  415. pDC->FillRect(rect2,&brush);
  416. brush.DeleteObject();
  417. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  418.                         rect.top+m_iconY+4+dy);
  419. if (IsNewShell())
  420. pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),
  421. GetSysColor(COLOR_3DHILIGHT));
  422. }
  423. else{
  424. pDC->FillRect (rect2,&m_brBackground);
  425. rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
  426.                         rect.top+m_iconY+4+dy);
  427. pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
  428. }
  429. CPoint ptImage(rect.left+2,rect.top+2+dy);
  430. if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
  431. }
  432. }
  433. if(nIconNormal<0 && state&ODS_CHECKED && !checkflag){
  434. rect2.SetRect(rect.left+1,rect.top+2+dy,rect.left+m_iconX+1,
  435. rect.top+m_iconY+2+dy);
  436. CMenuItemInfo info;
  437. info.fMask = MIIM_CHECKMARKS;
  438. ::GetMenuItemInfo((HMENU)lpDIS->hwndItem,lpDIS->itemID,
  439. MF_BYCOMMAND, &info);
  440. if(state&ODS_CHECKED || info.hbmpUnchecked) {
  441. Draw3DCheckmark(pDC, rect2, state&ODS_SELECTED,
  442. state&ODS_CHECKED ? info.hbmpChecked :
  443. info.hbmpUnchecked);
  444. }
  445. }
  446. //This is needed always so that we can have the space for check marks
  447. x0=rect.left;y0=rect.top;
  448. rect.left = rect.left + m_iconX + 8 + BCMENU_GAP; 
  449. if(!strText.IsEmpty()){
  450. CRect rectt(rect.left,rect.top-1,rect.right,rect.bottom-1);
  451. //   Find tabs
  452. CString leftStr,rightStr;
  453. leftStr.Empty();rightStr.Empty();
  454. int tablocr=strText.ReverseFind(_T('t'));
  455. if(tablocr!=-1){
  456. rightStr=strText.Mid(tablocr+1);
  457. leftStr=strText.Left(strText.Find(_T('t')));
  458. rectt.right-=m_iconX;
  459. }
  460. else leftStr=strText;
  461. int iOldMode = pDC->GetBkMode();
  462. pDC->SetBkMode( TRANSPARENT);
  463. // Draw the text in the correct colour:
  464. UINT nFormat  = DT_LEFT|DT_SINGLELINE|DT_VCENTER;
  465. UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
  466. if(!(lpDIS->itemState & ODS_GRAYED)){
  467. pDC->SetTextColor(crText);
  468. pDC->DrawText (leftStr,rectt,nFormat);
  469. if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
  470. }
  471. else{
  472. // Draw the disabled text
  473. if(!(state & ODS_SELECTED)){
  474. RECT offset = *rectt;
  475. offset.left+=1;
  476. offset.right+=1;
  477. offset.top+=1;
  478. offset.bottom+=1;
  479. pDC->SetTextColor(GetSysColor(COLOR_BTNHILIGHT));
  480. pDC->DrawText(leftStr,&offset, nFormat);
  481. if(tablocr!=-1) pDC->DrawText (rightStr,&offset,nFormatr);
  482. pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
  483. pDC->DrawText(leftStr,rectt, nFormat);
  484. if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
  485. }
  486. else{
  487. // And the standard Grey text:
  488. pDC->SetTextColor(m_clrBack);
  489. pDC->DrawText(leftStr,rectt, nFormat);
  490. if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
  491. }
  492. }
  493. pDC->SetBkMode( iOldMode );
  494. }
  495. m_penBack.DeleteObject();
  496. m_brSelect.DeleteObject();
  497. }
  498. m_brBackground.DeleteObject();
  499. }
  500. COLORREF BCMenu::LightenColor(COLORREF col,double factor)
  501. {
  502. if(factor>0.0&&factor<=1.0){
  503. BYTE red,green,blue,lightred,lightgreen,lightblue;
  504. red = GetRValue(col);
  505. green = GetGValue(col);
  506. blue = GetBValue(col);
  507. lightred = (BYTE)((factor*(255-red)) + red);
  508. lightgreen = (BYTE)((factor*(255-green)) + green);
  509. lightblue = (BYTE)((factor*(255-blue)) + blue);
  510. col = RGB(lightred,lightgreen,lightblue);
  511. }
  512. return(col);
  513. }
  514. COLORREF BCMenu::DarkenColor(COLORREF col,double factor)
  515. {
  516. if(factor>0.0&&factor<=1.0){
  517. BYTE red,green,blue,lightred,lightgreen,lightblue;
  518. red = GetRValue(col);
  519. green = GetGValue(col);
  520. blue = GetBValue(col);
  521. lightred = (BYTE)(red-(factor*red));
  522. lightgreen = (BYTE)(green-(factor*green));
  523. lightblue = (BYTE)(blue-(factor*blue));
  524. col = RGB(lightred,lightgreen,lightblue);
  525. }
  526. return(col);
  527. }
  528. void BCMenu::DrawItem_WinXP (LPDRAWITEMSTRUCT lpDIS)
  529. {
  530. ASSERT(lpDIS != NULL);
  531. CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  532. #ifdef BCMENU_USE_MEMDC
  533. BCMenuMemDC *pMemDC=NULL;
  534. #endif
  535. CRect rect,rect2;
  536. UINT state = (((BCMenuData*)(lpDIS->itemData))->nFlags);
  537. COLORREF m_newclrBack=GetSysColor(COLOR_3DFACE);
  538. COLORREF m_clrBack=GetSysColor(COLOR_WINDOW);
  539. m_clrBack=DarkenColor(m_clrBack,0.02);
  540. CFont m_fontMenu,*pFont=NULL;
  541. LOGFONT m_lf;
  542. if(!IsWinXPLuna())m_newclrBack=LightenColor(m_newclrBack,0.25);
  543. CBrush m_newbrBackground,m_brBackground;
  544. m_brBackground.CreateSolidBrush(m_clrBack);
  545. m_newbrBackground.CreateSolidBrush(m_newclrBack);
  546. int BCMENU_PAD=4;
  547. if(xp_draw_3D_bitmaps)BCMENU_PAD=7;
  548. int barwidth=m_iconX+BCMENU_PAD;
  549. // remove the selected bit if it's grayed out
  550. if(lpDIS->itemState & ODS_GRAYED&&!xp_select_disabled){
  551. if(lpDIS->itemState & ODS_SELECTED)lpDIS->itemState=lpDIS->itemState & ~ODS_SELECTED;
  552. #ifdef BCMENU_USE_MEMDC
  553. pMemDC=new BCMenuMemDC(pDC,&lpDIS->rcItem);
  554. pDC = pMemDC;
  555. ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
  556. NONCLIENTMETRICS nm;
  557. nm.cbSize = sizeof (NONCLIENTMETRICS);
  558. VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); 
  559. m_lf =  nm.lfMenuFont;
  560. m_fontMenu.CreateFontIndirect (&m_lf);
  561. pFont = pDC->SelectObject (&m_fontMenu);
  562. #endif
  563. }
  564. if(state & MF_SEPARATOR){
  565. rect.CopyRect(&lpDIS->rcItem);
  566. pDC->FillRect (rect,&m_brBackground);
  567. rect2.SetRect(rect.left,rect.top,rect.left+barwidth,rect.bottom);
  568. rect.top+=rect.Height()>>1;
  569. rect.left = rect2.right+BCMENU_PAD;
  570. pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
  571. pDC->FillRect (rect2,&m_newbrBackground);
  572. pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
  573. }
  574. else{
  575. BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
  576. BOOL checkflag=FALSE;
  577. COLORREF crText = GetSysColor(COLOR_MENUTEXT);
  578. COLORREF crSelect = GetSysColor(COLOR_HIGHLIGHT);
  579. COLORREF crSelectFill;
  580. if(!IsWinXPLuna())crSelectFill=LightenColor(crSelect,0.85);
  581. else crSelectFill=LightenColor(crSelect,0.7);
  582. CBrush m_brSelect;
  583. CPen m_penBack;
  584. int x0,y0,dx,dy;
  585. int nIconNormal=-1,xoffset=-1,global_offset=-1;
  586. int faded_offset=1,shadow_offset=2,disabled_offset=3;
  587. CImageList *bitmap=NULL;
  588. BOOL CanDraw3D=FALSE;
  589. // set some colors
  590. m_penBack.CreatePen (PS_SOLID,0,m_clrBack);
  591. m_brSelect.CreateSolidBrush(crSelectFill);
  592. // draw the colored rectangle portion
  593. rect.CopyRect(&lpDIS->rcItem);
  594. rect2=rect;
  595. // draw the up/down/focused/disabled state
  596. UINT state = lpDIS->itemState;
  597. CString strText;
  598. if(lpDIS->itemData != NULL){
  599. nIconNormal = (((BCMenuData*)(lpDIS->itemData))->menuIconNormal);
  600. xoffset = (((BCMenuData*)(lpDIS->itemData))->xoffset);
  601. bitmap = (((BCMenuData*)(lpDIS->itemData))->bitmap);
  602. strText = ((BCMenuData*) (lpDIS->itemData))->GetString();
  603. global_offset = (((BCMenuData*)(lpDIS->itemData))->global_offset);
  604. if(xoffset==0&&xp_draw_3D_bitmaps&&bitmap&&bitmap->GetImageCount()>2)CanDraw3D=TRUE;
  605. if(nIconNormal<0&&xoffset<0&&global_offset>=0)
  606. {
  607. xoffset=global_offset;
  608. nIconNormal=0;
  609. bitmap = &m_AllImages;
  610. if(xp_draw_3D_bitmaps&&CanDraw3DImageList(global_offset))
  611. {
  612. CanDraw3D=TRUE;
  613. faded_offset=global_offset+1;
  614. shadow_offset=global_offset+2;
  615. disabled_offset=global_offset+3;
  616. }
  617. }
  618. if(state&ODS_CHECKED && nIconNormal<0){
  619. if(state&ODS_SELECTED && m_selectcheck>0)checkflag=TRUE;
  620. else if(m_unselectcheck>0) checkflag=TRUE;
  621. }
  622. else if(nIconNormal != -1){
  623. standardflag=TRUE;
  624. if(state&ODS_SELECTED && !(state&ODS_GRAYED))selectedflag=TRUE;
  625. else if(state&ODS_GRAYED) disableflag=TRUE;
  626. }
  627. }
  628. else{
  629. strText.Empty();
  630. }
  631. if(state&ODS_SELECTED)
  632. { // draw the down edges
  633. CPen *pOldPen = pDC->SelectObject (&m_penBack);
  634. pDC->FillRect (rect,&m_brSelect);
  635. pDC->Draw3dRect (rect,crSelect,crSelect);
  636. pDC->SelectObject (pOldPen);
  637. }
  638. else 
  639. {
  640. rect2.SetRect(rect.left,rect.top,rect.left+barwidth,rect.bottom);
  641. CPen *pOldPen = pDC->SelectObject (&m_penBack);
  642. pDC->FillRect (rect,&m_brBackground);
  643. pDC->FillRect (rect2,&m_newbrBackground);
  644. pDC->SelectObject (pOldPen);
  645. // draw the up edges
  646. pDC->Draw3dRect (rect,m_clrBack,m_clrBack);
  647. pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
  648. }
  649. // draw the text if there is any
  650. //We have to paint the text only if the image is nonexistant
  651. dy = (int)(0.5+(rect.Height()-m_iconY)/2.0);
  652. dy = dy<0 ? 0 : dy;
  653. dx = (int)(0.5+(barwidth-m_iconX)/2.0);
  654. dx = dx<0 ? 0 : dx;
  655. rect2.SetRect(rect.left+1,rect.top+1,rect.left+barwidth-2,rect.bottom-1);
  656. if(checkflag||standardflag||selectedflag||disableflag){
  657. if(checkflag && checkmaps){
  658. pDC->FillRect (rect2,&m_newbrBackground);
  659. CPoint ptImage(rect.left+dx,rect.top+dy);
  660. if(state&ODS_SELECTED)checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
  661. else checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
  662. }
  663. else if(disableflag){
  664. if(!selectedflag){
  665. if(CanDraw3D){
  666. CPoint ptImage(rect.left+dx,rect.top+dy);
  667. bitmap->Draw(pDC,disabled_offset,ptImage,ILD_TRANSPARENT);
  668. }
  669. else{
  670. CBitmap bitmapstandard;
  671. GetBitmapFromImageList(pDC,bitmap,xoffset,bitmapstandard);
  672. COLORREF transparentcol=m_newclrBack;
  673. if(state&ODS_SELECTED)transparentcol=crSelectFill;
  674. if(disable_old_style)
  675. DitherBlt(lpDIS->hDC,rect.left+dx,rect.top+dy,m_iconX,m_iconY,
  676. (HBITMAP)(bitmapstandard),0,0,transparentcol);
  677. else
  678. DitherBlt2(pDC,rect.left+dx,rect.top+dy,m_iconX,m_iconY,
  679. bitmapstandard,0,0,transparentcol);
  680. if(state&ODS_SELECTED)pDC->Draw3dRect (rect,crSelect,crSelect);
  681. bitmapstandard.DeleteObject();
  682. }
  683. }
  684. }
  685. else if(selectedflag)
  686. {
  687. CPoint ptImage(rect.left+dx,rect.top+dy);
  688. if(state&ODS_CHECKED){
  689. CBrush brushin;
  690. brushin.CreateSolidBrush(LightenColor(crSelect,0.55));
  691. pDC->FillRect(rect2,&brushin);
  692. brushin.DeleteObject();
  693. pDC->Draw3dRect(rect2,crSelect,crSelect);
  694. ptImage.x-=1;ptImage.y-=1;
  695. }
  696. else pDC->FillRect (rect2,&m_brSelect);
  697. if(bitmap)
  698. {
  699. if(CanDraw3D&&!(state&ODS_CHECKED)){
  700. CPoint ptImage1(ptImage.x+1,ptImage.y+1);
  701. CPoint ptImage2(ptImage.x-1,ptImage.y-1);
  702. bitmap->Draw(pDC,shadow_offset,ptImage1,ILD_TRANSPARENT);
  703. bitmap->Draw(pDC,xoffset,ptImage2,ILD_TRANSPARENT);
  704. }
  705. else bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
  706. }
  707. }
  708. else{
  709. if(state&ODS_CHECKED){
  710. CBrush brushin;
  711. brushin.CreateSolidBrush(LightenColor(crSelect,0.85));
  712. pDC->FillRect(rect2,&brushin);
  713. brushin.DeleteObject();
  714. pDC->Draw3dRect(rect2,crSelect,crSelect);
  715. CPoint ptImage(rect.left+dx-1,rect.top+dy-1);
  716. if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
  717. }
  718. else{
  719. pDC->FillRect (rect2,&m_newbrBackground);
  720. pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
  721. CPoint ptImage(rect.left+dx,rect.top+dy);
  722. if(bitmap){
  723. if(CanDraw3D)
  724. bitmap->Draw(pDC,faded_offset,ptImage,ILD_TRANSPARENT);
  725. else
  726. bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
  727. }
  728. }
  729. }
  730. }
  731. if(nIconNormal<0 && state&ODS_CHECKED && !checkflag){
  732. CMenuItemInfo info;
  733. info.fMask = MIIM_CHECKMARKS;
  734. ::GetMenuItemInfo((HMENU)lpDIS->hwndItem,lpDIS->itemID,
  735. MF_BYCOMMAND, &info);
  736. if(state&ODS_CHECKED || info.hbmpUnchecked) {
  737. DrawXPCheckmark(pDC, rect2,state&ODS_CHECKED ? info.hbmpChecked :
  738. info.hbmpUnchecked,crSelect,state&ODS_SELECTED);
  739. }
  740. }
  741. //This is needed always so that we can have the space for check marks
  742. x0=rect.left;y0=rect.top;
  743. rect.left = rect.left + barwidth + 8; 
  744. if(!strText.IsEmpty()){
  745. CRect rectt(rect.left,rect.top-1,rect.right,rect.bottom-1);
  746. //   Find tabs
  747. CString leftStr,rightStr;
  748. leftStr.Empty();rightStr.Empty();
  749. int tablocr=strText.ReverseFind(_T('t'));
  750. if(tablocr!=-1){
  751. rightStr=strText.Mid(tablocr+1);
  752. leftStr=strText.Left(strText.Find(_T('t')));
  753. rectt.right-=m_iconX;
  754. }
  755. else leftStr=strText;
  756. int iOldMode = pDC->GetBkMode();
  757. pDC->SetBkMode( TRANSPARENT);
  758. // Draw the text in the correct colour:
  759. UINT nFormat  = DT_LEFT|DT_SINGLELINE|DT_VCENTER;
  760. UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
  761. if(!(lpDIS->itemState & ODS_GRAYED)){
  762. pDC->SetTextColor(crText);
  763. pDC->DrawText (leftStr,rectt,nFormat);
  764. if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
  765. }
  766. else{
  767. RECT offset = *rectt;
  768. offset.left+=1;
  769. offset.right+=1;
  770. offset.top+=1;
  771. offset.bottom+=1;
  772. if(!IsWinXPLuna()){
  773. COLORREF graycol=GetSysColor(COLOR_GRAYTEXT);
  774. if(!(state&ODS_SELECTED))graycol = LightenColor(graycol,0.4);
  775. pDC->SetTextColor(graycol);
  776. }
  777. else pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
  778. pDC->DrawText(leftStr,rectt, nFormat);
  779. if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
  780. }
  781. pDC->SetBkMode( iOldMode );
  782. }
  783. m_penBack.DeleteObject();
  784. m_brSelect.DeleteObject();
  785. }
  786. m_brBackground.DeleteObject();
  787. m_newbrBackground.DeleteObject();
  788. #ifdef BCMENU_USE_MEMDC
  789. if(pFont)pDC->SelectObject (pFont); //set it to the old font
  790. m_fontMenu.DeleteObject();
  791. if(pMemDC)delete pMemDC;
  792. #endif
  793. }
  794. BOOL BCMenu::GetBitmapFromImageList(CDC* pDC,CImageList *imglist,int nIndex,CBitmap &bmp)
  795. {
  796. HICON hIcon = imglist->ExtractIcon(nIndex);
  797. CDC dc;
  798. dc.CreateCompatibleDC(pDC);
  799. bmp.CreateCompatibleBitmap(pDC,m_iconX,m_iconY);
  800. CBitmap* pOldBmp = dc.SelectObject(&bmp);
  801. CBrush brush ;
  802. COLORREF m_newclrBack;
  803. m_newclrBack=GetSysColor(COLOR_3DFACE);
  804. brush.CreateSolidBrush(m_newclrBack);
  805. ::DrawIconEx(
  806. dc.GetSafeHdc(),
  807. 0,
  808. 0,
  809. hIcon,
  810. m_iconX,
  811. m_iconY,
  812. 0,
  813. (HBRUSH)brush,
  814. DI_NORMAL
  815. );
  816. dc.SelectObject( pOldBmp );
  817. dc.DeleteDC();
  818. // the icon is not longer needed
  819. ::DestroyIcon(hIcon);
  820. return(TRUE);
  821. }
  822. /*
  823. ==========================================================================
  824. void BCMenu::MeasureItem(LPMEASUREITEMSTRUCT)
  825. ---------------------------------------------
  826.   Called by the framework when it wants to know what the width and height
  827.   of our item will be.  To accomplish this we provide the width of the
  828.   icon plus the width of the menu text, and then the height of the icon.
  829.   
  830. ==========================================================================
  831. */
  832. void BCMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
  833. {
  834. UINT state = (((BCMenuData*)(lpMIS->itemData))->nFlags);
  835. int BCMENU_PAD=4;
  836. if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps)BCMENU_PAD=7;
  837. if(state & MF_SEPARATOR){
  838. lpMIS->itemWidth = 0;
  839. int temp = GetSystemMetrics(SM_CYMENU)>>1;
  840. if(IsLunaMenuStyle())
  841. lpMIS->itemHeight = 3;
  842. else
  843. lpMIS->itemHeight = temp>(m_iconY+BCMENU_PAD)/2 ? temp : (m_iconY+BCMENU_PAD)/2;
  844. }
  845. else{
  846. CFont m_fontMenu;
  847. LOGFONT m_lf;
  848. ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
  849. NONCLIENTMETRICS nm;
  850. nm.cbSize = sizeof (NONCLIENTMETRICS);
  851. VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
  852. nm.cbSize,&nm,0)); 
  853. m_lf =  nm.lfMenuFont;
  854. m_fontMenu.CreateFontIndirect (&m_lf);
  855. // Obtain the width of the text:
  856. CWnd *pWnd = AfxGetMainWnd();            // Get main window
  857. if (pWnd == NULL) pWnd = CWnd::GetDesktopWindow();
  858. CDC *pDC = pWnd->GetDC();              // Get device context
  859. CFont* pFont=NULL;    // Select menu font in...
  860. if (IsNewShell())
  861. pFont = pDC->SelectObject (&m_fontMenu);// Select menu font in...
  862.         
  863. //Get pointer to text SK
  864. const wchar_t *lpstrText = ((BCMenuData*)(lpMIS->itemData))->GetWideString();//SK: we use const to prevent misuse
  865.     
  866. SIZE size;
  867. size.cx=size.cy=0;
  868. if (Win32s!=g_Shell)
  869. VERIFY(::GetTextExtentPoint32W(pDC->m_hDC,lpstrText,
  870. wcslen(lpstrText),&size)); //SK should also work on 95
  871. #ifndef UNICODE //can't be UNICODE for Win32s
  872. else{//it's Win32suckx
  873. RECT rect;
  874. rect.left=rect.top=0;
  875. size.cy=DrawText(pDC->m_hDC,(LPCTSTR)lpstrText,
  876. wcslen(lpstrText),&rect,
  877. DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_CALCRECT);
  878. //+3 makes at least three pixels space to the menu border
  879. size.cx=rect.right-rect.left+3;
  880. size.cx += 3*(size.cx/wcslen(lpstrText));
  881. }
  882. #endif    
  883. CSize t = CSize(size);
  884. if(IsNewShell())
  885. pDC->SelectObject (pFont);  // Select old font in
  886. pWnd->ReleaseDC(pDC);  // Release the DC
  887. // Set width and height:
  888. if(IsLunaMenuStyle())lpMIS->itemWidth = m_iconX+BCMENU_PAD+8+t.cx;
  889. else lpMIS->itemWidth = m_iconX + t.cx + m_iconX + BCMENU_GAP;
  890. int temp = GetSystemMetrics(SM_CYMENU);
  891. lpMIS->itemHeight = temp>m_iconY+BCMENU_PAD ? temp : m_iconY+BCMENU_PAD;
  892. m_fontMenu.DeleteObject();
  893. }
  894. }
  895. void BCMenu::SetIconSize (int width, int height)
  896. {
  897. m_iconX = width;
  898. m_iconY = height;
  899. }
  900. BOOL BCMenu::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,
  901.                            int nIconNormal)
  902. {
  903. USES_CONVERSION;
  904. return AppendODMenuW(A2W(lpstrText),nFlags,nID,nIconNormal);//SK: See MFC Tech Note 059
  905. }
  906. BOOL BCMenu::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,
  907.                            int nIconNormal)
  908. {
  909. // Add the MF_OWNERDRAW flag if not specified:
  910. if(!nID){
  911. if(nFlags&MF_BYPOSITION)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  912. else nFlags=MF_SEPARATOR|MF_OWNERDRAW;
  913. }
  914. else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
  915. if(nFlags & MF_POPUP){
  916. m_AllSubMenus.Add((HMENU)nID);
  917. m_SubMenus.Add((HMENU)nID);
  918. }
  919. BCMenuData *mdata = new BCMenuData;
  920. m_MenuList.Add(mdata);
  921. mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
  922. mdata->menuIconNormal = -1;
  923. mdata->xoffset = -1;
  924. if(nIconNormal>=0){
  925. CImageList bitmap;
  926. int xoffset=0;
  927. LoadFromToolBar(nID,nIconNormal,xoffset);
  928. if(mdata->bitmap){
  929. mdata->bitmap->DeleteImageList();
  930. mdata->bitmap=NULL;
  931. }
  932. bitmap.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  933. if(AddBitmapToImageList(&bitmap,nIconNormal)){
  934. mdata->global_offset = AddToGlobalImageList(&bitmap,xoffset,nID);
  935. }
  936. }
  937. else mdata->global_offset = GlobalImageListOffset(nID);
  938. mdata->nFlags = nFlags;
  939. mdata->nID = nID;
  940. BOOL returnflag=CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata);
  941. if(m_loadmenu)RemoveTopLevelOwnerDraw();
  942. return(returnflag);
  943. }
  944. BOOL BCMenu::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,
  945.                            CImageList *il,int xoffset)
  946. {
  947. USES_CONVERSION;
  948. return AppendODMenuW(A2W(lpstrText),nFlags,nID,il,xoffset);
  949. }
  950. BOOL BCMenu::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,
  951.                            CImageList *il,int xoffset)
  952. {
  953. // Add the MF_OWNERDRAW flag if not specified:
  954. if(!nID){
  955. if(nFlags&MF_BYPOSITION)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  956. else nFlags=MF_SEPARATOR|MF_OWNERDRAW;
  957. }
  958. else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
  959. if(nFlags & MF_POPUP){
  960. m_AllSubMenus.Add((HMENU)nID);
  961. m_SubMenus.Add((HMENU)nID);
  962. }
  963. BCMenuData *mdata = new BCMenuData;
  964. m_MenuList.Add(mdata);
  965. mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
  966. if(il){
  967. mdata->menuIconNormal = 0;
  968. mdata->xoffset=0;
  969. if(mdata->bitmap)mdata->bitmap->DeleteImageList();
  970. else mdata->bitmap=new(CImageList);
  971. ImageListDuplicate(il,xoffset,mdata->bitmap);
  972. }
  973. else{
  974. mdata->menuIconNormal = -1;
  975. mdata->xoffset = -1;
  976. }
  977. mdata->nFlags = nFlags;
  978. mdata->nID = nID;
  979. return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
  980. }
  981. BOOL BCMenu::InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,
  982.                            int nIconNormal)
  983. {
  984. USES_CONVERSION;
  985. return InsertODMenuW(nPosition,A2W(lpstrText),nFlags,nID,nIconNormal);
  986. }
  987. BOOL BCMenu::InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,
  988.                            int nIconNormal)
  989. {
  990. if(!(nFlags & MF_BYPOSITION)){
  991. int iPosition =0;
  992. BCMenu* pMenu = FindMenuOption(nPosition,iPosition);
  993. if(pMenu){
  994. return(pMenu->InsertODMenuW(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,nIconNormal));
  995. }
  996. else return(FALSE);
  997. }
  998. if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  999. else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
  1000. int menustart=0;
  1001. if(nFlags & MF_POPUP){
  1002. if(m_loadmenu){
  1003. menustart=GetMenuStart();
  1004. if(nPosition<(UINT)menustart)menustart=0;
  1005. }
  1006. m_AllSubMenus.Add((HMENU)nID);
  1007. m_SubMenus.Add((HMENU)nID);
  1008. }
  1009. //Stephane Clog suggested adding this, believe it or not it's in the help 
  1010. if(nPosition==(UINT)-1)nPosition=GetMenuItemCount();
  1011. BCMenuData *mdata = new BCMenuData;
  1012. m_MenuList.InsertAt(nPosition-menustart,mdata);
  1013. mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
  1014. mdata->menuIconNormal = nIconNormal;
  1015. mdata->xoffset=-1;
  1016. if(nIconNormal>=0){
  1017. CImageList bitmap;
  1018. int xoffset=0;
  1019. LoadFromToolBar(nID,nIconNormal,xoffset);
  1020. if(mdata->bitmap){
  1021. mdata->bitmap->DeleteImageList();
  1022. mdata->bitmap=NULL;
  1023. }
  1024. bitmap.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  1025. if(AddBitmapToImageList(&bitmap,nIconNormal)){
  1026. mdata->global_offset = AddToGlobalImageList(&bitmap,xoffset,nID);
  1027. }
  1028. }
  1029. else mdata->global_offset = GlobalImageListOffset(nID);
  1030. mdata->nFlags = nFlags;
  1031. mdata->nID = nID;
  1032. BOOL returnflag=CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata);
  1033. if(m_loadmenu)RemoveTopLevelOwnerDraw();
  1034. return(returnflag);
  1035. }
  1036. BOOL BCMenu::InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,
  1037.                            CImageList *il,int xoffset)
  1038. {
  1039. USES_CONVERSION;
  1040. return InsertODMenuW(nPosition,A2W(lpstrText),nFlags,nID,il,xoffset);
  1041. }
  1042. BOOL BCMenu::InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,
  1043.                            CImageList *il,int xoffset)
  1044. {
  1045. if(!(nFlags & MF_BYPOSITION)){
  1046. int iPosition =0;
  1047. BCMenu* pMenu = FindMenuOption(nPosition,iPosition);
  1048. if(pMenu){
  1049. return(pMenu->InsertODMenuW(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,il,xoffset));
  1050. }
  1051. else return(FALSE);
  1052. }
  1053. if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
  1054. else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
  1055. if(nFlags & MF_POPUP){
  1056. m_AllSubMenus.Add((HMENU)nID);
  1057. m_SubMenus.Add((HMENU)nID);
  1058. }
  1059. //Stephane Clog suggested adding this, believe it or not it's in the help 
  1060. if(nPosition==(UINT)-1)nPosition=GetMenuItemCount();
  1061. BCMenuData *mdata = new BCMenuData;
  1062. m_MenuList.InsertAt(nPosition,mdata);
  1063. mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
  1064. mdata->menuIconNormal = -1;
  1065. mdata->xoffset = -1;
  1066. if(il){
  1067. if(mdata->bitmap){
  1068. mdata->bitmap->DeleteImageList();
  1069. mdata->bitmap=NULL;
  1070. }
  1071. mdata->global_offset = AddToGlobalImageList(il,xoffset,nID);
  1072. }
  1073. mdata->nFlags = nFlags;
  1074. mdata->nID = nID;
  1075. return(CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata));
  1076. }
  1077. BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,int nIconNormal)
  1078. {
  1079. USES_CONVERSION;
  1080. return ModifyODMenuW(A2W(lpstrText),nID,nIconNormal);//SK: see MFC Tech Note 059
  1081. }
  1082. BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,int nIconNormal)
  1083. {
  1084. int nLoc;
  1085. BCMenuData *mdata;
  1086. CArray<BCMenu*,BCMenu*>bcsubs;
  1087. CArray<int,int&>bclocs;
  1088. // Find the old BCMenuData structure:
  1089. BCMenu *psubmenu = FindMenuOption(nID,nLoc);
  1090. do{
  1091. if(psubmenu && nLoc>=0)mdata = psubmenu->m_MenuList[nLoc];
  1092. else{
  1093. // Create a new BCMenuData structure:
  1094. mdata = new BCMenuData;
  1095. m_MenuList.Add(mdata);
  1096. }
  1097. ASSERT(mdata);
  1098. if(lpstrText)
  1099. mdata->SetWideString(lpstrText);  //SK: modified for dynamic allocation
  1100. mdata->menuIconNormal = -1;
  1101. mdata->xoffset = -1;
  1102. if(nIconNormal>=0){
  1103. CImageList bitmap;
  1104. int xoffset=0;
  1105. LoadFromToolBar(nID,nIconNormal,xoffset);
  1106. if(mdata->bitmap){
  1107. mdata->bitmap->DeleteImageList();
  1108. mdata->bitmap=NULL;
  1109. }
  1110. bitmap.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  1111. if(AddBitmapToImageList(&bitmap,nIconNormal)){
  1112. mdata->global_offset = AddToGlobalImageList(&bitmap,xoffset,nID);
  1113. }
  1114. }
  1115. else mdata->global_offset = GlobalImageListOffset(nID);
  1116. mdata->nFlags &= ~(MF_BYPOSITION);
  1117. mdata->nFlags |= MF_OWNERDRAW;
  1118. mdata->nID = nID;
  1119. bcsubs.Add(psubmenu);
  1120. bclocs.Add(nLoc);
  1121. if(psubmenu && nLoc>=0)psubmenu = FindAnotherMenuOption(nID,nLoc,bcsubs,bclocs);
  1122. else psubmenu=NULL;
  1123. }while(psubmenu);
  1124. return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
  1125. }
  1126. BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,CImageList *il,int xoffset)
  1127. {
  1128. USES_CONVERSION;
  1129. return ModifyODMenuW(A2W(lpstrText),nID,il,xoffset);
  1130. }
  1131. BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,CImageList *il,int xoffset)
  1132. {
  1133. int nLoc;
  1134. BCMenuData *mdata;
  1135. CArray<BCMenu*,BCMenu*>bcsubs;
  1136. CArray<int,int&>bclocs;
  1137. // Find the old BCMenuData structure:
  1138. BCMenu *psubmenu = FindMenuOption(nID,nLoc);
  1139. do{
  1140. if(psubmenu && nLoc>=0)mdata = psubmenu->m_MenuList[nLoc];
  1141. else{
  1142. // Create a new BCMenuData structure:
  1143. mdata = new BCMenuData;
  1144. m_MenuList.Add(mdata);
  1145. }
  1146. ASSERT(mdata);
  1147. if(lpstrText)
  1148. mdata->SetWideString(lpstrText);  //SK: modified for dynamic allocation
  1149. mdata->menuIconNormal = -1;
  1150. mdata->xoffset = -1;
  1151. if(il){
  1152. if(mdata->bitmap){
  1153. mdata->bitmap->DeleteImageList();
  1154. mdata->bitmap=NULL;
  1155. }
  1156. mdata->global_offset = AddToGlobalImageList(il,xoffset,nID);
  1157. }
  1158. mdata->nFlags &= ~(MF_BYPOSITION);
  1159. mdata->nFlags |= MF_OWNERDRAW;
  1160. mdata->nID = nID;
  1161. bcsubs.Add(psubmenu);
  1162. bclocs.Add(nLoc);
  1163. if(psubmenu && nLoc>=0)psubmenu = FindAnotherMenuOption(nID,nLoc,bcsubs,bclocs);
  1164. else psubmenu=NULL;
  1165. }while(psubmenu);
  1166. return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
  1167. }
  1168. BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,CBitmap *bmp)
  1169. {
  1170. USES_CONVERSION;
  1171. return ModifyODMenuW(A2W(lpstrText),nID,bmp);
  1172. }
  1173. BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,CBitmap *bmp)
  1174. {
  1175. if(bmp){
  1176. CImageList temp;
  1177. temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  1178. if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
  1179. else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
  1180. return ModifyODMenuW(lpstrText,nID,&temp,0);
  1181. }
  1182. return ModifyODMenuW(lpstrText,nID,NULL,0);
  1183. }
  1184. // courtesy of Warren Stevens
  1185. BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,COLORREF fill,COLORREF border,int hatchstyle,CSize *pSize)
  1186. {
  1187. USES_CONVERSION;
  1188. return ModifyODMenuW(A2W(lpstrText),nID,fill,border,hatchstyle,pSize);
  1189. }
  1190. BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,COLORREF fill,COLORREF border,int hatchstyle,CSize *pSize)
  1191. {
  1192. CWnd *pWnd = AfxGetMainWnd();            // Get main window
  1193. CDC *pDC = pWnd->GetDC();              // Get device context
  1194. SIZE sz;
  1195. if(!pSize){
  1196. sz.cx = m_iconX;
  1197. sz.cy = m_iconY;
  1198. }
  1199. else{
  1200. sz.cx = pSize->cx;
  1201. sz.cy = pSize->cy;
  1202. }
  1203. CSize bitmap_size(sz);
  1204. CSize icon_size(m_iconX,m_iconY);
  1205. CBitmap bmp;
  1206. ColorBitmap(pDC,bmp,bitmap_size,icon_size,fill,border,hatchstyle);
  1207. pWnd->ReleaseDC(pDC);
  1208. return ModifyODMenuW(lpstrText,nID,&bmp);
  1209. }
  1210. BOOL BCMenu::ModifyODMenuA(const char *lpstrText,const char *OptionText,
  1211.                            int nIconNormal)
  1212. {
  1213. USES_CONVERSION;
  1214. return ModifyODMenuW(A2W(lpstrText),A2W(OptionText),nIconNormal);//SK: see MFC  Tech Note 059
  1215. }
  1216. BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,wchar_t *OptionText,
  1217.                            int nIconNormal)
  1218. {
  1219. BCMenuData *mdata;
  1220. // Find the old BCMenuData structure:
  1221. CString junk=OptionText;
  1222. mdata=FindMenuOption(OptionText);
  1223. if(mdata){
  1224. if(lpstrText)
  1225. mdata->SetWideString(lpstrText);//SK: modified for dynamic allocation
  1226. mdata->menuIconNormal = nIconNormal;
  1227. mdata->xoffset=-1;
  1228. if(nIconNormal>=0){
  1229. mdata->xoffset=0;
  1230. if(mdata->bitmap)mdata->bitmap->DeleteImageList();
  1231. else mdata->bitmap=new(CImageList);
  1232. mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  1233. if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
  1234. mdata->bitmap->DeleteImageList();
  1235. delete mdata->bitmap;
  1236. mdata->bitmap=NULL;
  1237. mdata->menuIconNormal = nIconNormal = -1;
  1238. mdata->xoffset = -1;
  1239. }
  1240. }
  1241. return(TRUE);
  1242. }
  1243. return(FALSE);
  1244. }
  1245. BCMenuData *BCMenu::NewODMenu(UINT pos,UINT nFlags,UINT nID,CString string)
  1246. {
  1247. BCMenuData *mdata;
  1248. mdata = new BCMenuData;
  1249. mdata->menuIconNormal = -1;
  1250. mdata->xoffset=-1;
  1251. #ifdef UNICODE
  1252. mdata->SetWideString((LPCTSTR)string);//SK: modified for dynamic allocation
  1253. #else
  1254. mdata->SetAnsiString(string);
  1255. #endif
  1256. mdata->nFlags = nFlags;
  1257. mdata->nID = nID;
  1258. // if(nFlags & MF_POPUP)m_AllSubMenus.Add((HMENU)nID);
  1259. if (nFlags&MF_OWNERDRAW){
  1260. ASSERT(!(nFlags&MF_STRING));
  1261. ModifyMenu(pos,nFlags,nID,(LPCTSTR)mdata);
  1262. }
  1263. else if (nFlags&MF_STRING){
  1264. ASSERT(!(nFlags&MF_OWNERDRAW));
  1265. ModifyMenu(pos,nFlags,nID,mdata->GetString());
  1266. }
  1267. else{
  1268. ASSERT(nFlags&MF_SEPARATOR);
  1269. ModifyMenu(pos,nFlags,nID);
  1270. }
  1271. return(mdata);
  1272. };
  1273. BOOL BCMenu::LoadToolbars(const UINT *arID,int n)
  1274. {
  1275. ASSERT(arID);
  1276. BOOL returnflag=TRUE;
  1277. for(int i=0;i<n;++i){
  1278. if(!LoadToolbar(arID[i]))returnflag=FALSE;
  1279. }
  1280. return(returnflag);
  1281. }
  1282. BOOL BCMenu::LoadToolbar(UINT nToolBar)
  1283. {
  1284. UINT nID,nStyle;
  1285. BOOL returnflag=FALSE;
  1286. CToolBar bar;
  1287. int xoffset=-1,xset;
  1288. CWnd* pWnd = AfxGetMainWnd();
  1289. if (pWnd == NULL)pWnd = CWnd::GetDesktopWindow();
  1290. bar.Create(pWnd);
  1291. if(bar.LoadToolBar(nToolBar)){
  1292. CImageList imglist;
  1293. imglist.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  1294. if(AddBitmapToImageList(&imglist,nToolBar)){
  1295. returnflag=TRUE;
  1296. for(int i=0;i<bar.GetCount();++i){
  1297. nID = bar.GetItemID(i); 
  1298. if(nID && GetMenuState(nID, MF_BYCOMMAND)
  1299. !=0xFFFFFFFF){
  1300. xoffset=bar.CommandToIndex(nID);
  1301. if(xoffset>=0){
  1302. bar.GetButtonInfo(xoffset,nID,nStyle,xset);
  1303. if(xset>0)xoffset=xset;
  1304. }
  1305. ModifyODMenu(NULL,nID,&imglist,xoffset);
  1306. }
  1307. }
  1308. }
  1309. }
  1310. return(returnflag);
  1311. }
  1312. BOOL BCMenu::LoadFromToolBar(UINT nID,UINT nToolBar,int& xoffset)
  1313. {
  1314. int xset,offset;
  1315. UINT nStyle;
  1316. BOOL returnflag=FALSE;
  1317. CToolBar bar;
  1318. CWnd* pWnd = AfxGetMainWnd();
  1319. if (pWnd == NULL)pWnd = CWnd::GetDesktopWindow();
  1320. bar.Create(pWnd);
  1321. if(bar.LoadToolBar(nToolBar)){
  1322. offset=bar.CommandToIndex(nID);
  1323. if(offset>=0){
  1324. bar.GetButtonInfo(offset,nID,nStyle,xset);
  1325. if(xset>0)xoffset=xset;
  1326. returnflag=TRUE;
  1327. }
  1328. }
  1329. return(returnflag);
  1330. }
  1331. // O.S.
  1332. BCMenuData *BCMenu::FindMenuItem(UINT nID)
  1333. {
  1334. BCMenuData *pData = NULL;
  1335. int i;
  1336. for(i = 0; i <= m_MenuList.GetUpperBound(); i++){
  1337. if (m_MenuList[i]->nID == nID){
  1338. pData = m_MenuList[i];
  1339. break;
  1340. }
  1341. }
  1342. if (!pData){
  1343. int loc;
  1344. BCMenu *pMenu = FindMenuOption(nID, loc);
  1345. ASSERT(pMenu != this);
  1346. if (loc >= 0){
  1347. return pMenu->FindMenuItem(nID);
  1348. }
  1349. }
  1350. return pData;
  1351. }
  1352. BCMenu *BCMenu::FindAnotherMenuOption(int nId,int& nLoc,CArray<BCMenu*,BCMenu*>&bcsubs,
  1353.   CArray<int,int&>&bclocs)
  1354. {
  1355. int i,numsubs,j;
  1356. BCMenu *psubmenu,*pgoodmenu;
  1357. BOOL foundflag;
  1358. for(i=0;i<(int)(GetMenuItemCount());++i){
  1359. #ifdef _CPPRTTI 
  1360. psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
  1361. #else
  1362. psubmenu=(BCMenu *)GetSubMenu(i);
  1363. #endif
  1364. if(psubmenu){
  1365. pgoodmenu=psubmenu->FindAnotherMenuOption(nId,nLoc,bcsubs,bclocs);
  1366. if(pgoodmenu)return(pgoodmenu);
  1367. }
  1368. else if(nId==(int)GetMenuItemID(i)){
  1369. numsubs=bcsubs.GetSize();
  1370. foundflag=TRUE;
  1371. for(j=0;j<numsubs;++j){
  1372. if(bcsubs[j]==this&&bclocs[j]==i){
  1373. foundflag=FALSE;
  1374. break;
  1375. }
  1376. }
  1377. if(foundflag){
  1378. nLoc=i;
  1379. return(this);
  1380. }
  1381. }
  1382. }
  1383. nLoc = -1;
  1384. return(NULL);
  1385. }
  1386. BCMenu *BCMenu::FindMenuOption(int nId,int& nLoc)
  1387. {
  1388. int i;
  1389. BCMenu *psubmenu,*pgoodmenu;
  1390. for(i=0;i<(int)(GetMenuItemCount());++i){
  1391. #ifdef _CPPRTTI 
  1392. psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
  1393. #else
  1394. psubmenu=(BCMenu *)GetSubMenu(i);
  1395. #endif
  1396. if(psubmenu){
  1397. pgoodmenu=psubmenu->FindMenuOption(nId,nLoc);
  1398. if(pgoodmenu)return(pgoodmenu);
  1399. }
  1400. else if(nId==(int)GetMenuItemID(i)){
  1401. nLoc=i;
  1402. return(this);
  1403. }
  1404. }
  1405. nLoc = -1;
  1406. return(NULL);
  1407. }
  1408. BCMenuData *BCMenu::FindMenuOption(wchar_t *lpstrText)
  1409. {
  1410. int i,j;
  1411. BCMenu *psubmenu;
  1412. BCMenuData *pmenulist;
  1413. for(i=0;i<(int)(GetMenuItemCount());++i){
  1414. #ifdef _CPPRTTI 
  1415. psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
  1416. #else
  1417. psubmenu=(BCMenu *)GetSubMenu(i);
  1418. #endif
  1419. if(psubmenu){
  1420. pmenulist=psubmenu->FindMenuOption(lpstrText);
  1421. if(pmenulist)return(pmenulist);
  1422. }
  1423. else{
  1424. const wchar_t *szWide;//SK: we use const to prevent misuse of this Ptr
  1425. for(j=0;j<=m_MenuList.GetUpperBound();++j){     
  1426. szWide = m_MenuList[j]->GetWideString ();
  1427. if(szWide && !wcscmp(lpstrText,szWide))//SK: modified for dynamic allocation
  1428. return(m_MenuList[j]);
  1429. }
  1430. }
  1431. }
  1432. return(NULL);
  1433. }
  1434. BOOL BCMenu::LoadMenu(int nResource)
  1435. {
  1436. return(BCMenu::LoadMenu(MAKEINTRESOURCE(nResource)));
  1437. };
  1438. BOOL BCMenu::LoadMenu(LPCTSTR lpszResourceName)
  1439. {
  1440. ASSERT_VALID(this);
  1441. ASSERT(lpszResourceName != NULL);
  1442. // Find the Menu Resource:
  1443. HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName,RT_MENU);
  1444. HRSRC hRsrc = ::FindResource(hInst,lpszResourceName,RT_MENU);
  1445. if (hRsrc == NULL){
  1446. hInst = NULL;
  1447. hRsrc = ::FindResource(hInst,lpszResourceName,RT_MENU);
  1448. }
  1449. if(hRsrc == NULL)return FALSE;
  1450. // Load the Menu Resource:
  1451. HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
  1452. if(hGlobal == NULL)return FALSE;
  1453. // first destroy the menu if we're trying to loadmenu again
  1454. DestroyMenu();
  1455. // Attempt to create us as a menu...
  1456. if(!CMenu::CreateMenu())return FALSE;
  1457. // Get Item template Header, and calculate offset of MENUITEMTEMPLATES
  1458. MENUITEMTEMPLATEHEADER *pTpHdr=
  1459. (MENUITEMTEMPLATEHEADER*)LockResource(hGlobal);
  1460. BYTE* pTp=(BYTE*)pTpHdr + 
  1461. (sizeof(MENUITEMTEMPLATEHEADER) + pTpHdr->offset);
  1462. // Variables needed during processing of Menu Item Templates:
  1463. int j=0;
  1464. WORD    dwFlags = 0;              // Flags of the Menu Item
  1465. WORD    dwID  = 0;              // ID of the Menu Item
  1466. UINT    uFlags;                  // Actual Flags.
  1467. wchar_t *szCaption=NULL;
  1468. int      nLen   = 0;                // Length of caption
  1469. CTypedPtrArray<CPtrArray, BCMenu*>  m_Stack;    // Popup menu stack
  1470. CArray<BOOL,BOOL>  m_StackEnd;    // Popup menu stack
  1471. m_Stack.Add(this);                  // Add it to this...
  1472. m_StackEnd.Add(FALSE);
  1473. do{
  1474. // Obtain Flags and (if necessary), the ID...
  1475. memcpy(&dwFlags, pTp, sizeof(WORD));pTp+=sizeof(WORD);// Obtain Flags
  1476. if(!(dwFlags & MF_POPUP)){
  1477. memcpy(&dwID, pTp, sizeof(WORD)); // Obtain ID
  1478. pTp+=sizeof(WORD);
  1479. }
  1480. else dwID = 0;
  1481. uFlags = (UINT)dwFlags; // Remove MF_END from the flags that will
  1482. if(uFlags & MF_END) // be passed to the Append(OD)Menu functions.
  1483. uFlags -= MF_END;
  1484. // Obtain Caption (and length)
  1485. nLen = 0;
  1486. szCaption=new wchar_t[wcslen((wchar_t *)pTp)+1];
  1487. wcscpy(szCaption,(wchar_t *)pTp);
  1488. pTp=&pTp[(wcslen((wchar_t *)pTp)+1)*sizeof(wchar_t)];//modified SK
  1489. // Handle popup menus first....
  1490. //WideCharToMultiByte
  1491. if(dwFlags & MF_POPUP){
  1492. if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
  1493. BCMenu* pSubMenu = new BCMenu;
  1494. pSubMenu->m_unselectcheck=m_unselectcheck;
  1495. pSubMenu->m_selectcheck=m_selectcheck;
  1496. pSubMenu->checkmaps=checkmaps;
  1497. pSubMenu->checkmapsshare=TRUE;
  1498. pSubMenu->CreatePopupMenu();
  1499. // Append it to the top of the stack:
  1500. m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption,uFlags,
  1501. (UINT)pSubMenu->m_hMenu, -1);
  1502. m_Stack.Add(pSubMenu);
  1503. m_StackEnd.Add(FALSE);
  1504. }
  1505. else {
  1506. m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption, uFlags,
  1507. dwID, -1);
  1508. if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
  1509. j = m_Stack.GetUpperBound();
  1510. while(j>=0 && m_StackEnd.GetAt(j)){
  1511. m_Stack[m_Stack.GetUpperBound()]->InsertSpaces();
  1512. m_Stack.RemoveAt(j);
  1513. m_StackEnd.RemoveAt(j);
  1514. --j;
  1515. }
  1516. }
  1517. delete[] szCaption;
  1518. }while(m_Stack.GetUpperBound() != -1);
  1519. for(int i=0;i<(int)GetMenuItemCount();++i){
  1520. CString str=m_MenuList[i]->GetString();
  1521. if(GetSubMenu(i)){
  1522. m_MenuList[i]->nFlags=MF_POPUP|MF_BYPOSITION;
  1523. ModifyMenu(i,MF_POPUP|MF_BYPOSITION,
  1524. (UINT)GetSubMenu(i)->m_hMenu,str);
  1525. }
  1526. else{
  1527. m_MenuList[i]->nFlags=MF_STRING|MF_BYPOSITION;
  1528. ModifyMenu(i,MF_STRING|MF_BYPOSITION,m_MenuList[i]->nID,str);
  1529. }
  1530. }
  1531. m_loadmenu=TRUE;
  1532. return(TRUE);
  1533. }
  1534. int BCMenu::GetMenuStart(void)
  1535. {
  1536. if(!m_loadmenu)return(0);
  1537. CString name,str;
  1538. int menuloc=-1,listloc=-1,menustart=0,i=0,j=0;
  1539. int nummenulist=m_MenuList.GetSize();
  1540. int nummenu=(int)GetMenuItemCount();
  1541. while(i<nummenu&&menuloc==-1){
  1542. GetMenuString (i, name, MF_BYPOSITION);
  1543. if(name.GetLength()>0){
  1544. for(j=0;j<nummenulist;++j){
  1545. str=m_MenuList[j]->GetString();
  1546. if(name==str){
  1547. menuloc=i;
  1548. listloc=j;
  1549. break;
  1550. }
  1551. }
  1552. }
  1553. ++i;
  1554. }
  1555. if(menuloc>=0&&listloc>=0&&menuloc>=listloc)menustart=menuloc-listloc;
  1556. return(menustart);
  1557. }
  1558. void BCMenu::RemoveTopLevelOwnerDraw(void)
  1559. {
  1560. CString str;
  1561. int i=0,j=0;
  1562. int nummenulist=m_MenuList.GetSize(),menustart;
  1563. menustart=GetMenuStart();
  1564. for(i=menustart,j=0;i<(int)GetMenuItemCount();++i,++j){
  1565. if(j<nummenulist){
  1566. str=m_MenuList[j]->GetString();
  1567. if(GetSubMenu(i)){
  1568. m_MenuList[j]->nFlags=MF_POPUP|MF_BYPOSITION;
  1569. ModifyMenu(i,MF_POPUP|MF_BYPOSITION,
  1570. (UINT)GetSubMenu(i)->m_hMenu,str);
  1571. }
  1572. }
  1573. }
  1574. }
  1575. void BCMenu::InsertSpaces(void)
  1576. {
  1577. if(IsLunaMenuStyle())
  1578. if(!xp_space_accelerators)return;
  1579. else
  1580. if(!original_space_accelerators)return;
  1581. int i,j,numitems,maxlength;
  1582. CString string,newstring;
  1583. CSize t;
  1584. CFont m_fontMenu;
  1585. LOGFONT m_lf;
  1586. ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
  1587. NONCLIENTMETRICS nm;
  1588. nm.cbSize = sizeof (NONCLIENTMETRICS);
  1589. VERIFY (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); 
  1590. m_lf =  nm.lfMenuFont;
  1591. m_fontMenu.CreateFontIndirect (&m_lf);
  1592. CWnd *pWnd = AfxGetMainWnd();  
  1593. if (pWnd == NULL)pWnd = CWnd::GetDesktopWindow();
  1594. CDC *pDC = pWnd->GetDC();
  1595. CFont* pFont = pDC->SelectObject (&m_fontMenu);
  1596. numitems=GetMenuItemCount();
  1597. maxlength = -1;
  1598. for(i=0;i<numitems;++i){
  1599. string=m_MenuList[i]->GetString();
  1600. j=string.Find((char)9);
  1601. newstring.Empty();
  1602. if(j!=-1)newstring=string.Left(j);
  1603. else newstring=string;
  1604. newstring+=_T(" ");//SK: modified for Unicode correctness. 
  1605. LPCTSTR lpstrText = (LPCTSTR)newstring;
  1606. t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
  1607. if(t.cx>maxlength)maxlength = t.cx;
  1608. }
  1609. for(i=0;i<numitems;++i){
  1610. string=m_MenuList[i]->GetString();
  1611. j=string.Find((char)9);
  1612. if(j!=-1){
  1613. newstring.Empty();
  1614. newstring=string.Left(j);
  1615. LPCTSTR lpstrText = (LPCTSTR)(newstring);
  1616. t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
  1617. while(t.cx<maxlength){
  1618. newstring+=_T(' ');//SK: modified for Unicode correctness
  1619. LPCTSTR lpstrText = (LPCTSTR)(newstring);
  1620. t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
  1621. }
  1622. newstring+=string.Mid(j);
  1623. #ifdef UNICODE      
  1624. m_MenuList[i]->SetWideString(newstring);//SK: modified for dynamic allocation
  1625. #else
  1626. m_MenuList[i]->SetAnsiString(newstring);
  1627. #endif
  1628. }
  1629. }
  1630. pDC->SelectObject (pFont);              // Select old font in
  1631. pWnd->ReleaseDC(pDC);       // Release the DC
  1632. m_fontMenu.DeleteObject();
  1633. }
  1634. void BCMenu::LoadCheckmarkBitmap(int unselect, int select)
  1635. {
  1636. if(unselect>0 && select>0){
  1637. m_selectcheck=select;
  1638. m_unselectcheck=unselect;
  1639. if(checkmaps)checkmaps->DeleteImageList();
  1640. else checkmaps=new(CImageList);
  1641. checkmaps->Create(m_iconX,m_iconY,ILC_MASK,2,1);
  1642. BOOL flag1=AddBitmapToImageList(checkmaps,unselect);
  1643. BOOL flag2=AddBitmapToImageList(checkmaps,select);
  1644. if(!flag1||!flag2){
  1645. checkmaps->DeleteImageList();
  1646. delete checkmaps;
  1647. checkmaps=NULL;
  1648. }
  1649. }
  1650. }
  1651. //--------------------------------------------------------------------------
  1652. //[18.06.99 rj]
  1653. BOOL BCMenu::GetMenuText(UINT id, CString& string, UINT nFlags/*= MF_BYPOSITION*/)
  1654. {
  1655. BOOL returnflag=FALSE;
  1656. if(MF_BYPOSITION&nFlags){
  1657. UINT numMenuItems = m_MenuList.GetUpperBound();
  1658. if(id<=numMenuItems){
  1659. string=m_MenuList[id]->GetString();
  1660. returnflag=TRUE;
  1661. }
  1662. }
  1663. else{
  1664. int uiLoc;
  1665. BCMenu* pMenu = FindMenuOption(id,uiLoc);
  1666. if(NULL!=pMenu) returnflag = pMenu->GetMenuText(uiLoc,string);
  1667. }
  1668. return(returnflag);
  1669. }
  1670. void BCMenu::DrawRadioDot(CDC *pDC,int x,int y,COLORREF color)
  1671. {
  1672. CRect rcDot(x,y,x+6,y+6);
  1673. CBrush brush;
  1674. CPen pen;
  1675. brush.CreateSolidBrush(color);
  1676. pen.CreatePen(PS_SOLID,0,color);
  1677. CBrush *pOldBrush=pDC->SelectObject(&brush);
  1678. CPen *pOldPen=pDC->SelectObject(&pen);
  1679. pDC->Ellipse(&rcDot);
  1680. pDC->SelectObject(pOldBrush);
  1681. pDC->SelectObject(pOldPen);
  1682. pen.DeleteObject();
  1683. brush.DeleteObject();
  1684. }
  1685. void BCMenu::DrawCheckMark(CDC* pDC,int x,int y,COLORREF color,BOOL narrowflag)
  1686. {
  1687. int dp=0;
  1688. CPen m_penBack;
  1689. m_penBack.CreatePen (PS_SOLID,0,color);
  1690. CPen *pOldPen = pDC->SelectObject (&m_penBack);
  1691. if(narrowflag)dp=1;
  1692. pDC->MoveTo(x,y+2);
  1693. pDC->LineTo(x,y+5-dp);
  1694. pDC->MoveTo(x+1,y+3);
  1695. pDC->LineTo(x+1,y+6-dp);
  1696. pDC->MoveTo(x+2,y+4);
  1697. pDC->LineTo(x+2,y+7-dp);
  1698. pDC->MoveTo(x+3,y+3);
  1699. pDC->LineTo(x+3,y+6-dp);
  1700. pDC->MoveTo(x+4,y+2);
  1701. pDC->LineTo(x+4,y+5-dp);
  1702. pDC->MoveTo(x+5,y+1);
  1703. pDC->LineTo(x+5,y+4-dp);
  1704. pDC->MoveTo(x+6,y);
  1705. pDC->LineTo(x+6,y+3-dp);
  1706. pDC->SelectObject (pOldPen);
  1707. m_penBack.DeleteObject();
  1708. }
  1709. BCMenuData *BCMenu::FindMenuList(UINT nID)
  1710. {
  1711. for(int i=0;i<=m_MenuList.GetUpperBound();++i){
  1712. if(m_MenuList[i]->nID==nID && !m_MenuList[i]->syncflag){
  1713. m_MenuList[i]->syncflag=1;
  1714. return(m_MenuList[i]);
  1715. }
  1716. }
  1717. return(NULL);
  1718. }
  1719. void BCMenu::InitializeMenuList(int value)
  1720. {
  1721. for(int i=0;i<=m_MenuList.GetUpperBound();++i)
  1722. m_MenuList[i]->syncflag=value;
  1723. }
  1724. void BCMenu::DeleteMenuList(void)
  1725. {
  1726. for(int i=0;i<=m_MenuList.GetUpperBound();++i){
  1727. if(!m_MenuList[i]->syncflag){
  1728. delete m_MenuList[i];
  1729. }
  1730. }
  1731. }
  1732. void BCMenu::SynchronizeMenu(void)
  1733. {
  1734. CTypedPtrArray<CPtrArray, BCMenuData*> temp;
  1735. BCMenuData *mdata;
  1736. CString string;
  1737. UINT submenu,nID=0,state,j;
  1738. InitializeMenuList(0);
  1739. for(j=0;j<GetMenuItemCount();++j){
  1740. mdata=NULL;
  1741. state=GetMenuState(j,MF_BYPOSITION);
  1742. if(state&MF_POPUP){
  1743. submenu=(UINT)GetSubMenu(j)->m_hMenu;
  1744. mdata=FindMenuList(submenu);
  1745. GetMenuString(j,string,MF_BYPOSITION);
  1746. if(!mdata)mdata=NewODMenu(j,
  1747. (state&0xFF)|MF_BYPOSITION|MF_POPUP|MF_OWNERDRAW,submenu,string);
  1748. else if(string.GetLength()>0)
  1749. #ifdef UNICODE
  1750. mdata->SetWideString(string);  //SK: modified for dynamic allocation
  1751. #else
  1752. mdata->SetAnsiString(string);
  1753. #endif
  1754. }
  1755. else if(state&MF_SEPARATOR){
  1756. mdata=FindMenuList(0);
  1757. if(!mdata)mdata=NewODMenu(j,
  1758. state|MF_BYPOSITION|MF_SEPARATOR|MF_OWNERDRAW,0,_T(""));//SK: modified for Unicode correctness
  1759. else ModifyMenu(j,mdata->nFlags,nID,(LPCTSTR)mdata);
  1760. }
  1761. else{
  1762. nID=GetMenuItemID(j);
  1763. mdata=FindMenuList(nID);
  1764. GetMenuString(j,string,MF_BYPOSITION);
  1765. if(!mdata)mdata=NewODMenu(j,state|MF_BYPOSITION|MF_OWNERDRAW,
  1766. nID,string);
  1767. else{
  1768. mdata->nFlags=state|MF_BYPOSITION|MF_OWNERDRAW;
  1769. if(string.GetLength()>0)
  1770. #ifdef UNICODE
  1771. mdata->SetWideString(string);//SK: modified for dynamic allocation
  1772. #else
  1773. mdata->SetAnsiString(string);
  1774. #endif
  1775. ModifyMenu(j,mdata->nFlags,nID,(LPCTSTR)mdata);
  1776. }
  1777. }
  1778. if(mdata)temp.Add(mdata);
  1779. }
  1780. DeleteMenuList();
  1781. m_MenuList.RemoveAll();
  1782. m_MenuList.Append(temp);
  1783. temp.RemoveAll(); 
  1784. }
  1785. void BCMenu::UpdateMenu(CMenu *pmenu)
  1786. {
  1787. #ifdef _CPPRTTI 
  1788. BCMenu *psubmenu = dynamic_cast<BCMenu *>(pmenu);
  1789. #else
  1790. BCMenu *psubmenu = (BCMenu *)pmenu;
  1791. #endif
  1792. if(psubmenu)psubmenu->SynchronizeMenu();
  1793. }
  1794. LRESULT BCMenu::FindKeyboardShortcut(UINT nChar, UINT nFlags,
  1795.                                      CMenu *pMenu)
  1796. {
  1797. #ifdef _CPPRTTI 
  1798. BCMenu *pBCMenu = dynamic_cast<BCMenu *>(pMenu);
  1799. #else
  1800. BCMenu *pBCMenu = (BCMenu *)pMenu;
  1801. #endif
  1802. if(pBCMenu && nFlags&MF_POPUP){
  1803. CString key(_T('&'),2);//SK: modified for Unicode correctness
  1804. key.SetAt(1,(TCHAR)nChar);
  1805. key.MakeLower();
  1806. CString menutext;
  1807. int menusize = (int)pBCMenu->GetMenuItemCount();
  1808. if(menusize!=(pBCMenu->m_MenuList.GetUpperBound()+1))
  1809. pBCMenu->SynchronizeMenu();
  1810. for(int i=0;i<menusize;++i){
  1811. if(pBCMenu->GetMenuText(i,menutext)){
  1812. menutext.MakeLower();
  1813. if(menutext.Find(key)>=0)return(MAKELRESULT(i,2));
  1814. }
  1815. }
  1816. }
  1817. return(0);
  1818. }
  1819. void BCMenu::DitherBlt (HDC hdcDest, int nXDest, int nYDest, int nWidth, 
  1820.                         int nHeight, HBITMAP hbm, int nXSrc, int nYSrc,
  1821. COLORREF bgcolor)
  1822. {
  1823. ASSERT(hdcDest && hbm);
  1824. ASSERT(nWidth > 0 && nHeight > 0);
  1825. // Create a generic DC for all BitBlts
  1826. HDC hDC = CreateCompatibleDC(hdcDest);
  1827. ASSERT(hDC);
  1828. if (hDC)
  1829. {
  1830. // Create a DC for the monochrome DIB section
  1831. HDC bwDC = CreateCompatibleDC(hDC);
  1832. ASSERT(bwDC);
  1833. if (bwDC)
  1834. {
  1835. // Create the monochrome DIB section with a black and white palette
  1836. struct {
  1837. BITMAPINFOHEADER bmiHeader; 
  1838. RGBQUAD      bmiColors[2]; 
  1839. } RGBBWBITMAPINFO = {
  1840. {    // a BITMAPINFOHEADER
  1841. sizeof(BITMAPINFOHEADER),  // biSize 
  1842. nWidth,         // biWidth; 
  1843. nHeight,        // biHeight; 
  1844. 1,            // biPlanes; 
  1845. 1,            // biBitCount 
  1846. BI_RGB,         // biCompression; 
  1847. 0,            // biSizeImage; 
  1848. 0,            // biXPelsPerMeter; 
  1849. 0,            // biYPelsPerMeter; 
  1850. 0,            // biClrUsed; 
  1851. 0            // biClrImportant; 
  1852. },    
  1853. {
  1854. { 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 }
  1855. };
  1856. VOID *pbitsBW;
  1857. HBITMAP hbmBW = CreateDIBSection(bwDC,
  1858. (LPBITMAPINFO)&RGBBWBITMAPINFO, DIB_RGB_COLORS, &pbitsBW, NULL, 0);
  1859. ASSERT(hbmBW);
  1860. if (hbmBW)
  1861. {
  1862. // Attach the monochrome DIB section and the bitmap to the DCs
  1863. HBITMAP olddib = (HBITMAP)SelectObject(bwDC, hbmBW);
  1864. HBITMAP hdcolddib = (HBITMAP)SelectObject(hDC, hbm);
  1865. // BitBlt the bitmap into the monochrome DIB section
  1866. BitBlt(bwDC, 0, 0, nWidth, nHeight, hDC, nXSrc, nYSrc, SRCCOPY);
  1867. // Paint the destination rectangle in gray
  1868. FillRect(hdcDest, CRect(nXDest, nYDest, nXDest + nWidth, nYDest +
  1869. nHeight), GetSysColorBrush(bgcolor));
  1870. //SK: looks better on the old shell
  1871. // BitBlt the black bits in the monochrome bitmap into COLOR_3DHILIGHT
  1872. // bits in the destination DC
  1873. // The magic ROP comes from the Charles Petzold's book
  1874. HBRUSH hb = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT));
  1875. HBRUSH oldBrush = (HBRUSH)SelectObject(hdcDest, hb);
  1876. BitBlt(hdcDest,nXDest+1,nYDest+1,nWidth,nHeight,bwDC,0,0,0xB8074A);
  1877. // BitBlt the black bits in the monochrome bitmap into COLOR_3DSHADOW
  1878. // bits in the destination DC
  1879. hb = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
  1880. DeleteObject(SelectObject(hdcDest, hb));
  1881. BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight,bwDC,0,0,0xB8074A);
  1882. DeleteObject(SelectObject(hdcDest, oldBrush));
  1883. VERIFY(DeleteObject(SelectObject(bwDC, olddib)));
  1884. SelectObject(hDC, hdcolddib);
  1885. }
  1886. VERIFY(DeleteDC(bwDC));
  1887. }
  1888. VERIFY(DeleteDC(hDC));
  1889. }
  1890. }
  1891. void BCMenu::GetFadedBitmap(CBitmap &bmp)
  1892. {
  1893. CDC ddc;
  1894. COLORREF bgcol,col;
  1895. BITMAP BitMap;
  1896. bmp.GetBitmap(&BitMap);
  1897. ddc.CreateCompatibleDC(NULL);
  1898. CBitmap * pddcOldBmp = ddc.SelectObject(&bmp);
  1899. // use this to get the background color, takes into account color shifting
  1900. CDC ddc2;
  1901. CBrush brush;
  1902. CBitmap bmp2;
  1903. ddc2.CreateCompatibleDC(NULL);
  1904. bmp2.CreateCompatibleBitmap(&ddc,BitMap.bmWidth,BitMap.bmHeight);
  1905. col=GetSysColor(COLOR_3DFACE);
  1906. brush.CreateSolidBrush(col);
  1907. CBitmap * pddcOldBmp2 = ddc2.SelectObject(&bmp2);
  1908. CRect rect(0,0,BitMap.bmWidth,BitMap.bmHeight);
  1909. ddc2.FillRect(rect,&brush);
  1910. bgcol=ddc2.GetPixel(1,1);
  1911. brush.DeleteObject();
  1912. ddc2.SelectObject(pddcOldBmp2);
  1913. for(int i=0;i<BitMap.bmWidth;++i){
  1914. for(int j=0;j<BitMap.bmHeight;++j){
  1915. col=ddc.GetPixel(i,j);
  1916. if(col!=bgcol)ddc.SetPixel(i,j,LightenColor(col,0.3));
  1917. }
  1918. }
  1919. ddc.SelectObject(pddcOldBmp);
  1920. }
  1921. void BCMenu::GetTransparentBitmap(CBitmap &bmp)
  1922. {
  1923. CDC ddc;
  1924. COLORREF bgcol,col,newcol;
  1925. BITMAP BitMap;
  1926. bmp.GetBitmap(&BitMap);
  1927. ddc.CreateCompatibleDC(NULL);
  1928. CBitmap * pddcOldBmp = ddc.SelectObject(&bmp);
  1929. // use this to get the background color, takes into account color shifting
  1930. CDC ddc2;
  1931. CBrush brush;
  1932. CBitmap bmp2;
  1933. ddc2.CreateCompatibleDC(NULL);
  1934. bmp2.CreateCompatibleBitmap(&ddc,BitMap.bmWidth,BitMap.bmHeight);
  1935. col=RGB(192,192,192);
  1936. brush.CreateSolidBrush(col);
  1937. CBitmap * pddcOldBmp2 = ddc2.SelectObject(&bmp2);
  1938. CRect rect(0,0,BitMap.bmWidth,BitMap.bmHeight);
  1939. ddc2.FillRect(rect,&brush);
  1940. bgcol=ddc2.GetPixel(1,1);
  1941. brush.DeleteObject();
  1942. ddc2.SelectObject(pddcOldBmp2);
  1943. newcol=GetSysColor(COLOR_3DFACE);
  1944. for(int i=0;i<BitMap.bmWidth;++i){
  1945. for(int j=0;j<BitMap.bmHeight;++j){
  1946. col=ddc.GetPixel(i,j);
  1947. if(col==bgcol)ddc.SetPixel(i,j,newcol);
  1948. }
  1949. }
  1950. ddc.SelectObject(pddcOldBmp);
  1951. }
  1952. void BCMenu::GetDisabledBitmap(CBitmap &bmp,COLORREF background)
  1953. {
  1954. CDC ddc;
  1955. COLORREF bgcol,col,discol;
  1956. BITMAP BitMap;
  1957. bmp.GetBitmap(&BitMap);
  1958. ddc.CreateCompatibleDC(NULL);
  1959. CBitmap * pddcOldBmp = ddc.SelectObject(&bmp);
  1960. // use this to get the background color, takes into account color shifting
  1961. CDC ddc2;
  1962. CBrush brush;
  1963. CBitmap bmp2;
  1964. ddc2.CreateCompatibleDC(NULL);
  1965. bmp2.CreateCompatibleBitmap(&ddc,BitMap.bmWidth,BitMap.bmHeight);
  1966. col=GetSysColor(COLOR_3DFACE);
  1967. brush.CreateSolidBrush(col);
  1968. CBitmap * pddcOldBmp2 = ddc2.SelectObject(&bmp2);
  1969. CRect rect(0,0,BitMap.bmWidth,BitMap.bmHeight);
  1970. ddc2.FillRect(rect,&brush);
  1971. bgcol=ddc2.GetPixel(1,1);
  1972. brush.DeleteObject();
  1973. ddc2.SelectObject(pddcOldBmp2);
  1974. discol=GetSysColor(COLOR_BTNSHADOW);
  1975. for(int i=0;i<BitMap.bmWidth;++i){
  1976. for(int j=0;j<BitMap.bmHeight;++j){
  1977. col=ddc.GetPixel(i,j);
  1978. if(col!=bgcol){
  1979. BYTE r = GetRValue(col);
  1980. BYTE g = GetGValue(col);
  1981. BYTE b = GetBValue(col);
  1982. int avgcol = (r+g+b)/3;
  1983. double factor = avgcol/255.0;
  1984. ddc.SetPixel(i,j,LightenColor(discol,factor));
  1985. }
  1986. else{
  1987. if(background)ddc.SetPixel(i,j,background);
  1988. }
  1989. }
  1990. }
  1991. ddc.SelectObject(pddcOldBmp);
  1992. }
  1993. void BCMenu::GetShadowBitmap(CBitmap &bmp)
  1994. {
  1995. CDC ddc;
  1996. COLORREF bgcol,col,shadowcol=GetSysColor(COLOR_BTNSHADOW);
  1997. BITMAP BitMap;
  1998. if(!IsWinXPLuna())shadowcol=LightenColor(shadowcol,0.49);
  1999. bmp.GetBitmap(&BitMap);
  2000. ddc.CreateCompatibleDC(NULL);
  2001. CBitmap * pddcOldBmp = ddc.SelectObject(&bmp);
  2002. // use this to get the background color, takes into account color shifting
  2003. CDC ddc2;
  2004. CBrush brush;
  2005. CBitmap bmp2;
  2006. ddc2.CreateCompatibleDC(NULL);
  2007. bmp2.CreateCompatibleBitmap(&ddc,BitMap.bmWidth,BitMap.bmHeight);
  2008. col=GetSysColor(COLOR_3DFACE);
  2009. brush.CreateSolidBrush(col);
  2010. CBitmap * pddcOldBmp2 = ddc2.SelectObject(&bmp2);
  2011. CRect rect(0,0,BitMap.bmWidth,BitMap.bmHeight);
  2012. ddc2.FillRect(rect,&brush);
  2013. bgcol=ddc2.GetPixel(1,1);
  2014. brush.DeleteObject();
  2015. ddc2.SelectObject(pddcOldBmp2);
  2016. for(int i=0;i<BitMap.bmWidth;++i){
  2017. for(int j=0;j<BitMap.bmHeight;++j){
  2018. col=ddc.GetPixel(i,j);
  2019. if(col!=bgcol)ddc.SetPixel(i,j,shadowcol);
  2020. }
  2021. }
  2022. ddc.SelectObject(pddcOldBmp);
  2023. }
  2024. BOOL BCMenu::AddBitmapToImageList(CImageList *bmplist,UINT nResourceID)
  2025. {
  2026. BOOL bReturn=FALSE;
  2027. // O.S.
  2028. if (m_bDynIcons){
  2029. bmplist->Add((HICON)nResourceID);
  2030. bReturn=TRUE;
  2031. }
  2032. else{
  2033. HBITMAP hbmp=LoadSysColorBitmap(nResourceID);
  2034. if(hbmp){
  2035. CBitmap bmp;
  2036. bmp.Attach(hbmp);
  2037. if(m_bitmapBackgroundFlag){
  2038. if(bmplist->Add(&bmp,m_bitmapBackground)>=0)bReturn=TRUE;
  2039. }
  2040. else{
  2041. if(bmplist->Add(&bmp,GetSysColor(COLOR_3DFACE))>=0)bReturn=TRUE;
  2042. }
  2043. bmp.Detach();
  2044. DeleteObject(hbmp);
  2045. }
  2046. else{ // a hicolor bitmap
  2047. CBitmap mybmp;
  2048. if(mybmp.LoadBitmap(nResourceID)){
  2049. hicolor_bitmaps=TRUE;
  2050. GetTransparentBitmap(mybmp);
  2051. if(m_bitmapBackgroundFlag){
  2052. if(bmplist->Add(&mybmp,m_bitmapBackground)>=0)bReturn=TRUE;
  2053. }
  2054. else{
  2055. if(bmplist->Add(&mybmp,GetSysColor(COLOR_3DFACE))>=0)bReturn=TRUE;
  2056. }
  2057. }
  2058. }
  2059. }
  2060. if(bReturn&&IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
  2061. CWnd *pWnd = AfxGetMainWnd();            // Get main window
  2062. if (pWnd == NULL) pWnd = CWnd::GetDesktopWindow();
  2063. CDC *pDC = pWnd->GetDC();              // Get device context
  2064. CBitmap bmp,bmp2,bmp3;
  2065. GetBitmapFromImageList(pDC,bmplist,0,bmp);
  2066. GetFadedBitmap(bmp);
  2067. bmplist->Add(&bmp,GetSysColor(COLOR_3DFACE));
  2068. GetBitmapFromImageList(pDC,bmplist,0,bmp2);
  2069. GetShadowBitmap(bmp2);
  2070. bmplist->Add(&bmp2,GetSysColor(COLOR_3DFACE));
  2071. GetBitmapFromImageList(pDC,bmplist,0,bmp3);
  2072. GetDisabledBitmap(bmp3);
  2073. bmplist->Add(&bmp3,GetSysColor(COLOR_3DFACE));
  2074. pWnd->ReleaseDC(pDC);  // Release the DC
  2075. }
  2076. return(bReturn);
  2077. }
  2078. void BCMenu::SetBitmapBackground(COLORREF color)
  2079. {
  2080. m_bitmapBackground=color;
  2081. m_bitmapBackgroundFlag=TRUE;
  2082. }
  2083. void BCMenu::UnSetBitmapBackground(void)
  2084. {
  2085. m_bitmapBackgroundFlag=FALSE;
  2086. }
  2087. // Given a toolbar, append all the options from it to this menu
  2088. // Passed a ptr to the toolbar object and the toolbar ID
  2089. // Author : Robert Edward Caldecott
  2090. void BCMenu::AddFromToolBar(CToolBar* pToolBar, int nResourceID)
  2091. {
  2092. for (int i = 0; i < pToolBar->GetCount(); i++) {
  2093. UINT nID = pToolBar->GetItemID(i);
  2094. // See if this toolbar option
  2095. // appears as a command on this
  2096. // menu or is a separator
  2097. if (nID == 0 || GetMenuState(nID, MF_BYCOMMAND) == 0xFFFFFFFF)
  2098. continue; // Item doesn't exist
  2099. UINT nStyle;
  2100. int nImage;
  2101. // Get the toolbar button info
  2102. pToolBar->GetButtonInfo(i, nID, nStyle, nImage);
  2103. // OK, we have the command ID of the toolbar
  2104. // option, and the tollbar bitmap offset
  2105. int nLoc;
  2106. BCMenuData* pData;
  2107. BCMenu *pSubMenu = FindMenuOption(nID, nLoc);
  2108. if (pSubMenu && nLoc >= 0)pData = pSubMenu->m_MenuList[nLoc];
  2109. else {
  2110. // Create a new BCMenuData structure
  2111. pData = new BCMenuData;
  2112. m_MenuList.Add(pData);
  2113. }
  2114. // Set some default structure members
  2115. pData->menuIconNormal = nResourceID;
  2116. pData->nID = nID;
  2117. pData->nFlags =  MF_BYCOMMAND | MF_OWNERDRAW;
  2118. pData->xoffset = nImage;
  2119. if (pData->bitmap)pData->bitmap->DeleteImageList();
  2120. else pData->bitmap = new CImageList;
  2121. pData->bitmap->Create(m_iconX, m_iconY,ILC_COLORDDB|ILC_MASK, 1, 1);
  2122. if(!AddBitmapToImageList(pData->bitmap, nResourceID)){
  2123. pData->bitmap->DeleteImageList();
  2124. delete pData->bitmap;
  2125. pData->bitmap=NULL;
  2126. pData->menuIconNormal = -1;
  2127. pData->xoffset = -1;
  2128. }
  2129. // Modify our menu
  2130. ModifyMenu(nID,pData->nFlags,nID,(LPCTSTR)pData);
  2131. }
  2132. }
  2133. BOOL BCMenu::Draw3DCheckmark(CDC *dc, const CRect& rc,
  2134.                              BOOL bSelected, HBITMAP hbmCheck)
  2135. {
  2136. CRect rcDest = rc;
  2137. CBrush brush;
  2138. COLORREF col;
  2139. if(IsWinXPLuna())col=GetSysColor(COLOR_3DFACE);
  2140. else col=GetSysColor(COLOR_MENU);
  2141. if(!bSelected)col = LightenColor(col,0.6);
  2142. brush.CreateSolidBrush(col);
  2143. dc->FillRect(rcDest,&brush);
  2144. brush.DeleteObject();
  2145. if (IsNewShell()) //SK: looks better on the old shell
  2146. dc->DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT);
  2147. if (!hbmCheck)DrawCheckMark(dc,rc.left+4,rc.top+4,GetSysColor(COLOR_MENUTEXT));
  2148. else DrawRadioDot(dc,rc.left+5,rc.top+4,GetSysColor(COLOR_MENUTEXT));
  2149. return TRUE;
  2150. }
  2151. BOOL BCMenu::DrawXPCheckmark(CDC *dc, const CRect& rc, HBITMAP hbmCheck,COLORREF &colorout,BOOL selected)
  2152. {
  2153. CBrush brushin;
  2154. COLORREF col;
  2155. int dx,dy;
  2156. dy = (rc.Height()>>1)-3;
  2157. dy = dy<0 ? 0 : dy;
  2158. dx = (rc.Width()>>1)-3;
  2159. dx = dx<0 ? 0 : dx;
  2160. if(selected) col = LightenColor(colorout,0.55);
  2161. else col = LightenColor(colorout,0.85);
  2162. brushin.CreateSolidBrush(col);
  2163. dc->FillRect(rc,&brushin);
  2164. brushin.DeleteObject();
  2165. dc->Draw3dRect (rc,colorout,colorout);
  2166. if (!hbmCheck)DrawCheckMark(dc,rc.left+dx,rc.top+dy,GetSysColor(COLOR_MENUTEXT),TRUE);
  2167. else DrawRadioDot(dc,rc.left+dx,rc.top+dy,GetSysColor(COLOR_MENUTEXT));
  2168. return TRUE;
  2169. }
  2170. void BCMenu::DitherBlt2(CDC *drawdc, int nXDest, int nYDest, int nWidth, 
  2171.                         int nHeight, CBitmap &bmp, int nXSrc, int nYSrc,
  2172. COLORREF bgcolor)
  2173. {
  2174. // create a monochrome memory DC
  2175. CDC ddc;
  2176. ddc.CreateCompatibleDC(0);
  2177. CBitmap bwbmp;
  2178. bwbmp.CreateCompatibleBitmap(&ddc, nWidth, nHeight);
  2179. CBitmap * pddcOldBmp = ddc.SelectObject(&bwbmp);
  2180. CDC dc;
  2181. dc.CreateCompatibleDC(0);
  2182. CBitmap * pdcOldBmp = dc.SelectObject(&bmp);
  2183. // build a mask
  2184. ddc.PatBlt(0, 0, nWidth, nHeight, WHITENESS);
  2185. dc.SetBkColor(GetSysColor(COLOR_BTNFACE));
  2186. ddc.BitBlt(0, 0, nWidth, nHeight, &dc, nXSrc,nYSrc, SRCCOPY);
  2187. dc.SetBkColor(GetSysColor(COLOR_BTNHILIGHT));
  2188. ddc.BitBlt(0, 0, nWidth, nHeight, &dc, nXSrc,nYSrc, SRCPAINT);
  2189. // Copy the image from the toolbar into the memory DC
  2190. // and draw it (grayed) back into the toolbar.
  2191. dc.FillSolidRect(0,0, nWidth, nHeight, bgcolor);
  2192. //SK: Looks better on the old shell
  2193. dc.SetBkColor(RGB(0, 0, 0));
  2194. dc.SetTextColor(RGB(255, 255, 255));
  2195. CBrush brShadow, brHilight;
  2196. brHilight.CreateSolidBrush(GetSysColor(COLOR_BTNHILIGHT));
  2197. brShadow.CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
  2198. CBrush * pOldBrush = dc.SelectObject(&brHilight);
  2199. dc.BitBlt(0,0, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
  2200. drawdc->BitBlt(nXDest+1,nYDest+1,nWidth, nHeight, &dc,0,0,SRCCOPY);
  2201. dc.BitBlt(1,1, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
  2202. dc.SelectObject(&brShadow);
  2203. dc.BitBlt(0,0, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
  2204. drawdc->BitBlt(nXDest,nYDest,nWidth, nHeight, &dc,0,0,SRCCOPY);
  2205. // reset DCs
  2206. ddc.SelectObject(pddcOldBmp);
  2207. ddc.DeleteDC();
  2208. dc.SelectObject(pOldBrush);
  2209. dc.SelectObject(pdcOldBmp);
  2210. dc.DeleteDC();
  2211. brShadow.DeleteObject();
  2212. brHilight.DeleteObject();
  2213. bwbmp.DeleteObject();
  2214. }
  2215. void BCMenu::DitherBlt3(CDC *drawdc, int nXDest, int nYDest, int nWidth, 
  2216.                         int nHeight, CBitmap &bmp,COLORREF bgcolor)
  2217. {
  2218. GetDisabledBitmap(bmp,bgcolor);
  2219. CDC dc;
  2220. dc.CreateCompatibleDC(NULL);
  2221. CBitmap * pdcOldBmp = dc.SelectObject(&bmp);
  2222. drawdc->BitBlt(nXDest,nYDest,nWidth, nHeight, &dc,0,0,SRCCOPY);
  2223. // reset DCs
  2224. dc.SelectObject(pdcOldBmp);
  2225. dc.DeleteDC();
  2226. }
  2227. void BCMenu::SetDisableOldStyle(void)
  2228. {
  2229. disable_old_style=TRUE;
  2230. }
  2231. void BCMenu::UnSetDisableOldStyle(void)
  2232. {
  2233. disable_old_style=FALSE;
  2234. }
  2235. BOOL BCMenu::GetDisableOldStyle(void)
  2236. {
  2237. return(disable_old_style);
  2238. }
  2239. WORD BCMenu::NumBitmapColors(LPBITMAPINFOHEADER lpBitmap)
  2240. {
  2241. if ( lpBitmap->biClrUsed != 0)
  2242. return (WORD)lpBitmap->biClrUsed;
  2243. switch (lpBitmap->biBitCount){
  2244. case 1:
  2245. return 2;
  2246. case 4:
  2247. return 16;
  2248. case 8:
  2249. return 256;
  2250. default:
  2251. return 0;
  2252. }
  2253. return 0;
  2254. }
  2255. HBITMAP BCMenu::LoadSysColorBitmap(int nResourceId)
  2256. {
  2257. HINSTANCE hInst = 
  2258. AfxFindResourceHandle(MAKEINTRESOURCE(nResourceId),RT_BITMAP);
  2259. HRSRC hRsrc = 
  2260. ::FindResource(hInst,MAKEINTRESOURCE(nResourceId),RT_BITMAP);
  2261. if (hRsrc == NULL){
  2262. hInst = NULL;
  2263. hRsrc = ::FindResource(hInst,MAKEINTRESOURCE(nResourceId),RT_BITMAP);
  2264. }
  2265. if (hRsrc == NULL)return NULL;
  2266. // determine how many colors in the bitmap
  2267. HGLOBAL hglb;
  2268. if ((hglb = LoadResource(hInst, hRsrc)) == NULL)
  2269. return NULL;
  2270. LPBITMAPINFOHEADER lpBitmap = (LPBITMAPINFOHEADER)LockResource(hglb);
  2271. if (lpBitmap == NULL)return NULL;
  2272. WORD numcol = NumBitmapColors(lpBitmap);
  2273. ::FreeResource(hglb);
  2274. if(numcol!=16)return(NULL);
  2275. return AfxLoadSysColorBitmap(hInst, hRsrc, FALSE);
  2276. }
  2277. BOOL BCMenu::RemoveMenu(UINT uiId,UINT nFlags)
  2278. {
  2279. if(MF_BYPOSITION&nFlags){
  2280. UINT uint = GetMenuState(uiId,MF_BYPOSITION);
  2281. if(uint&MF_SEPARATOR && !(uint&MF_POPUP)){
  2282. delete m_MenuList.GetAt(uiId);
  2283. m_MenuList.RemoveAt(uiId);
  2284. }
  2285. else{
  2286. BCMenu* pSubMenu = (BCMenu*) GetSubMenu(uiId);
  2287. if(NULL==pSubMenu){
  2288. UINT uiCommandId = GetMenuItemID(uiId);
  2289. for(int i=0;i<m_MenuList.GetSize(); i++){
  2290. if(m_MenuList[i]->nID==uiCommandId){
  2291. delete m_MenuList.GetAt(i);
  2292. m_MenuList.RemoveAt(i);
  2293. break;
  2294. }
  2295. }
  2296. }
  2297. else{
  2298. int numSubMenus = m_SubMenus.GetUpperBound();
  2299. for(int m = numSubMenus; m >= 0; m--){
  2300. if(m_SubMenus[m]==pSubMenu->m_hMenu){
  2301. int numAllSubMenus = m_AllSubMenus.GetUpperBound();
  2302. for(int n = numAllSubMenus; n>= 0; n--){
  2303. if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
  2304. }
  2305. m_SubMenus.RemoveAt(m);
  2306. }
  2307. }
  2308. int num = pSubMenu->GetMenuItemCount();
  2309. for(int i=num-1;i>=0;--i)pSubMenu->RemoveMenu(i,MF_BYPOSITION);
  2310. for(i=m_MenuList.GetUpperBound();i>=0;i--){
  2311. if(m_MenuList[i]->nID==(UINT)pSubMenu->m_hMenu){
  2312. delete m_MenuList.GetAt(i);
  2313. m_MenuList.RemoveAt(i);
  2314. break;
  2315. }
  2316. }
  2317. delete pSubMenu; 
  2318. }
  2319. }
  2320. }
  2321. else{
  2322. int iPosition =0;
  2323. BCMenu* pMenu = FindMenuOption(uiId,iPosition);
  2324. // bug fix RIA 14th September 2000 
  2325. // failed to return correct value on call to remove menu as the item was 
  2326. // removed twice. The second time its not found 
  2327. // so a value of 0 was being returned 
  2328. if(pMenu) return pMenu->RemoveMenu(iPosition,MF_BYPOSITION); // added return 
  2329. }
  2330. return CMenu::RemoveMenu(uiId,nFlags);
  2331. }
  2332. BOOL BCMenu::DeleteMenu(UINT uiId,UINT nFlags)
  2333. {
  2334. if(MF_BYPOSITION&nFlags){
  2335. UINT uint = GetMenuState(uiId,MF_BYPOSITION);
  2336. if(uint&MF_SEPARATOR && !(uint&MF_POPUP)){
  2337. // make sure it's a separator
  2338. int menulistsize=m_MenuList.GetSize();
  2339. if(uiId<(UINT)menulistsize){
  2340. CString str=m_MenuList[uiId]->GetString();
  2341. if(str==""){
  2342. delete m_MenuList.GetAt(uiId);
  2343. m_MenuList.RemoveAt(uiId);
  2344. }
  2345. }
  2346. }
  2347. else{
  2348. BCMenu* pSubMenu = (BCMenu*) GetSubMenu(uiId);
  2349. if(NULL==pSubMenu){
  2350. UINT uiCommandId = GetMenuItemID(uiId);
  2351. for(int i=0;i<m_MenuList.GetSize(); i++){
  2352. if(m_MenuList[i]->nID==uiCommandId){
  2353. delete m_MenuList.GetAt(i);
  2354. m_MenuList.RemoveAt(i);
  2355. break;
  2356. }
  2357. }
  2358. }
  2359. else{
  2360. int numSubMenus = m_SubMenus.GetUpperBound();
  2361. for(int m = numSubMenus; m >= 0; m--){
  2362. if(m_SubMenus[m]==pSubMenu->m_hMenu){
  2363. int numAllSubMenus = m_AllSubMenus.GetUpperBound();
  2364. for(int n = numAllSubMenus; n>= 0; n--){
  2365. if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
  2366. }
  2367. m_SubMenus.RemoveAt(m);
  2368. }
  2369. }
  2370. int num = pSubMenu->GetMenuItemCount();
  2371. for(int i=num-1;i>=0;--i)pSubMenu->DeleteMenu(i,MF_BYPOSITION);
  2372. for(i=m_MenuList.GetUpperBound();i>=0;i--){
  2373. if(m_MenuList[i]->nID==(UINT)pSubMenu->m_hMenu){
  2374. delete m_MenuList.GetAt(i);
  2375. m_MenuList.RemoveAt(i);
  2376. break;
  2377. }
  2378. }
  2379. delete pSubMenu;
  2380. }
  2381. }
  2382. }
  2383. else{
  2384. int iPosition =0;
  2385. BCMenu* pMenu = FindMenuOption(uiId,iPosition);
  2386. if(pMenu)return pMenu->DeleteMenu(iPosition,MF_BYPOSITION);
  2387. }
  2388. return(CMenu::DeleteMenu(uiId,nFlags));
  2389. }
  2390. BOOL BCMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,int nIconNormal)
  2391. {
  2392. USES_CONVERSION;
  2393. return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),nIconNormal);
  2394. }
  2395. BOOL BCMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,int nIconNormal)
  2396. {
  2397. return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,nIconNormal);
  2398. }
  2399. BOOL BCMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CImageList *il,int xoffset)
  2400. {
  2401. USES_CONVERSION;
  2402. return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),il,xoffset);
  2403. }
  2404. BOOL BCMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CImageList *il,int xoffset)
  2405. {
  2406. return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,il,xoffset);
  2407. }
  2408. BOOL BCMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CBitmap *bmp)
  2409. {
  2410. USES_CONVERSION;
  2411. return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),bmp);
  2412. }
  2413. BOOL BCMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CBitmap *bmp)
  2414. {
  2415. if(bmp){
  2416. CImageList temp;
  2417. temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  2418. if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
  2419. else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
  2420. return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,&temp,0);
  2421. }
  2422. return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,NULL,0);
  2423. }
  2424. BOOL BCMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,int nIconNormal)
  2425. {
  2426. USES_CONVERSION;
  2427. return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),nIconNormal);
  2428. }
  2429. BOOL BCMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,int nIconNormal)
  2430. {
  2431. return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,nIconNormal);
  2432. }
  2433. BOOL BCMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CImageList *il,int xoffset)
  2434. {
  2435. USES_CONVERSION;
  2436. return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),il,xoffset);
  2437. }
  2438. BOOL BCMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CImageList *il,int xoffset)
  2439. {
  2440. return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,il,xoffset);
  2441. }
  2442. BOOL BCMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CBitmap *bmp)
  2443. {
  2444. USES_CONVERSION;
  2445. return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),bmp);
  2446. }
  2447. BOOL BCMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CBitmap *bmp)
  2448. {
  2449. if(bmp){
  2450. CImageList temp;
  2451. temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  2452. if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
  2453. else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
  2454. return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,&temp,0);
  2455. }
  2456. return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,NULL,0);
  2457. }
  2458. //--------------------------------------------------------------------------
  2459. //[21.06.99 rj]
  2460. BCMenu* BCMenu::AppendODPopupMenuW(wchar_t *lpstrText)
  2461. {
  2462. BCMenu* pSubMenu = new BCMenu;
  2463. pSubMenu->m_unselectcheck=m_unselectcheck;
  2464. pSubMenu->m_selectcheck=m_selectcheck;
  2465. pSubMenu->checkmaps=checkmaps;
  2466. pSubMenu->checkmapsshare=TRUE;
  2467. pSubMenu->CreatePopupMenu();
  2468. AppendODMenuW(lpstrText,MF_POPUP,(UINT)pSubMenu->m_hMenu, -1);
  2469. return pSubMenu;
  2470. }
  2471. //--------------------------------------------------------------------------
  2472. //[21.06.99 rj]
  2473. BCMenu* BCMenu::AppendODPopupMenuA(LPCSTR lpstrText)
  2474. {
  2475. USES_CONVERSION;
  2476. return AppendODPopupMenuW(A2W(lpstrText));
  2477. }
  2478. BOOL BCMenu::ImageListDuplicate(CImageList *il,int xoffset,CImageList *newlist)
  2479. {
  2480. if (il == NULL||newlist==NULL||xoffset<0) return FALSE;
  2481. HICON hIcon = il->ExtractIcon(xoffset);
  2482. int cx, cy;
  2483. ImageList_GetIconSize(il->m_hImageList, &cx, &cy);
  2484. newlist->Create(cx,cy,ILC_COLORDDB|ILC_MASK,1,1);
  2485. newlist->Add(hIcon);
  2486. ::DestroyIcon(hIcon);
  2487. if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
  2488. CWnd *pWnd = AfxGetMainWnd();            // Get main window
  2489. if (pWnd == NULL) pWnd = CWnd::GetDesktopWindow();
  2490. CDC *pDC = pWnd->GetDC();              // Get device context
  2491. CBitmap bmp,bmp2,bmp3;
  2492. GetBitmapFromImageList(pDC,newlist,0,bmp);
  2493. GetFadedBitmap(bmp);
  2494. newlist->Add(&bmp,GetSysColor(COLOR_3DFACE));
  2495. GetBitmapFromImageList(pDC,newlist,0,bmp2);
  2496. GetShadowBitmap(bmp2);
  2497. newlist->Add(&bmp2,GetSysColor(COLOR_3DFACE));
  2498. GetBitmapFromImageList(pDC,newlist,0,bmp3);
  2499. GetDisabledBitmap(bmp3);
  2500. newlist->Add(&bmp3,GetSysColor(COLOR_3DFACE));
  2501. pWnd->ReleaseDC(pDC);  // Release the DC
  2502. }
  2503. return TRUE;
  2504. }
  2505. // 2001-07-12, Damir Valiulin:
  2506. //          Added GetSubMenu (LPCTSTR lpszSubMenuName) function
  2507. //
  2508. CMenu* BCMenu::GetSubMenu(int nPos)
  2509. {
  2510. return CMenu::GetSubMenu (nPos);
  2511. }
  2512. CMenu* BCMenu::GetSubMenu(LPCTSTR lpszSubMenuName)
  2513. {
  2514. int num = GetMenuItemCount ();
  2515. CString name;
  2516. for (int i=0; i<num; i++)
  2517. {
  2518. GetMenuString (i, name, MF_BYPOSITION);
  2519. if (name.Compare (lpszSubMenuName) == 0)
  2520. {
  2521. return CMenu::GetSubMenu (i);
  2522. }
  2523. }
  2524. return NULL;
  2525. }
  2526. BCMenu* BCMenu::GetSubBCMenu(char* pText)
  2527. {
  2528. USES_CONVERSION;
  2529. return GetSubBCMenu(A2W(pText));
  2530. }
  2531. BCMenu* BCMenu::GetSubBCMenu(wchar_t* lpszSubMenuName)
  2532. {
  2533. BCMenuData *mdata;
  2534. mdata=FindMenuOption(lpszSubMenuName);
  2535. if(mdata){
  2536. HMENU bchmenu=(HMENU)mdata->nID;
  2537. CMenu *ptr=FromHandle(bchmenu);
  2538. if(ptr){
  2539. BOOL flag=ptr->IsKindOf(RUNTIME_CLASS( BCMenu ));
  2540. if(flag)return((BCMenu *)ptr);
  2541. }
  2542. }
  2543. return NULL;
  2544. }
  2545. // Tongzhe Cui, Functions to remove a popup menu based on its name. Seperators
  2546. // before and after the popup menu can also be removed if they exist.
  2547. int BCMenu::GetMenuPosition(char* pText)
  2548. {
  2549. USES_CONVERSION;
  2550. return GetMenuPosition(A2W(pText));
  2551. }
  2552. int BCMenu::GetMenuPosition(wchar_t* pText)
  2553. {
  2554. int i,j;
  2555. BCMenu* psubmenu;
  2556. for(i=0;i<(int)(GetMenuItemCount());++i)
  2557. {
  2558. psubmenu=(BCMenu *)GetSubMenu(i);
  2559. if(!psubmenu)
  2560. {
  2561. const wchar_t *szWide;//SK: we use const to prevent misuse of this Ptr
  2562. for(j=0;j<=m_MenuList.GetUpperBound();++j)
  2563. {     
  2564. szWide = m_MenuList[j]->GetWideString ();
  2565. if(szWide && !wcscmp(pText,szWide))//SK: modified for dynamic allocation
  2566. return j;
  2567. }
  2568. }
  2569. }
  2570. // means no found;
  2571. return -1;
  2572. }
  2573. int BCMenu::RemoveMenu(char* pText, BC_Seperator sPos)
  2574. {
  2575. USES_CONVERSION;
  2576. return RemoveMenu(A2W(pText), sPos);
  2577. }
  2578. int BCMenu::RemoveMenu(wchar_t* pText, BC_Seperator sPos)
  2579. {
  2580. int nPos = GetMenuPosition(pText);
  2581. if(nPos != -1)
  2582. {
  2583. RemoveMenu(nPos, MF_BYPOSITION);
  2584. }
  2585. if(sPos == BCMENU_HEAD)
  2586. {
  2587. ASSERT(nPos - 1 >= 0);
  2588. RemoveMenu(nPos-1, MF_BYPOSITION);
  2589. }
  2590. else if(sPos == BCMENU_TAIL)
  2591. {
  2592. RemoveMenu(nPos-1, MF_BYPOSITION);
  2593. }
  2594. else if(sPos == BCMENU_BOTH)
  2595. {
  2596. // remove the end first;
  2597. RemoveMenu(nPos-1, MF_BYPOSITION);
  2598. // remove the head;
  2599. ASSERT(nPos - 1 >= 0);
  2600. RemoveMenu(nPos-1, MF_BYPOSITION);
  2601. }
  2602. return nPos;
  2603. }
  2604. int BCMenu::DeleteMenu(char* pText, BC_Seperator sPos)
  2605. {
  2606. USES_CONVERSION;
  2607. return DeleteMenu(A2W(pText), sPos);
  2608. }
  2609. int BCMenu::DeleteMenu(wchar_t* pText, BC_Seperator sPos)
  2610. {
  2611. int nPos = GetMenuPosition(pText);
  2612. if(nPos != -1)
  2613. {
  2614. DeleteMenu(nPos, MF_BYPOSITION);
  2615. }
  2616. if(sPos == BCMENU_HEAD)
  2617. {
  2618. ASSERT(nPos - 1 >= 0);
  2619. DeleteMenu(nPos-1, MF_BYPOSITION);
  2620. }
  2621. else if(sPos == BCMENU_TAIL)
  2622. {
  2623. DeleteMenu(nPos-1, MF_BYPOSITION);
  2624. }
  2625. else if(sPos == BCMENU_BOTH)
  2626. {
  2627. // remove the end first;
  2628. DeleteMenu(nPos-1, MF_BYPOSITION);
  2629. // remove the head;
  2630. ASSERT(nPos - 1 >= 0);
  2631. DeleteMenu(nPos-1, MF_BYPOSITION);
  2632. }
  2633. return nPos;
  2634. }
  2635. // Larry Antram
  2636. BOOL BCMenu::SetMenuText(UINT id, CString string, UINT nFlags/*= MF_BYPOSITION*/ )
  2637. {
  2638. BOOL returnflag=FALSE;
  2639. if(MF_BYPOSITION&nFlags)
  2640. {
  2641. UINT numMenuItems = m_MenuList.GetUpperBound();
  2642. if(id<=numMenuItems){
  2643. #ifdef UNICODE
  2644. m_MenuList[id]->SetWideString((LPCTSTR)string);
  2645. #else
  2646. m_MenuList[id]->SetAnsiString(string);
  2647. #endif
  2648. returnflag=TRUE;
  2649. }
  2650. }
  2651. else{
  2652. int uiLoc;
  2653. BCMenu* pMenu = FindMenuOption(id,uiLoc);
  2654. if(NULL!=pMenu) returnflag = pMenu->SetMenuText(uiLoc,string);
  2655. }
  2656. return(returnflag);
  2657. }
  2658. // courtesy of Warren Stevens
  2659. void BCMenu::ColorBitmap(CDC* pDC,CBitmap& bmp,CSize bitmap_size,CSize icon_size,COLORREF fill,COLORREF border,int hatchstyle)
  2660. {
  2661. CDC bmpdc;
  2662. COLORREF m_newclrBack;
  2663. int x1=0,y1=0,x2=bitmap_size.cx,y2=bitmap_size.cy;
  2664. if(IsWinXPLuna())m_newclrBack=GetSysColor(COLOR_3DFACE);
  2665. else m_newclrBack=GetSysColor(COLOR_MENU);
  2666. bmpdc.CreateCompatibleDC(pDC);
  2667. bmp.CreateCompatibleBitmap(pDC, icon_size.cx, icon_size.cy);
  2668. CBitmap* pOldBitmap = bmpdc.SelectObject(&bmp);
  2669. if(bitmap_size!=icon_size){
  2670. CBrush background_brush;
  2671. background_brush.CreateSolidBrush(m_newclrBack);
  2672. CRect rect(0,0, icon_size.cx, icon_size.cy);
  2673. bmpdc.FillRect(rect,&background_brush);
  2674. x1 = (icon_size.cx-bitmap_size.cx)/2;
  2675. y1 = (icon_size.cy-bitmap_size.cy)/2;
  2676. x2 = x1+bitmap_size.cx;
  2677. y2 = y1+bitmap_size.cy;
  2678. background_brush.DeleteObject();
  2679. }
  2680. CPen border_pen(PS_SOLID, 1, border);
  2681. CBrush fill_brush;
  2682. if(hatchstyle!=-1) { fill_brush.CreateHatchBrush(hatchstyle, fill); }
  2683. else      { fill_brush.CreateSolidBrush(fill);             }
  2684. CPen*    pOldPen    = bmpdc.SelectObject(&border_pen);
  2685. CBrush*  pOldBrush  = bmpdc.SelectObject(&fill_brush);
  2686. bmpdc.Rectangle(x1,y1,x2,y2);
  2687. if(NULL!=pOldBrush)  { bmpdc.SelectObject(pOldBrush);  }
  2688. if(NULL!=pOldPen)    { bmpdc.SelectObject(pOldPen);    }
  2689. if(NULL!=pOldBitmap) { bmpdc.SelectObject(pOldBitmap); }
  2690. }
  2691. BOOL BCMenu::IsWindowsClassicTheme(void)
  2692. {
  2693. TCHAR Buf[_MAX_PATH+10];
  2694. HKEY hKey;
  2695. DWORD size,type; 
  2696. long lRetCode; 
  2697. static BOOL XPTheme_returnflag=FALSE;
  2698. static BOOL XPTheme_checkflag=FALSE;
  2699. if(XPTheme_checkflag)return(XPTheme_returnflag);
  2700. XPTheme_checkflag=TRUE;
  2701. lRetCode = RegOpenKeyEx ( HKEY_CURRENT_USER, 
  2702. _T("Software\Microsoft\Plus!\Themes\Current"), 
  2703. 0,KEY_READ,&hKey);  
  2704. if (lRetCode == ERROR_SUCCESS){ 
  2705. size = _MAX_PATH;type=REG_SZ;
  2706. lRetCode=::RegQueryValueEx(hKey,NULL,NULL,&type,
  2707. (unsigned char *)Buf,&size);
  2708. if(lRetCode == ERROR_SUCCESS){
  2709. TCHAR szClassicTheme[]=_T("Windows Classic.theme");
  2710. int len=lstrlen(Buf);
  2711. if(len>=lstrlen(szClassicTheme)){
  2712. if(!lstrcmpi(&Buf[len-lstrlen(szClassicTheme)],szClassicTheme)){
  2713. XPTheme_returnflag=TRUE;
  2714. }
  2715. }
  2716. }
  2717. RegCloseKey(hKey);  
  2718. }
  2719. return(XPTheme_returnflag);
  2720. }
  2721. int BCMenu::GlobalImageListOffset(int nID)
  2722. {
  2723. int numcurrent=m_AllImagesID.GetSize();
  2724. int existsloc = -1;
  2725. for(int i=0;i<numcurrent;++i)
  2726. {
  2727. if(m_AllImagesID[i]==nID)
  2728. {
  2729. existsloc=i;
  2730. break;
  2731. }
  2732. }
  2733. return existsloc;
  2734. }
  2735. BOOL BCMenu::CanDraw3DImageList(int offset)
  2736. {
  2737. BOOL retflag=FALSE;
  2738. int numcurrent=m_AllImagesID.GetSize();
  2739. if(offset+1<numcurrent&&offset+2<numcurrent)
  2740. {
  2741. int nID=m_AllImagesID[offset];
  2742. if(m_AllImagesID[offset+1]==nID&&m_AllImagesID[offset+2]==nID)retflag=TRUE;
  2743. }
  2744. return(retflag);
  2745. }
  2746. int BCMenu::AddToGlobalImageList(CImageList *il,int xoffset,int nID)
  2747. {
  2748. int loc = -1;
  2749. HIMAGELIST hImageList = m_AllImages.m_hImageList;
  2750. if(!hImageList){
  2751. m_AllImages.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  2752. }
  2753. HICON hIcon = il->ExtractIcon(xoffset);
  2754. if(hIcon){
  2755. CBitmap bmp,bmp2,bmp3;
  2756. if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
  2757. CWnd *pWnd = AfxGetMainWnd();            // Get main window
  2758. if (pWnd == NULL) pWnd = CWnd::GetDesktopWindow();
  2759. CDC *pDC = pWnd->GetDC();              // Get device context
  2760. GetBitmapFromImageList(pDC,il,xoffset,bmp);
  2761. GetFadedBitmap(bmp);
  2762. GetBitmapFromImageList(pDC,il,xoffset,bmp2);
  2763. GetShadowBitmap(bmp2);
  2764. GetBitmapFromImageList(pDC,il,xoffset,bmp3);
  2765. GetDisabledBitmap(bmp3);
  2766. pWnd->ReleaseDC(pDC);  // Release the DC
  2767. }
  2768. int numcurrent=m_AllImagesID.GetSize();
  2769. int existsloc = -1;
  2770. for(int i=0;i<numcurrent;++i){
  2771. if(m_AllImagesID[i]==nID){
  2772. existsloc=i;
  2773. break;
  2774. }
  2775. }
  2776. if(existsloc>=0){
  2777. m_AllImages.Replace(existsloc,hIcon);
  2778. loc = existsloc;
  2779. if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
  2780. if(existsloc+1<numcurrent&&m_AllImagesID[existsloc+1]==nID){
  2781. if(existsloc+2<numcurrent&&m_AllImagesID[existsloc+2]==nID){
  2782. CImageList il2;
  2783. il2.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
  2784. il2.Add(&bmp,GetSysColor(COLOR_3DFACE));
  2785. HICON hIcon2 = il2.ExtractIcon(0);
  2786. m_AllImages.Replace(existsloc+1,hIcon2);
  2787. il2.Add(&bmp2,GetSysColor(COLOR_3DFACE));
  2788. HICON hIcon3 = il2.ExtractIcon(1);
  2789. m_AllImages.Replace(existsloc+2,hIcon3);
  2790. il2.Add(&bmp3,GetSysColor(COLOR_3DFACE));
  2791. HICON hIcon4 = il2.ExtractIcon(2);
  2792. m_AllImages.Replace(existsloc+3,hIcon4);
  2793. ::DestroyIcon(hIcon2);
  2794. ::DestroyIcon(hIcon3);
  2795. ::DestroyIcon(hIcon4);
  2796. }
  2797. }
  2798. }
  2799. }
  2800. else{
  2801. m_AllImages.Add(hIcon);
  2802. m_AllImagesID.Add(nID);
  2803. loc=numcurrent;
  2804. if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
  2805. m_AllImages.Add(&bmp,GetSysColor(COLOR_3DFACE));
  2806. m_AllImages.Add(&bmp2,GetSysColor(COLOR_3DFACE));
  2807. m_AllImages.Add(&bmp3,GetSysColor(COLOR_3DFACE));
  2808. m_AllImagesID.Add(nID);
  2809. m_AllImagesID.Add(nID);
  2810. m_AllImagesID.Add(nID);
  2811. }
  2812. }
  2813. ::DestroyIcon(hIcon);
  2814. }
  2815. return(loc);
  2816. }