VC++技术内幕(第四版)笔记(第12~15章)

第十二章:菜单、键盘加速键、复文本编辑控件和属性表


1,主框架窗口包含标题栏和菜单栏,而各种各样的子窗口(包括工具栏窗口、状态栏窗口和视图窗口)覆盖着主框架窗口的客户区域。应用程序通过框架和视图之间的消息传递来控制框架和视图之间的相互作用。

2,MFC应用程序框架提供了一个非常复杂的命令消息传递系统,这些消息来自菜单的选择、键盘加速、以及工具栏和对话框按钮,另外,命令消息也可以通过调用CWnd::SendMessage或PostMessage函数来发送。
1)大多数命令消息都来自主框架窗口,但应用程序框架并没有对其一一的响应处理,需要我们自己在适当的地方添加响应函数加以响应处理。
2)当应用程序框架接收到框架窗口的命令,它将按下列次序来寻找其消息控制函数:
SDI程序(单文档):视图(VIEW类)-》文档(DOC类)-》SDI主框架窗口(FRAME类)-》应用程序(APP类)。
MDI程序(多文档):视图--》文档--》MDI子框架窗口--》MDI主框架窗口--》应用程序。
说明:
当框架接收到框架窗口命令,安上叙的次序寻找其消息控制函数的时候,一旦找到,就停止继续往下寻找,这样当路径中有多个该消息控制函数的时候,只执行先找到的那个。

3,命令传递系统反映对命令消息控制的一个方面,类的层次结构反映了对命令消息进行控制处理的另一个方面。
1)一般,派生类会继承基类所有的消息映射函数,其中包括命令消息函数。
2)如果想对基类的消息映射函数进行重载,就必须在派生类中加入相应的消息映射函数和相应的消息映射入口(及函数声明)。

4,所有的弹出式菜单都属于主框架窗口。
1)弹出式菜单上按钮(及资源编辑器中菜单项)的ID必须在0x8000-0xDFFF范围内,才可以产生可被传递的命令消息。
2)使用符号编辑器来输入ID,可以保证ID范围落在0x8000-0xDFFF范围内。
(注:书中是弹出式对话框,不过应该是弹出式菜单才对。)

5,CFrameWnd::m_bAutoMenuEnable
//Controls automatic enable and disable functionality for menu items.
//CFrameWnd类中的BOOL型数据成员,默认为TRUE。
//如果m_bAutoMenuEnable设为TRUE,则如果某菜单项在当前命令路径中无法找到相应的命令消息控制函数,则此时应用程序框架便禁用该菜单项,并将该菜单项设为灰色。
//如果m_bAutoMenuEnable设为FALSE,便可以禁止上叙自动禁用无控制函数菜单项的特性。
(试一试:自己在框架类构造函数CMainFrame::CMainFrame()中添加this->m_bAutoMenuEnable=TRUE语句,然后看看菜单里菜单项里看看有什么变化哦)


6,MFC文本编辑选择
1)CEditView类:文本大小限制在64K以内,不能设混合字体,实现了基本的编制功能。
2)CRichEditView类:使用了富文本编辑控件,支持混合字体和大数据量文本。
3)CRichEditCtrl类:封装了富文本编辑控件。
//CRichEditCtrl   A window in which the user can enter and edit text with character and paragraph formatting. The control can include embedded OLE objects.


