VC++的菜单控制和自绘菜单
2020-11-27 07:26
标签:des style class ext color width 菜单控制 需要将CFrameWnd::
m_bAutomenuEnable设置为FALSE,如果该数据成员为TRUE(缺省值),工作框将自动地禁止没有ON_UPDATE_COMMAND_UI或者ON_COMMAND的菜单项。 //Disable
MFC from automatically disabling menu
items. m_bAuoMenuEnable=FALSE; //Now
enable the menu item. CMenu* pMenu=GetMenu
(); ASSERT_VALID
(pMenu); pMenu->EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND
|
MF_ENABLED); 如何给系统菜单添加一个菜单项 给系统菜单添加一个菜单项需要进行下述三个步骤: 首先,使用Resource
Symbols对话(在View菜单中选择Resource
Symbols... 可以显示该对话)定义菜单项ID,该ID应大于0x0F而小于0xF000; 其次,调用CWnd::GetSystemMenu获取系统菜单的指针并调用CWnd::
Appendmenu将菜单项添加到菜单中。下例给系统菜单添加两个新的菜单项: int CMainFrame::
OnCreate (LPCREATESTRUCT
lpCreateStruct) { … //Make
sure system menu item is in the right range. ASSERT
(IDM_MYSYSITEM &0xFFF0)==IDM_MYSYSITEM); ASSERT
(IDM-MYSYSITEM //Get pointer to system
menu. CMenu* pSysmenu=GetSystemmenu
(FALSE); ASSERT_VALID (pSysMenu); //Add
a separator and our menu item to system menu. CString
StrMenuItem (_T ("New menu item")); pSysMenu->Appendmenu
(MF_SEPARATOR); pSysMenu->AppendMenu (MF_STRING,
IDM_MYSYSITEM,
strMenuitem); … } 现在,选择系统菜单项时用户应进行检测。使用ClassWizard处理 WM_SYSCOMMAND消息并检测用户菜单的nID参数: void
CMainFrame:: OnSysCommand (UINT nID,LPARAM
lParam) { //Determine if our system menu
item was selected. if ( (nID &
0xFFF0)==IDM_MYSYSITEM) { //TODO-process
system menu
item } else CMDIFrameWnd::
OnSysCommand (nID,
lParam); } 最后,一个设计良好的UI应用程序应当在系统菜单项加亮时在状态条显示一个帮助信息,这可以通过增加一个包含系统菜单基ID的串表的入口来实现。 如何确定顶层菜单所占据的菜单行数 这可以通过简单的减法和除法来实现。首先,用户需要计算主框窗口的高度和客户区;其次,从主框窗口的高度中减去客户区、框边界以及标题的高度;最后,除以菜单栏的高度。下例成员函数是一个计算主框菜单所占据的行数的代码实现。 int
CMainFrame:: GetMenuRows () { CRect
rcFrame,rcClient; GetWindowRect
(rcFrame); GetClientRect
(rcClient); return (rcFrame.Height () -rcClient.Height
()- :: GetSystemMetrics (SM_CYCAPTION)
- (:: getSystemMetrics (SM_CYFRAME) *2))
/ :: GetSystemMetrics
(SM_CYMENU); } 在这里提供一个C++类(CCustomMenu),该类是CMenu的子类,并且拥有自绘能力。它可以向你提供以下的功能: 设置字体颜色。 1、定义CCustomMenu的实例,和MENUDATA结构变量。 CCustomMenu
m_cCustomMenu; 3、在你的窗口中重载OnMeasureItem(...)函数。 下面的函数将帮助你设置菜单属性。 void
SetTextColor (COLORREF ); 下面是文件代码: #if #if
_MSC_VER >= 1000 typedef enum {Normal,TextOnly}
HIGHLIGHTSTYLE; //////////////////////////////////////////////// class CCustomMenu : public
CMenu //
Attributes //
Operations //
Overrides //
Implementation // Generated message map
functions //{{AFX_MSG(CCustomMenu) /////////////////////////////////////// //{{AFX_INSERT_LOCATION}} #endif
//!defined(AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_) //************************************************************************* #include
"stdafx.h" #ifdef _DEBUG //////////////////////////////////////////////// CCustomMenu::CCustomMenu() m_clrHilight = GetSysColor
(COLOR_HIGHLIGHT); ZeroMemory ((PVOID)
&m_lf,sizeof (LOGFONT)); //Get the system metrics for
the Captionfromhere m_lf =
nm.lfMenuFont; CCustomMenu::~CCustomMenu() //////////////////////////////////////////////// CDC* pDC =
CDC::FromHandle(lpDIS->hDC); //
draw the up/down/focused/disabled state UINT
action = lpDIS->itemAction; CFont
dispFont; TRACE1
("Draw for %s\n",
strText); if ( (state
& ODS_SELECTED)
) CPen
*pOldPen = pDC->SelectObject
(&m_penBack); //You
need only Text highlight and thats what you
get pDC->SelectObject
(pOldPen); //While
selected move the text a
bit TRACE0 ("SELECT,
NORMAL\n"); // draw
the text if there is any if (
!strText.IsEmpty()) int iOldMode =
pDC->GetBkMode(); pDC->SetBkMode(
TRANSPARENT); pDC->SetTextColor(
crText); pFont =
pDC->SelectObject
(&dispFont); void CCustomMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS
) if
(m_iconX) lpMIS->itemWidth = iconX +
tm.tmAveCharWidth * lstrlen(((MENUDATA*)(lpMIS->itemData))->menuText)
+10; void
CCustomMenu::SetIconSize (int width, int
height) void
CCustomMenu::SetTextColor (COLORREF
clrText) void
CCustomMenu::SetBackColor (COLORREF
clrBack) void CCustomMenu::SetHighlightColor (COLORREF
clrHilight) void CCustomMenu::SetHighlightTextColor (COLORREF
clrHilightText)
为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态
自绘菜单
闻怡洋译
设置高亮度颜色。
设置高亮度时的风格。
设置选中时和在普通状态下的菜单显示的图标。
设置显示图标大小。
在CCustomMenu中定义了结构MENUDATA,你必须根据你的需要填充该结构,并且在增加菜单时提供该结构的指针(调用AppendMenu,InsertMenu)。下面是一个例子:
MENUDATA menuData [8]; //
as many menu items are present , You should be able to
use
//new
and do the
same
2、调用CreateMenu()设置有关参数。
m_customMenu.CreateMenu
();
m_customMenu.SetIconSize (25,25);
//This is to set the size of the
Icon.
//
This should be used only once for any
menu
// in order to resize it, destroy
and create the menu again with different
size.
m_customMenu.SetHighlightStyle
(Normal); //Or TextOnly, if you want
the
// background color to remain the
same
// and the Text color to change to
the Highlight
color.
// The
following setXXXColor sets the menu colors. If you dont want to change any, Dont
call these member
functions.
m_customMenu.SetTextColor
(RGB
(255,0,0));
m_customMenu.SetBackColor
(RGB
(255,255,255));
m_customMenu.SetHighlightColor
(RGB
(0,0,255));
3、设置MENUDATA变量,并增加菜单项。
lstrcpy
(menuData[0].menuText ,
"text1");
menuData[0].menuIconNormal=
IDI_ICON1;
m_customMenu.AppendMenu
(MF_OWNERDRAW,3,(LPCTSTR)menuData);
void
CMyView::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT
lpMeasureItemStruct)
{
if
( lpMeasureItemStruct->CtlType == ODT_MENU
&&
IsMenu((HMENU)lpMeasureItemStruct->itemID)
&&
(lpMeasureItemStruct->itemID
== (UINT)m_hMenuSub)
)
{
m_customMenu.MeasureItem
(lpMeasureItemStruct);
}
else
//
let MFC‘s self-drawing handle
it
CView::OnMeasureItem(nIDCtl,
lpMeasureItemStruct);
}
void
SetBackColor (COLORREF);
void
SetHighlightColor (COLORREF);
void
SetIconSize (int, int);
void
SetHighlightStyle (HIGHLIGHTSTYLE ); // HIGHLIGHTSTYLE : enum {Normal,
TextOnly}
void SetHighlightTextColor
(COLORREF);
//*************************************************************************
//
CustomMenu.h : header
file
//
!defined(AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_)
#define
AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_
#pragma once
#endif //
_MSC_VER >= 1000
class
MENUDATA
{
public:
MENUDATA
() { menuIconNormal = -1; menuIconSelected =
-1;};
char
menuText[32];
UINT
menuIconNormal;
UINT
menuIconSelected;
};
//
//
CCustomMenu window
{
//
Construction
public:
CCustomMenu();
public:
public:
// ClassWizard generated
virtual function
overrides
//{{AFX_VIRTUAL(CCustomMenu)
//}}AFX_VIRTUAL
public:
virtual
~CCustomMenu();
virtual void DrawItem(
LPDRAWITEMSTRUCT);
virtual void
MeasureItem( LPMEASUREITEMSTRUCT );
void
SetTextColor (COLORREF );
void
SetBackColor (COLORREF);
void
SetHighlightColor (COLORREF);
void
SetIconSize (int, int);
void
SetHighlightStyle (HIGHLIGHTSTYLE
);
void SetHighlightTextColor
(COLORREF);
protected:
COLORREF
m_crText;
COLORREF
m_clrBack;
COLORREF
m_clrText;
COLORREF
m_clrHilight;
COLORREF
m_clrHilightText;
LOGFONT
m_lf;
CFont
m_fontMenu;
UINT
m_iMenuHeight;
BOOL
m_bLBtnDown;
CBrush
m_brBackground,m_brSelect;
CPen
m_penBack;
int
m_iconX,m_iconY;
HIGHLIGHTSTYLE
m_hilightStyle;
//
NOTE - the ClassWizard will add and remove member functions
here.
//}}AFX_MSG
};
//
// Microsoft Developer
Studio will insert additional declarations immediately before the previous
line.
//
CustomMenu.cpp : implementation file
//
#include "CustomMenu.h"
#define new
DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] =
__FILE__;
#endif
//
//
CCustomMenu
{
m_clrText
= GetSysColor (COLOR_MENUTEXT);
m_clrBack =
GetSysColor
(COLOR_MENU);
m_brBackground.CreateSolidBrush
(m_clrBack);
m_penBack.CreatePen
(PS_SOLID,0,m_clrBack);
m_crText =
m_clrText;
m_bLBtnDown =
FALSE;
m_iconX = GetSystemMetrics (
SM_CXMENUCHECK);
m_iconY = GetSystemMetrics
(SM_CYMENUCHECK );
m_brSelect.CreateSolidBrush
(m_clrHilight);
m_clrHilightText = GetSysColor
(COLOR_HIGHLIGHTTEXT);
NONCLIENTMETRICS
nm;
nm.cbSize = sizeof
(NONCLIENTMETRICS);
VERIFY (SystemParametersInfo
(SPI_GETNONCLIENTMETRICS,0,&nm,0));
m_iMenuHeight =
nm.iMenuHeight;
m_fontMenu.CreateFontIndirect
(&m_lf);
}
{
if
((HBRUSH) m_brBackground !=
NULL)
m_brBackground.DeleteObject
();
if ((HFONT)m_fontMenu
!=NULL)
m_fontMenu.DeleteObject
();
if ((HBRUSH)m_brSelect !=
NULL)
m_brSelect.DeleteObject
();
}
//
//
CCustomMenu message handlers
void CCustomMenu::DrawItem
(LPDRAWITEMSTRUCT lpDIS)
{
ASSERT(lpDIS !=
NULL);
CRect
rect;
HICON
hIcon;
COLORREF crText =
m_crText;
// draw the colored rectangle
portion
rect.CopyRect(&lpDIS->rcItem);
UINT state =
lpDIS->itemState;
CString
strText;
LOGFONT lf;
lf =
m_lf;
CFont
*pFont;
//GetWindowText(strText);
if
(lpDIS->itemData !=
NULL)
{
strText
= (((MENUDATA*)
(lpDIS->itemData))->menuText);
if
((((MENUDATA *)(lpDIS->itemData))->menuIconNormal) ==
-1)
hIcon
= NULL;
else if (state &
ODS_SELECTED)
{
if
((((MENUDATA *)(lpDIS->itemData))->menuIconSelected) !=
-1)
hIcon
= AfxGetApp ()->LoadIcon (((MENUDATA
*)(lpDIS->itemData))->menuIconSelected);
else
hIcon
= AfxGetApp()->LoadIcon
(((MENUDATA*)(lpDIS->itemData))->menuIconNormal);
}
else
hIcon
= AfxGetApp()->LoadIcon
(((MENUDATA*)(lpDIS->itemData))->menuIconNormal);
}
else
{
strText.Empty();
hIcon
= NULL;
}
{
//
draw the down edges
if (m_hilightStyle !=
Normal)
{
pDC->FillRect
(rect,&m_brBackground);
}
else
{
pDC->FillRect
(rect,&m_brSelect);
}
pDC->Draw3dRect
(rect,GetSysColor
(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
lf.lfWeight
= FW_BOLD;
if
((HFONT)dispFont !=
NULL)
dispFont.DeleteObject
();
dispFont.CreateFontIndirect
(&lf);
crText =
m_clrHilightText;
TRACE0
("SELECT,SELECTED\n");
}
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
}
//We have to paint the text
only if the image is nonexistant
if (hIcon !=
NULL)
{
if(DrawIconEx
(pDC->GetSafeHdc(),rect.left,rect.top,hIcon,
(m_iconX)?m_iconX:32,(m_iconY)?m_iconY:32,0,NULL,DI_NORMAL))
TRACE0("Wrote
the icon
successfully\n");
else
TRACE0
("SORRY.NOGO\n");
}
//This
is needed always so that we can have the space for check
marks
rect.left = rect.left
+((m_iconX)?m_iconX:32);
{
//
pFont->GetLogFont
(&lf);
TRACE1(
"About To DrawText
%s\n",strText);
pDC->DrawText
(strText,rect,DT_LEFT|DT_SINGLELINE|DT_VCENTER);
TRACE0("Done\n");
pDC->SetBkMode(
iOldMode
);
pDC->SelectObject
(pFont); //set it to the old
font
}
dispFont.DeleteObject
();
}
{
CDC *pDC =
AfxGetApp()->m_pMainWnd->GetDC();
CFont* pFont
= pDC->SelectObject (&m_fontMenu);
int iconX =
0,iconY= 0;
TEXTMETRIC
tm;
pDC->GetTextMetrics
(&tm);
pDC->SelectObject
(pFont);
AfxGetApp()->m_pMainWnd->ReleaseDC
(pDC);
iconX =
m_iconX;
if
(m_iconY)
iconY =
m_iconY;
lpMIS->itemHeight = (iconY >
(m_iMenuHeight+1))?iconY:m_iMenuHeight + 1;
}
{
m_iconX =
width;
m_iconY = height;
}
{
m_crText = clrText;
}
{
m_clrBack =
clrBack;
if ((HBRUSH)m_brBackground !=
NULL)
m_brBackground.DeleteObject
();
m_brBackground.CreateSolidBrush
(clrBack);
}
{
m_clrHilight =
clrHilight;
if ((HBRUSH)m_brSelect !=
NULL)
m_brSelect.DeleteObject
();
m_brSelect.CreateSolidBrush
(clrHilight);
}
{
m_clrHilightText =
clrHilightText;
}
void CCustomMenu::SetHighlightStyle
(HIGHLIGHTSTYLE hilightStyle)
{
m_hilightStyle =
hilightStyle;
}