論壇中有人曾經問過這樣的問題:如何在C++/MFC程序中實現類似IE工具欄中帶下拉箭頭的按鈕,如圖一所示:
圖一 IE工具欄中帶下拉箭頭的按鈕
本文將告訴你如何實現,方法其實很簡單:
1、新建一個MFC/SDI工程,一路都取默認的設置。
2、在mainframe.cpp文件中找到 CMainFrame::OnCreate()框架窗口創建函數。在末尾添加如下代碼行:
DWORD dwExStyle = TBSTYLE_EX_DRAWDDARROWS;
m_wndToolBar.GetToolBarCtrl().SendMessage(TB_SETEXTENDEDSTYLE, 0, (LPARAM)dwExStyle);
這兩行代碼的作用是讓工具欄具有處理下拉箭頭的能力,接著要用SetButtonStyle()方法在選定的地方添加下拉箭頭按鈕,在例子程序裡,下拉箭頭按鈕是加在了文件打開菜單上:
DWORD dwStyle = m_wndToolBar.GetButtonStyle(m_wndToolBar.CommandToIndex(ID_FILE_OPEN));
dwStyle |= TBSTYLE_DROPDOWN;
m_wndToolBar.SetButtonStyle(m_wndToolBar.CommandToIndex(ID_FILE_OPEN), dwStyle);
加了上述代碼行之後,編譯一次程序,然後運行程序,你就可以看到下拉箭頭了。但此時還不能操作。
3、接下來要做的事情是添加下拉箭頭的消息處理代碼以及程序要用的菜單資源。現在假設你已經創建了菜單資源,且假設這個菜單的資源ID是IDR_MENU1。如圖二所示。
圖二 新創建的菜單資源IDR_MENU1
在CMainFrame類的消息映射中加入下拉箭頭的TBN_DROPDOWN消息映射:
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
...
ON_NOTIFY(TBN_DROPDOWN, AFX_IDW_TOOLBAR, OnToolbarDropDown)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
4、在MainFrame.h頭文件中加入消息處理函數的聲明:
//{{AFX_MSG(CMainFrame)
...
afx_msg void OnToolbarDropDown(NMTOOLBAR* pnmh, LRESULT* plRes);
//}}AFX_MSG
5、在MainFrame.cpp文件中加入TBN_DROPDOWN消息處理的實現代碼:
void CMainFrame::OnToolbarDropDown(NMTOOLBAR* pnmtb, LRESULT *plr)
{
CWnd *pWnd;
UINT nID;
// Switch on button command id''s.
switch (pnmtb->iItem)
{
case ID_FILE_OPEN:
pWnd = &m_wndToolBar;
nID = IDR_MENU1;
break;
default:
return;
}
// load and display popup menu
CMenu menu;
menu.LoadMenu(nID);
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup);
CRect rc;
pWnd->SendMessage(TB_GETRECT, pnmtb->iItem, (LPARAM)&rc);
pWnd->ClientToScreen(&rc);
pPopup->TrackPopupMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
rc.left, rc.bottom, this, &rc);
}
6、前面第三步創建的菜單資源裡有三個菜單命令,“最近打開的文件”、“打開關於對話框”、“VC知識庫主頁”。它們對應的菜單ID為:ID_FILE_MRU_FILE1、ID_APP_ABOUT、ID_VCKBASE_HOME,前兩個ID都是MFC默認的菜單,它們調用的命令函數在例子程序中也是MFC自動創建和調用的。ID_VCKBASE_HOME菜單項在例子程序中是通過ClassView關聯到視圖類進行處理的,用戶選擇這個菜單項時調用OnGotoVckbaseHomePage():
void CMyView::OnGotoVckbaseHomePage()
{
// TODO: Add your command handler code here
ShellExecute(NULL,"open","http://www.vckbase.com",NULL,NULL,SW_SHOWNORMAL);
}
它打開默認的浏覽器並訪問VC知識庫主頁。
好了,現在編譯並運行程序吧。下面是例子程序運行畫面(圖三):
圖三 例子程序運行畫面
注意本文提供源代碼僅僅只是個例子程序,在現實的軟件設計和編程行為中,沒有誰會在“打開文件”功能菜單裡加入什麼“打開關於對話框”和“VC知識庫主頁”之類的菜單命令。這有悖於Windows程序的UI規則。