7,示例事例说明:
事例EX12A(未优化前的)中使用CRichEditCtrl类来在基类为CView类的项目中设计编辑功能:
1)方法:构造CRichEditCtrl类对象,并为之创建控件窗口与之关联,设置控件窗口为当前视图客户区大小,使CRichEditCtrl类控件窗口覆盖当前视图客户区,CRichEditCtrl类控件窗口具有富文本编辑功能,从而完成设计。
2)实现细节:
CRichEditCtrl m_rich;//构造CRichEditCtrl对象
m_rich.Create(ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN | WS_CHILD | WS_VISIBLE | WS_VSCROLL,rect,this,1);//创建控件窗口用以初始化CRichEditCtrl对象
m_rich.SetWindowPos(&wndTop,0,0,rect.right-rect.left,rect.bottom-rect.top,SWP_SHOWWINDOW);
//设置CRichEditCtrl控件窗口大小(使用GetClientRect(rect)获得视图客户区大小)和位置,即覆盖视图客户区域。
3)获取和保存控件文本技巧:
在VIEW类中获取对应DOC类对象指针:CEX12aDoc *pDoc=GetDocument();
获取控件窗口文本:m_rich.SetWindowText(pDoc->m_strText);
设置控件窗口文本:m_rich.GetWindowText(pDoc->m_strText);
技巧说明:在视图类中利用GetDocument()函数获取其对应文档类对象指针,从而可将m_rich控件窗口文本保持到文档类数据成员m_strText中。
4)CRichEditCtrl::SetModify
void SetModify( BOOL bModified = TRUE );
bModified》》A value of TRUE indicates(象征,预示) that the text has been modified, and a value of FALSE indicates it is unmodified. By default, the modified flag is set.
5)关于加速键的添加:在在资源管理器Accelerator中添加(如:ID_GETDATA   VK_F2)。

8,学用属性表
这里提供一种利用资源管理器创建属性表的方法:
第一步:利用资源管理器添加几个对话框作为属性页(这样可方便往属性页上添加控件并处理了)。
第二步:分别为作为属性页的对话框创建类,基类采用CPropertyPage。
第三步:利用类向导创建用户属性表类,基类采用CPropertySheet。
第四步:在刚创建的用户属性表类中添加需要属性页类数据成员,并在属性表类构造函数中调用CPropertySheet::AddPage函数将所需要的属性页一一添加到属性表中去。目前为止属性表类创建结束。
第五步: 在需要创建和显示属性表的地方构造用户属性表对象,并调用CPropertySheet::DoModal显示。
说明:
1)CPropertySheet
Objects of class CPropertySheet represent property sheets, otherwise known as tab dialog boxes. A property sheet consists of a CPropertySheet object and one or more CPropertyPage objects. A property sheet is displayed by the framework as a window with a set of tab indices, with which the user selects the current page, and an area for the currently selected page.

Even though CPropertySheet is not derived from CDialog, managing a CPropertySheet object is similar to managing a CDialog object.

Exchanging data between a CPropertySheet object and some external object is similar to exchanging data with a CDialog object.

2)CPropertyPage
Objects of class CPropertyPage represent individual pages of a property sheet, otherwise known as a tab dialog box. As with standard dialog boxes, you derive a class from CPropertyPage for each page in your property sheet. To use CPropertyPage-derived objects, first create a CPropertySheet object, and then create an object for each page that goes in the property sheet. Call CPropertySheet::AddPage for each page in the sheet, and then display the property sheet by calling CPropertySheet::DoModal for a modal property sheet, or CPropertySheet::Create for a modeless property sheet.

3)Apply按钮的处理:
在所有的属性表类中,只要控件给属性页发送一个消息(如:点击或选择属性页上的控件,框架便调用该属性页OnCommand函数来响应这些控件所发出的通告消息,OnCommand函数是虚函数),在每个属性页中重载OnCommand函数设置SetModified(TRUE)可使Apply按钮有效。
当用户点击Apply按钮,框架自动调用OnApply函数,可以在重载它来完成一些重要的任务。
CWnd::OnCommand 
virtual BOOL OnCommand( WPARAM wParam, LPARAM lParam );
//The framework calls this member function when the user selects an item from a menu, when a child control sends a notification message, or when an accelerator keystroke is translated.

CPropertyPage::OnApply
virtual BOOL OnApply( );
//This member function is called by the framework when the user chooses the OK or the Apply Now button. When the framework calls this function, changes made on all property pages in the property sheet are accepted, the property sheet retains focus, and OnApply returns TRUE (the value 1). Before OnApply can be called by the framework, you must have called SetModified and set its parameter to TRUE. This will activate the Apply Now button as soon as the user makes a change on the property page.

Override this member function to specify what action your program takes when the user clicks the Apply Now button. When overriding, the function should return TRUE to accept changes and FALSE to prevent changes from taking effect.

The default implementation of OnApply calls OnOK.


9,CMenu类
CMenu类对象可以用来表示各种Windows菜单,包括顶层菜单项及相应的弹出式菜单。
添加菜单方法:
程序添加法:1)定义菜单资源;2)构造菜单对象;3)调用CMenu::LoadMenu函数将菜单将菜单资源载入;4)调用CWnd::SetMenu函数将菜单连接到框架窗口中;5)调用CMenu::Detach函数把对象HMENU句柄独立出来(这样当CMenu对象销毁时候,菜单不随之销毁)
/
/

另一中简便的添加菜单方法:如果想为某对话框添加菜单,可从话框属性中Menu项中选择资源管理器中的需要的菜单完成添加工作。

10,创建浮动式弹出菜单
步骤:
1)用资源编辑器添加菜单资源
2)在视图类或其他接收鼠标右键单击的窗口类中添加WM_CONTEXTMENU消息控制函数,编辑代码如下:
void CAboutDlg::OnContextMenu(CWnd* pWnd, CPoint point)
{
 CMenu menu;
 menu.LoadMenu(IDR_MENU1);
 menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,point.x,point.y,this);
 
}
说明:
GetSubMenu函数得到指向弹出式菜单的CMenu指针。
TrackPopupMenu在指定位置显示浮动菜单,并跟踪弹出菜单的选择项。

11,关于扩展命令的处理:
扩展命令无法使用向导添加,需要自己添加,添加的方法如普通的命令处理类似。具体参看书P256-257页。


/
后续章节笔记待续


 

第十三章:工具栏和状态栏

 

1,工具栏是CToolBar类一个对象,状态栏是CStatusBar类的对象.CToolBar类和CStatusBar类均由CControlBar类派生.CControlBar类则由CWnd类派生.
CControlBar类所支持的控制栏窗口位于主框架窗口内,并且这些控制栏窗口能够随着主框架窗口的尺寸改变或移动自动调整自己的尺寸与位置.
控制栏对象的构造与析构以及窗口的创建都是由应用程序框架来管理的,其向导产生的代码位于框架头文件和代码文件中.

2,工具栏的按钮被按下是会象菜单或加速键一样,发送相应的命令消息(该命令消息会象菜单命令一样进行传递.原因:工具栏对象以及状态栏对象都与主框架窗口联系.).
更新命令UI消息控制函数一方面可以用来更新工具栏中的按钮的状态,另一方面可以用来修改工具栏中的按钮图形.
整个工具栏只有一个位图,每一个按钮在其中占一个高15像素宽16像素的位图片.
注意:不要直接编辑工具栏位图,而是应该使用DeveloperStudio的特定工具栏编辑工具进行编辑.

3,更新命令消息控件函数主要是用来对菜单项进行禁止和复选的,但也可以作用于工具栏按钮.
1)CCmdUI::Enable
virtual void Enable( BOOL bOn = TRUE );
//bOn: TRUE to enable the item, FALSE to disable it.
//Call this member function to enable or disable the user-interface item for this command.
2)CCmdUI::SetCheck
virtual void SetCheck( int nCheck = 1 );
//nCheck: Specifies the check state to set. If 0, unchecks; if 1, checks; and if 2, sets indeterminate.
//Call this member function to set the user-interface item for this command to the appropriate check state. This member function works for menu items and toolbar buttons. The indeterminate state applies only to toolbar buttons.

4,当某菜单项所在的弹出式菜单弹出时候,对该菜单项进行处理的更新命令UI消息控制函数才会被调用.
工具栏总是处于显示状态,对它进行处理的更新命令UI控制函数是在应用程序的空状态处理过程中被调用的.
当同一个更新命令UI控制函数既需要对某菜单项处理,又需要对某工具栏按钮进行处理,则在空状态处理过程及当该菜单项所在的弹出式菜单弹出时候,该控制函数都会被调用.

5,创建工具提示:
把提示文本加在菜单提示的后面,前面加一个换行符.如在Prompt:打印活动文档/n打印

6,几个重要函数
1)CWnd::GetParentFrame 
CFrameWnd* GetParentFrame( ) const;
//Return Value:A pointer to a frame window if successful; otherwise NULL.
//Call this member function to retrieve the parent frame window. The member function searches up the parent chain until a CFrameWnd (or derived class) object is found.
//MDI中得到的是MDI子框架窗口.
2)AfxGetApp 
CWinApp* AfxGetApp( );
//Return Value:A pointer to the single CWinApp object for the application.
//The pointer returned by this function can be used to access application information such as the main message-dispatch code or the topmost window.
通过应用程序获得主框架窗口指针:(单文档和多文档程序均适用)
 CMainFrame* pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;
 CToolBar* pToolBar=&pFrame->m_wndToolBar;
注:在SDI程序中,当视图的OnCreate函数被调用时候,m_pMainWnd还没有被设置,这时候可通过CWnd::GetParentFrame来获取主框架窗口指针.
说明:
在MDI程序中AppWizard向导自动生成了对m_pMainWain的赋值代码.而在SDI中,框架是在视图的创建的过程中对m_pMainWain的赋值代码的.


7,工具栏编辑器的使用:用鼠标选中某按钮,然后按DEL键可以擦除该按钮的像素;如果想删掉某个按钮,只需要把它拖出工具栏即可.

8,工具栏的停靠:
在CMainFrame::OnCreate函数中可以看到如下代码,该代码允许工具栏在框架窗口任何边筐处停靠:
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
说明:
1)CControlBar::EnableDocking
//Call this function to enable a control bar to be docked. The sides specified must match one of the sides enabled for docking in the destination frame window, or the control bar cannot be docked to that frame window.
2)CFrameWnd::EnableDocking
//Call this function to enable dockable control bars in a frame window. By default, control bars will be docked to a side of the frame window in the following order: top, bottom, left, right.
3)CFrameWnd::DockControlBar
//Causes a control bar to be docked to the frame window. The control bar will be docked to one of the sides of the frame window specified in the calls to both CControlBar::EnableDocking and CFrameWnd::EnableDocking. The side chosen is determined by nDockBarID.

 

9,状态栏既不接受用户输入也不产生命令消息,它的作用就是在程序的控制下在窗格(pane)中显示一些文本.
状态栏支持两种类型文本窗格(信息行窗格 和 状态指示器窗格).
注:为实现在状态栏中显示一些应用程序的特殊数据,必须先禁止标准状态栏显示菜单提示及键盘状态.(具体方法?)
1)AppWizard在MainFrm.cpp文件中产生的静态数组indicators是用以定义状态栏的.
static UINT indicators[] =
{
 ID_SEPARATOR,           // status line indicator
 ID_INDICATOR_CAPS, //以下均为串资源ID
 ID_INDICATOR_NUM,
 ID_INDICATOR_SCRL,
};
2)CStatusBar::SetIndicators//根据indicators[]数组内容对状态栏进行设置.
BOOL SetIndicators( const UINT* lpIDArray, int nIDCount );
//Sets each indicator’s ID to the value specified by the corresponding element(对应元素) of the array lpIDArray, loads the string resource specified by each ID, and sets the indicator’s text to the string.
//SetIndicators在应用程序的派生框架类中被调用.在CMainFrame::OnCreate函数中可以看见.
3)信息行窗格所显示的是储蓄动态提供的字符串.
对信息行的设置:首先访问状态栏对象,然后再用从0开始的索引参数来调用CStatusBar::SetPaneText函数设置.
如:
 CMainFrame* pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;
 CStatusBar* pStatus=&pFrame->m_wndStatusBar;
 pStatus->SetPaneText(0,"message line for first pane");
4)状态指示器窗格总是与一个字符串相连,该字符串是由字符串资源来提供的(在string table里设置),它是否被显示完全取决于相应的更新命令UI控制函数.
指示器是由一个字符串资源ID来标识的,该ID也被用来传递更新命令UI消息.
afx_msg void CMainFrame::OnUpdateKeyCapsLock(CCmdUI *pCmdUI);
ON_UPDATE_COMMAND_UI(ID_INDICATOR_CAPS,OnUpdateKeyCapsLock)
void CMainFrame::OnUpdateKeyCapsLock(CCmdUI *pCmdUI)
{
 pCmdUI->Enable(::GetKeyState(VK_CAPITAL)&1);
}
说明:
状态栏的更新命令UI消息控制函数是在空闲处理阶段被调用的.(推测:调用的时候传入CCmdUI指针).
5)状态指示器窗格的长度即为相应字符串资源的长度.


10,获取状态栏的控制.
1)用于键盘状态指示器的更新命令UI控制函数被嵌入在主框架窗口类中,它们与资源字符串ID(indicators[]中定义的串资源ID)相联.
2)状态栏实际上有一个子窗口(即status line indicator),其默认ID在CMainFrm::OnCreate函数中的CStatusBar::Create函数中设置为AFX_IDW_STATUS_BAR.改变这个ID可以实现禁止框架在0号窗格中显示菜单提示.
具体实现如下:
将CMainFrm::OnCreate函数中的CStatusBar::Create函数由m_wndStatusBar.Create(this)改成m_wndStatusBar.Create( this,WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, ID_MY_STATUS_BAR(自定义的ID)).


11,注意,左右鼠标按钮跟键盘上的键一样有虚键码,可以通过GetKeyState函数获取。

强烈建议自己动手实现书中两个事例,尤其是第二个了,自己做了就明白这章讲的是什么个回事了.

///
//

第十四章:可重用框架窗口类


1, 可重用基类的设计:为某个工程所设计的类应该能够被提取出来 ,使它进一步一般化后被应用于其他的应用程序。

2, 一些重要函数:
1)CFrameWnd::ActivateFrame
virtual void ActivateFrame( int nCmdShow = -1 );
//以nCmdShow作为参数调用CWnd::ShowWindow函数来显示框架窗口(其菜单视图控制栏窗口也会被同时显示)。nCmdShow决定窗口是最大化还是最小化等。
//在派生类中重载ActivateFrame ,在nCmdShow传递给CFrameWnd::ActivateFrame之前修改nCmdShow的值。还可以调用CWnd::SetWindowPlacement设置框架窗口的位置和尺寸并还可以设置控制栏的可视状态。
2)CWnd::PreCreateWindow
virtual BOOL PreCreateWindow( CREATESTRUCT& cs );
//PreCreateWindow在调用ActivateFrame函数之前被框架调用,用以在窗口显示之前改变其窗口的特性(特性主要参考:CREATESTRUCT结构。
//在派生类中重载它,在CS传给基类之前改变CS结构中值,从而实现定制(显示)窗口。
3)在MDI中,主框架窗口的ShowWindow函数是由应用程序类InitInstance函数调用,不是由CFrameWnd::ActivateFrame函数调用。故要控制MDI主框架窗口的一些特性,应该在应用程序类InitInstance函数中添加相应的代码。

3,Window注册表
1)Window注册表是一组系统文件,由Window管理,Windows和其他的应用程序可以在注册表中保存一些永久的信息。
Windows 注册表被组织成一个层次的数据库,字符和整型数据可以通过一个多部分键值来访问。
2)操作:
SetRegistryKey   Causes application settings to be stored in the registry instead of .INI files.

GetProfileInt   Retrieves an integer from an entry in the application’s .INI file.
WriteProfileInt  Writes an integer to an entry in the application’s .INI file.
GetProfileString  Retrieves a string from an entry in the application’s .INI file.
WriteProfileString  Writes a string to an entry in the application’s .INI file.
说明:
1)vc5开始,AppWziard在应用程序类的InitInstance函数中有对CWinApp::SetRegistryKey函数的调用,如下:
 SetRegistryKey(_T("Local AppWizard-Generated Applications"));
该函数的调用使应用程序使用注册表,如果去掉则应用程序不使用注册表,仅在Windows目录下创建一个INI文件,并使用该文件。
SetRegistryKey的字符串参数建立最上层键,其后的注册表函数定义下面的两层(称为头名和入口名)。
2)为能够使用注册表访问函数,需要一个指向应用实例对象的指针,可以通过AfxGetApp函数获得。如下:
AfxGetApp()->WriteProfileString("Text formatting","Font","Times Roman");
AfxGetApp()->WriteProfileInt("Text Formatting","Points",10);
3)注册表访问函数可以将注册表当成CString对象或无符号整数来处理。


4,CString类中,LPCTSTR并不是一个指向CString对象的指针,而是一个用来代替const char*的Unicode版本。
1) CString str;
 char ch[]="abcdefg";
 strcpy(str.GetBuffer(strlen(ch)),ch);
 str.ReleaseBuffer();
 pDC->TextOut(0,0,str);
输出:abcdefg
2) CString str("abcdefg");
 char ch[20];
 strcpy(ch,LPCTSTR(str));
 pDC->TextOut(0,0,ch);
输出:abcdefg
说明:
char *strcpy( char *strDestination, const char *strSource );
3)编写带字符串参数的函数原则:
a,如果不改变字符串内容:可以使用const char*形参,可以使用CString&类型形参
b,如果改变字符串内容,可以使用CString&类型形参(当然可以使用指针,但这儿不建议)。


5,获取窗口坐标
GetWindowPlacement
//Retrieves the show state and the normal (restored), minimized, and maximized positions of a window.
SetWindowPlacement(可以返回最大化前的屏幕坐标)
//Sets the show state and the normal (restored), minimized, and maximized positions for a window.
GetWindowRect
//Gets the screen coordinates of CWnd.


/
第十五章:文档与视图的分离

 

1,SDI应用程序文档类由CDocument类派生,一个文档类可以有一个或多个由CView类派生的视图类。
 
2,重要成员函数:
1)CView::GetDocument
CDocument* GetDocument( ) const;
//文档对象是用来保存数据的,而视图对象则是用来显示数据的。
//一个视图对象只有一个与之相关连的文档对象。
//Return A pointer to the CDocument object associated with the view.Return NULL if the view is not attached to a document.
//Call this function to get a pointer to the view’s document. This allows you to call the document’s member functions.

2)CDocument::UpdateAllViews
void UpdateAllViews( CView* pSender, LPARAM lHint = 0L, CObject* pHint = NULL );
//当文档数据发生修改的时候,调用该函数通知所有的视图对所显示的数据进行相应得更新。
//pSender:Points to the view that modified the document, or NULL if all views are to be updated.
//如果在派生文档类中调用UpdateAllViews函数,则pSender应该设置为NULL;如果UpdateAllViews函数在派生视图类成员函数中调用,则pSender参数应该设置成this(如:GetDocument()->UpdateAllViews(this);)

3)CView::OnUpdate
virtual void OnUpdate( CView* pSender, LPARAM lHint, CObject* pHint );
//当应用程序调用了CDocument::UpdateAllViews函数时,会调用OnUpdate函数更新视图显示。
//通常视图类OnUpdate函数先对文档进行访问,读取文档的数据,然后对视图的数据成员或控制进行更新,以反应文档的变化。
//可以利用OnUpdate函数使视图的某部分无效,以触发视图的OnDraw函数调用,从而利用文档数据来重绘对应的视图窗口。
//默认的OnUpdate函数使得整个窗口矩形无效。
//当程序调用CDocument::UpdateAllViews函数,如果pSender参数指向了某个特定的视图对象,则除了该指定的视图之外,文档的所有其它视图的OnUpdate函数都会被调用。

4)CView::OnInitialUpdate
virtual void OnInitialUpdate( );
//当应用程序被启动,或当用户从File菜单选择了New时候,或当用户从File菜单选择了Open时候,该虚函数都会被自动调用。
//CView基类中的OnInitialUpdate函数除调用OnUpdate函数中没做其它任何事情。如果在派生类中重载该函数一定要调用基类的OnInitialUpdate函数,或调用派生类的OnUpdate函数。
//当应用程序启动时,框架调用视图类的OnCreate函数之后立即调用OnInitialUpdate函数。OnCreate函数只能被调用一次,而OnInitialUpdate可以被调用多次。
//可以通过在派生重载OnInitialUpdate函数,在其中对视图对象进行初始化。

5)CDocument::OnNewDocument
virtual BOOL OnNewDocument( );
//Called by the framework as part of the File New command. The default implementation of this function calls the DeleteContents member function to ensure that the document is empty and then marks the new document as clean. Override this function to initialize the data structure for a new document. You should call the base class version of this function from your override.
//If the user chooses the File New command in an SDI application, the framework uses this function to reinitialize the existing document, rather than creating a new one. If the user chooses File New in a multiple document interface (MDI) application, the framework creates a new document each time and then calls this function to initialize it. You must place your initialization code in this function instead of in the constructor for the File New command to be effective in SDI applications.


