1、 GetMenu()-SetDefaultItem(ID_DRAW_NONE); c. 在CMainFrame:OnCreate()中,使菜单项“新建”变成灰色,不可用状态:/禁止“打印预览”菜单项: /EnableMenuItem()需要将CFrameWnd:m_bAutomenuEnable设置为FALSE,/如果该数据成员为TRUE(缺省值),工作框将自动地禁止没有/ON_COMMAND或者ON_UPDATE_COMMAND_UI的菜单项。 m_bAutoMenuEnable = FALSE;GetSubMenu(0)-EnableMenuItem(6, MF_BYPOSITION |
2、MF_DISABLED | MF_GRAYED); d. 在CMainFrame:OnCreate()中,给Save As菜单项增加图标: CString str; str.Format(x=%d,y=%d, GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK); MessageBox(str); CBitmap bitmap; bitmap.LoadBitmap(IDB_BITMAP1);SetMenuItemBitmaps(3, MF_BYPOSITION, &bitmap, &bitmap); bitmap.
3、Detach(); /使HBITMAP和CBitmap解除捆绑,否则会使SetMenuItemBitmaps失效。 说明:int GetSystemMetrics()获取系统信息度量。可以用它来获取菜单标题的尺寸从而设置位图标题菜单中位图的大小。 e. 在CMainFrame:OnCreate()中,移除/增加菜单 CMenu *pMenu = this-GetMenu(); this-SetMenu(NULL); /移除菜单SetMenu(pMenu); /增加菜单3. 在资源管理器中设置加速键。然后在CApp类的InitInstance()中加载快捷键,使定义的Ctrl+L等起作用:HAC
4、CEL hAccelTable = LoadAccelerators(theApp.m_hInstance, MAKEINTRESOURCE(IDR_MAINFRAME);4. 菜单消息传递顺序:View类-Doc类-CMainFrame类-App类。菜单消息一旦在其中一个类中响应则不再在其它类中查找响应函数。5. 使用TrackPopupMenu函数,添加右键弹出菜单:1)用资源管理器添加一个菜单资源,也可以利用主菜单中的某个子菜单作为要弹出的菜单。2)在鼠标右键消息响应函数中,加载菜单资源,并获得要显示的子菜单指针,并用该指针调用TrackPopupMenu函数便完成任务(但要注意:鼠标响
5、应函数传进来的坐标是客户区坐标,而TrackPopupMenu函数中使用的是屏幕坐标,在调用TrackPopupMenu前要调用ClientToScreen客户区坐标到屏幕坐标的转换),如:void CMiniCADView:OnRButtonUp(UINT nFlags, CPoint point) /CMenu menu; /menu.LoadMenu(IDR_MAINFRAME); /CMenu *pPopup=menu.GetSubMenu(4); /ClientToScreen(&point); /pPopup-TrackPopupMenu(TPM_LEFTALIGN | TPM_R
6、IGHTBUTTON, point.x, point.y, GetParent(); CView:OnRButtonUp(nFlags, point);3) 可用WM_CONTEXTMENU消息替换在鼠标右键消息响应函数来完成TrackPopupMenu的工作。如:OnContextMenu(CWnd* pWnd, CPoint point) /CMenu *pPopup = menu.GetSubMenu(4); GetParent()-TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, GetParent()
7、;6. 动态菜单编程: 创建动态菜单。常用函数有:CMenu:CreatePopupMenu /创建一个Popup菜单,如“电话本”DrawMenuBar /绘制菜单AppendMenu /给菜单增加一项,查MSDN,注意nFlags参数的用法AppendMenu(MF_POPUP, (UINT)m_menu.m_hMenu, 电话本);m_menu.AppendMenu(MF_STRING, m_nIndex + IDM_PHONE1, 张三 为动态菜单添加响应函数:(注意,不是自定义消息)首先在resource.h中定义菜单ID,如:#define IDM_PHONE1 32777#def
8、ine IDM_PHONE2 32778 第二,消息映射,如:ON_COMMAND(IDM_PHONE1, OnPhone1)ON_COMMAND(IDM_PHONE2, OnPhone2) 第三,定义菜单响应函数,如:afx_msg void OnPhone1();afx_msg void OnPhone2(); 第四,实现菜单响应函数。OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) / TODO: Add your message handler code here and/or call default if (nChar = 13) /回车
9、m_nIndex+; /m_nIndex初值为-1 if (0 = m_nIndex) /说明“电话本”菜单项还没有创建,则创建之 m_menu.CreatePopupMenu(); this- GetParent()-DrawMenuBar(); m_menu.AppendMenu(MF_STRING, m_nIndex + IDM_PHONE1, m_strLine.Left(m_strLine.Find( ); /将记录保存进字符串数组 m_strArray.Add(m_strLine); /CStringArray /清空, 清屏, 为输入下一个人的号码做好准备 m_strLine =
10、 ; this-Invalidate(); /清屏 else CClientDC dc(this); m_strLine += (char)nChar; dc.TextOut(10, 10, m_strLine);OnChar(nChar, nRepCnt, nFlags);OnPhone1() CClientDC dc(this); dc.TextOut(10, 10, m_strArray0);OnPhone2() dc.TextOut(10, 10, m_strArray1);二、工具条编辑工具栏资源:在资源管理视图中,打开ToolBar目录。新建一个工具条资源IDR_TOOLBAR1。
11、 如下图:工具条一般是和菜单相关联的,将工具栏上的某个图标的ID设置为菜单项的ID即可。工具栏图标的索引记数顺序也是从左到右,由0开始,分隔符也算索引号。CToolBar属于控制栏中的一种,由CControlBar派生。一般在CMainFrame:OnCreate函数中创建工具栏,分2个步骤:先用CToolBar:Create建立工具条对象,建立工具条窗口句柄。然后CToolBar:LoadToolBar加载工具栏资源技巧:要增加一个新的m_wndToolBar1,可以在CMainFrame:OnCreate中,复制m_wndToolBar的相关代码,将m_wndToolBar改成m_wndT
12、oolBar1,将资源IDR_MAINFRAME改成IDR_TOOLBAR1即可。主要函数: CreateEx函数:如果dwCtrlStyle=0,则工具栏为VC5以前的凸起风格。dwStyle 包含了丰富的工具栏风格CBRS_SIZE_DYNAMIC和CBRS_SIZE_FIXED是两个相反的风格。CBRS_SIZE_DYNAMIC是动态尺寸的,在漂浮时可拖拉改变尺寸。CBRS_SIZE_FIXED在漂浮时是紧凑的,无法拖拉改变尺寸。CBRS_GRIPPER风格包含一个突起的掐子,使嵌入的工具栏更方便的拖。CBRS_TOOLTIPS风格使鼠标在工具按钮上方时,可以现实黄色小提示。 DockC
13、ontrolBar 停靠 FloatControlBar 浮动 ShowControlBar 显示三、再回首菜单栏,往事不再依旧:UPDATE_COMMAND_UI消息改变了这一切。增加菜单:查看-绘图栏,添加消息ON_COMMAND(ID_VIEW_DRAWBAR, OnViewDrawbar):void CMainFrame:OnViewDrawbar() ShowControlBar(&m_wndToolBar1,!m_wndToolBar1.IsWindowVisible(), FALSE);继续添加消息ON_UPDATE_COMMAND_UI(ID_VIEW_DRAWBAR, OnU
14、pdateViewDrawbar):OnUpdateViewDrawbar(CCmdUI *pCmdUI) pCmdUI-SetCheck(m_wndToolBar1.IsWindowVisible();菜单项状态的维护是基于UPDATE_COMMAND_UI消息,谁捕获该消息,MFC就为谁创建一个CCmdUI对象。可以手工或用ClassWizard来给菜单项添加UPDATE_COMMAND_UI消息响应。在OnUpdatexxx中用CCmdUI控制菜单项可用、不可用,变灰,打勾等操作。只能设置,而不能获取。为菜单ID_DRAW_NONE, ID_DRAW_LINE, ID_DRAW_RECT
15、, ID_DRAW_ELLIPSE添加UPDATE_COMMAND_UI消息,写入SetCheck代码,同时去掉ON_COMMAND中起打勾作用的代码,再次运行,会发现,绘图栏上对应的按钮处于被按下状态了。对用户来说,就更加直观了。修改后的部分代码如下:OnDrawNone() m_nDrawType = 0;OnDrawLine() m_nDrawType = 1;OnUpdateDrawNone(CCmdUI* pCmdUI) SetCheck(0 = m_nDrawType);OnUpdateDrawLine(CCmdUI* pCmdUI) SetCheck(1 = m_nDrawTyp
16、e);绘图栏上的按钮被按下的效果如下图所示:四、状态栏上面的工具栏可以有多个,状态栏一般只有一个。在CStatusBar中,常用的状态栏操作函数有:/Create:创建CStatusBarSetIndicators:设置状态条上指示器CommandToIndex:获取IndexSetPaneText:设置指示器文字SetPaneStyle:设置指示器风格SetPaneInfo:设置指示器属性如下代码在状态栏中增加了一个显示当前时间的指示器:a. 在String资源中添加IDS_TIMER 23:59:59的定义, 不要ID_INDICATOR_TIMER,否则不显示时间b. 在MainFrm.
17、cpp中的indicators数组中添加IDS_TIMERc. 在MainFrm.cpp中OnCreate()中添加 /设置时间栏 CTime t = CTime:GetCurrentTime(); CString str = t.Format(%H:%M:%S int index = m_wndStatusBar.CommandToIndex(IDS_TIMER); m_wndStatusBar.SetPaneText(index, str);SetTimer(123, 1000, NULL); /每秒更新一次时间栏d. 在OnTimer()中添加上述更新时间的代码五、完善MiniCAD,使
18、其具有图形保持功能。 上面的MiniCAD绘图后,如果改变一下窗口大小,就会擦掉所绘的图形。这是因为我们的绘图代码没有写在OnDraw函数中,而当窗口重绘(WM_PAINT)时,只会重绘OnDraw中代码所写的绘图功能;但是上述工程在OnDraw中没有写任何绘图代码,因此,WM_PAINT时就擦掉了在OnLButtonUp等事件中绘制的图形。 解决思路:将用户绘制的一个个图形都保存起来,然后在OnDraw中一个个的重绘出来。1、定义一个CShape类,用于表示用户所画图形的数据结构,包括图形类型、起点、终点和颜色。class CShape public: UINT m_nDrawType; /
19、绘图类型0不绘图1直线2矩形3椭圆 CPoint m_ptBegin; /起点 CPoint m_ptEnd; /终点 COLORREF m_color; /颜色 CShape(); CShape(UINT nDrawType, CPoint ptBegin, CPoint ptEnd, COLORREF m_color)m_nDrawType = nDrawType;m_ptBegin = ptBegin;m_ptEnd = ptEnd;m_color = color; ; virtual CShape();2、定义一个CMiniCADView成员变量CPtrArray m_ptrArray
20、,用于保存所绘制的一个个图形。在OnLButtonUp最后面,输入以下代码:OnLButtonUp(UINT nFlags, CPoint point) /. /保存当前图形 /CShape shape(m_nDrawType, m_ptBegin, m_ptEnd); /m_ptrArray.Add(&shape); /这种方式保存不了真正的数据,因为shape析构时就销毁了 CShape *pShape = new CShape(m_nDrawType, m_ptBegin, m_ptEnd, m_color); m_ptrArray.Add(pShape);OnLButtonUp(nFl
21、ags, point);3、在OnDraw中进行绘图:#include Shape.hOnDraw(CDC* pDC) CMiniCADDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); add draw code for native data here /保存老的画笔和画刷,用于后面的恢复。 CPen *pOldPen = pDC-GetCurrentPen(); CBrush *pOldBrush = pDC-GetCurrentBrush(); /透明画刷 CBrush *pBrush = CBrush:FromHandle(HBRUSH):G
22、etStockObject(NULL_BRUSH); pDC-SelectObject(pBrush); for (int i = m_ptrArray.GetSize() - 1; i = 0; i-) CShape *pShape = (CShape *)m_ptrArray.GetAt(i); /设置画笔颜色:m_color色 CPen pen(PS_SOLID, 1, pShape-m_color); pDC-SelectObject(&pen); /开始绘图 if (pShape-m_nDrawType = 1) /画线 pDC-MoveTo(pShape-m_ptBegin);Li
23、neTo(pShape-m_ptEnd); else if (pShape-m_nDrawType = 2) /画矩形Rectangle(pShape-m_ptBegin.x, pShape-m_ptBegin.y, pShape-m_ptEnd.x, pShape-m_ptEnd.y);m_nDrawType = 3) /画椭圆Ellipse(pShape-m_ptBegin.y, pShape- /恢复SelectObject(pOldBrush);SelectObject(pOldPen);4、其他:AfxGet. SetCursorOnMouseMove(UINT nFlags, CP
24、oint point) /设置鼠标位置状态栏 /#include MainFrm.h /public: CToolBar m_wndStatusBar CMainFrame *pMainFrame = (CMainFrame *)AfxGetMainWnd(); CString sPos; sPos.Format(%d, %d, point.x, point.y); int index = pMainFrame-m_wndStatusBar.CommandToIndex(IDS_MOUSEPOS); pMainFrame-m_wndStatusBar.SetPaneText(index, sPos); /设置绘图时的光标/ :SetClassLong(m_hWnd, GCL_HCURSOR, (LONG):LoadCursor(NULL, m_nDrawType = 0 ? IDC_ARROW : IDC_CROSS); SetCursor(: IDC_ARROW :作业:在状态栏添加一个鼠标位置指示器,以显示鼠标当前的位置。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1