📄 cjmenu.cpp
字号:
//*************************************************************************
// CJMenu.cpp : implementation file
// Version : 3.033
// Date : April 2002
// Author : Brent Corkum
// Email : corkum@rocscience.com
// Latest Version : http://www.rocscience.com/~corkum/BCMenu.html
//
// Bug Fixes and portions of code supplied by:
//
// Ben Ashley,Girish Bharadwaj,Jean-Edouard Lachand-Robert,
// Robert Edward Caldecott,Kenny Goers,Leonardo Zide,
// Stefan Kuhr,Reiner Jung,Martin Vladic,Kim Yoo Chul,
// Oz Solomonovich,Tongzhe Cui,Stephane Clog,Warren Stevens,
// Damir Valiulin,David Kinder,Marc Loiry
//
// You are free to use/modify this code but leave this header intact.
// This class is public domain so you are free to use it any of
// your applications (Freeware,Shareware,Commercial). All I ask is
// that you let me know so that if you have a real winner I can
// brag to my buddies that some of my code is in your app. I also
// wouldn't mind if you sent me a copy of your application since I
// like to play with new stuff.
//*************************************************************************
/****************************************************************************
*
* $Date: 15/12/02 17:59 $
* $Revision: 6 $
* $Archive: /Projects/Libraries/CJLibrary/CJLibrary/CJMenu.cpp $
*
* $History: CJMenu.cpp $
*
* ***************** Version 6 *****************
* User: Anna Date: 15/12/02 Time: 17:59
* Updated in $/Projects/Libraries/CJLibrary/CJLibrary
* Added 2 new overloads of CCJMenu::LoadMenu() to allow the HINSTANCE of
* the module to be specified
*
*
*
* ***************** Version 5 *****************
* User: Andy Date: 10/05/02 Time: 14:07
* Updated in $/Projects/Libraries/CJLibrary/CJLibrary
* Integrated BCMenu 3.03
*
* ***************** Version 4 *****************
* User: Andy Date: 2/26/02 Time: 4:13p
* Updated in $/Projects/Libraries/CJLibrary/CJLibrary
* Integrated BCMenu 3.01
*
* ***************** Version 3 *****************
* User: Andy Date: 1/14/02 Time: 8:19p
* Updated in $/Projects/AddIns/ResOrg/CJLibrary/CJLibrary
* XP style now suppports default menu items
*
* ***************** Version 2 *****************
* User: Andy Date: 1/04/02 Time: 10:48p
* Updated in $/Projects/AddIns/ResOrg/CJLibrary/CJLibrary
* Upgraded to BCMenu 3.0 (WinXP style and lots of bug fixes)
*
* ***************** Version 6 *****************
* User: Kirk Stowell Date: 10/24/99 Time: 2:09a
* Updated in $/CodeJock/CJLibrary
* Upgraded to version 2.5 of BCMenu
*
* ***************** Version 5 *****************
* User: Kirk Stowell Date: 10/14/99 Time: 12:41p
* Updated in $/CodeJock/CJLibrary
* Added source control history to file header.
*
***************************************************************************/
#include "stdafx.h" // Standard windows header file
#include "CJMenu.h" // CCJMenu class declaration
#include <afxpriv.h> //SK: makes A2W and other spiffy AFX macros work
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define CCJMenu_GAP 1
#ifndef OBM_CHECK
#define OBM_CHECK 32760 // from winuser.h
#endif
#if _MFC_VER <0x400
#error This code does not work on Versions of MFC prior to 4.0
#endif
static CPINFO CPInfo;
// how the menu's are drawn in win9x/NT/2000
UINT CCJMenu::original_drawmode=CCJMenu_DRAWMODE_XP;
BOOL CCJMenu::original_select_disabled=TRUE;
// how the menu's are drawn in winXP
UINT CCJMenu::xp_drawmode=CCJMenu_DRAWMODE_XP;
BOOL CCJMenu::xp_select_disabled=FALSE;
BOOL CCJMenu::xp_draw_3D_bitmaps=TRUE;
BOOL CCJMenu::hicolor_bitmaps=FALSE;
// Variable to set how accelerators are justified. The default mode (TRUE) right
// justifies them to the right of the longes string in the menu. FALSE
// just right justifies them.
BOOL CCJMenu::xp_space_accelerators=TRUE;
BOOL CCJMenu::original_space_accelerators=TRUE;
CImageList CCJMenu::m_AllImages;
CArray<int,int&> CCJMenu::m_AllImagesID;
int CCJMenu::m_iconX = 16;
int CCJMenu::m_iconY = 15;
enum Win32Type{
Win32s,
WinNT3,
Win95,
Win98,
WinME,
WinNT4,
Win2000,
WinXP
};
Win32Type IsShellType()
{
Win32Type ShellType;
DWORD winVer;
OSVERSIONINFO *osvi;
winVer=GetVersion();
if(winVer<0x80000000){/*NT */
ShellType=WinNT3;
osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
if (osvi!=NULL){
memset(osvi,0,sizeof(OSVERSIONINFO));
osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
GetVersionEx(osvi);
if(osvi->dwMajorVersion==4L)ShellType=WinNT4;
else if(osvi->dwMajorVersion==5L&&osvi->dwMinorVersion==0L)ShellType=Win2000;
else if(osvi->dwMajorVersion==5L&&osvi->dwMinorVersion==1L)ShellType=WinXP;
free(osvi);
}
}
else if (LOBYTE(LOWORD(winVer))<4)
ShellType=Win32s;
else{
ShellType=Win95;
osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
if (osvi!=NULL){
memset(osvi,0,sizeof(OSVERSIONINFO));
osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
GetVersionEx(osvi);
if(osvi->dwMajorVersion==4L&&osvi->dwMinorVersion==10L)ShellType=Win98;
else if(osvi->dwMajorVersion==4L&&osvi->dwMinorVersion==90L)ShellType=WinME;
free(osvi);
}
}
return ShellType;
}
static Win32Type g_Shell=IsShellType();
void CCJMenuData::SetAnsiString(LPCSTR szAnsiString)
{
USES_CONVERSION;
SetWideString(A2W(szAnsiString)); //SK: see MFC Tech Note 059
}
CString CCJMenuData::GetString(void)//returns the menu text in ANSI or UNICODE
//depending on the MFC-Version we are using
{
CString strText;
if (m_szMenuText)
{
#ifdef UNICODE
strText = m_szMenuText;
#else
USES_CONVERSION;
strText=W2A(m_szMenuText); //SK: see MFC Tech Note 059
#endif
}
return strText;
}
CTypedPtrArray<CPtrArray, HMENU> CCJMenu::m_AllSubMenus; // Stores list of all sub-menus
IMPLEMENT_DYNAMIC( CCJMenu, CMenu )
/*
===============================================================================
CCJMenu::CCJMenu()
CCJMenu::~CCJMenu()
-----------------
Constructor and Destructor.
===============================================================================
*/
CCJMenu::CCJMenu()
{
m_bDynIcons = FALSE; // O.S. - no dynamic icons by default
disable_old_style=FALSE;
m_selectcheck = -1;
m_unselectcheck = -1;
checkmaps=NULL;
checkmapsshare=FALSE;
// set the color used for the transparent background in all bitmaps
m_bitmapBackground=RGB(192,192,192); //gray
m_bitmapBackgroundFlag=FALSE;
GetCPInfo(CP_ACP,&CPInfo);
m_loadmenu=FALSE;
}
CCJMenu::~CCJMenu()
{
DestroyMenu();
}
BOOL CCJMenu::IsNewShell ()
{
return (g_Shell>=Win95);
}
BOOL CCJMenu::IsWinXPLuna()
{
if(g_Shell==WinXP){
if(IsWindowsClassicTheme())return(FALSE);
else return(TRUE);
}
return(FALSE);
}
BOOL CCJMenu::IsLunaMenuStyle()
{
if(IsWinXPLuna()){
if(xp_drawmode==CCJMenu_DRAWMODE_XP)return(TRUE);
}
else{
if(original_drawmode==CCJMenu_DRAWMODE_XP)return(TRUE);
}
return(FALSE);
}
CCJMenuData::~CCJMenuData()
{
if(bitmap)
delete(bitmap);
delete[] m_szMenuText; //Need not check for NULL because ANSI X3J16 allows "delete NULL"
}
void CCJMenuData::SetWideString(const wchar_t *szWideString)
{
delete[] m_szMenuText;//Need not check for NULL because ANSI X3J16 allows "delete NULL"
if (szWideString)
{
m_szMenuText = new wchar_t[sizeof(wchar_t)*(wcslen(szWideString)+1)];
if (m_szMenuText)
wcscpy(m_szMenuText,szWideString);
}
else
m_szMenuText=NULL;//set to NULL so we need not bother about dangling non-NULL Ptrs
}
BOOL CCJMenu::IsMenu(CMenu *submenu)
{
int m;
int numSubMenus = m_AllSubMenus.GetUpperBound();
for(m=0;m<=numSubMenus;++m){
if(submenu->m_hMenu==m_AllSubMenus[m])return(TRUE);
}
return(FALSE);
}
BOOL CCJMenu::IsMenu(HMENU submenu)
{
int m;
int numSubMenus = m_AllSubMenus.GetUpperBound();
for(m=0;m<=numSubMenus;++m){
if(submenu==m_AllSubMenus[m])return(TRUE);
}
return(FALSE);
}
BOOL CCJMenu::DestroyMenu()
{
// Destroy Sub menus:
int m,n;
int numAllSubMenus = m_AllSubMenus.GetUpperBound();
for(n = numAllSubMenus; n>= 0; n--){
if(m_AllSubMenus[n]==this->m_hMenu)m_AllSubMenus.RemoveAt(n);
}
int numSubMenus = m_SubMenus.GetUpperBound();
for(m = numSubMenus; m >= 0; m--){
numAllSubMenus = m_AllSubMenus.GetUpperBound();
for(n = numAllSubMenus; n>= 0; n--){
if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
}
CMenu *ptr=FromHandle(m_SubMenus[m]);
BOOL flag=ptr->IsKindOf(RUNTIME_CLASS( CCJMenu ));
if(flag)delete((CCJMenu *)ptr);
}
m_SubMenus.RemoveAll();
// Destroy menu data
int numItems = m_MenuList.GetUpperBound();
for(m = 0; m <= numItems; m++)delete(m_MenuList[m]);
m_MenuList.RemoveAll();
if(checkmaps&&!checkmapsshare){
delete checkmaps;
checkmaps=NULL;
}
// Call base-class implementation last:
return(CMenu::DestroyMenu());
};
int CCJMenu::GetMenuDrawMode(void)
{
if(IsWinXPLuna())return(xp_drawmode);
return(original_drawmode);
}
BOOL CCJMenu::GetSelectDisableMode(void)
{
if(IsLunaMenuStyle())return(xp_select_disabled);
return(original_select_disabled);
}
/*
==========================================================================
void CCJMenu::DrawItem(LPDRAWITEMSTRUCT)
---------------------------------------
Called by the framework when a particular item needs to be drawn. We
overide this to draw the menu item in a custom-fashion, including icons
and the 3D rectangle bar.
==========================================================================
*/
void CCJMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
{
ASSERT(lpDIS != NULL);
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
if(pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)DrawItem_Win9xNT2000(lpDIS);
else{
if(IsWinXPLuna()){
if(xp_drawmode==CCJMenu_DRAWMODE_XP) DrawItem_WinXP(lpDIS);
else DrawItem_Win9xNT2000(lpDIS);
}
else{
if(original_drawmode==CCJMenu_DRAWMODE_XP) DrawItem_WinXP(lpDIS);
else DrawItem_Win9xNT2000(lpDIS);
}
}
}
void CCJMenu::DrawItem_Win9xNT2000 (LPDRAWITEMSTRUCT lpDIS)
{
ASSERT(lpDIS != NULL);
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CRect rect;
UINT state = (((CCJMenuData*)(lpDIS->itemData))->nFlags);
CBrush m_brBackground;
COLORREF m_clrBack;
if(IsWinXPLuna())m_clrBack=GetSysColor(COLOR_3DFACE);
else m_clrBack=GetSysColor(COLOR_MENU);
m_brBackground.CreateSolidBrush(m_clrBack);
// remove the selected bit if it's grayed out
if(lpDIS->itemState & ODS_GRAYED&&!original_select_disabled){
if(lpDIS->itemState & ODS_SELECTED)lpDIS->itemState=lpDIS->itemState & ~ODS_SELECTED;
}
if(state & MF_SEPARATOR){
rect.CopyRect(&lpDIS->rcItem);
pDC->FillRect (rect,&m_brBackground);
rect.top += (rect.Height()>>1);
pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
}
else{
CRect rect2;
BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
BOOL checkflag=FALSE;
COLORREF crText = GetSysColor(COLOR_MENUTEXT);
CBrush m_brSelect;
CPen m_penBack;
int x0,y0,dy;
int nIconNormal=-1,xoffset=-1,global_offset=-1;
CImageList *bitmap=NULL;
// set some colors
m_penBack.CreatePen (PS_SOLID,0,m_clrBack);
m_brSelect.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
// draw the colored rectangle portion
rect.CopyRect(&lpDIS->rcItem);
rect2=rect;
// draw the up/down/focused/disabled state
UINT state = lpDIS->itemState;
CString strText;
if(lpDIS->itemData != NULL){
nIconNormal = (((CCJMenuData*)(lpDIS->itemData))->menuIconNormal);
xoffset = (((CCJMenuData*)(lpDIS->itemData))->xoffset);
global_offset = (((CCJMenuData*)(lpDIS->itemData))->global_offset);
bitmap = (((CCJMenuData*)(lpDIS->itemData))->bitmap);
strText = ((CCJMenuData*) (lpDIS->itemData))->GetString();
if(nIconNormal<0&&global_offset>=0){
xoffset=global_offset;
nIconNormal=0;
bitmap = &m_AllImages;
}
if(state&ODS_CHECKED && nIconNormal<0){
if(state&ODS_SELECTED && m_selectcheck>0)checkflag=TRUE;
else if(m_unselectcheck>0) checkflag=TRUE;
}
else if(nIconNormal != -1){
standardflag=TRUE;
if(state&ODS_SELECTED && !(state&ODS_GRAYED))selectedflag=TRUE;
else if(state&ODS_GRAYED) disableflag=TRUE;
}
}
else{
strText.Empty();
}
if(state&ODS_SELECTED){ // draw the down edges
CPen *pOldPen = pDC->SelectObject (&m_penBack);
// You need only Text highlight and thats what you get
if(checkflag||standardflag||selectedflag||disableflag||state&ODS_CHECKED)
rect2.SetRect(rect.left+m_iconX+4+CCJMenu_GAP,rect.top,rect.right,rect.bottom);
pDC->FillRect (rect2,&m_brSelect);
pDC->SelectObject (pOldPen);
crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -