按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
…………………………………………………………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……………………………………………………………
ON_MAND(ID_DRAW_LINE; OnDrawLine)
ON_MAND(ID_DRAW_CIRCLE; OnDrawCircle)
ON_MAND(ID_DRAW_RECTANGLE; OnDrawRectangle)
ON_MAND(ID_DYNCMODIFY_INSERT; OnDyncmodifyInsert)
ON_MAND(ID_HELP_INSERT; OnHelpInsert)
ON_MAND(ID_APP_EXIT; OnAppExit)
ON_MAND(ID_DYNCMODIFY_APPEND; OnDyncmodifyAppend)
ON_MAND(ID_HELP_APPEND; OnHelpAppend)
ON_MAND(ID_DYNCMODIFY_DELETE; OnDyncmodifyDelete)
ON_MAND(ID_DYNCMODIFY_MODIFY; OnDyncmodifyModify)
ON_MAND(ID_DYNCMODIFY_MODIFYSYSTEMMENU; OnDyncmodifyModifysystemmenu)
ON_MAND(ID_DYNCMODIFY_RESET; OnDyncmodifyReset)
ON_MAND(ID_CHANGE; OnChange)
ON_WM_SYSMAND()
//此处为系统菜单消息响应声明,改变系统菜单后的消息处理必须声明该响应
ON_MAND(ID_FILE_NEW; OnFileNew)
ON_MAND(ID_VIEW_LONGMENU; OnViewLongmenu)
//}}AFX_MSG_MAP
END_MESSAGE_MAP( )
//以上函数映射部分仅供读者选用菜单ID时参考。但是,
//将这部分代码与实现系统菜单时的消息映射作一对比是有意义的。
static UINT indicators'' =
{
ID_SEPARATOR; // status line indicator
ID_INDICATOR_CAPS;
ID_INDICATOR_NUM;
…………………………………………………………Page 223……………………………………………………………
ID_INDICATOR_SCRL;
};
//此处为状态栏上的分配,具体我们在后面会有提及。
/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction
CMainFrame::CMainFrame()
{
// TODO: add member initialization code here
bInsert=TRUE;//防止菜单被重复插入的控制变量
bAppend=TRUE;//防止菜单被重复加入的控制变量
bDelete=TRUE;//防止菜单被重复删除的控制变量
bModify=TRUE;//防止菜单被重复修改的控制变量
bBitmap=FALSE;//标识是否使用了图符菜单
}
//在CMainFrame类的构造函数中,我们加入了一部分支持菜单动态
//处理控制的BOOL型变量,它们的定义在函数CMainFrame。h中
// 。。。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// 。。。
// 提示: 以下部分代码用于控制工具条提示及工具条本身实现,
//如果不需要可以将下面两行代码移去
m_wndToolBar。SetBarStyle(m_wndToolBar。GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
//提示:下面三行代码控制工具条是否可以移动,如果你并不
//希望工具条可以在屏幕内移动,可以删去它们。
…………………………………………………………Page 224……………………………………………………………
m_wndToolBar。EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
hLongMenu。LoadMenu(IDR_MAINFRAME1);
hNormalMenu。LoadMenu(IDR_MAINFRAME0);
hLine。LoadBitmap(IDB_LINE);
hCircle。LoadBitmap(IDB_CIRCLE);
hRectangle。LoadBitmap(IDB_RECTANGLE);
hText。LoadBitmap(IDB_TEXT);
//以上几行代码装入资源 (菜单,位图),但由于上下文菜单
//处理机制不一样,其资源并不在此处装入。
return