友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
富士康小说网 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

C语言实例教程(PDF格式)-第19部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!



      的第一部分为  菜单标题,其最后一部分则为标识该菜单项的 

      ID号。需要注意的是,具有子菜单的弹出式菜单项是没有标 

      识的ID号的。   



l 我们程序的最初的菜单;并不包含程序执行后结果的一些菜单;最 

  初的菜单中仅仅包含前四幅图中的菜单。  



l IDR_MAINFRAME0 MENU PRELOAD DISCARDABLE  



l BEGIN  



l POPUP 〃&File〃  



l BEGIN  



l MENUITEM 〃&NewtCtrl+N〃; ID_FILE_NEW  



l MENUITEM 〃&Open。。。tCtrl+O〃; ID_FILE_OPEN  



l MENUITEM 〃&SavetCtrl+S〃; ID_FILE_SAVE  



l MENUITEM 〃Save &As。。。〃; ID_FILE_SAVE_AS  



l MENUITEM SEPARATOR  



l MENUITEM 〃&Print。。。tCtrl+P〃; ID_FILE_PRINT  



l MENUITEM 〃Print Pre&view〃; ID_FILE_PRINT_PREVIEW  



l MENUITEM 〃P&rint Setup。。。〃; ID_FILE_PRINT_SETUP  



l MENUITEM SEPARATOR  



l MENUITEM 〃Recent File〃; ID_FILE_MRU_FILE1; GRAYED  



l MENUITEM SEPARATOR  


…………………………………………………………Page 209……………………………………………………………

l MENUITEM 〃E&xit〃; ID_APP_EXIT  



l END  



l POPUP 〃&Edit〃  



l BEGIN  



l MENUITEM 〃&UndotCtrl+Z〃; ID_EDIT_UNDO  



l MENUITEM SEPARATOR  



l MENUITEM 〃Cu&ttCtrl+X〃; ID_EDIT_CUT  



l MENUITEM 〃&CopytCtrl+C〃; ID_EDIT_COPY  



l MENUITEM 〃&PastetCtrl+V〃; ID_EDIT_PASTE  



l END  



l POPUP 〃&View〃  



l BEGIN  



l MENUITEM 〃&Toolbar〃; ID_VIEW_TOOLBAR  



l MENUITEM 〃&Status Bar〃; ID_VIEW_STATUS_BAR  



l MENUITEM 〃&Long menu〃; ID_VIEW_LONGMENU  



l END  



l POPUP 〃&Draw〃  



l BEGIN  



l MENUITEM 〃&Line〃; ID_DRAW_LINE  



l MENUITEM 〃&Circle〃; ID_DRAW_CIRCLE  



l MENUITEM 〃&Rectangle〃; ID_DRAW_RECTANGLE  



l MENUITEM 〃&Bitmap〃; ID_CHANGE  



l END  


…………………………………………………………Page 210……………………………………………………………

l POPUP 〃&Help〃  



l BEGIN  



l MENUITEM 〃&About Menu。。。〃; ID_APP_ABOUT  



l END  



l END  



l   



l IDR_MAINFRAME1 MENU DISCARDABLE  



l BEGIN  



l POPUP 〃&File〃  



l BEGIN  



l MENUITEM 〃&NewtCtrl+N〃; ID_FILE_NEW  



l MENUITEM 〃&Open。。。tCtrl+O〃; ID_FILE_OPEN  



l MENUITEM 〃&SavetCtrl+S〃; ID_FILE_SAVE  



l MENUITEM 〃Save &As。。。〃; ID_FILE_SAVE_AS  



l MENUITEM SEPARATOR  



l MENUITEM 〃&Print。。。tCtrl+P〃; ID_FILE_PRINT  



l MENUITEM 〃Print Pre&view〃; ID_FILE_PRINT_PREVIEW  



l MENUITEM 〃P&rint Setup。。。〃; ID_FILE_PRINT_SETUP  



l MENUITEM SEPARATOR  



l MENUITEM 〃Recent File〃; ID_FILE_MRU_FILE1; GRAYED  



l MENUITEM SEPARATOR  



