分类:
2009-11-13 11:14:07
单击右键弹出菜单
0397 单击右键弹出菜单
在应用程序中单击右键弹出菜单可以方便用户的操作,要实现右键弹出菜单需要调用CMenu类的TrackPopupMenu方法,该方法用于显示一个弹出式菜单。如图6.38所示。
程序代码如下:
void CPopupMenuDlg::On
{
CMenu* pPopup = m_Menu.GetSubMenu(0);
CRect rc;
ClientToScreen(&point);
rc.top = point.x;
rc.left = point.y;
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
rc.top,rc.left,this,&rc);
CDialog::On
}
图6.38 单击右键弹出菜单
0398 可以下拉的菜单
在使用Word等程序时,会发现一些不常用的菜单都被隐藏了,取而代之的是一个下箭头“︾”,单击这个菜单项后会显示出那些被隐藏的菜单。通过DeleteMenu方法和InsertMenu方法来动态删除和添加菜单,从而实现这个功能。如图6.39和图6.40所示。
图6.39 初始时显示菜单 图6.40 下拉后的菜单
程序代码如下:
void CDownMenuDlg::On
{
CMenu* m_pMenu;
m_pMenu = m_Menu.GetSubMenu(0);
m_pMenu->DeleteMenu(3,MF_BYPOSITION);
m_pMenu->InsertMenu(3,MF_BYPOSITION,10001,"复制");
m_pMenu->InsertMenu(4,MF_BYPOSITION,10002,"粘贴");
m_pMenu->InsertMenu(5,MF_BYPOSITION,10003,"打印");
SetMenu(&m_Menu);
}
0399 任务栏托盘弹出菜单
要设计任务栏托盘菜单,需要使用Shell_NotifyIcon函数和NOTIFYICONDATA结构来实现。如图6.41所示。
图6.41 任务栏托盘弹出菜单
程序代码如下:
BOOL CSysSalverDlg::On
{
…… //此处代码省略
m_Menu.LoadMenu(IDR_MENU1);
//添加系统托盘
char lpszTip[]="明日科技";
NOTIFYICONDATA da
da
da
lstrcpyn(da
da
da
da
da
Shell_NotifyIcon(NIM_ADD,&da
return TRUE;
}
void CSysSalverDlg::On
{
UINT uMouseMsg=(UINT) lParam;
if(uMouseMsg==WM_RBUTTONDOWN)
{
CMenu* pPopup = m_Menu.GetSubMenu(0);
CPoint point;
GetCursorPos(&point);
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_VERTICAL,
point.x,point.y,AfxGetApp()->m_pMainWnd,TPM_LEFTALIGN);
}
}
void CSysSalverDlg::On
{
if(MessageBox("确定要退出吗?","系统提示",MB_OKCANCEL|MB_ICONQUESTION)!=1)
return;
CDialog::On
}
void CSysSalverDlg::On
{
CDialog::On
NOTIFYICONDATA da
da
da
Shell_NotifyIcon(NIM_DELETE,&da
}
0400 绘制渐变效果的菜单
如今的许多应用软件都具有漂亮的菜单。在Visual C++中,如何设计这些菜单呢?本例中设计了一个渐变效果的菜单,效果如图6.42所示。
图6.42 绘制渐变效果的菜单
实现菜单的绘制,需要改写CMenu类的DrawItem方法和MeasureItem方法,在DrawItem方法中根据菜单项的当前状态绘制菜单,在MeasureItem方法中根据菜单项的文本设置菜单项的大小。程序主要代码如下:
//菜单类的声明
struct CMenuItemInfo
{
CString m_ItemText; //菜单项文本
int m_ItemID; //菜单标记 -2顶层菜单,-1弹出式菜单,0分隔条,其他普通菜单
};
class CMyMenu : public CMenu
{
public:
CMyMenu();
virtual ~CMyMenu();
CMenuItemInfo m_ItemLists[MAX_MENUCOUNT]; //菜单项信息
int m_index; //临时索引
int m_iconindex; //菜单项图标索引
BOOL ChangeMenuItem(CMenu* m_menu,BOOL m_Toped = FALSE);
BOOL AttatchMenu(UINT m_uID);
void DrawItemText(CDC* m_pdc,LPSTR str,CRect m_rect);
void DrawTopMenu(CDC* m_pdc,CRect m_rect,BOOL m_selected = FALSE); //绘制顶层菜单
void DrawSeparater(CDC* m_pdc,CRect m_rect);//绘制分隔条
void DrawComMenu(CDC* m_pdc,CRect m_rect,COLORREF m_fromcolor,COLORREF m_tocolor, BOOL m_selected = FALSE);
//override memu's virtual method
virtual void MeasureItem( LPMEASUREITEMSTRUCT lpStruct ); //设置菜单项大小
virtual void DrawItem( LPDRAWITEMSTRUCT lpStruct ); //重绘菜单项
};
//菜单类的实现
CMyMenu::CMyMenu()
{
m_index= 0;
}
CMyMenu::~CMyMenu()
{
}
BOOL CMyMenu::AttatchMenu(UINT m_uID)
{
this->LoadMenu(m_uID);
return TRUE;
}
BOOL CMyMenu::ChangeMenuItem(CMenu* m_menu,BOOL m_Toped)
{
if (m_menu != NULL)
{
int m_itemcount = m_menu->GetMenuItemCount();
for (int i=0;i
{
m_menu->GetMenuString(i,m_ItemLists[m_index].m_ItemText,MF_BYPOSITION);
int m_itemID = m_menu->GetMenuItemID(i);
if (m_itemID==-1 && m_Toped)
{
m_itemID = -2;//顶层菜单
};
m_ItemLists[m_index].m_ItemID = m_itemID;
m_menu->ModifyMenu(i,MF_OWNERDRAW|MF_BYPOSITION |MF_STRING,m_ItemLists[m_index].m_ItemID,(LPSTR)&(m_ItemLists[m_index]));
m_index+=1;
CMenu* m_subMenu = m_menu->GetSubMenu(i);
if (m_subMenu)
{
ChangeMenuItem(m_subMenu);
}
}
}
return TRUE ;
}
void CMyMenu::MeasureItem( LPMEASUREITEMSTRUCT lpStruct )
{
if (lpStruct->CtlType==ODT_MENU)
{
lpStruct->itemHeight = ITEMHEIGHT;
lpStruct->itemWidth = ITEMWIDTH;
CMenuItemInfo* m_iteminfo;
m_iteminfo = (CMenuItemInfo*)lpStruct->itemData;
lpStruct->itemWidth =
((CMenuItemInfo*)lpStruct->itemData)->m_ItemText.GetLength()*10;
switch(m_iteminfo->m_ItemID)
{
case 0: //分隔条
{
lpStruct->itemHeight = 1;
break;
}
}
}
}
void CMyMenu::DrawItem( LPDRAWITEMSTRUCT lpStruct )
{
if (lpStruct->CtlType==ODT_MENU)
{
if(lpStruct->itemData == NULL) return;
unsigned int m_state = lpStruct->itemState;
CDC* m_dc = CDC::FromHandle(lpStruct->hDC);
CString str = ((CMenuItemInfo*)(lpStruct->itemData))->m_ItemText;
LPSTR m_str = str.GetBuffer(str.GetLength());
int m_itemID = ((CMenuItemInfo*)(lpStruct->itemData))->m_ItemID;
CRect m_rect = lpStruct->rcItem;
m_dc->SetBkMode(TRANSPARENT);
switch(m_itemID)
{
case -2:
{
DrawTopMenu(m_dc,m_rect,(m_state&ODS_SELECTED)||(m_state&0x0040)); //0x0040 ==ODS_HOTLIGHT
DrawItemText(m_dc,m_str,m_rect);
break;
}
case -1:
{
DrawItemText(m_dc,m_str,m_rect);
break;
}
case 0:
{
DrawSeparater(m_dc,m_rect);
break;
}
default:
{
DrawComMenu(m_dc,m_rect,0xfaa0,0xf00ff,m_state&ODS_SELECTED);
DrawItemText(m_dc,m_str,m_rect);
break;
}
}
}
}
void CMyMenu::DrawItemText(CDC* m_pdc,LPSTR str,CRect m_rect)
{
m_rect.DeflateRect(20,0);
m_pdc->DrawText(str,m_rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);
}
void CMyMenu::DrawTopMenu(CDC* m_pdc,CRect m_rect,BOOL m_selected )
{
if (m_selected)
{
m_pdc->SelectStockObject(BLACK_PEN);
m_pdc->Rectangle(&m_rect);
m_rect.DeflateRect(1,1);
m_pdc->FillSolidRect(m_rect,RGB(150, 185, 255));
}
else
{
CRect rect;
AfxGetMainWnd()->GetClientRect(rect);
rect.top = m_rect.top;
rect.bottom = m_rect.bottom;
rect.left= 350;
rect.right +=4;
m_pdc->FillSolidRect(&rect,RGB(192,192, 192));
m_pdc->FillSolidRect(&m_rect,RGB(192,192, 192));
}
}
void CMyMenu::DrawSeparater(CDC* m_pdc,CRect m_rect)
{
if (m_pdc != NULL)
{
m_pdc->Draw3dRect(m_rect,RGB(255,0,0),RGB(0,0,255));
}
}
void CMyMenu::DrawComMenu(CDC* m_pdc,CRect m_rect,COLORREF m_fromcolor,COLORREF m_tocolor, BOOL m_selected )
{
if (m_selected)
{
m_pdc->Rectangle(m_rect);
m_rect.DeflateRect(1,1);
int r1,g1,b1;
//读取渐变起点的颜色值
r1 = GetRValue(m_fromcolor);
g1 = GetGValue(m_fromcolor);
b1 = GetBValue(m_fromcolor);
int r2,g2,b2;
//读取渐变终点的颜色值
r2 = GetRValue(m_tocolor);
g2 = GetGValue(m_tocolor);
b2 = GetBValue(m_tocolor);
float r3,g3,b3;
r3 = ((float)(r2-r1)) / (float)(m_rect.Height());
g3 = (float)(g2-g1)/(float)(m_rect.Height());
b3 = (float)(b2-b1)/(float)(m_rect.Height());
COLORREF r,g,b;
CPen* m_oldpen ;
for (int i = m_rect.top;i
{
r = r1+(int)r3*(i-m_rect.top);
g = g1+(int)g3*(i-m_rect.top);
b = b1+ (int)b3*(i-m_rect.top);
CPen m_pen (PS_SOLID,1,RGB(r,g,b));
m_oldpen = m_pdc->SelectObject(&m_pen);
m_pdc->MoveTo(m_rect.left,i);
m_pdc->LineTo(m_rect.right,i);
}
m_pdc->SelectObject(m_oldpen);
}
else
{
m_pdc->FillSolidRect(m_rect,RGB(0x000000F9, 0x000000F8, 0x000000F7));
}
}
0401 将菜单项的字体设置为粗体
在设计应用程序时,有时需要修改菜单项的字体。在程序中可以使用SystemParametersInfo函数来设置菜单项的字体信息。该函数语法如下:
BOOL SystemParametersInfo(UINT uiAction, UINT uiParam,PVOID pvParam,UINT fWinIni );
参数说明如下。
l uiAction:表示函数执行的动作,如果为SPI_SETNONCLIENTMETRICS,表示这种窗口非客户区域的信息。
l uiParam:该参数的含义依赖于uiAction参数。
l pvParam:表示设置的参数信息。
l fWinIni:表示是否更新用户窗口。
程序主要代码如下:
//获取
NONCLIENTMETRICS info;
info.cbSize =sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS),&info,0);
info.lfMenuFont.lfWeight = 700;
SystemParametersInfo(SPI_SETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS),
&info,SPIF_SENDCHANGE);