按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
445
…………………………………………………………Page 508……………………………………………………………
第篇 湷觥 FC 程式設計
标准菜单File / Edit / View / Window / Help
仔细观察你所能搜集到的各种MDI 程序,你会发现它们几乎都有两组菜单。一组是当
没有任何子窗口(文件窗口)存在时出现(本例代码是IDR_MAINFRAME ):
另一组则是当有任何子窗口(文件窗口)存在时出现(本例代码是IDR_SCRIBTYPE ):
446
…………………………………………………………Page 509……………………………………………………………
第7章 簡單而完整:MFC 骨幹程式
前者多半只有【File 】、【View 】、【Help 】等选项,后者就复杂了,程序所有的功能都
在上面。本例的IDR_MAINFRAME 和IDR_SCRIBTYPE 就代表RC 档中的两组菜单。
当使用者打开一份文件文件,程序应该把主窗口上的菜单换掉,这个动作在SDK 程序中
由程序员负责,在MFC 程序中则由Framework 代劳了。
拉下这些菜单仔细瞧瞧,你会发现Framework 真的已经为我们做了不少琐事。凡是菜单
项目会引起对话框的,像是Open 对话框、Save As 对话框、Print 对话框、Print Setup 对
话盒、Find 对话框、Replace 对话框,都已经恭候差遣;Edit 菜单上的每一项功能都已
经可以应用在由CEditView 掌控的文字编辑器上;File 菜单最下方记录着最近使用过的
(所谓LRU )四个文件名称(个数可在Appwizard 中更改),以方便再开启;View 选
单允许你把工具栏和状态列设为可见或隐藏;Window 菜单提供重新排列子窗口图标的
能力,以及对子窗口的排列管理,包括卡片式(Cascade )或拼贴式(Tile )。
下表是预设之菜单命令项及其处理例程的摘要整理。最后一个字段「是否预有关联」如
果是Yes ,意指只要你的程序菜单中有此命令项,当它被选按,自然就会引发命令处理
例程,应用程序不需要在任何类别的Message Map 中拦截此命令消息。但如果是No ,
表示你必须在应用程序中拦截此消息。
菜单内容 命令项ID 预设的处理函数 预有关联
File
New ID_FILE_NEW CWinApp::OnFileNew No
Open ID_FILE_OPEN CWinApp::OnFileOpen No
Close ID_FILE_CLOSE CDocument::OnFileClose Yes
Save ID_FILE_SAVE CDocument::OnFileSave Yes
Save As ID_FILE_SAVEAS CDocument::OnFileSaveAs Yes
Print ID_FILE_PRINT CView::OnFilePrint No
Print Pre&view ID_FILE_PRINT_PREVIEW CView::OnFilePrintPreview No
Print Setup ID_FILE_PRINT_SETUP CWinApp::OnFilePrintSetup No
〃Recent File Name〃 ID_FILE_MRU_FILE1~4 CWinApp::OnOpenRecentFile Yes
447
…………………………………………………………Page 510……………………………………………………………
第篇 湷觥 FC 程式設計
菜单内容 命令项ID 预设的处理函数 预有关联
Exit ID_APP_EXIT CWinApp::OnFileExit Yes
Edit
Undo ID_EDIT_UNDO None
Cut ID_EDIT_CUT None
Copy ID_EDIT_COPY None
Paste ID_EDIT_PASTE None
View
Toolbar ID_VIEW_TOOLBAR FrameWnd::OnBarCheck Yes
Status Bar ID_VIEW_STATUS_BAR FrameWnd::OnBarCheck Yes
( )
Window MDI only
New Window ID_WINDOW_NEW MDIFrameWnd::OnWindowNew Yes
Cascade ID_WINDOW_CASCADE MDIFrameWnd::OnWindowCmd Yes
Tile ID_WINDOW_TILE_HORZ MDIFrameWnd::OnWindowCmd Yes
Arrange Icons ID_WINDOW_ARRANGE MDIFrameWnd::OnWindowCmd Yes
Help
About AppName ID_APP_ABOUT None
上表的最后一字段为No 者有五笔,表示虽然那些命令项有预设的处理例程,但你必须
在自己的Message Map 中设定映射项目,它们才会起作用。噢,AppWizard 此时又表现
出了它的善体人意,自动为我们做出了这些码:
BEGIN_MESSAGE_MAP(CScribbleApp; CWinApp)
。。。
ON_MAND(ID_FILE_NEW; CWinApp::OnFileNew)
ON_MAND(ID_FILE_OPEN; CWinApp::OnFileOpen)
ON_MAND(ID_FILE_PRINT_SETUP; CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
BEGIN_MESSAGE_MAP(CScribbleView; CView)
。。。
ON_MAND(ID_FILE_PRINT; CView::OnFilePrint)
ON_MAND(ID_FILE_PRINT_PREVIEW; CView::OnFilePrintPreview)
END_MESSAGE_MAP()
448
…………………………………………………………Page 511……………………………………………………………
第7章 簡單而完整:MFC 骨幹程式
对话框
Scribble 可以激活许多对话框,前一节提了许多。唯一要程序员自己动手(我的意思是
出现在我们的程序代码中)的只有About 对话框。
为了拦截WM_MAND 的ID_APP_ABOUT 项目,首先我们必须设定其Message
Map :
BEGIN_MESSAGE_MAP(CScribbleApp; CWinApp)
ON_MAND(ID_APP_ABOUT; OnAppAbout)
ON_MAND(ID_FILE_NEW; CWinApp::OnFileNew)
ON_MAND(ID_FILE_OPEN; CWinApp::OnFileOpen)
ON_MAND(ID_FILE_PRINT_SETUP; CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
当消息送来,就由OnAppAbout 处理:
void CScribbleApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg。DoModal();
}
其中CAboutDlg 是CDialog 的衍生类别:
class CAboutDlg : public CDialog
{
enum { IDD = IDD_ABOUTBOX }; // IDD_ABOUTBOX 是RC 文件中的对话框模板资源
。。。
DECLARE_MESSAGE_MAP()
};
比之于SDK 程序中的对话框,这真是方便太多了。传统SDK 程序要在RC 文件中定义
对话框模板(dialog template,也就是其外形),在C 程序中设计对话框函数。现在只
需从CDialog 衍生出一个类别,然后产生该类别之对象,并指定RC 文件中的对话框面
板资源,再调用对话框对象的DoModal 成员函数即可。
第10 章一整章将讨论所谓的对话框数据交换(DDX )与对话框数据确认(DDV)。
449
…………………………………………………………Page 512……………………………………………………………
第篇 湷觥 FC 程式設計
改用CEditView
Scribble step0 除了把一个应用程序的空壳做好,不能再贡献些什么。如果我们在
AppWizard 步骤六中把CScribbleView 的基础类别从CView 改为CEditView,那可就
有大妙用了:
CEditView 是一个已具备文字编辑能力的类别,它所使用的窗口是Windows 的标准控
制组件之一Edit ,其SerializeRaw 成员函数可以把Edit 控制组件中的raw text (而非
「对象」所持有的资料)写到文件中。当我们在AppWizard 步骤六选择了它,程序代码中
所有的CView 统统变成CEditView,而最重要的两个虚拟函数则变成:
void CScribbleDoc::Serialize(CArchive& ar)
{
// CEditView contains an edit control which handles all serialization
((CEditView*)m_viewList。GetHead())…》SerializeRaw(ar);
}
void CScribbleView::OnDraw(CDC* pDC)
{