l MENUITEM 〃E&xit〃; ID_APP_EXIT  



l END  


…………………………………………………………Page 211……………………………………………………………

l POPUP 〃&View〃  



l BEGIN  



l MENUITEM 〃&Toolbar〃; ID_VIEW_TOOLBAR  



l MENUITEM 〃&Status Bar〃; ID_VIEW_STATUS_BAR  



l MENUITEM 〃&Normal menu〃; ID_VIEW_NORMALMENU  



l END  



l POPUP 〃&Dyncmodify〃  



l BEGIN  



l MENUITEM 〃&Insert a menuitem〃; ID_DYNCMODIFY_INSERT  



l MENUITEM 〃&Delete a menuitem〃; ID_DYNCMODIFY_DELETE  



l MENUITEM 〃&Append a menuitem〃; ID_DYNCMODIFY_APPEND  



l MENUITEM 〃&Modify help〃; ID_DYNCMODIFY_MODIFY  



l MENUITEM 〃M&odify system menu〃; ID_DYNCMODIFY_MODIFYSYSTEMMENU  



l MENUITEM 〃&Reset system menu〃; ID_DYNCMODIFY_RESET  



l END  



l POPUP 〃&Help〃  



l BEGIN  



l MENUITEM 〃&About Menu。。。〃; ID_APP_ABOUT  



l END  



l END  



l   



l IDR_CONTEXTMENU MENU DISCARDABLE  



l BEGIN  


…………………………………………………………Page 212……………………………………………………………

  l POPUP 〃dummy〃  



  l BEGIN  



  l MENUITEM 〃&Line〃; ID_DRAW_LINE  



  l MENUITEM 〃&Circle〃; ID_DRAW_CIRCLE  



  l MENUITEM 〃&Rectangle〃; ID_DRAW_RECTANGLE  



  l END  



  l END  



    



                                             



                    图5。 11 上下文菜单的一个运行画面  



为了建立弹出式菜单,在上述代码中,我们发现还有一个菜单 

IDR_CONTEXTMENU没有提及。它在该文件中与其它菜单的表现形式是 

一样的。下图为弹出式菜单的一个运行画面。  



下面我们看看怎样改变菜单项的缺省名称。如图5。12所示,在 

WorkSpace中于IDR-MAINFRAME上右击鼠标,在弹出式菜单中选择属 

性项 (Property),在接下来的属性设置对话框中在ID设置区输入后 

者从下拉列表选择所需的菜单ID号即可。依此处理其它各菜单项。  



  l 注意:  



  l 菜单项ID号的设置务请同我们给 出的保持一致,由于ID号是辨识 

    菜单消息的唯一手段,此处的差别将会导致你在下面的学习过程 

    中将不得不跟我们给 出的代码有一些差异。  


…………………………………………………………Page 213……………………………………………………………

                                          



                          



                  图5。 12 改变菜单项ID值  



现在,试着运行一下我们的程序,会发现它并没有能比最初的 

AppWizard建立的标准程序多做些什么。这是必然的,毕竟,我们还 

没有编写一行让它动起来的代码吗 !不过不要紧,我们接下来所要做 

的,就是这项工作。(不用担心IDR_MAINFRAME0对IDR_MAINFRAME的 

替代会有什么不良结果,实际上,ClassWizard监测到这些,并已在 

程序代码中作了相应的变动以反应这一变化。)  



首先,由于对菜单的动态改变在菜单IDR_MAINFRAME1的菜单项中实 

现,因此,我们所要做的第一步工作就是实现菜单IDR_MAINFRAME1对 

菜单IDR_MAINFRAME0的动态替换。这可以用CWnd类的一个成员函数 

SetMenu实现。函数SetMenu的原型为:  



BOOL SetMenu(CMenu * pMenu);  



其中pMenu为一指向欲替换原有菜单的一CMenu类的对象的指针,函数 

的返回值仅仅在菜单没有发生改变时为0。  



  l 注意:  



  l 如果你以空值NULL作为指向CMenu的指针,那你的程序的菜单就算 

   消失了。除非在程序中以适当方式告诉用户重新得到菜单的方 

   法,用户很难再得到菜单了。不过,在一些情形下,实现菜单的 

   消隐/显示可以实现对屏幕显示空间的有效管理。  



尽管通过第四章的学习,你已经掌握了一些在程序中添加消息响应函 

数的方法,但基于文档/视结构的成员函数的添加还是有自己的很大 

程度上的不同。在我们已经生成的程序中,添加对菜单消息的响应的 


…………………………………………………………Page 214……………………………………………………………

函数是有一些自己的特殊性的。下面我们结合图示顺序讲解。  



1。                   在菜单项上或源代码编辑区中右击鼠标,或选择 

View/ClassWizard…菜单项,打开ClassWizard对话框。  



2。  在Class  name:选项中,确认为CMainFrame,在Object  IDs:中选 

择ID_VIEW_LONGMENU;在Message:选项中选择MAND,如图5。13。  



                                                             



                     图5。 13 为菜单项增加消息响应函数  



                                                 



                        图5。 14 选择响应函数名称  



3。  单击Add Class…为响应函数命名 (如图5。14所示),一般说,接 

受系统提供的缺省名就足可以了。  



4。 单击OK后进入源代码编辑区进行编辑。  



如下所示,为我们为函数OnViewLongmenu所加的代码:  



void CMainFrame::OnViewLongmenu()   



{  



// TODO: Add your mand handler code here  



SetMenu(&hLongMenu);  


…………………………………………………………Page 215……………………………………………………………

}  



理解这段代码并不困难,但参数hLongMenu从何而来?这是我们在程序 

中创建的一个标识菜单IDR_MAINFRAME1的CMenu类的一个对象。在文 

件MainFrm。cpp的下示函数中我们对其进行了初始化 (这两处代码均是 

手工加入的):  



int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)  



{  



// 。。。  



hLongMenu。LoadMenu(IDR_MAINFRAME1);   



// 。。。  



}  



而其定义在头文件MainFrm。h中:  



class CMainFrame : public CFrameWnd  



{  



// 。。。  



CMenu hLongMenu;  



// 。。。  



}   



对View菜单的前三个菜单项的响应涉及到GDI绘图的一些知识,读者 

如果暂时弄不清楚,可以留待看过相应章节后再回头来理解。下面我 

们看一看对菜单的动态操作。  



    


…………………………………………………………Page 216……………………………………………………………

                                                 



                     图5。 15 在程序中增加位图资源  



在前面的第四章的那个例程中,我们对这类实现作了些简要的介绍, 

在这里,我们结合本章的程序作一些更深入的介绍。  



首先,对菜单的动态操作的几个函数,其最后一个参数都可以用一个 

位图指针替代。本章例程中Draw菜单下的图符菜单即由此实现。当 

然,要使用位图作为菜单项,首先必须创建位图资源。  



在Visual  C++菜单中选择Insert/Resource…;再在弹出的对话框中选 

择Bitmap,如图5。15所示。  



如果有现成的位图,可以选择Import…,当然,在很多情况下,我们 

可以选New直接在资源编辑器中对它们进行创建、编辑。位图编辑器 

的使用很容易掌握,在此不再赘述。图形可以参考前面的插图。下面 

的代码摘自Menu。rc,以便读者在指定位图属性时作参考。  



IDB_LINE BITMAP DISCARDABLE 〃resline。bmp〃  



IDB_CIRCLE BITMAP DISCARDABLE 〃resbitmap1。bmp〃  



IDB_RECTANGLE BITMAP DISCARDABLE 〃resrectangl。bmp〃  



IDB_TEXT BITMAP DISCARDABLE 〃resbmp00001。bmp〃  



同时,当然也应该注意映射的关系。只要与欲执行该功能的字符菜单 

项的ID号一致,那么,它们所实现的功能就是一样的。下面的几行代 

码摘自MainFrm。cpp  



void CMainFrame::OnChange()   



{  



// TODO: Add your mand handler code here  



if(!bBitmap)  


…………………………………………………………Page 217……………………………………………………………

{  



bBitmap=TRUE;  



CMenu *pMenu=GetMenu();  



CMenu *pSubMenu=pMenu…》GetSubMenu(3);  



pSubMenu…》ModifyMenu(ID_DRAW_LINE;MF_BYMAND;ID_DRAW_LINE;&hLine);  



pSubMenu…》ModifyMenu(ID_DRAW_CIRCLE;MF_BYMAND;ID_DRAW_CIRCLE;&hCircle);  



pSubMenu…》ModifyMenu(ID_DRAW_RECTANGLE;  



MF_BYMAND;ID_DRAW_RECTANGLE;&hRectangle);  



pSubMenu…》ModifyMenu(ID_CHANGE;MF_BYMAND;ID_CHANGE;&hText);  



}  



else  



{  



bBitmap=FALSE;  



CMenu *pMenu=GetMenu();  



CMenu *pSubMenu=pMenu…》GetSubMenu(3);  



pSubMenu…》ModifyMenu(ID_DRAW_LINE;MF_BYMAND;ID_DRAW_LINE;〃&Line〃);  



pSubMenu…》ModifyMenu(ID_DRAW_CIRCLE;MF_BYMAND;ID_DRAW_CIRCLE;〃&Circle〃);  



pSubMenu…》ModifyMenu(ID_DRAW_RECTANGLE;  



MF_BYMAND;ID_DRAW_RECTANGLE;〃&Rectangle〃);   



pSubMenu…》ModifyMenu(ID_CHANGE;MF_BYMAND;ID_CHANGE;〃&Bitmap〃);  



}  



}   



而下面这段程序完成了位图资源的装入与初始化:  



int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)  



{  



// 。。。  


…………………………………………………………Page 218……………………………………………………………

hLine。LoadBitmap(IDB_LINE);  



hCircle。LoadBitmap(IDB_CIRCLE);  



hRectangle。LoadBitmap(IDB_RECTANGLE);  



hText。LoadBitmap(IDB_TEXT);  



// 。。。  



}  



工作间,此时,系统检测到资源已经在系统外部发生变化,询问是否 

重组数据库,选择是,我们所需要的就已经全部准备完毕。下面给出 

这一变化前后文件Menu。rc的变化情况。  



//改变以前:  



POPUP 〃&Help〃  



BEGIN  



MENUITEM 〃&About Menu。。。〃; ID_APP_ABOUT  



MENUITEM 〃&I ’m Menu inserted〃; ID_HELP_INSERT   



//上面这行代码我们在实现了消息映射后将将其删除  



END  



//改变以后:  



POPUP 〃&Help〃  



BEGIN  



MENUITEM 〃&About Menu。。。〃; ID_APP_ABOUT  



END  



通过以上的比较我们不难发现,使用第二种方式进行修改是比较方便 

的。  



                                                              



                         图5。 16 系统菜单改变后的任务条  


…………………………………………………………Page 219……………………………………………………………

下面我们讲一下有关系统菜单的消息响应问题。如图5。16,在我们改 

变系统菜单后,当在任务栏右单击鼠标时,弹出的系统菜单具有了与 

原来不同的形式。  



顺便提一下,如果我们不希望用户在程序外部直接退出程序,改变系 

统菜单就是这个方法的一个途径。(如果将系统菜单设为NULL,用户 

就只有进入应用程序进行选择了。当然,除非这是必要的,否则,不 

要强迫用户改变他们的操作习惯。)  



首先,我们必须取得系统菜单,这可以通过调用CWnd类的一个成员函 

数GetSystemMenu)达到。此函数的原型为:  



CMenu *GetSystemMenu(BOOL bRevert) const;  



在以TRUE作为bRevert的值进行调用时,恢复原系统菜单设置。在更 

多的情况下,我们以FALSE进行调用,此时我们可以对系统菜单进胁 

僮鳌 5牵孟⑾煊??/FONT》OnSysmand函数,而且,此消息响 

应函数是系统设定的,不允许程序员另行指定。  



  l 注意:  



  l 我们可以通过系统提供的Spy++来查看系统菜单的消息发送及响应 

   状况。至于详细的情况,在我们随后给出了详细的解释。与该消 

   息相应的代码,我们将用具有底纹的文字标出。  



