日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MFC菜单栏(CMenu)控件

發布時間:2023/12/18 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MFC菜单栏(CMenu)控件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.設置菜單左邊顯示位圖和背景位圖

CMenu類里要了解的函數

SetMenuItemBitmaps//設置菜單項左邊的位圖

函數定義:BOOL SetMenuItemBitmaps( UINT nPosition, UINT nFlags, const CBitmap* pBmpUnchecked, const CBitmap* pBmpChecked );
nPostion指明具體要設置的菜單項,可以是菜單項索引,菜單項ID,具體由nFlags參數指明,為MF_BYPOSITION,則以菜單項索引指明,

為MF_BYCOMMAND則第一個參數nPosition是菜單項ID號。pBmpUnchecked未被檢測時顯示的位圖(正常時),pBmpChecked檢測時顯示的圖片(就是菜單項被打上勾時所顯示的圖片,跟CheckMenuItem函數有關聯)

一個API函數SetMenuInfo,這個函數可以設置菜單重繪時選擇的填充畫刷類型,該函數有兩個參數,第一個是要設置的菜單句柄,第二個是一個MENUINFO結構指針,我們只要了解這結構里有一個成員hbrBack就行了,hbrBack是一個畫刷句柄,而菜單背景位圖就通過創建位圖畫刷來實現的。

好了,以上面的工程為例,引入三張位圖,ID號默認不變,然后再引入一張位圖(菜單背景位圖,ID:IDB_MENUBACK),接著在對話框類的OnInitDialog函數里添加如下語句:

CMenu *pMenu=GetMenu();//獲取對話框關聯菜單
?CMenu *pSubMenu=pMenu->GetSubMenu(0);//獲得子菜單(如果有)0表示索引,對應“文件”菜單
?for(int i=0;i<3;i++)
?{
?????CBitmap bmp;
?????bmp.LoadBitmap(IDB_BITMAP1+i);
??pSubMenu->SetMenuItemBitmaps(i,MF_BYPOSITION,&bmp,&bmp);
??bmp.Detach();
?}
?CBitmap bmp;
?CBrush m_BKBrush;
?bmp.LoadBitmap(IDB_MENUBACK);
?m_BKBrush.CreatePatternBrush(&bmp);//創建位圖畫刷
?MENUINFO mnInfo;
?memset(&mnInfo,0,sizeof(MENUINFO));
?mnInfo.cbSize=sizeof(MENUINFO);
?mnInfo.fMask=MIM_BACKGROUND;
?mnInfo.hbrBack=m_BKBrush;
?::SetMenuInfo(pSubMenu->m_hMenu,&mnInfo);
????m_BKBrush.Detach();

運行效果如下圖:

(PS:不知道大家有沒有碰到過這個問題,MENUINFO結構未定義,解決的方法是進入文件選項卡(FileView),在Source??File文件下的StdAfx.cpp文件里的最前面部分添加這個語句:#define??WINVER 0x0501)

2.設計彈出式菜單

?CMenu類里要了解的函數:

TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd,LPCRECT lpRect = NULL );
該函數用于在界面顯示菜單,nFlags參數指明菜單顯示標志,x,y用于確定菜單顯示基于的坐標點,pWnd是菜單相關聯的窗口。

在“MFC類庫詳解”中有關參數nFlags的解釋如下:

指定屏幕位置標志或鼠標鍵標志。
屏幕位置標志可以為下列值之一: · TPM_CENTERALIGN 使彈出菜單在水平方向相對于x指定的坐標居中。 · TPM_LEFTALIGN 放置彈出菜單,以便彈出菜單在由坐標值x指定的位置左對齊。 · TPM_RIGHTALIGN 放置彈出菜單,以便彈出菜單在由坐標值x指定的位置右對齊。?
鼠標鍵標志可以為下列值之一: · TPM_LEFTBUTTON 導致彈出菜單追蹤鼠標左鍵。 · TPM_RIGHTBUTTON 導致彈出菜單追蹤鼠標右鍵。

以上面工程為例,給對話框添加鼠標右鍵抬起(WM_RBUTTONUP)消息處理函數,在函數里添加如下代碼:
void CSeventhDlg::OnRButtonUp(UINT nFlags, CPoint point)
{
?// TODO: Add your message handler code here and/or call default
?CMenu *Menu=GetMenu();
?ClientToScreen(&point);//將窗口坐標轉換成屏幕坐標
?Menu->GetSubMenu(0)->TrackPopupMenu(
??TPM_LEFTBUTTON|TPM_VERTICAL,point.x,point.y,this);
?Menu->Detach();
?CDialog::OnRButtonUp(nFlags, point);
}
要注意的是,要在界面顯示的菜單,必須是一個彈出菜單,雖然Menu->TrackPopupMenu也可以顯示,但顯然不是想要的結果。

運行效果:

3.動態(純代碼)創建一個菜單
上面的例子,都是使用了菜單資源創建的菜單,這一次我們用代碼來創建菜單,其實本質跟前面的用控件類的Create函數創建一個控件一樣。只不過這里的“Create”函數是CreateMenu和CreatePopupMenu函數。

CMenu類里要了解的函數:

CreateMenu //創建一個主菜單,函數沒有參數

CreatePopupMenu//創建一個具有彈出屬性的菜單,函數沒有參數

AppendMenu//往一個菜單里添加菜單項,或彈出式菜單

AppendMenu函數定義如下:

BOOL AppendMenu( UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL );
nFlags參數常用取值如下:

?MF_STRING 表明添加的是一個不具有彈出屬性的菜單項。

MF_POPUP 添加的一個彈出菜單項

MF_SEPARATOR 添加的是一個菜單分隔條

MF_OWNERDRAW??表明對應菜單具有自繪屬性

nIDNewItem參數,如果添加的是一個不具有彈出屬性的菜單項,那么該值就是菜單項ID號,否則是彈出式菜單句柄,lpszNewItem是菜單項名稱(菜單文本內容)

好了,接著我們來動態創建一個菜單,首先往對話框里添加一個按鈕控件,當單擊這個按鈕時,就創建菜單,響應這個按鈕控件的單擊消息,消息處理函數里添加如下代碼:

CMenu Menu;
??Menu.CreateMenu();//創建一個主菜單
??CMenu popMenu;
??popMenu.CreatePopupMenu();//創建一個彈出式菜單
??popMenu.AppendMenu(MF_STRING,1001,"新建");//添加菜單項
??popMenu.AppendMenu(MF_STRING,1002,"打開");
??popMenu.AppendMenu(MF_STRING,1003,"保存");
??Menu.AppendMenu(MF_POPUP,(UINT)popMenu.m_hMenu,"文件");//添加彈出菜單項
??SetMenu(&Menu);//關聯到窗口中
??Menu.Detach();
??popMenu.Detach();

4.更改菜單項大小(寬高),設置菜單文本字體大小

由于CMenu類里并沒有提供設置菜單項大小以及字體大小的函數,所以我們如果要實現上述功能的話,只能采取自繪的方法。

如果對CMenu類的某些函數不了解的話,可以參考"MFC 類大全",這里就不講述了

首先從CMenu派生出一個子類CNewMenu(類的類型為Generic Class),然后往這個類添加三個成員函數,MeasureItem(設置菜單寬高),

DrawItem(自繪菜單),ChangeMenuItem(修改菜單項類型)

三個函數分別定義如下:

void CNewMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)

void CNewMenu::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)

void CNewMenu::ChangeMenuItem(CMenu *pMenu)

其中MeasureItem和DrawItem是CMenu類的虛函數。

各函數的代碼如下:

void CNewMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
?lpMeasureItemStruct->itemHeight=25;//項高
?lpMeasureItemStruct->itemWidth=120;//項寬
}

