第 4章 菜单、快捷键和控制条内容摘要:
1,菜单
2,快捷菜单
3,动态生成菜单
4,工具条
5,状态条返回目录
4.1 菜单学习目标
1,响应菜单消息
2,控制菜单状态
3,使用快捷键
4.1
返回第 4章程序的实现步骤
1,利用 AppWizard生成程序框架 (MenuTest)
2,编辑资源
3,加入菜单消息处理函数
4,菜单命令的更新控制
4.1
步骤 1 生成程序框架 (MenuTest)
1,项目名称,MenuTest
2,选择单文档界面应用程序( Single document)
4.1
步骤 2 编辑资源
1.编辑菜单资源画图 Pop-up 选中
Caption ID Prompt
矩形 (&R)\tCtrl+R ID_DRAW_RECT 在视中画矩形椭圆 (&C)\tAlt+C ID_DRAW_CIRCLE 在视中画椭圆
2.编辑快捷键资源
ID Modifiers Key
ID_DRAW_RECT Ctrl R
ID_DRAW_CIRCL Alt C
4.1
步骤 3 加入菜单消息处理函数
Class Name Objects IDs Messages
1,CMenuTestView ID_DRAW_RECT COMMAND
2,CMenuTestView ID_DRAW_ CIRCLE COMMAND
4.1
void CMenuTestView::OnDrawRect()
{
CClientDC dc(this);
dc.Rectangle(50,50,200,150);
}
void CMenuTestView::OnDrawCircle()
{
CClientDC dc(this);
dc.Ellipse(250,50,400,150);
}
步骤 4 菜单命令的更新控制
1,在画图 菜单中再添加两个菜单项
Caption ID Prompt
允许画矩形 ID_DRAW_ENABLE --------
禁止画矩形 ID_DRAW_DISABLE --------
2,在视类中添加一个记录当前“矩形”菜单项状态的变量
BOOL m_Enable;
3,在构造函数中初始化数据成员 m_Enable
m_ Enable =TRUE;
4.1
步骤 4 菜单命令的更新控制
4,添加 菜单响应函数
Class Name Objects IDs Messages
1,CMenuTestView ID_DRAW_ENABLE COMMAND
2,CMenuTestView ID_DRAW_ DISABLE COMMAND
3,CMenuTestView ID_DRAW_RECT UPDATE_COMMAND_UI
4,CMenuTestView ID_DRAW_ENABLE UPDATE_COMMAND_UI
5,CMenuTestView ID_DRAW_ DISABLE UPDATE_COMMAND_UI
4.1
void CMenuTestView::OnUpdateDrawRect(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_Enable);
}
步骤 4 菜单命令的更新控制 4.1
void CMenuTestView::OnDrawDisable()
{
m_Enable = FALSE;
}
void CMenuTestView::OnDrawEnable()
{
m_Enable = TRUE;
}
void CMenuTestView::OnUpdateDrawEnable(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_Enable? 1:0);
}
void CMenuTestView::OnUpdateDrawDisable(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_Enable? 0:1);
}
基本知识
1,pCmdUI->Enable(true | false);
2,pCmdUI->SetCheck( 1| 0);
3,使用 COMMAND消息响应菜单项的选择事件
4,UPDATE_COMMAND_UI消息控制菜使用单项状态
4.1
4.2 快捷菜单学习目标
1,实现快捷菜单
4.2
返回第 4章程序的实现步骤
1,编辑快捷菜单资源
2,显示跟踪菜单
3,添加菜单响应函数
4,实现对话框功能
4.2
步骤 1 编辑快捷菜单资源添加菜单 (IDR_POPUP_MENU )
Popup1 选中 Pop-up
Caption ID
编辑矩形坐标 ID_EDIT_RECT
编辑椭圆坐标 ID_EDIT_CIRCLE
4.2
步骤 2 显示快捷菜单添加响应函数
Class Name ObjectsIDs Messages
CMainFrame CMainFrame WM_CONTEXTMENU
4.2
void CMainFrame::OnContextMenu(CWnd* pWnd,CPoint point)
{
// TODO,Add your message handler code here
CMenu menu;
if(menu.LoadMenu(IDR_POPUP_MENU))
{
CMenu *pPopup=menu.GetSubMenu(0);
pPopup->TrackPopupMenu
(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);
}
}
步骤 2 显示快捷菜单
4.2
步骤 3 添加菜单消息处理函数
(1) 编辑对话框资源静态文本框,IDC_STATIC,左上角坐标 ( X1,Y1)
静态文本框,IDC_STATIC,右下角坐标 ( X2,Y2)
编辑框,IDC_EDIT_X1
编辑框,IDC_EDIT_Y1
编辑框,IDC_EDIT_X2
编辑框,IDC_EDIT_Y2
按扭控件,IDOK,确定按扭控件,IDCANCEL,取消
4.2
步骤 3 添加菜单消息处理函数
(2)为对话框添加控件关联变量
IDC_EDIT_X1,int,m_nX1
IDC_EDIT_Y1,int,m_nX1
IDC_EDIT_X2,int,m_nX1
IDC_EDIT_Y2,int,m_nX1
(3)在主框架中加入变量并初始化
int m_nRectLeft;
int m_nRectTop;
int m_nRectRight;
int m_nRectBottom;
int m_nCircleLeft;
int m_nCircleTop;
int m_nCircleRight;
int m_nCircleBottom;
4.2
CMainFrame::CMainFrame()
{
// TODO,add member initialization code here
m_nRectLeft = 50;
m_nRectTop = 50;
m_nRectRight = 200;
m_nRectBottom = 150;
m_nCircleLeft = 50;
m_nCircleTop = 50;
m_nCircleRight = 200;
m_nCircleBottom = 150;
}
步骤 3 添加菜单消息处理函数
4.2
void CMenuTestView::OnDrawRect()
{
CMainFrame *pMainFrame = (CMainFrame *) AfxGetApp()->GetMainWnd();
CClientDC dc(this);
dc.Rectangle(pMainFrame->m_nRectLeft,pMainFrame->m_nRectTop,
pMainFrame->m_nRectRight,pMainFrame->m_nRectBottom);
}
void CMenuTestView::OnDrawCircle()
{
CMainFrame *pMainFrame = (CMainFrame *) AfxGetApp()->GetMainWnd();
CClientDC dc(this);
dc.Ellipse(pMainFrame->m_nCircleLeft,pMainFrame->m_nCircleTop,
pMainFrame->m_nCircleRight,pMainFrame->m_nCircleBottom);
}
步骤 3 添加菜单消息处理函数
(4) 修改画图函数
4.2
步骤 3 添加菜单消息处理函数
(5)加入菜单消息处理函数
void CMenuTestView::OnEditRect()
{
CDlgEdit dlg(1);
dlg.DoModal();
}
void CMenuTestView::OnEditCircle()
{
CDlgEdit dlg(2);
dlg.DoModal();
}
4.2
步骤 4 实现对话框功能
( 1)修改构造函数
CDlgEdit::CDlgEdit(int type,CWnd* pParent /*=NULL*/)
,CDialog(CDlgEdit::IDD,pParent)
{
//{{AFX_DATA_INIT(CDlgEdit)
m_nX1 = 0;
m_nX2 = 0;
m_nY1 = 0;
m_nY2 = 0;
//}}AFX_DATA_INIT
m_nType = type;
}
( 2)添加确定命令按扭响应函数 OnOK()
4.2
现对话框功能
void CDlgEdit::OnOK()
{
UpdateData(TRUE);
CMainFrame *pMainFrame= (CMainFrame *) AfxGetApp()->GetMainWnd();
if(m_nType== 1)
{
pMainFrame->m_nRectLeft = m_nX1;
pMainFrame->m_nRectTop = m_nY1;
pMainFrame->m_nRectRight = m_nX2;
pMainFrame->m_nRectBottom = m_nY2;
}
else if(m_nType== 2)
{
pMainFrame->m_nCircleLeft = m_nX1;
pMainFrame->m_nCircleTop = m_nY1;
pMainFrame->m_nCircleRight = m_nX2;
pMainFrame->m_nCircleBottom= m_nY2;
}
CDialog::OnOK();
}
4.2
基本知识
1,OnContextMenu( )函数
2,CMenu类
1,LoadMenu( ) 函数
2,TrackPopupMenu( ) 函数
3,AfxGetApp()函数
4,CWinApp 类的 GetMainWnd()函数
4.2
4.3 动态菜单学习目标
1,菜单动态增加与删除
2,用户自定义消息
3,动态菜单消息响应
4.3
返回第 4章程序的实现步骤
1,编辑菜单资源
2,添加菜单响应函数
3,加入动态菜单响应函数
4.3
步骤 1 编辑菜单资源为菜单 (IDR_POPUP_MENU )添加两个菜单项:
Caption ID
1.Seprator
2.增加椭圆控制菜单 ID_ADD_MENU
3.删除椭圆控制菜单 ID_DELETE_MENU
4.3
步骤 2 添加菜单响应函数
1,OnAddMenu()
2,OnDeleteMenu()
4.3
步骤 2 添加菜单响应函数 4.3void CMainFrame::OnAddMenu(){
// TODO,Add your command handler code here
CString menu[2];
menu[0]="允许画椭圆 ";
menu[1]="禁止画椭圆 ";
CWnd *pMainFrame=AfxGetMainWnd();
CMenu *pMenuDyna=NULL;
CMenu *pMenu=NULL;
CMenu *pTopMenu=pMainFrame->GetMenu();
int iPos;
for(iPos=pTopMenu->GetMenuItemCount()-1; iPos>=0; iPos--)
{
pMenu=pTopMenu->GetSubMenu(iPos);
if(pMenu && pMenu->GetMenuItemID(0)==ID_DRAW_RECT)
{
pMenuDyna=pMenu;
break;
}
步骤 2 添加菜单响应函数 4.3void CMainFrame::OnDeleteMenu(){
// TODO,Add your command handler code here
CWnd *pMainFrame=AfxGetMainWnd();
CMenu *pMenuDyna=NULL;
CMenu *pMenu=NULL;
CMenu *pTopMenu=pMainFrame->GetMenu();
int iPos;
for(iPos=pTopMenu->GetMenuItemCount()-1; iPos>=0; iPos--)
{
pMenu=pTopMenu->GetSubMenu(iPos);
if(pMenu && pMenu->GetMenuItemID(0)==ID_DRAW_RECT)
{
pMenuDyna=pMenu;
break;
}
}
for(iPos=pMenuDyna->GetMenuItemCount()-1; iPos>=5; iPos--)
pMenuDyna->DeleteMenu(iPos,MF_BYPOSITION);
步骤 3 添加动态菜单响应函数
1,在类 CMainFrame中增加一个变量并初始化
int m_SelectMenu;
当 m_SelectMenu为 0时,第一项为选中状态,允许画椭圆。否则第二项为选中状态,禁止画椭圆。
4.3
CMainFrame::CMainFrame()
{
// TODO,add member initialization code here
m_SelectMenu =0;
}
步骤 3 添加动态菜单响应函数
2,重载主框架类的 OnCmdMsg()函数
Project,MenuTest
Class Name,CMainFrame
Objects IDs,CMainFrame
Messages,OnCmdMsg
4.3
4.3
步骤 3 添加动态菜单响应函数
BOOL CMainFrame::OnCmdMsg(UINT nID,int nCode,void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
{
if(pHandlerInfo==NULL)
{
for(int i=0; i<2; i++)
{
if(nID==(UINT) (WM_USER+10+i))
{
if(nCode==CN_COMMAND)
DoSelectMenu(i);
else if(nCode==CN_UPDATE_COMMAND_UI)
DoUpdateSelectMenu(i,(CCmdUI *) pExtra);
return true;
}
}
}
return CFrameWnd::OnCmdMsg(nID,nCode,pExtra,pHandlerInfo);
}
步骤 3 添加动态菜单响应函数
3,在 CMainFrame类中增加两个函数
DoSelectMenu()
DoUpdateSelectMenu()
4.3
void CMainFrame::DoSelectMenu(int i)
{
m_nSelectMenu = i;
}
步骤 3 添加动态菜单响应函数
4.3
void CMainFrame::DoUpdateSelectMenu(int i,CCmdUI *pCmdUI)
{
if(i==m_nSelectMenu)
pCmdUI->SetCheck(1);
else
pCmdUI->SetCheck(0);
pCmdUI->Enable(true);
}
步骤 3 添加动态菜单响应函数
4.为椭圆菜单项加入 UPDATE_COMMAND_UI
消息处理函数
4.3
void CMainFrame::OnUpdateDrawCircle(CCmdUI* pCmdUI)
{
// TODO,Add your command update UI handler code here
if(m_nSelectMenu == 0)
pCmdUI->Enable(true);
else
pCmdUI->Enable(false);
}
基本知识
1,CWnd 类,GetMenu() 函数
2,CMenu类
1,GetMenuItemCount()函数
2,GetMenuItemID()函数
3,DeleteMenu( ) 函数
4,AppendMenu( ) 函数
3,OnCmdMsg消息
4.3
4.4 工具条学习目标
1,自定义工具条
2,在工具条中添加控件
4.4
返回第 4章程序的实现步骤
1,编辑工具条资源
2,创建工具条
3,在工具条上添加控件
4,加入控件响应函数
4.4
步骤 1 编辑工具条资源添加工具条 (IDR_MYTOOLBAR ):
4.4
ID_DRAW_RECT ID_DRAW_CIRCLE
ID_DRAW_LINE ID_COMBOBOX
工具条含四个工具按扭,其中前两个与菜单“画图”的前两个菜单项的 ID
号相同,第三个按扭用于画直线,第四个按扭用来显示组合框 。
步骤 2 创建工具条
1,在类 CmainFrame中定义工具条数据成员,
CToolBar m_wndMyToolBar;
2,在类 CMainFrame的 OnCreate函数中加入以下代码,
4.4
if (!m_wndMyToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD | WS_VISIBLE |
CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY |
CBRS_SIZE_DYNAMIC) ||
!m_wndMyToolBar.LoadToolBar(IDR_MYTOOLBAR))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
…………………,
m_wndMyToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndMyToolBar);
步骤 2 创建工具条
3,添加画线响应函数
4.4
void CMenuTestView::OnDrawLine()
{
// TODO,Add your command handler code here
CClientDC dc(this);
dc.MoveTo(20,20);
dc.LineTo(200,200);
}
步骤 3 在工具条上添加控件
1,在类 CMainFrame中定义数据成员
CComboBox m_ComboBox;
2,在 CMainFrame的 OnCreate函数中加入代码
4.4
CRect rect;
m_wndMyToolBar.SetButtonInfo(3,ID_COMBOBOX,TBBS_SEPARATOR,160);
m_wndMyToolBar.GetItemRect(3,&rect);
rect.bottom += 100;
if(!m_ComboBox.Create(CBS_DROPDOWNLIST | WS_VISIBLE |
WS_TABSTOP | CBS_AUTOHSCROLL,rect,&m_wndMyToolBar,
ID_COMBOBOX))
return -1;
m_ComboBox.AddString("First Item");
m_ComboBox.AddString("Second Item");
m_ComboBox.AddString("Third Item");
m_ComboBox.SetCurSel(0);
步骤 4 加入组合框响应函数
1,定位到 MainFrm.h中类的定义处,在其中添加消息响应函数的原形:
afx_msg void OnSelchangeCombo();
2,定位到 MainFrm.cpp中消息映射宏的定义处,在其中添加 ComboBox控件的 ON_CBNSELCHANGE消息的映射宏:
ON_CBN_SELCHANGE(ID_COMBOBOX,OnSelc
hangeCombo)
4.4
步骤 4 加入组合框响应函数
3,在 MainFrm.cpp中添加消息映射函数体:
4.4
void CMainFrame::OnSelchangeCombo()
{
CString mess;
int CurSel;
CurSel = m_ComboBox.GetCurSel();
mess = "您选择了第 ";
char No[3];
itoa(CurSel,No,10);
mess += No;
mess += " 项 !";
MessageBox(mess,"消息框 ",MB_OK | MB_ICONINFORMATION);
}
基本知识
1,CToolBar 类:
1,CreateEx() 函数
2,SetButtonInfo ()
3,GetItemRect ()
2,CComboBox 类
1,Create ()函数
2,AddString()函数
3,SetCurSel ( ) 函数
3,手工添加消息响应函数
4.4
4.5 状态条学习目标
1,在状态信息行显示信息
2,在状态指示器 显示键盘状态
4.5
返回第 4章程序的实现步骤
1,在文件 MainFrm.cpp中,找到状态条 indicators
数组的定义处添加代码
2,创建 Ctrl键和 Shift键状态指示器的字符串资源
3,为状态条添加标识号
4,在函数 CMainFrame::OnCreate()函数中,
添加状态条的设置代码
5,显示控制键状态
6,显示鼠标在视中的位置坐标
4.5
步骤 1 在 indicators数组中添加新元素 4.5
static UINT indicators[] =
{
ID_SEPARATOR,// status line indicator
ID_SEPARATOR,//显示 x坐标
ID_SEPARATOR,//显示 x坐标
ID_INDICATOR_CTRL,//显示 Ctrl键的状态
ID_INDICATOR_SHIFT,//显示 Shift键的状态
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
步骤 2 创建 Ctrl键和 Shift键状态指示器的字符串资源 4.5
在 Workspace窗口中双击 ResourceView标签的 String Table,打开字符串资源编辑器。选中一个以 ID_INDICATOR为开头的字符串资源,按 Insert键,插入两个新的字符串资源:
ID Caption
ID_INDICATOR_CTRL Ctrl
ID_INDICATOR_SHIFT Shift
步骤 3 为状态条添加标识号通过菜单 View下的 Resource Symbols菜单项,打开 Resource
Symbol对话框,单击 New按扭,在 Name中输入
IDC_STATUSBAR,Value取默任值,单击 OK按扭。
步骤 4 在函数 CMainFrame::OnCreate()函数中,
添加状态条的设置代码
4.5
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
m_wndStatusBar.SetPaneInfo(1,IDC_STATUSBAR,SBPS_POPOUT,50);
m_wndStatusBar.SetPaneInfo(2,IDC_STATUSBAR,SBPS_POPOUT,50);
步骤 5 显示控制键状态
4.5
1,在 MainFrm.h文件中的类定义内加入消息响应函数的原形,
并将成员 m_wndStatusBar改成公用类型:
public:
CStatusBar m_wndStatusBar;
……
afx_msg void OnUpdateKeyCtrl(CCmdUI *pCmdUI);
afx_msg void OnUpdateKeyShift(CCmdUI *pCmdUI);
2,在文件 MainFrm.cpp消息映射宏的定义处添加两消息映射宏
ON_UPDATE_COMMAND_UI(ID_INDICATOR_CTRL,OnUpdateKeyCtrl)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_SHIFT,OnUpdateKeyShift)
步骤 5 显示控制键状态
4.5
3,在文件 MainFrm.cpp中添加消息映射函数体
void CMainFrame::OnUpdateKeyCtrl(CCmdUI *pCmdUI)
{
pCmdUI->Enable(::GetKeyState(VK_CONTROL)<0);
}
void CMainFrame::OnUpdateKeyShift(CCmdUI *pCmdUI)
{
pCmdUI->Enable(::GetKeyState(VK_SHIFT)<0);
}
步骤 6 显示鼠标在视中的位置坐标
4.5
在类 CMenuTestView中添加鼠标移动消息响应函数
void CMenuTestView::OnMouseMove(UINT nFlags,CPoint point)
{
// TODO,Add your message handler code here and/or call default
char PositionString[20];
CMainFrame *MainFrame=(CMainFrame *) AfxGetMainWnd();
sprintf(PositionString,"X:%d",point.x);
MainFrame->m_wndStatusBar.SetPaneText(1,PositionString);
sprintf(PositionString,"y:%d",point.y);
MainFrame->m_wndStatusBar.SetPaneText(2,PositionString);
CView::OnMouseMove(nFlags,point);
}
基本知识
1,CStatusBar 类:
1,SetPaneInfo() 函数
2,SetIndicators()函数
3,SetPaneText()函数
2,GetKeyState(VK_SHIFT)函数
4.5
返回第 4章