📄 bcmenu.cpp
字号:
//*************************************************************************
// BCMenu.cpp : implementation file
// Version : 2.1
// Date : April 2, 1998
// Author : Brent Corkum
//
// Portions of code supplied by:
// Ben Ashley,Girish Bharadwaj,Jean-Edouard Lachand-Robert,
// Robert Edward Caldecott,Kenny Goers,Leonardo Zide,
// Stefan Kuhr
//
// Bug Fixes:
// Stefan Kuhr,Martin Vladic
//
// You are free to use/modify this code but leave this header intact.
//
#include "stdafx.h" // Standard windows header file
#include "BCMenu.h" // BCMenu class declaration
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define 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;
enum Win32Type{
Win32s,
Windoze95,
WinNT3,
WinNT4orHigher
};
Win32Type IsNewShell()
{
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=WinNT4orHigher;//yup, it is NT 4 or higher!
free(osvi);
}
}
else if (LOBYTE(LOWORD(winVer))<4)
ShellType=Win32s;/*Win32s*/
else
ShellType=Windoze95;/*Windoze95*/
return ShellType;
}
static Win32Type g_Shell=IsNewShell();
void BCMenuData::SetAnsiString(LPCSTR szAnsiString)
{
ASSERT(szAnsiString);
int iBufSize=(CPInfo.MaxCharSize==1)?strlen(szAnsiString):_mbstrlen(szAnsiString);
iBufSize++;//Increment for the terminating NULL
wchar_t *szText=new wchar_t[iBufSize];
VERIFY(MultiByteToWideChar(
CP_ACP, // code page
MB_PRECOMPOSED, // character-type options
szAnsiString, // address of string to map
-1, // number of characters in string
szText, // address of wide-character buffer
iBufSize*sizeof(wchar_t)// size of buffer
));
ASSERT(wcslen(szText)<=strlen(szAnsiString));/////////////这里我修改过///////////
//ASSERT(wcslen(szText)==strlen(szAnsiString));
wcscpy(menuText,szText);
delete[] szText;
}
CString BCMenuData::GetString(void)//returns the menu text in ANSI or UNICODE
//depending on the MFC-Version we are using
{
CString strText;
#ifdef UNICODE
strText = menuText;
#else
int iLen=(wcslen(menuText)+1)*sizeof(wchar_t);
char *szAnsiString=new char[iLen];
if (*menuText){
VERIFY(WideCharToMultiByte(
CP_ACP, // code page
0, // performance and mapping flags
menuText, // address of wide-character string
-1, // number of characters in string
szAnsiString, // address of buffer for new string
iLen, // size of buffer
NULL, // address of default for unmappable characters
NULL // address of flag set when default char. used
));
strText=szAnsiString;
}
else strText.Empty();
delete[] szAnsiString;
#endif
return strText;
}
/*
===============================================================================
BCMenu::BCMenu()
TCMeny::~BCMenu()
-----------------
Constructor and Destructor.
===============================================================================
*/
BCMenu::BCMenu()
{
disable_old_style=FALSE;
m_iconX = 16; // Icon sizes default to 16 x 16
m_iconY = 15; // ...
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);
}
BCMenu::~BCMenu()
{
DestroyMenu();
}
BCMenuData::~BCMenuData()
{
if(bitmap)delete(bitmap);
}
BOOL BCMenu::IsMenu(CMenu *submenu)
{
int m;
int numSubMenus = m_SubMenus.GetUpperBound();
for(m=0;m<=numSubMenus;++m){
if(submenu==m_SubMenus[m])return(TRUE);
}
return(FALSE);
}
BOOL BCMenu::DestroyMenu()
{
// Destroy Sub menus:
int m;
int numSubMenus = m_SubMenus.GetUpperBound();
for(m = numSubMenus; m >= 0; m--)delete(m_SubMenus[m]);
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());
};
///////////////////////////////////////////////////////////////////////////
//
// BCMenu message handlers
/*
==========================================================================
void BCMenu::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 BCMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
{
ASSERT(lpDIS != NULL);
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CRect rect;
UINT state = (((BCMenuData*)(lpDIS->itemData))->nFlags);
if(state & MF_SEPARATOR){
rect.CopyRect(&lpDIS->rcItem);
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;
CBitmap bitmapstandard;
COLORREF crText = GetSysColor(COLOR_MENUTEXT);
COLORREF m_clrBack=GetSysColor(COLOR_MENU);
CBrush m_brBackground,m_brSelect;
CPen m_penBack;
int x0,y0,dy;
int nIconNormal=-1,xoffset=-1;
CImageList *bitmap=NULL;
CFont m_fontMenu;
LOGFONT m_lf;
// set some colors and the font
m_penBack.CreatePen (PS_SOLID,0,GetSysColor(COLOR_MENU));
m_brBackground.CreateSolidBrush(GetSysColor(COLOR_MENU));
m_brSelect.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
NONCLIENTMETRICS nm;
nm.cbSize = sizeof (NONCLIENTMETRICS);
VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0));
m_lf = nm.lfMenuFont;
m_fontMenu.CreateFontIndirect (&m_lf);
// draw the colored rectangle portion
rect.CopyRect(&lpDIS->rcItem);
rect2=rect;
// draw the up/down/focused/disabled state
UINT action = lpDIS->itemAction;
UINT state = lpDIS->itemState;
CString strText;
LOGFONT lf;
lf = m_lf;
CFont dispFont;
CFont *pFont;
if(lpDIS->itemData != NULL){
nIconNormal = (((BCMenuData*)(lpDIS->itemData))->menuIconNormal);
xoffset = (((BCMenuData*)(lpDIS->itemData))->xoffset);
bitmap = (((BCMenuData*)(lpDIS->itemData))->bitmap);
strText = ((BCMenuData*) (lpDIS->itemData))->GetString();
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+GAP,rect.top,rect.right,rect.bottom);
pDC->FillRect (rect2,&m_brSelect);
pDC->SelectObject (pOldPen);
if((HFONT)dispFont != NULL)dispFont.DeleteObject ();
dispFont.CreateFontIndirect (&lf);
crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
}
else {
CPen *pOldPen = pDC->SelectObject (&m_penBack);
pDC->FillRect (rect,&m_brBackground);
pDC->SelectObject (pOldPen);
// draw the up edges
pDC->Draw3dRect (rect,m_clrBack,m_clrBack);
if ((HFONT)dispFont != NULL) dispFont.DeleteObject ();
dispFont.CreateFontIndirect (&lf); //Normal
}
// draw the text if there is any
//We have to paint the text only if the image is nonexistant
dy = (rect.Height()-4-m_iconY)/2;
dy = dy<0 ? 0 : dy;
if(checkflag||standardflag||selectedflag||disableflag){
rect2.SetRect(rect.left+1,rect.top+1+dy,rect.left+m_iconX+3,
rect.top+m_iconY+3+dy);
pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
if(checkflag && checkmaps){
pDC->FillRect (rect2,&m_brBackground);
rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
rect.top+m_iconY+4+dy);
pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
CPoint ptImage(rect.left+2,rect.top+2+dy);
if(state&ODS_SELECTED)checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
else checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
}
else if(disableflag){
if(!selectedflag){
HBITMAP hbmp=LoadSysColorBitmap(nIconNormal);
if(hbmp){
bitmapstandard.Attach(hbmp);
rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
rect.top+m_iconY+4+dy);
pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
if(disable_old_style)
DitherBlt(lpDIS->hDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
(HBITMAP)(bitmapstandard),xoffset*m_iconX,0);
else
DitherBlt2(pDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
bitmapstandard,xoffset*m_iconX,0);
bitmapstandard.DeleteObject();
}
}
}
else if(selectedflag){
pDC->FillRect (rect2,&m_brBackground);
rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
rect.top+m_iconY+4+dy);
if (Windoze95==g_Shell || WinNT4orHigher==g_Shell){
if(state&ODS_CHECKED)
pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),
GetSysColor(COLOR_3DHILIGHT));
else
pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DHILIGHT),
GetSysColor(COLOR_3DSHADOW));
}
CPoint ptImage(rect.left+2,rect.top+2+dy);
if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
}
else{
if(state&ODS_CHECKED){
CBrush brush;
COLORREF col =GetSysColor(COLOR_3DLIGHT);
brush.CreateSolidBrush(col);
pDC->FillRect(rect2,&brush);
brush.DeleteObject();
rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
rect.top+m_iconY+4+dy);
if (Windoze95==g_Shell || WinNT4orHigher==g_Shell)
pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),
GetSysColor(COLOR_3DHILIGHT));
}
else{
pDC->FillRect (rect2,&m_brBackground);
rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
rect.top+m_iconY+4+dy);
pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
}
CPoint ptImage(rect.left+2,rect.top+2+dy);
if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
}
}
if(nIconNormal<0 && state&ODS_CHECKED && !checkflag){
rect2.SetRect(rect.left+1,rect.top+2+dy,rect.left+m_iconX+1,
rect.top+m_iconY+2+dy);
CMenuItemInfo info;
info.fMask = MIIM_CHECKMARKS;
::GetMenuItemInfo((HMENU)lpDIS->hwndItem,lpDIS->itemID,
MF_BYCOMMAND, &info);
if(state&ODS_CHECKED || info.hbmpUnchecked) {
Draw3DCheckmark(pDC, rect2, state&ODS_SELECTED,
state&ODS_CHECKED ? info.hbmpChecked :
info.hbmpUnchecked);
}
}
//This is needed always so that we can have the space for check marks
x0=rect.left;y0=rect.top;
rect.left = rect.left + m_iconX + 8 + GAP;
if(!strText.IsEmpty()){
CRect rectt(rect.left,rect.top-1,rect.right,rect.bottom-1);
// Find tabs
CString leftStr,rightStr;
leftStr.Empty();rightStr.Empty();
int tablocr=strText.ReverseFind(_T('\t'));
if(tablocr!=-1){
rightStr=strText.Mid(tablocr+1);
leftStr=strText.Left(strText.Find(_T('\t')));
rectt.right-=m_iconX;
}
else leftStr=strText;
int iOldMode = pDC->GetBkMode();
pDC->SetBkMode( TRANSPARENT);
// Draw the text in the correct colour:
UINT nFormat = DT_LEFT|DT_SINGLELINE|DT_VCENTER;
UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
if(!(lpDIS->itemState & ODS_GRAYED)){
pDC->SetTextColor(crText);
pDC->DrawText (leftStr,rectt,nFormat);
if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
}
else{
// Draw the disabled text
if(!(state & ODS_SELECTED)){
RECT offset = *rectt;
offset.left+=1;
offset.right+=1;
offset.top+=1;
offset.bottom+=1;
pDC->SetTextColor(GetSysColor(COLOR_BTNHILIGHT));
pDC->DrawText(leftStr,&offset, nFormat);
if(tablocr!=-1) pDC->DrawText (rightStr,&offset,nFormatr);
pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
pDC->DrawText(leftStr,rectt, nFormat);
if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
}
else{
// And the standard Grey text:
pDC->SetTextColor(m_clrBack);
pDC->DrawText(leftStr,rectt, nFormat);
if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
}
}
pFont = pDC->SelectObject (&dispFont);
pDC->SetBkMode( iOldMode );
pDC->SelectObject (pFont); //set it to the old font
}
m_penBack.DeleteObject();
m_brBackground.DeleteObject();
m_fontMenu.DeleteObject();
m_brSelect.DeleteObject();
dispFont.DeleteObject ();
}
}
/*
==========================================================================
void BCMenu::MeasureItem(LPMEASUREITEMSTRUCT)
---------------------------------------------
Called by the framework when it wants to know what the width and height
of our item will be. To accomplish this we provide the width of the
icon plus the width of the menu text, and then the height of the icon.
==========================================================================
*/
void BCMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
{
UINT state = (((BCMenuData*)(lpMIS->itemData))->nFlags);
if(state & MF_SEPARATOR){
lpMIS->itemWidth = 0;
lpMIS->itemHeight = GetSystemMetrics(SM_CYMENU)>>1;
}
else{
CFont m_fontMenu;
LOGFONT m_lf;
ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
NONCLIENTMETRICS nm;
nm.cbSize = sizeof (NONCLIENTMETRICS);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -