Lesson 04MFC骨干程序Word文件下载.docx
《Lesson 04MFC骨干程序Word文件下载.docx》由会员分享,可在线阅读,更多相关《Lesson 04MFC骨干程序Word文件下载.docx(14页珍藏版)》请在冰豆网上搜索。
Childfrm.h
Childfrm.cpp
CScribbleDoc
CDocument
ScribbleDoc.h
ScribbleDoc.cpp
CScribbleView
CView
ScribbleView.h
ScribbleView.cpp
CAboutDlg
CDialog
2.骨干程序(MDI)使用的所有MFC类
表2MDI程序使用的所有MFC类
MFC类名称
用户类名称
功能
应用程序对象
MDI主窗口
CMultiDocTemplate
直接使用
管理Document/View
文档,负责数据结构与文件操作
视图,负责数据的显示与打印
MDI子窗口
CToolBar
工具栏
CStatusBar
状态栏
About对话框
3.程序中的九个对象如图4
图4Scribble程序中的九个对象
注意:
虚线框表示应用程序通常不必改写该基础类,可以直接用
4.程序流程说明如下:
(1)~(4)theApp应用程序对象:
AfxWinMain()内部执行与前一课相同。
(5)改写InitInstance虚函数。
(6)new一个CMultiDocTemplate对象,该对象规划Document、View以及DocumentFrame窗口三者之间的关系。
(7)new一个CMyMDIFrameWnd对象,作为主窗口对象。
(8)调用LoadFrame,产生主窗口并加挂菜单等元素,指定窗口标题、文件标题、文件扩展名等(关键在IDR_MAINFRAME常量)。
LoadFrame内部将调用Create,后者将调用CreateWindowEx,于是触发WM_CREATE消息。
(9)由于在CMainFrame之中拦截WM_CREATE(利用ON_WM_CREATE宏),所以WM_CREATE产生之际Framework会调用OnCreate。
在此为主窗口挂上工具栏和状态栏。
(10)回到InitInstance,执行ShowWindow显示窗口。
(11)InitInstance结束,回到AfxWinMain,执行Run,进入消息循环。
(12)消息经过MessageRouting机制,在各类的MessageMap中寻求其相应的处理程序。
WM_COMMAND/ID_FILE_OPEN消息将由CWinApp:
:
OnFileOpen函数处理,此函数由MFC提供,在显示过[FileOpen]对话框之后调用Serialize函数。
(13)改写Serialize函数进行我们自己的读写操作。
(14)WM_COMMAND/ID_APP_ABOUT消息将由OnAppAbout函数处理。
(15)OnAppAbout函数利用CDialog的性质很方便地产生一个对话框。
5.DocumentTemplate的意义
程序每打开一份文件(数据),就会产生三份对象:
(1)一份Document对象(数据内容)
(2)一份View对象(数据表象)
(3)一份CMDIChildWnd对象,其作为外框窗口(容纳数据表象)
这三份对象由DocumentTemplate对象来管理,关键在CMultiDocTemplate:
BOOLCScribbleApp:
InitInstance()
{
……
CMultiDocTemplate*pDocTemplate;
pDocTemplate=newCMultiDocTemplate(
IDR_SCRIBBTYPE,
RUNTIME_CLASS(CScribbleDoc),
RUNTIME_CLASS(CChildFrame),//customMDIchildframe
RUNTIME_CLASS(CScribbleView));
AddDocTemplate(pDocTemplate);
}
如果程序支持不同的数据格式,如TEXT和BITMAP,则需要不同的DocumentTemplate:
BOOLCMyWinApp:
IDR_TEXTTYPE,
RUNTIME_CLASS(CTextDoc),
RUNTIME_CLASS(CTextView));
IDR_BMPTYPE,
RUNTIME_CLASS(CBmpDoc),
RUNTIME_CLASS(CBmpView));
CMultiDocTemplate的构造函数:
CMultiDocTemplate(UINTnIDResource,
CRuntimeClass*pDocClass,
CRuntimeClass*pFrameClass,
CRuntimeClass*pViewClass);
参数:
●nIDResource
SpecifiestheIDoftheresourcesusedwiththedocumenttype.Thismayincludemenu,icon,acceleratortable,andstringresources.
不同种类的资源可以使用相同的ID
IDR_SCRIBBTYPEICONDISCARDABLE"
res\\ScribbleDoc.ico"
IDR_SCRIBBTYPEMENUPRELOADDISCARDABLE
……
STRINGTABLEPRELOADDISCARDABLE
BEGIN
IDR_MAINFRAME"
Scribble"
IDR_SCRIBBTYPE"
\nScribb\nScribb\n\n\nScribble.Document\nScribbDocument”
END
●pDocClass
PointstotheCRuntimeClassobjectofthedocumentclass.ThisclassisaCDocument-derivedclassyoudefinetorepresentyourdocuments.
●pFrameClass
PointstotheCRuntimeClassobjectoftheframe-windowclass.ThisclasscanbeaCMDIChildWnd-derivedclass,oritcanbeCMDIChildWnditselfifyouwantdefaultbehaviorforyourdocumentframewindows
●pViewClass
PointstotheCRuntimeClassobjectoftheviewclass.ThisclassisaCView-derivedclassyoudefinetodisplayyourdocuments
关于字符串资源:
以‘\n’分隔为七个子字符串
如本例中:
\nScribb\nScribb\n\n\nScribble.Document\nScribbDocument
按顺序各子字符串意义:
每个子字符串都可在程序进行过程中取得,调用CDocTemplate:
GetDocString并在第二个参数中指定索引值(1~7)即可。
最好以CDocTemplate所定义的七个常量代替索引值。
CDocTemplate的七个常量定义:
(文件:
AFXWIN.H)
#ifdef_AFXDLL
classCDocTemplate:
publicCCmdTarget
#else
classAFX_NOVTABLECDocTemplate:
#endif
enumDocStringIndex
{
windowTitle,//defaultwindowtitle
docName,//uservisiblenamefordefaultdocument
fileNewName,//uservisiblenameforFileNew
//forfilebaseddocuments:
filterName,//uservisiblenameforFileOpen
filterExt,//uservisibleextensionforFileOpen
//forfilebaseddocumentswithShellopensupport:
regFileTypeId,//REGEDITvisibleregisteredfiletypeidentifier
regFileTypeName,//Shellvisibleregisteredfiletypename
};
程序中可以象下面这样:
CStringstrDefExt,strDocName;
pDocTemplate->
GetDocString(strDefExt,CDocTemplate:
filterExt);
GetDocString(strDocName,CDocTemplate:
docName);
七个子字符串的具体意义:
Index
意义
1.CDocTemplate:
windowTitle
主窗口标题栏上的字符串,SDI程序要指定,MDI程序不需要指定,以IDR_MAINFRAME字符串为默认值。
2.CDocTemplate:
docName
文件基底名,加流水号码为新文件名,未指定文件默认名称为“Untitled”
3.CDocTemplate:
fileNewName
文件类型名称,程序支持多文件,此字符串会显示在新建文件对话框,否则不显示,新建文件时也不会显示对话框。
4.CDocTemplate:
filterName
打开文件时的过滤字符串
5.CDocTemplate:
filterExt
文件扩展名,未指明时不能在打开文件对话框中处理该类文件
6.CDocTemplate:
regFileTypeId
注册表中注册的文件类型,未指明则无法注册,鼠标拖放功能受影响
7.CDocTemplate:
regFileTypeName
也是存储在注册表中的文件类型。
6.Document/View设计
(1)文件读写
CDocument中的Serialize函数。
(2)数据的显示与编辑等
●DocumentFrame窗口收到WM_PAINT消息,窗口内的View的OnPaint函数被调用,OnPaint又调用OnDraw。
所以为了显示数据一般要改写OnDraw。
OnPaint一般只输出到屏幕而不到打印机。
●为了接受编辑操作,一般在View中接受鼠标或键盘消息并处理。
例如:
afx_msgvoidOnLButtonDown(UINTnFlags,CPointpoint);
afx_msgvoidOnLButtonUp(UINTnFlags,CPointpoint);
afx_msgvoidOnMouseMove(UINTnFlags,CPointpoint);
7.主窗口的诞生
建立MDI主窗口:
new一个CMDIFameWnd对象;
调用LoadFrame函数
LoadFrame源代码如下:
WINFRM.CPP)
BOOLCFrameWnd:
LoadFrame(UINTnIDResource,DWORDdwDefaultStyle,
CWnd*pParentWnd,CCreateContext*pContext)
//onlydothisonce
ASSERT_VALID_IDR(nIDResource);
ASSERT(m_nIDHelp==0||m_nIDHelp==nIDResource);
m_nIDHelp=nIDResource;
//IDforhelpcontext(+HID_BASE_RESOURCE)
CStringstrFullString;
if(strFullString.LoadString(nIDResource))
AfxExtractSubString(m_strTitle,strFullString,0);
//firstsub-string
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
//attempttocreatethewindow
LPCTSTRlpszClass=GetIconWndClass(dwDefaultStyle,nIDResource);
LPCTSTRlpszTitle=m_strTitle;
if(!
Create(lpszClass,lpszTitle,dwDefaultStyle,rectDefault,
pParentWnd,MAKEINTRESOURCE(nIDResource),0L,pContext))
returnFALSE;
//willselfdestructonfailurenormally
}
//savethedefaultmenuhandle
ASSERT(m_hWnd!
=NULL);
m_hMenuDefault=:
GetMenu(m_hWnd);
//loadacceleratorresource
LoadAccelTable(MAKEINTRESOURCE(nIDResource));
if(pContext==NULL)//sendinitialupdate
SendMessageToDescendants(WM_INITIALUPDATE,0,0,TRUE,TRUE);
returnTRUE;
窗口产生之际会发出WM_CREATE消息,CMainFrame:
OnCreate会被执行,在那里进行工具栏和状态栏的建立。
LoadFrame函数的参数(IDR_MAINFRAME)用来设定窗口所使用的资源。
IDR_MAINFRAMEICONDISCARDABLE"
res\\Scribble.ico"
IDR_MAINFRAMEMENUPRELOADDISCARDABLE
{……}
IDR_MAINFRAMEACCELERATORSPRELOADMOVEABLEPURE
IDR_MAINFRAME"
(将作为主窗口的标题)
LoadFrame执行如图5所示:
图5构建MDI主窗口
8.工具栏和状态栏的产生(Toolbar&
Statusbar)
(1)工具栏和状态栏对象声明
(2)OnCreate函数中与工具栏和状态栏的产生和设定有关的操作
●IDR_MAINFRAME在RC文件中代表两种与工具栏有关的资源:
BITMAP和TOOLBAR
●状态栏中有关indicators的七种定义(文件:
AFXRES.H)
//Modeindicatorsinstatusbar-theseareroutedlikecommands
#defineID_INDICATOR_EXT0xE700//extendedselectionindicator
#defineID_INDICATOR_CAPS0xE701//caplockindicator
#defineID_INDICATOR_NUM0xE702//numlockindicator
#defineID_INDICATOR_SCRL0xE703//scrolllockindicator
#defineID_INDICATOR_OVR0xE704//overtypemodeindicator
#defineID_INDICATOR_REC0xE705//recordmodeindicator
#defineID_INDICATOR_KANA0xE706//kanalockindicator
例子程序中使用的三种:
9.工具栏和状态栏的产生(Toolbar&
每一个派生自CCmdTarget的类都可以有自己的MessageMap用于处理消息。
先在类声明处加DECLARE_MESSAGE_MAP宏,然后在.cpp文件中使用BEGIN_MESSAGE_MAP和END_MESSAGE_MAP两个宏,宏中间的就是消息与处理函数的对应关系。
例如CScribbleApp类中的消息映射:
BEGIN_MESSAGE_MAP(CScribbleApp,CWinApp)
//{{AFX_MSG_MAP(CScribbleApp)
ON_COMMAND(ID_APP_ABOUT,OnAppAbout)
//NOTE-theClassWizardwilladdandremovemappingmacroshere.
//DONOTEDITwhatyouseeintheseblocksofgeneratedcode!
//}}AFX_MSG_MAP
//Standardfilebaseddocumentcommands
ON_COMMAND(ID_FILE_NEW,CWinApp:
OnFileNew)
ON_COMMAND(ID_FILE_OPEN,CWinApp:
OnFileOpen)
//Standardprintsetupcommand
ON_COMMAND(ID_FILE_PRINT_SETUP,CWinApp:
OnFilePrintSetup)
END_MESSAGE_MAP()
10.标准菜单File/Edit/View/Window/help
MDI程序一般会有两组菜单:
一种是当没有任何子窗口(文件窗口)存在时出现(本例代码是IDR_MAINFRAME),另一组是当有任何子窗口(文件窗口)存在时出现(本例代码是IDR_SCRIBTYPE)。
菜单内容
命令项ID
默认的处理函数
预有关联
File
New
ID_FILE_NEW
CWinApp:
OnFileNew
No
Open
ID_FILE_OPEN
OnFileOpen
Close
ID_FILE_CLOSE
CDocument:
OnFileClose
Yes
Save
ID_FILE_SAVE
OnFileSave
SaveAs
ID_FILE_SAVEAS
OnFileSaveAs
Print
ID_FILE_PRINT
CView:
OnFilePrint
PrintPre&
view
ID_FILE_PRINT_PREVIEW
OnFilePrintPreview
PrintSetup
ID_FILE_PRINT_SETUP
OnFilePrintSetup
"
RecentFileName"
ID_FILE_MRU_FILE1~4
OnOpenRecentFile
Exit
ID_APP_EXIT
OnFileExit
Edit
Undo
ID_EDIT_UNDO