深入浅出MFC第2版(PDF格式)-第90部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
ID_SEPARATOR; // status line indicator
ID_INDICATOR_CAPS;
ID_INDICATOR_CAPS;
ID_INDICATOR_NUM;
ID_INDICATOR_NUM;
ID_INDICATOR_SCRL;
ID_INDICATOR_SCRL;
};
};
鼠标拖放(Drag and Drop)
MFC 程序很容易拥有Drag and Drop 功能。意思是,你可以从Shell (例如Windows 95
的文件总管)中以鼠标拉动一个文件,拖到你的程序中,你的程序因而打开此文件并读
其内容,将内容放到一个Document Frame 窗口中。甚至,使用者在Shell 中以鼠标对
某个文件文件(你的应用程序的文件文件)快按两下,也能激活你这个程序,并自动完成开
档,读档,显示等动作。
442
…………………………………………………………Page 505……………………………………………………………
第7章 簡單而完整:MFC 骨幹程式
在SDK 程序中要做到Drag and Drop ,并不算太难,这里简单提一下它的原理以及作
法。当使用者从Shell 中拖放一个文件到程序A,Shell 就配置一块全域内存,填入被
拖曳的文件名称(包含路径),然后发出WM_DROPFILES 传到程序A的消息队列。程
式A取得此消息后,应该把内存的内容取出,再想办法开档读档。
并不是张三和李四都可以收到WM_DROPFILES ,只有具备WS_EX_ACCEPTFILES 风格
的窗口才能收到此一消息。欲让窗口具备此一风格,必须使用CreateWindowEx (而不
是传统的CreateWindow),并指定第一个参数为WS_EX_ACCEPTFILES 。
剩下的事情就简单了:想办法把内存中的文件名和其它信息取出(内存handle 放在
WM_DROPFILES 消息的wParam 中)。这件事情有DragQueryFile 和DragQueryPoint
两个API 函数可以帮助我们完成。
SDK 的方法真的不难,但是MFC 程序更简单:
BOOL CScribbleApp::InitInstance()
{
。。。
// Enable drag/drop open
m_pMainWnd…》DragAcceptFiles();
// Enable DDE Execute open
EnableShellOpen();
RegisterShellFileTypes(TRUE);
。。。
}
这三个函数的用途如下:
CWnd::DragAcceptFile(BOOL bAccept=TRUE); 参数TRUE 表示你的主窗口以
及每一个子窗口(文件窗口)都愿意接受来自Shell 的拖放文件。CFrameWnd 内
有一个OnDropFiles 成员函数,负责对WM_DROPFIELS 消息做出反应,它
会通知application 对象的OnOpenDocument (此函数将在第8章介绍),并夹
带被拖放的文件的名称。
443
…………………………………………………………Page 506……………………………………………………………
第篇 湷觥 FC 程式設計
CWinApp::EnableShellOpen(); 当使用者在Shell 中对着本程序的文件文件快按
两下时,本程序能够打开文件并读内容。如果当时本程序已执行,Framework
不会再执行起程序的另一副本,而只是以DDE (Dynamic Data Exchange ,动态
资料交换)通知程序把文件(文件)读进来。DDE 处理例程内建在CDocManager
之中(第8章会谈到这个类别)。也由于DDE 的能力,你才能够很方便地把
文件图标拖放到打印机图标上,将文件打印出来。
通常此函数后面跟随着RegisterShellFileTypes 。
CWinApp::RegisterShellFileTypes(); 此函数将向Shell 注册本程序的文件型
态。有了这样的注册动作,使用者在Shell 的双击动作才有着力点。这个函数
搜寻Document Template 串行中的每一种文件类型,然后把它加到系统所维护
的registry (登录数据库)中。
在传统的Windows 程序中,对Registry 的注册动作不外乎两种作法,一是准
备一个。reg 档,由使用者利用Windows 提供的一个小工具regedit。exe ,将。reg
合并到系统的Registry 中。第二种方法是利用::RegCreateKey 、::RegSetValue
等Win32 函数,直接编辑Registry 。MFC 程序的作法最简单,只要调用
CWinApp::RegisterShellFileTypes 即可。
必须注意的是,如果某一种文件类型已经有其对应的应用程序(例如。txt 对应
Notepad ,。bmp 对应PBrush ,。ppt 对应PowerPoint ,。xls 对应Excel ),那么你的程序
就不能够横刀夺爱。如果本例Scribble 的文件档扩展名为。txt ,使用者在Shell 中双击
这种文件,激活的将是Notepad 而不是Scribble。
另一个要注意的是,拖放动作可以把任何类型的文件文件拉到你的窗口中,并不只限于你
所注册的文件类型。你可以把。bmp 文件从Shell 拉到Scribble 窗口,Scribble 程序一样
会读它并为它准备一个窗口。想当然耳,那会是个无言的结局:
444
…………………………………………………………Page 507……………………………………………………………
第7章 簡單而完整:MFC 骨幹程式
消息映射(Message Map)
每一个衍生自CCmdTarget 的类别都可以有自己的Message Map 以处理消息。首先你应
该在类别声明处加上DECLARE_MESSAGE_MAP 宏, 然后在。CPP 档中使用
BEGIN_MESSAGE_MAP 和END_MESSAGE_MAP 两个宏,宏中间夹带的就是「讯
息与函数对映关系」的一笔笔记录。
你可以从图7…6 那个浓缩的Scribble 源代码中看到各类别的Message Map 。
本例CScribbleApp 类别接受四个WM_MAND 消息:
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()
除了ID_APP_ABOUT 是由我们自己设计一个OnAppAbout 函数处理之,其它三个讯
息都交给CWinApp 成员函数去处理,因为那些动作十分制式,没什么好改写的。到底
有哪些制式动作呢?看下一节!
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