void CNewMenu::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
?CRect rect=lpDrawItemStruct->rcItem;
?CDC dc;
?dc.Attach(lpDrawItemStruct->hDC);
?dc.FillSolidRect(rect,RGB(0,166,170));
?CFont Font;
?Font.CreatePointFont(125,"宋體");//創建字體
?dc.SelectObject(&Font);
?CString *pText=(CString *)lpDrawItemStruct->itemData;
?if(lpDrawItemStruct->itemState&ODS_SELECTED)
???dc.FillSolidRect(rect,RGB(80,89,202));//菜單被選中
?dc.SetTextColor(RGB(10,0,181));//設置文本顏色
?dc.DrawText(*pText,rect,DT_VCENTER|DT_LEFT|DT_SINGLELINE);
?dc.Detach();

}

void CNewMenu::ChangeMenuItem(CMenu *pMenu)
{
int itemCount=pMenu->GetMenuItemCount();
for(int i=0;i<itemCount;i++)
{
????CString *pText=new CString;
?UINT itemID=pMenu->GetMenuItemID(i);//獲取菜單項ID號
?pMenu->GetMenuString(i,*pText,MF_BYPOSITION);//獲取菜單文本

//ModifyMenu函數最后一個參數對應DRAWITEMSTRUCT結構里的itemData變量
?pMenu->ModifyMenu(i,MF_OWNERDRAW|MF_BYPOSITION|MF_STRING,itemID,(LPSTR)pText);
??if(itemID==-1)//如果是一個彈出式菜單
?{
??ChangeMenuItem(pMenu->GetSubMenu(i));
?}
}??
}
必須讓每個菜單項具有MF_OWNERDRAW屬性,不然接不到WM_MEASUREITEM和WM_DRAWITEM消息,而且菜單項不具有MF_OWNERDRAW屬性, 即使接到消息,也無法自繪,所以上面的ChangeMenuItem函數就是用于修改菜單項屬性
WM_MEASUREITEM和WM_DRAWITEM消息不是直接發給菜單窗口的,會被父窗口給收到,所以得處理父窗口的WM_MEASUREITEM和WM_DRAWITEM消息,給話框類添加這兩個消息處理函數,兩個函數里的代碼分別如下:

void CFirstDlg::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
?// TODO: Add your message handler code here and/or call default
?????if(lpMeasureItemStruct->CtlType==ODT_MENU)//如果類型是菜單
???????newMenu.MeasureItem(lpMeasureItemStruct);//調用CNewMenu類的MeasureItem成員函數
???????else
????CDialog::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
??
}

void CFirstDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
?// TODO: Add your message handler code here and/or call default
?if(lpDrawItemStruct->CtlType==ODT_MENU)
??newMenu.DrawItem(lpDrawItemStruct);
?else
?CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
}

接著我們在對話類添加一個成員變量:

CNewMenu newMenu; (記得要包含頭文件:"NewMenu.h"),然后在對話框類的OnInitDialog函數添加如下代碼:

?newMenu.LoadMenu(IDR_MENU1);
?SetMenu(&newMenu);
?//只更改下主菜單下的第一項,更改全部:newMenu.ChangeMenuItem(&newMenu);
?newMenu.ChangeMenuItem(newMenu.GetSubMenu(0));

IDR_MENU1是菜單資源的ID號,可自行創建。好了,到了這里大功已經告成了,點編譯運行,效果如下:

跟自繪按鈕控件一樣,上面依然沒處理菜單的所有狀態,如獲得焦點,被核記,有無關聯圖片。也不處理菜單分隔條。。
如果想處理這些狀態的話。建議查看DRAWITEMSTRUCT結構的itemState變量,這個成員指明菜單項的狀態,
關聯圖片,就查看CMenu類的函數。。。



原文:https://blog.csdn.net/lanmeng_smile/article/details/26285705?
?

總結

以上是生活随笔為你收集整理的MFC菜单栏(CMenu)控件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。