3,简单文档视图交互应用程序步骤(单文档单视图):
1)在派生文档类中定义文档的数据成员,用以保存程序中数据。为了方便派生视图类的访问可以将这些数据成员定义成公有类型或将派生视图类定义为派生文档类的友元类。
2)在派生视图类中对OnInitialUpdate虚成员函数进行重载。当文档数据被初始化或被从磁盘中读出后,框架会自动调用OnInittialUpdate函数。该函数对视图进行更新,以便放映出当前的文档数据。
3)在派生视图类中,让窗口消息控制函数和命令消息控制函数直接读取和更新文档数据成员,利用GetDocument函数对文档对象进行访问。

对应事件发生次序:
程序启动: CMyDocument对象被创建-》CMyView对象被创建-》视图窗口被创建-》CMyView::OnCreate函数被调用(如果被映射)-》CMyDocument::OnNewDocument函数被调用-》
CMyView::OnInitialUpdate函数被调用-》视图对象被初始化-》视图窗口无效-》CMyView:OnDraw函数被调用
用户编辑数据: CMyView类中函数对CMyDocument数据成员进行更新
退出程序: CMyView对象被删除-》CMyDocument对象被删除


4,CFormView类
CFormView类具有许多无模式对话框的特点,其派生类也和相应的对话框资源相联系,也支持DDX和DDV等。
CFormView类对象可以直接接收来之本身的控制通告消息,也可接收来自框架窗口的命令消息。(同时具有许多无模式类对话框和视图类特征)。
派生层次:CView|CScrolView|CFromView
CFormView类虽然不是从CDialog类派生,但是围绕对话框创建,因而可以使用许多CDialog类成员函数。(这时只需将CFormView指针强制转换成CDialog类指针即可)如:((CDialog*)this)->GotoDlgCtrl(GetDlgItem(IDC_NAME));


5,高级文档视图交互应用程序步骤(单文档多视图):
编写多视图应用程序,只要对其中某一视图编辑改变了文档,则其它的文档需要随之更新,以反映出文档的变化。
步骤:
1)在派生文档类中定义需要的数据成员。同时设计访问该数据成员的方法,或将视图类设计成文档类的友元类。
2)在派生视图类中,利用向导重载OnUpdate虚成员函数。当文档数据被修改后,应用程序框架会自动调用该函数。利用重载的OnUpdate函数来完成视图的更新,以反映当前的文档数据。
3)对所有的命令消息判断其哪些是针对文档的哪些是针对视图的,然后将其映射到相应的类中。
4)在派生视图类中,允许对文档数据进行更改,在退出之前,一定要调用CDocument::UpdateAllViews函数更新其它的视图。使用CView::GetDocument获取相关联的文档对象指针。
5)在派生文档类中,允许对文档数据进行修改,修改后退出前要调用UpdateAllViews函数更新与其关联的所有视图。

对应发生的事件次序:
应用程序启动:CMyDocument对象被创建-》CMyView对象被创建-》其它视图对象被创建-》视图窗口被创建-》CMyView::OnCreate函数被调用(如果被映射)-》CMyDocument::OnNewDocument函数被调用-》CMyView::OnInitialUpdate函数被调用-》调用CMyView::OnUpdate-》初始化视图
用户编辑数据: 视图类中函数对CMyDocument数据成员进行更新
  退出时候调用CDocument::UpdateAllViews函数更新其它的视图
退出程序: 视图对象被删除-》CMyDocument对象被删除


6,笔记略过内容:诊断信息转储(参见P296-P300),CObList集合类(参见P308-312)
1)选择Debug目标时_DEBUG常量候被定义,程序中的诊断代码会被连到程序中去。
2)选择Release目标,诊断信息转储被禁止,诊断代码也不会被连到程序中去。由Release目标生成的可执行文件非常小(比使用Debug目标生成的目标文件小很多呢)。
3)CObList很重要的特性是可以包含混合指针。


///
/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值