在本章的最后;我们不妨来看看怎样在程序中实现右击鼠标时出现的 

上下文菜单;与前面我们所遇到的其他弹出式菜单在CmainFrame中实 

现不同;上下文菜单要在类CmenuView中实现。从本质上来说,实现上 

下文菜单时发送的消息与标准的菜单消息并没有什么两样,它们都发 

送ON_MAND消息。但是,由于上下文菜单的特殊性,我们首先必须 

保证我们能接收到这样的消息。同时,由于上下文菜单中没有顶层菜 

单,我们对它们的跟踪有一定的特殊性。我们采用CMenu类的一个成 

员函数TrackPopupMenu来实现。该函数的原型为:  



BOOL TrackPopupMenu(UINT nFlags; int x; int y; CWnd* pWnd; LPCRECT lpRect =  

NULL )  



该函数中,参数nFlags指明屏幕位置与鼠标位置风格,x;y为一依赖 

于前面所指定风格的上下文菜单的屏幕位置坐标,pWnd为一指向拥有 

该菜单的窗口指针,而lpRect指明用户不会丢失掉上下文菜单的矩形 

域。参数nFlags可以取以下值:  



屏幕位置风格:TPM_CENTERALIGN;TPM_LEFTALIGN,TPM_RIGHTALIGN  


…………………………………………………………Page 220……………………………………………………………

鼠标位置风格:TPM_LEFTBUTTON,TPM_RIGHTBUTTON  



至于说它们的取值是可以互相取 “或”的,而它们的实际效果,我们 

希望读者通过实践具体看看。下面的程序段摘自例程中文件 

CMenuView。cpp中:  



void CMenuView::OnRButtonDown(UINT nFlags; CPoint point)   



{  



// TODO: Add your message handler code here and/or call default  



CMenu ContextMenu;  



if(!ContextMenu。LoadMenu(IDR_CONTEXTMENU))  



AfxThrowResourceException();  



CMenu *pPopupMenu=ContextMenu。GetSubMenu(0);  



ASSERT(pPopupMenu!=NULL);  



ClientToScreen(&point);  



pPopupMenu…》TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON;  



point。x;point。y;AfxGetMainWnd());  



CView::OnRButtonDown(nFlags; point);  



}  



下面我们对这一段代码作简要分析:  



程序中先装入该菜单 (使用LoadMenu装入),接下来由于上下文菜单 

的定位使用屏幕坐标,所以使用了一个CWnd类的成员函数 

ClientToScreen,然后使用了TrackPopupMenu将菜单以上下文方式显 

示,最后,程序调用CView类的通用代码处理一些平常信息。  



   l 注意:  



   l 由于该函数在类CMenuView中实现,在使用ClassWizard时务请注 

     意基类的选择。如 图5。17所示 (如果错选 了CMaimFrame类,程序 

     最后所调用的处理例程为CWnd类的处理函数,上下文菜单的显示 

    就成了问题)。  


…………………………………………………………Page 221……………………………………………………………

                                                     



                     图5。 17 选择上下文菜单实现的基类  



在本章的最后,我们给出一部分关键性代码,其中手工加入的部分以 

具有底纹的文字给出 (基于版面方面的考虑,我们对一些重复性的代 

码略去了)。  



   l 注意:  



   l 由于菜单项的选择标记及使能实现较简单,此处省去了该部分。 

    但实现时需调用消息响应WM_INITMENU。  



   l 为了节省篇幅,在程序中我们没有在窗口变化后进行重绘,这部 

    分的详细内容请参见GDI绘图一节。  



// MainFrm。cpp : 类CMainFrame 的实现  



//  



#include 〃stdafx。h〃  



// 。。。  



IMPLEMENT_DYNCREATE(CMainFrame; CFrameWnd)  



BEGIN_MESSAGE_MAP(CMainFrame; CFrameWnd)  



//{{AFX_MSG_MAP(CMainFrame)  



ON_WM_CREATE()  



ON_MAND(ID_VIEW_NORMALMENU; OnViewNormalmenu)  


…………………………………………………………Page 222…
返回目录 上一页 下一页 回到顶部 9 9
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!