框架窗口文档和视图_第1页
框架窗口文档和视图_第2页
框架窗口文档和视图_第3页
框架窗口文档和视图_第4页
框架窗口文档和视图_第5页
已阅读5页,还剩56页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

框架窗口文档和视图第1页,课件共61页,创作于2023年2月7.1框架窗口7.1.1主窗口和文档窗口 主窗口是应用程序直接放置在桌面上的那个窗口,每个应用程序只能有一个主窗口,主窗口的标题栏上往往显示应用程序的名称。 文档窗口对于SDI程序来说,它和主窗口是一致的,即主窗口就是文档窗口;而对于MDI程序,文档窗口是主窗口的子窗口,如图。文档窗口一般都有相应的可见边框,它的客户区是由相应的视图来构成的,因此可以说视图是文档窗口内的子窗口。文档窗口时刻跟踪当前处于活动状态的视图的变化,并将用户或系统产生的命令消息传递给当前活动视图。而主窗口负责管理各个用户交互对象并根据用户操作相应地创建或更新文档窗口及其视图。图7.1MDI应用程序的框架窗口文档窗口主窗口第2页,课件共61页,创作于2023年2月7.1框架窗口7.1.2窗口风格的设置窗口风格 窗口风格通常有一般和扩展两种形式。这两种形式的窗口风格可在函数CWnd::Create或CWnd::CreateEx参数中指定,CreateEx函数可同时支持以上两种风格,而CWnd::Create只能指定窗口的一般风格。需要说明的是,对于控件和对话框这样的窗口来说,它们的窗口风格可直接通过其属性对话框来设置。 需要说明的是,除了上述风格外,框架窗口还有以下三个自己的风格。它们都可以在PreCreateWindow重载函数中指定。FWS_ADDTOTITLE

该风格指定相关的信息如文档名添加到框架窗口标题的后面。FWS_PREFIXTITLE

该风格使得框架窗口标题中的文档名显示在应用程序名之前。FWS_SNAPTOBARS

该风格用来调整窗口的大小,使它刚好包含了框架窗口中的控制栏。第3页,课件共61页,创作于2023年2月7.1框架窗口用MFCAppWizard设置图7.2MFCAppWizard的窗口风格设置第4页,课件共61页,创作于2023年2月7.1框架窗口修改CREATESTRUCT结构 窗口创建之前,系统自动调用PreCreateWindow虚函数。在用MFCAppWizard创建SDI/MDI应用程序结构时,MFC已为主窗口或文档窗口类自动重载了该虚函数。可以在此函数中通过修改CREATESTRUCT结构来设置窗口的绝大多数风格。 例如,在SDI程序中,框架窗口默认的风格是WS_OVERLAPPEDWINDOW和FWS_ADDTOTITLE的组合,更改风格代码:

BOOLCMainFrame::PreCreateWindow(CREATESTRUCT&cs) { //新窗口不带有[最大化]按钮

cs.style&=~WS_MAXIMIZEBOX; //将窗口的大小设为1/3屏幕并居中

cs.cy=::GetSystemMetrics(SM_CYSCREEN)/3; cs.cx=::GetSystemMetrics(SM_CXSCREEN)/3; cs.y=((cs.cy*3)-cs.cy)/2; cs.x=((cs.cx*3)-cs.cx)/2; //调用基类的PreCreateWindow函数

returnCFrameWnd::PreCreateWindow(cs); }

对于MDI程序,文档窗口的风格可用下列的代码更改:

BOOLCChildFrame::PreCreateWindow(CREATESTRUCT&cs) { //创建不含有[最大化]按钮的子窗口

cs.style&=~WS_MAXIMIZEBOX; //调用基类的PreCreateWindow函数

returnCMDIChildWnd::PreCreateWindow(cs); }第5页,课件共61页,创作于2023年2月7.1框架窗口使用ModifyStyle和ModifyStyleEx CWnd类中的成员函数ModifyStyle和ModifyStyleEx也可用来更改窗口的风格,其中ModifyStyleEx还可更改窗口的扩展风格。这两个函数具有相同的参数,其含义如下。

BOOLModifyXXXX(DWORDdwRemove,DWORDdwAdd,UINTnFlags=0);

参数dwRemove用来 指定需要删除的风格,dwAdd用来指定需要增加的风格,nFlags表示SetWindowPos的标志,0(默认)表示更改风格的同时不调用SetWindowPos函数。 由于框架窗口在创建时不能直接设定其扩展风格,因此只能通过调用ModifyStyle函数来进行。

第6页,课件共61页,创作于2023年2月7.1框架窗口

[例Ex_Vscroll]多文档(MDI)的子文档窗口增加垂直滚动条。

(1)用MFCAppWizard创建一个多文档应用程序。

(2)用ClassWizard为子文档窗口类CChildFrame添加OnCreateClient消息处理,并增加下列代码:

BOOLCChildFrame::OnCreateClient(LPCREATESTRUCTlpcs,CCreateContext*pContext) { ModifyStyle(0,WS_VSCROLL,0); returnCMDIChildWnd::OnCreateClient(lpcs,pContext); }

(3)编译并运行,如图。图7.3为文档子窗口添加垂直滚动条第7页,课件共61页,创作于2023年2月7.1框架窗口设置TopMost窗口风格 最顶(TopMost)窗口是指那些始终出现在桌面的最前方且不会被其他窗口覆盖的窗口。如果要创建这样的一个最顶窗口,则在运行时必须指定WS_EX_TOPMOST扩展窗口风格。此风格的设置是在CWnd::SetWindowPos函数中进行;作为技巧,我们可以先调用CWnd::GetExStyle函数来确定是否已经设置了WS_EX_TOPMOST风格。例如下面的代码:

voidSetWindowTopMost(CWnd*pWnd) { ASSERT_VALID(pWnd); pWnd->SetWindowPos((pWnd->GetExStyle()&WS_EX_TOPMOST)? &wndNoTopMost:&wndTopMost,0,0,0,0, SWP_NOSIZE|SWP_NOMOVE); }

函数SetWindowPos具体的使用方法将在下一节中介绍。第8页,课件共61页,创作于2023年2月7.1框架窗口7.1.3窗口状态的改变用ShowWindow改变窗口的显示状态 当一个新的应用程序创建之后,InitInstance函数总会调用ShowWindow函数来显示窗口 想要改变改变窗口显示状态,只需根据上表选择所需的参数值,调用ShowWindow函数就可达到目的。当然,也可对CWinApp的公有型(public)成员变量m_nCmdShow进行赋值,同样能达到效果。下面的代码是将窗口的初始状态设置为“最小化”:

BOOLCEx_SdiApp::InitInstance() { ... m_nCmdShow=SW_SHOWMINIMIZED; //由于CEx_SdiApp类继承了基类CWinApp的特性,因此也可在派生类

//CEx_SdiApp使用这个公有型成员变量m_nCmdShow。

m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); returnTRUE; }第9页,课件共61页,创作于2023年2月7.1框架窗口用SetWindowPos或MoveWindow改变窗口的大小和位置SetWindowPos不仅可以改变窗口的大小、位置,还可以改变所有窗口在堆栈排列的次序(Z次序),这个次序是根据它们在屏幕出现的先后来确定的。函数CWnd::MoveWindow也可用来改变窗口的大小和位置,用户必须在MoveWindow函数中指定窗口的大小。

voidMoveWindow(intx,inty,intnWidth,intnHeight,BOOLbRepaint=TRUE); voidMoveWindow(LPCRECTlpRect,BOOLbRepaint=TRUE);

参数x和y表示 窗口新的左上角坐标,nWidth和nHeight表示窗口新的宽度和高度,bRepaint用于指定窗口是否重绘,lpRect表示窗口新的大小和位置。使用上述两个函数把主窗口移动到屏幕的(100,100)处(代码添在CEx_SdiApp::InitInstance中[returnTRUE]语句之前)。

//使用SetWindowPos函数的示例

m_pMainWnd->SetWindowPos(NULL,100,100,0,0,SWP_NOSIZE|SWP_NOZORDER); CRectrcWindow; //使用MoveWindow函数的示例

m_pMainWnd->GetWindowRect(rcWindow); m_pMainWnd->MoveWindow(100,100,rcWindow.Width(),rcWindow.Height(),TRUE);改变窗口的大小和位置的CWnd成员函数还不止以上两个。例如CenterWindow函数是使窗口居于父窗口中央,就像下面的代码:

CenterWindow(CWnd::GetDesktopWindow()); //将窗口置于屏幕中央

AfxGetMainWnd()->CenterWindow(); //将主框架窗口居中第10页,课件共61页,创作于2023年2月7.2文档及其序列化

7.2.1单文档和多文档 一个多文档应用程序的示例过程:

(1)用MFCAppWizard创建一个多文档应用程序项目Ex_Mdi。由于向导默认创建的就是这种程序类型,因此只要在向导的Step1对话框中单击[Finish]按钮即可创建一个默认的多文档应用程序。

(2)打开CEx_MdiApp::InitInstance可看出与默认的单文档应用程序不同的代码是: BOOLCEx_MdiApp::InitInstance() { …

CMultiDocTemplate*pDocTemplate; pDocTemplate=newCMultiDocTemplate( IDR_EX_MDITYPE,

RUNTIME_CLASS(CEx_MdiDoc), RUNTIME_CLASS(CChildFrame),//MDI文档子窗口 RUNTIME_CLASS(CEx_MdiView)); AddDocTemplate(pDocTemplate); //创建MDI主框架窗口 CMainFrame*pMainFrame=newCMainFrame; if(!pMainFrame->LoadFrame(IDR_MAINFRAME)) returnFALSE; m_pMainWnd=pMainFrame; … }第11页,课件共61页,创作于2023年2月7.2文档及其序列化

(3)用ClassWizard为该项目添加一个CDocument派生类CAnotherDoc,并在CEx_Mdi-App::InitInstance增加下列代码:

BOOLCEx_MdiApp::InitInstance() { … CMultiDocTemplate*pDocTemplate; pDocTemplate=newCMultiDocTemplate(IDR_EX_MDITYPE, RUNTIME_CLASS(CEx_MdiDoc), RUNTIME_CLASS(CChildFrame),//MDI文档子窗口

RUNTIME_CLASS(CEx_MdiView)); AddDocTemplate(pDocTemplate); CMultiDocTemplate*pAnother; pAnother=newCMultiDocTemplate(IDR_EX_MDITYPE, RUNTIME_CLASS(CAnotherDoc), RUNTIME_CLASS(CChildFrame),//MDI文档子窗口

RUNTIME_CLASS(CEx_MdiView)); AddDocTemplate(pAnother); //创建MDI主框架窗口

CMainFrame*pMainFrame=newCMainFrame; if(!pMainFrame->LoadFrame(IDR_MAINFRAME)) returnFALSE; m_pMainWnd=pMainFrame; … }第12页,课件共61页,创作于2023年2月7.2文档及其序列化

(4)在Ex_Mdi.cpp文件的开始处,添加包含CAnotherDoc类的头文件:

#include"AnotherDoc.h"

(5)编译并运行后,如图,从中选择一个文档类型。任何时候,选择Ex_Mdi程序的“文件”菜单

“新建”命令或单击“新建”工具按钮都将弹出此对话框。 选定第二个文档类型后,单击[确定]。这时程序出现一个断言错误,这是因为在视图类中有一个GetDocument函数,它的代码如下:

CEx_MdiDoc*CEx_MdiView::GetDocument()//non-debugversionisinline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CEx_MdiDoc))); return(CEx_MdiDoc*)m_pDocument; }

创建的文档类型是CAnotherDoc时,由于两种类型的文档共用一个视图,调用的GetDocument函数是同一个函数,因此断言不成立,程序不能正常运行。

(6)用ClassWizard为该项目添加一个CView类的派生类CAnotherView,并将InitInstance第二模板pAnother中的CEx_MdiView改成CAnotherView,然后在该源文件前面添加CAnotherView的头文件AnotherView.h。

(7)再次运行,上述问题得到解决。但是,图7.4的文档“新建”对话框中显示的文档类型名称应该怎么修改呢?这时就需要使用文档的字串资源。图7.4文档“新建”对话框第13页,课件共61页,创作于2023年2月7.2文档及其序列化7.2.2文档的字串资源 通过对文档的字串资源修改可以改变文档窗口标题、文档类型以及通用文件对话框中的某些内容。例如下面的示例过程: (1)打开前面的多文档应用程序项目Ex_Mdi。 (2)打开StringTable,将IDR_EX_MDITYPE字串资源复制,复制后的ID为IDR_ANOTHERTYPE,修改这两个字串资源,结果如下表所示。 如果IDR_ANOTHERTYPE的值不等于130,可在其属性对话框中直接给标识赋值,如图。 (3)将InitInstance第二模板pAnother中的资源号IDR_EX_MDITYPE改成IDR_ANOTHERTYPE。图7.5指定标识值第14页,课件共61页,创作于2023年2月7.2文档及其序列化

(4)重新编译并运行,如图。测试后还发现“打开”或“保存”对话框中的“文件类型”框中显示出文档字串资源定义的类型名,如图。 文档资源字串的内容也可在文档应用程序创建时的AdvancedOptions对话框中指定,如图,图中数字表示该项的含义与表中对应串号的含义相同。图7.7Ex_Mdi运行结果图7.8AdvancedOptions对话框0456213图7.6“新建”对话框第15页,课件共61页,创作于2023年2月7.2文档及其序列化7.2.3SDI序列化过程创建空文档

应用程序类的InitInstance函数在调用了AddDocTemplate函数之后,会通过CWinApp::ProcessShellCommand间接调用CWinApp的另一个非常有用的成员函数OnFileNew,并依次完成下列工作:

(1)构造文档对象,但并不从磁盘中读数据。

(2)构造主框架类CMainFrame的对象,并创建该主框架窗口,但不显示。

(3)构造视图对象,并创建视图窗口,也不显示。

(4)通过内部机制,使文档、主框架和视图“对象”之间“真正”建立联系。AddDocTemplate函数建立的是“类”之间的联系。

(5)调用文档对象的CDocument::OnNewDocument虚成员函数,并调用CDocument::DeleteContents(清除文档对象的内容)虚函数。

(6)调用视图对象的CView::OnInitialUpdate虚成员函数。

(7)调用框架对象的CFrameWnd::ActiveFrame虚成员函数,以便显示出具有菜单、工具栏、状态栏以及视图窗口的主框架窗口。

MFCAppWizard为用户在文档类中自动产生OnNewDocument虚函数的重载,用户利用此函数框架可以对文档对象进行初始化。

第16页,课件共61页,创作于2023年2月7.2文档及其序列化打开文档

MFCAppWizard创建应用程序时,它会自动将“文件(File)”菜单中的“打开(Open)”命令(ID号为ID_FILE_OPEN)映射到CWinApp的OnFileOpen成员函数。这一结果可以从应用类(.cpp)的消息入口处得到验证:

BEGIN_MESSAGE_MAP(CEx_SdiApp,CWinApp) …… 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() OnFileOpen函数还会进一步完成下列工作:

(1)弹出通用“打开”对话框,供用户选择一个文件。

(2)调用文档对象的CDocument::OnOpenDocument虚成员函数。该函数将打开文件,并调用DeleteContents清除文档对象的内容,然后创建一个CArchive对象用于数据的读取,接着又自动调用Serialize函数。

(3)调用视图对象的CView::OnInitialUpdate虚成员函数。第17页,课件共61页,创作于2023年2月7.2文档及其序列化

MFC为我们重载了Serialize函数,使得我们不必使用CFile类就可以完成相应的文档操作。例如,在文档类中有这样的代码: voidCEx_SdiDoc::Serialize(CArchive&ar) { if(ar.IsStoring()) { //TODO:addstoringcodehere } else { //TODO:addloadingcodehere } } 只需根据ar.IsStoring()结果的“真”与“假”就可决定向文档写与读数据。例如,在此判断体中,可以增加一些代码来读取文档中的数据: voidCEx_SdiDoc::Serialize(CArchive&ar) { if(ar.IsStoring()) {} else { for(inti=0;i<sizeof(m_ch);i++) ar>>m_ch[i]; CStringstr; str.Format(_T(“%s”),m_ch); AfxMessageBox(str); } }第18页,课件共61页,创作于2023年2月7.2文档及其序列化保存文档

MFCAppWizard创建应用程序时,会自动将“文件(File)”菜单中的“保存(Save)”命令与文档类CDocument的OnFileSave函数在内部关联起来,在程序框架中看不到相应的代码。OnFileSave函数还会进一步完成下列工作:

(1)弹出通用“保存”对话框,让用户提供一个文件名。

(2)调用文档对象的CDocument::OnSaveDocument虚成员函数,接着又自动调用Serialize函数,将CArchive对象的内容保存在文档中。

需要说明的是:只有在保存文档之前还没有存过盘或读取的文档是“只读”的,OnFileSave函数才会弹出通用“保存”对话框。否则,只执行第二步。“文件(File)”菜单中还有一个“另存为(SaveAs)”命令,它是与文档类CDocument的OnFileSaveAs函数相关联。不管文档有没有保存过,OnFileSaveAs都有会执行上述两个步骤。 可以用ClassWizard来重载CDocument::OnSaveDocument函数,并可在Serialize函数体的ar.IsStorinr()为“真”的条件语句处添加代码来在文档中保存用户自己的数据,第19页,课件共61页,创作于2023年2月7.2文档及其序列化关闭文档

试图关闭文档时,应用程序会根据文档是否修改进一步完成下列任务:若文档内容已被修改,则弹出一个消息对话框,询问用户是否需要将文档保存。若用户选择“是”,则应用程序执行OnFileSave过程。调用CDocument::OnCloseDocument虚成员函数,关闭所有与该文档相关联的文档窗口及相应的视图,调用文档类CDocument的DeleteContents清除文档数据。MFC应用程序通过CDocument的数据成员m_bModified的逻辑值来判断用户是否对文档进行修改,如果m_bModified为“真”,则表示文档被修改。protected类型的m_bModified标记是通过CDocument的SetModifiedFlag和IsModified成员函数被访问的。当文档创建、从磁盘中读出以及文档存盘时,文档的这个标记就被置为FALSE(假);而当文档数据被修改时,必须使用SetModifiedFlag函数将该标记置为TRUE。关闭文档时,应用程序才会显示询问消息对话框。第20页,课件共61页,创作于2023年2月7.2文档及其序列化7.2.4使用CFile和CArchive类使用CFile类

(1)文件的打开和关闭

在MFC中,使用CFile打开一个文件通常使用下列两个步骤:构造一个不带指定任何参数的CFile对象;调用成员函数Open并指定文件路径以及文件标志。 Open函数的原型如下: BOOLOpen(LPCTSTRlpszFileName,UINTnOpenFlags,CFileException*pError=NULL);第21页,课件共61页,创作于2023年2月7.2文档及其序列化

(2)文件的读写和定位

CFile类支持文件的读、写和定位操作。它们相关函数的原型如下:UINTRead(void*lpBuf,UINTnCount);

将文件中指定大小的数据读入指定的缓冲区,返回向缓冲区传输的字节数。voidWrite(constvoid*lpBuf,UINTnCount);

此函数将缓冲区的数据写到文件中。LONGSeek(LONGlOff,UINTnFrom);

定位文件指针的位置,若要定位的位置是合法的,返回从文件开始的偏移量。否则,返回值是不定的且激活一个CFileException对象。函数voidSeekToBegin()和DWORDSeekToEnd()分别将文件指针移动到文件开始和结尾位置,对于后者还将返回文件的大小。

第22页,课件共61页,创作于2023年2月7.2文档及其序列化

(3)获取文件的有关信息

BOOLGetStatus(CFileStatus&rStatus)const; staticBOOLPASCALGetStatus(LPCTSTRlpszFileName,CFileStatus&rStatus);

若指定文件的状态信息成功获得,该函数返回TRUE,否则返回FALSE。rStatus用来存放文件状态信息,是一个CFileStatus结构类型,该结构具有下列成员:

CTimem_ctime 文件创建日期和时间

CTimem_mtime 文件最后一次修改日期和时间

CTimem_atime 文件最后一次访问日期和时间

LONGm_size 文件的逻辑大小字节数,就像DOS命令中DIR所显示的大小

BYTEm_attribute 文件属性

charm_szFullName[_MAX_PATH]文件名 例如下面的代码:

CFiletheFile; char*szFileName="c:\\test\\myfile.dat"; BOOLbOpenOK; CFileStatusstatus; if(CFile::GetStatus(szFileName,status)) { bOpenOK=theFile.Open(szFileName,CFile::modeWrite); } else { bOpenOK=theFile.Open(szFileName,CFile::modeCreate|CFile::modeWrite); }第23页,课件共61页,创作于2023年2月7.2文档及其序列化使用CArchive类

(1)CArchive类对象的创建和关闭 创建CArchive对象,有两种方法:一是通过框架隐式创建CArchive对象,另一是显式创建CArchive对象。

(2)使用“<<”和“>>”运算符

(3)文件文本的读写

CArchive提供成员函数ReadString和WriteString用来从一个文件对象中读写一行文本,它们的原型如下:

BoolReadString(CString&rString); LPTSTRReadString(LPTSTRlpsz,UINTnMax); voidWriteString(LPCTSTRlpsz);第24页,课件共61页,创作于2023年2月7.2文档及其序列化7.2.5使用简单数组集合类简单数组集合类的构造及元素的添加 对简单数组集合类构造的方法都是一样的,都是使用各自的构造函数,它们的原型如下:

CByteArray CByteArray(); CDWordArray CDWordArray(); CPtrArray CPtrArray(); CStringArray CStringArray(); CUIntArray CUIntArray(); CWordArray CWordArray();

为了有效使用内存,在使用简单数组集合类之前最好调用成员函数SetSize设置此数组的大小,与其对应的函数是GetSize,用来返回数组的大小。它们的原型如下:

voidSetSize(intnNewSize,intnGrowBy=-1); intGetSize()const;

向简单数组集合类添加一个元素,可使用成员函数Add和Append,它们的原型如下:

intAdd(CObject*newElement); intAppend(constCObArray&src);第25页,课件共61页,创作于2023年2月7.2文档及其序列化访问简单数组集合类的元素 在MFC中,一个简单数组集合类元素的访问既可以使用GetAt函数,也可使用“[]”操作符,例如: //CObArray::operator[]示例 CObArrayarray; CAge*pa; //CAge是一个用户类 array.Add(newCAge(21)); //添加一个元素 array.Add(newCAge(40)); //再添加一个元素 pa=(CAge*)array[0]; //获取元素0 ASSERT(*pa==CAge(21)); array[0]=newCAge(30); //替换元素0; ASSERT(*(CAge*)array[0]==CAge(30)); //CObArray::GetAt示例 CObArrayarray; array.Add(newCAge(21)); //元素0 array.Add(newCAge(40)); //元素1 ASSERT(*(CAge*)array.GetAt(0)==CAge(21));第26页,课件共61页,创作于2023年2月7.2文档及其序列化删除简单数组集合类的元素 删除简单数组集合类中的元素一般需要进行以下几个步骤:

(1)使用函数GetSize()和整数下标值访问简单数组集合类中的元素。

(2)若对象元素是在堆中创建的,则使用delete删除每一个对象元素。

(3)调用函数RemoveAll()删除简单数组集合类中的所有元素。 例如,下面代码过程是一个CObArray的删除示例:

CObArrayarray; CAge*pa1; CAge*pa2; array.Add(pa1=newCAge(21)); array.Add(pa2=newCAge(40)); ASSERT(array.GetSize()==2); for(inti=0;i<array.GetSize();i++)deletearray.GetAt(i); array.RemoveAll();

函数RemoveAll是删除数组中的所有元素,而函数RemoveAt(intnIndex,intnCount=1)则表示要删除数组中指定元素开始的指定数目的元素。第27页,课件共61页,创作于2023年2月7.3视图及视图类

7.3.1一般视图类的使用图7.9“Step6”对话框第28页,课件共61页,创作于2023年2月7.3视图及视图类CFormView类CFormView类是一个非常有用的视图类,它具有许多无模式对话框的特点。像CDiolog的派生类一样,CFormView的派生类也和相应的对话框资源相联系,它也支持对话框数据交换和对话框数据确认(DDX和DDV)。CFormView是所有表单视(如CRecordView、CDaoRecordView、CHtmlView等)的基类;一个基于表单的应用程序能让用户在程序中创建和使用一个或多个表单。创建表单应用程序的基本方法除了在创建SDI/MDI的第六步中选择CFormView作为应用程序视图类的基类外。还可通过相关菜单命令来自动插入一个表单,其步骤如下:

(1)切换到ClassView标签项,在项目名称上右击鼠标按钮。从弹出的快捷菜单中选择“NewForm”命令,或者直接在主菜单中选择“Insert”

“NewForm...”菜单命令,弹出如图7.10的“NewForm”对话框。

(2)在“NewForm”对话框中,键入表单名称。如果想要表单支持“自动化”特性,则选择“Automation”单选框。在“DocumentTemplateInformation”栏中,指定和表单并联的文档内容。如果想要更改文件扩展名或文档模板字串资源,则可按击[Change]按钮。

(3)单击[OK]按钮,这样,一个表单视图派生类的程序框架就被添加到用户程序中;此时,我们就可用对话框编辑器为表单增加一些控件。第29页,课件共61页,创作于2023年2月7.3视图及视图类CEditView类

CEditView类对象是一种视图,提供窗口编辑控制功能,可以执行简单文本操作。由于CEditView类自动封装上述功能的映射函数,因此只要在文档模板中使用CEditView类,那么应用程序的“编辑”菜单和“文件”菜单里的菜单项都可自动激活。 但CEditView仍然摆脱不了所有编辑控件的限制,如:CEditView不具有所见即所得编辑功能。CEditView只能将文本作单一字体的显示,不支持特殊格式的字符。CEditView可容纳的文本总数有限,在32位Windows中最多不超过1M字节。图7.10“NewForm”对话框第30页,课件共61页,创作于2023年2月7.3视图及视图类

CRichEditView类

CRichEditView类使用了复文本编辑控件,因此它支持混合字体格式和更大数据量的文本。CRichEditView类被设计成与CRichEditDoc和CRichEditCntrItem类一起使用,它们可实现一个完整的ActiveX包容器应用程序。

CHtmlView类

CHtmlView类是在文档视图结构中提供WebBrowser控件的功能。WebBrowser控件可以浏览网址,也可以作为本地文件和网络文件系统的窗口,它支持超级链接、统一资源定位(URL)导航器并维护历史列表等。CScrollView类

CScrollView类不仅能直接支持视图的滚动操作,而且还能管理视口的大小和映射模式,并能响应滚动条消息、键盘消息以及鼠标滚轮消息。 滚动视图第一次被创建时,往往在重载的CView::OnInitialUpdate或CView::OnUpdate中调用CScrollView成员函数SetScrollSizes来设置相关参数,如映射模式、滚动逻辑窗口的大小、水平或垂直方向的滚动量等。如果仅需要视图具有自动缩放功能(而不具有滚动特性),则用CScrollView::SetScaleToFitSize函数代替SetScrollSizes即可。第31页,课件共61页,创作于2023年2月7.3视图及视图类7.3.2列表控件和列表视图列表控件的风格及其修改第32页,课件共61页,创作于2023年2月7.3视图及视图类列表项的基本操作

函数SetImageList用来为列表控件设置一个关联的图像列表,其原型如下:

CImageList*SetImageList(CImageList*pImageList,intnImageList);函数InsertItem用来向列表控件中插入一个列表项。该函数成功时返回新列表项的索引号,否则返回-1。函数原型如下:

intInsertItem(constLVITEM*pItem); intInsertItem(intnItem,LPCTSTRlpszItem); intInsertItem(intnItem,LPCTSTRlpszItem,intnImage); pItem用来指定一个指向LVITEM结构的指针,其结构描述如下:

typedefstruct_LVITEM { UINT mask; //指明哪些参数有效

int iItem; //列表项索引

int iSubItem; //子项索引

UINT state; //列表项状态

UINT stateMask; //指明state哪些位是有效的,-1全部有效

LPTSTR pszText; //列表项文本标签

int cchTextMax; //文本大小

int iImage; //在图像列表中列表项图标的索引号。

LPARAM lParam; //32位值

int iIndent; //项目缩进数量,1个数量等于1个图标的像素宽度

}LVITEM,FAR*LPLVITEM;第33页,课件共61页,创作于2023年2月7.3视图及视图类函数DeleteItem和DeleteAllItems分别用来删除指定的列表项和全部列表项,函数原型如下:

BOOLDeleteItem(intnItem); BOOLDeleteAllItems();函数FindItem用来查寻列表项,函数成功查找时返回列表项的索引号,否则返回-1。其原型如下:

intFindItem(LVFINDINFO*pFindInfo,intnStart=-1)const; pFindInfo表示要查找的信息,其结构描述如下:

typedefstructtagLVFINDINFO { UINT flags; //查找方式

LPCTSTR psz; //匹配的文本

LPARAM lParam; //匹配的值

POINT pt; //查找开始的位置坐标。

UINT vkDirection;//查找方向,用虚拟方向健值表示。

}LVFINDINFO,FAR*LPFINDINFO;函数Arrange用来按指定方式重新排列列表项,其原型如下:

BOOLArrange(UINTnCode);第34页,课件共61页,创作于2023年2月7.3视图及视图类函数InsertColumn用来向列表控件插入新的一列,函数成功调用后返回新的列的索引,否则返回-1。其原型如下:

intInsertColumn(intnCol,constLVCOLUMN*pColumn); intInsertColumn(intnCol,LPCTSTRlpszColumnHeading,intnFormat=LVCFMT_LEFT, intnWidth=-1,intnSubItem=-1); pColumn表示包含新列信息的LVCOLUMN结构地址,其结构描述如下:

typedefstruct_LVCOLUMN { UINT mask; //指明哪些参数有效

int fmt; //列的标题或子项文本格式

int cx; //列的像素宽度

LPTSTR pszText; //列的标题文本

int cchTextMax; //列的标题文本大小

int iSubItem; //和列相关的子项索引

int iImage; //图像列表中的图像索引

int iOrder; //列的序号,最左边的列为0 }LVCOLUMN,FAR*LPLVCOLUMN;函数DeleteColumn用来从列表控件中删除一个指定的列,其原型如下:

BOOLDeleteColumn(intnCol);GetItemCount用来返回列表控件中的列表项个数等。它们的原型如下:

BOOLSetColumnWidth(intnCol,intcx); intGetItemCount();第35页,课件共61页,创作于2023年2月7.3视图及视图类列表控件的消息

常用的列表控件消息有:

LVN_BEGINDRAG 用户按左鼠拖动列表列表项

LVN_BEGINLABELEDIT 用户对某列表项标签进行编辑

LVN_COLUMNCLICK 某列被按击

LVN_ENDLABELEDIT 用户对某列表项标签结束编辑

LVN_ITEMACTIVATE 用户激活某列表项

LVN_ITEMCHANGED 当前列表项已被改变

LVN_ITEMCHANGING 当前列表项即将改变

LVN_KEYDOWN 某键被按下 在用ClassWizard处理上述这些消息时,其消息处理函数参数中往往会出现NM_LISTVIEW结构,其定义如下:

typedefstructtagNMLISTVIEW { NMHDR hdr; //包含通知消息的结构

int iItem; //列表项索引,没有为-1 int iSubItem; //子项索引,没有为0 UINT uNewState; //新的项目状态

UINT uOldState; //原来的项目状态

UINT uChanged; //项目属性更改标志

POINT ptAction; //事件发生的地点

LPARAM lParam; //用户定义的32位值

}NMLISTVIEW,FAR*LPNMLISTVIEW;第36页,课件共61页,创作于2023年2月7.3视图及视图类

[例Ex_Lview]将当前文件夹中的文件用“大图标”、“小图标”、“列表视图”以及“报表视图”四种不同方式在列表视图中显示出来。当双击某个列表项时,还将该项的文本标签内容用消息对话框的形式显示出来。

(1)用MFCAppWziard创建一个单文档应用程序Ex_List,在创建的第六步将视图的基类选择为CListView。

(2)为CEx_ListView类添加下列成员函数和成员函数:

public: CImageList m_ImageList; CImageList m_ImageListSmall; CStringArraym_strArray; voidSetCtrlStyle(HWNDhWnd,DWORDdwNewStyle);

(3)将项目工作区窗口切换到ResourceView页面,打开Accelerator节点下的IDR_MAINFRAME,为其添加一个键盘加速键Ctrl+Shift+X,其ID号为ID_VIEW_CHANGE。

(4)用ClassWizard为CEx_ListView类添加ID_VIEW_CHANGE的COMMAND消息映射函数,并增加下列代码:

voidCEx_ListView::OnViewChange() { staticintnStyleIndex=1; DWORDstyle[4]={LVS_REPORT,LVS_ICON,LVS_SMALLICON,LVS_LIST}; CListCtrl&m_ListCtrl=GetListCtrl(); SetCtrlStyle(m_ListCtrl.GetSafeHwnd(),style[nStyleIndex]); nStyleIndex++; if(nStyleIndex>3)nStyleIndex=0; }第37页,课件共61页,创作于2023年2月7.3视图及视图类

(5)用ClassWizard为CEx_ListView类添加NM_DBLCLK消息映射函数,增加代码:

voidCEx_ListView::OnDblclk(NMHDR*pNMHDR,LRESULT*pResult) { LPNMITEMACTIVATElpItem=(LPNMITEMACTIVATE)pNMHDR; intnIndex=lpItem->iItem; if(nIndex>=0) { CListCtrl&m_ListCtrl=GetListCtrl(); CStringstr=m_ListCtrl.GetItemText(nIndex,0); MessageBox(str); } *pResult=0; } (6)在CEx_ListView::OnInitialUpdate中添加下列代码:

voidCEx_ListView::OnInitialUpdate() { CListView::OnInitialUpdate(); //创建图像列表

m_ImageList.Create(32,32,ILC_COLOR8|ILC_MASK,1,200); m_ImageListSmall.Create(16,16,ILC_COLOR8|ILC_MASK,1,200); CListCtrl&m_ListCtrl=GetListCtrl(); m_ListCtrl.SetImageList(&m_ImageList,LVSIL_NORMAL); m_ListCtrl.SetImageList(&m_ImageListSmall,LVSIL_SMALL); LV_COLUMNlistCol; char*arCols[4]={"文件名","大小","类型","修改日期"}; listCol.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;第38页,课件共61页,创作于2023年2月7.3视图及视图类

for(intnCol=0;nCol<4;nCol++) { listCol.iSubItem=nCol; listCol.pszText=arCols[nCol]; if(nCol==1) listCol.fmt=LVCFMT_RIGHT; else listCol.fmt=LVCFMT_LEFT; m_ListCtrl.InsertColumn(nCol,&listCol); } //查找当前目录下的文件

CFileFindfinder; BOOLbWorking=finder.FindFile("*.*"); intnItem=0,nIndex,nImage; CTimem_time; CStringstr,strTypeName; while(bWorking) { bWorking=finder.FindNextFile(); if(finder.IsArchived()) { str=finder.GetFilePath(); SHFILEINFOfi; SHGetFileInfo(str,0,&fi,sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_LARGEICON|SHGFI_TYPENAME); strTypeName=fi.szTypeName; nImage=-1;

第39页,课件共61页,创作于2023年2月7.3视图及视图类

for(inti=0;i<m_strArray.GetSize();i++) { if(m_strArray[i]==strTypeName) { nImage=i; break; } } if(nImage<0) { nImage=m_ImageList.Add(fi.hIcon); SHGetFileInfo(str,0,&fi,sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_SMALLICON); m_ImageListSmall.Add(fi.hIcon); m_strArray.Add(strTypeName); } nIndex=m_ListCtrl.InsertItem(nItem,finder.GetFileName(),nImage); DWORDdwSize=finder.GetLength(); if(dwSize>1024) str.Format("%dK",dwSize/1024); else str.Format("%d",dwSize); m_ListCtrl.SetItemText(nIndex,1,str); m_ListCtrl.SetItemText(nIndex,2,strTypeName); finder.GetLastWriteTime(m_time); m_ListCtrl.SetItemText(nIndex,3,m_time.Format("%Y-%m-%d")); nItem++; }}第40页,课件共61页,创作于2023年2月7.3视图及视图类

SetCtrlStyle(m_ListCtrl.GetSafeHwnd(),LVS_REPORT); m_ListCtrl.SetColumnWidth(0,LVSCW_AUTOSIZE);//设置列宽

m_ListCtrl.SetColumnWidth(1,100); m_ListCtrl.SetColumnWidth(2,LVSCW_AUTOSIZE); m_ListCtrl.SetColumnWidth(3,200); } (7)编译并运行,如图。

图7.11Ex_List运行结果第41页,课件共61页,创作于2023年2月7.3视图及视图类7.3.3树控件和树视图树形视图的风格第42页,课件共61页,创作于2023年2月7.3视图及视图类树控件的常用操作函数InsertItem用来向树控件插入一个新项,操作成功后,函数返回新项的句柄,否则返回NULL。函数原型如下:

HTREEITEMInsertItem(UINTnMask,LPCTSTRlpszItem,intnImage,intnSelectedImage, UINTnState,UINTnStateMask,LPARAMlParam, HTREEITEMhParent,HTREEITEMhInsertAfter); HTREEITEMInsertItem(LPCTSTRlpszItem,HTREEITEMhParent=TVI_ROOT, HTREEITEMhInsertAfter=TVI_LAST); HTREEITEMInsertItem(LPCTSTRlpszItem,intnImage,intnSelectedImage, HTREEITEMhParent=TVI_ROOT, HTREEITEMhInsertAfter=TVI_LAST);函数DeleteItem和DeleteAllItems分别用来删除指定的项和全部的项。它们的原型如下:

BOOLDeleteAllItems(); BOOLDeleteItem(HTREEITEMhItem);函数Expand用来用来展开或收缩指定父项的所有子项,其原型如下:

BOOLExpand(HTREEETEMhItem,UINTnCode);第43页,课件共61页,创作于2023年2月7.3视图及视图类树形视图控件的通知消息 树视图可以用ClassWizard映射公共控件消息和树控件消息。常用的树控件消息有:

TVN_BEGINDRAG 开始拖放操作

TVN_BEGINLABELEDIT 开始编辑标签

TVN_BEGINRDRAG 鼠标右按钮开始拖放操作

TVN_ENDLABELEDIT 标签编辑结束

TVN_ITEMEXPANDED 含有子项的父项已展开或收缩

TVN_ITEMEXPANDING 含有子项的父项将要展开或收缩

TVN_SELCHANGED 当前选择项发生改变

TVN_SELCHANGING 当前选择项将要发生改变 用ClassWizard处理上述这些消息时,其消息处理函数参数中往往会出现NM_TREEVIEW结构,定义如下:

typedefstructtagNMTREEVIEW { NMHDR hdr; //含有通知代码的信息结构

UINT action; //通知方式标志

TVITEM itemOld; //原有项的信息

TVITEM itemNew; //现在项的信息

POINT ptDrag; //事件产生时,鼠标的位置

}NMTREEVIEW,FAR*LPNMTREEVIEW;第44页,课件共61页,创作于2023年2月7.3视图及视图类

[例Ex_Tree]遍历本地磁盘所有的目录。

(1)用MFCAppWziard创建一个单文档应用程序Ex_Tree,在创建的第六步将视图的基类选择为CTreeView。

(2)按快捷键Ctrl+R,选定资源类型Icon,单击Import按钮,从外部调入六个图标,分别表示“我的电脑”、“软驱”、“硬盘”、“光驱”、“文件夹”以及“打开的文件夹”,相应的ID号设为IDI_MYCOMP、IDI_35FLOPPY、IDI_DRIVE、IDI_CDDRIVE、IDI_CLSDFOLD和IDI_OPENFOLD,如图。图7.12从外部调入的图标第45页,课件共61页,创作于2023年2月7.3视图及视图类

(3)为CEx_TreeView类添加下列成员函数和成员函数:

public: CImageList m_ImageList; CString m_strPath; //文件夹路径

voidInsertFoldItem(HTREEITEMm_hItem); voidSetCtrlStyle(HWNDhWnd,DWORDdwNewStyle); InsertFoldItem函数的代码如下:

voidCEx_TreeView::InsertFoldItem(HTREEITEMm_hItem) { CFileFindfinder; BOOLbWorking=finder.FindFile(m_strPath); CStringm_str; while(bWorking) { bWorking=finder.FindNextFile(); if(finder.IsDirectory()&&!finder.IsHidden()) { m_str=finder.GetFileName(); m_str.TrimRight(); m_str.TrimLeft(); if((m_str!=_T("."))&&(m_str!=_T(".."))) { CTreeCtrl&m_TreeCtrl=GetTreeCtrl(); m_TreeCtrl.InsertItem(m_str,4,5,m_hItem);} } } }

第46页,课件共61页,创作于2023年2月7.3视图及视图类

(4)为CEx_TreeView类添加TVN_ITEMSELECTED消息处理,增加代码:

voidCEx_TreeView::OnSelchanged(NMHDR*pNMHDR,LRESULT*pResult) { NM_TREEVIEW*pNMTreeView=(NM_TREEVIEW*)pNMHDR; HTREEITEMm_hSelected=pNMTreeView->itemNew.hItem; CTreeCtrl&m_TreeCtrl=GetTreeCtrl(); if((!m_TreeCtrl.ItemHasChildren(m_hSelected))&&(m_hSelected)){ BOOLm_bIsTop=FALSE; CStringm_str; m_strPath.Empty(); HTREEITEMm_hTemp=m_hSelected; while(!m_bIsTop){ m_str=m_TreeCtrl.GetItemText(m_hTemp); m_str.TrimLeft(); m_str.TrimRight(); m_strPath=m_str+"\\"+m_strPath; m_TreeCtrl.GetParentItem(m_hTemp); if(m_TreeCtrl.GetParentItem(m_TreeCtrl.GetParentItem(m_hTemp))){ m_hTemp=m_TreeCtrl.GetParentItem(m_hTemp); }elsem_bIsTop=TRUE; } m_strPath+=_T("*."); InsertFoldItem(m_hSelected); m_TreeCtrl.Expand(m_hSelected,TVE_EXPAND); } *pResult=0; }

第47页,课件共61页,创作于2023年2月7.3视图及视图类

(5)在CEx_TreeView::OnInitialUpdate函数中添加下列代码:

voidCEx_TreeView::OnInitialUpdate() { CTreeView::OnInitialUpdate(); CTreeCtrl&m_TreeCtrl=GetTreeCtrl(); m_ImageList.Create(16,16,ILC_COLOR|ILC_MASK,6,0); m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_MYCOMP)); m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_35FLOPPY)); m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_DRIVE)); m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_CDDRIVE)); m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_CLSDFOLD)); m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_OPENFOLD)); m_TreeCtrl.SetImageList(&m_ImageList,TVSIL_NORMAL); HTREEITEMm_hRootItem,m_hTempItem; m_hRootItem=m_TreeCtrl.InsertItem("我的电脑",0,0); //查找并检测已有的驱动器

DWORDdwDrives=GetLogicalDrives(); UINTuType; CStringm_strDrive,m_strTemp;第48页,课件共61页,创作于2023年2月7.3视图及视图类

for(inti=0;i<32;i++) { DWORDdwTemp=dwDrives; if(dwTemp&1) { m_strTemp.Format(_T("%c:\\."),'A'+(char)i); uType=GetDriveType(m_strTemp); m_strTemp.Format(_T("%c:"),'A'+(char)i); switch(uType){ caseDRIVE_REMOVABLE: m_TreeCt

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论