}
4.为什么我们自己的应用程序程序只能打开自己保存的文件,别的程序(如Windows的记事本)不能打开我们的程序生成的文件?
回答:
文档的串行化在Serialize成员函数中进行。
当用户选择FileSave、SaveAs或Open命令时,都会自动执行这一成员函数。
打开保存文件的执行顺序是这样的。
当应用程序响应File->Open、File-Save和File-SaveAs命令时,应用程序框架都会通过调用CDocument成员函数(对于File->Open调用OnOpenDocument,对于File->Save和File->SaveAs调用OnSaveDocument)创建CFile对象,并以适当的方式打开文件,对于File->Open是打开文件并读,对于Save和SaveAs是打开文件并写。
然后框架会自动把文件对象连接到一个CArchive对象上,并设置CArchive的读写方式。
因为保存的时候是按照我们自己规定的格式保存的,别的应用程序不知道我们文件的保存格式,自然不能打开我们的应用程序保存的文件,而我们自己的程序读文件的格式同保存文件的格式相同,自然可以打开自己的文件。
5.如何解决插入符位置不正确(每添加一个字符,插入符位置不正确)?
这是因为映射模式的设置问题,将映射模式设置为MM_LOENGLISH时,
●MM_LOENGLISH Eachlogicalunitisconvertedto0.01inch.Positivexistotheright;positiveyisup.
●MM_TEXT Eachlogicalunitisconvertedto1devicepixel.Positivexistotheright;positiveyisdown.
解决办法:
注释掉OnDraw函数中的模式设置语句
//intOldMapMode=pDC->SetMapMode(MM_LOENGLISH);
//pDC->SetMapMode(OldMapMode);
如果你在视图类OnInitialUpdate()中设置了滚动模式,注释掉视图类OnInitialUpdate()中的
//SetScrollSizes(MM_LOENGLISH,docSize,pageSize,lineSize);
6.如何响应回车等虚键?
回答:
这里仅以回车键的响应为例,其余键的响应自己完善。
(1)打开EditScroll工程,在视图类中添加一变量
intm_RowHeight;
(2)在视图类的构造函数中初始化该变量
m_RowHeight=0;
(3)修改视图类的OnChar函数如下:
voidCEditScollView:
:
OnChar(UINTnChar,UINTnRepCnt,UINTnFlags)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
CEditScollDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
switch(nChar)
{
caseVK_RETURN:
//响应回车键
pDoc->m_Count++;//字符串加1
//重新设置文本输出和插入符的位置
pDoc->m_StartPoint[pDoc->m_Count].x=pDoc->CaretPosition.x=
pDoc->m_StartPoint[pDoc->m_Count-1].x;
pDoc->m_StartPoint[pDoc->m_Count].y=pDoc->CaretPosition.y=
pDoc->m_StartPoint[pDoc->m_Count-1].y+m_RowHeight;
Invalidate();
pDoc->SetModifiedFlag(TRUE);//设置文件修改标志
break;
default:
pDoc->m_Text[pDoc->m_Count]+=nChar;
Invalidate();
pDoc->SetModifiedFlag(TRUE);//设置文件修改标志
}
CScrollView:
:
OnChar(nChar,nRepCnt,nFlags);
}
7.改变应用程序(视图类基于CEditView)的背景颜色
CEditView的定义在“..\MicroSoftVisualStdio\VC98\MFC\Include\”目录下“AFXEXT.H”文件中,实现文件在“..\MicroSoftVisualStdio\VC98\MFC\SRC\”目录下“VIEWEDIT.CPP”文件中。
(1)新建一工程SDI工程TestEditView,第六步选择视图类从CEditView派生,在文档类中添加一颜色变量:
public:
COLORREFm_bkColor;
(2)在文档类的构造函数中初始化
m_bkColor=RGB(12,150,200);
(3)在菜单上添加一个菜单项,ID为ID_BKCOLOR,并在视图类中添加消息响应函数,添加如下代码:
voidCTestEditViewView:
:
OnBkcolor()
{
CTestEditViewDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
CColorDialogdlg;
if(dlg.DoModal()==IDOK)
pDoc->m_bkColor=dlg.GetColor();
InvalidateRect(NULL);
}
(4)为视图类添加WM_ERASEBKGND的消息响应函数,添加如下代码:
BOOLCTestEditViewView:
:
OnEraseBkgnd(CDC*pDC)
{
CTestEditViewDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
CBrushBrush(pDoc->m_bkColor);
//Selectthebrushintothedevicecontext.
CBrush*pOldBrush=pDC->SelectObject(&Brush);
//Gettheareathatneedstobeerased.
CRectrect;
GetClientRect(&rect);
//Paintthearea.
pDC->PatBlt(rect.left,rect.top,
rect.Width(),rect.Height(),PATCOPY);
//Unselectbrushoutofdevicecontext.
pDC->SelectObject(pOldBrush);
pDC->SetBkMode(TRANSPARENT);
//Returnnonzerotohalffrutherprocessing.
returnTRUE;
//returnCEditView:
:
OnEraseBkgnd(pDC);
}
(5)为视图类添加WM_CHAR的消息响应函数,添加如下代码:
voidCTestEditViewView:
:
OnChar(UINTnChar,UINTnRepCnt,UINTnFlags)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
CEditView:
:
OnChar(nChar,nRepCnt,nFlags);
InvalidateRect(NULL);
}
(6)编译连接运行,即可改变背景颜色。
8.改变应用程序(视图类基于CEditView)的文本颜色。
(1)承接前面工程TestEditView,在文档类中添加一颜色变量:
public:
COLORREFm_txtColor;
(2)在文档类的构造函数中初始化
m_txtColor=RGB(0,0,0);
(3)在菜单上添加一个菜单项,ID为ID_TXTCOLOR,并在视图类中添加消息响应函数,添加如下代码:
voidCTestEditViewView:
:
OnTxtcolor()
{
CTestEditViewDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
CColorDialogdlg;
if(dlg.DoModal()==IDOK)
pDoc->m_txtColor=dlg.GetColor();
InvalidateRect(NULL);
}
(4)为视图类添加WM_CTLCOLOR的消息响应函数,添加如下代码:
HBRUSHCTestEditViewView:
:
CtlColor(CDC*pDC,UINTnCtlColor)
{
CTestEditViewDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
pDC->SetTextColor(pDoc->m_txtColor);
return!
NULL;
//TODO:
Returnanon-NULLbrushiftheparent'shandlershouldnotbecalled
//returnNULL;
}
(5)编译连接运行。
9.改变应用程序(视图类基于CEditView)的字体。
(1)承接前面工程TestEditView,在文档类中添加两个公有变量:
CFontm_Font;
LOGFONTm_lf;
(2)为视图类添加WM_CREATE的消息响应函数,并添加如下代码:
intCTestEditViewView:
:
OnCreate(LPCREATESTRUCTlpCreateStruct)
{
if(CEditView:
:
OnCreate(lpCreateStruct)==-1)
return-1;
//TODO:
Addyourspecializedcreationcodehere
CTestEditViewDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
CEdit&edit=GetEditCtrl();//定义指向视图的CEdit控件
if(pDoc->m_Font.m_hObject==NULL)
{
pDoc->m_Font.CreatePointFont(120,"Fixedsys");
}
if(pDoc->m_Font.m_hObject!
=NULL)
edit.SetFont(&pDoc->m_Font);
edit.SetTabStops(16);
return0;
}
(3)为系统菜单添加一个字体菜单,ID为ID_Font,添加相应的消息响应函数,并添加代码:
voidCTestEditViewView:
:
OnFont()
{
//LOGFONTlf;
CTestEditViewDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
CFont*font=this->GetEditCtrl().GetFont();//得到当前字体
if(font==NULL)//当前无字体,创建默认的字体
{
font=newCFont;
font->CreatePointFont(120,"Fixedsys");
font->GetLogFont(&pDoc->m_lf);
deletefont;
}
else
{
font->GetLogFont(&pDoc->m_lf);
}
CFontDialogcf(&pDoc->m_lf,CF_SCREENFONTS|CF_INITTOLOGFONTSTRUCT);
if(cf.DoModal()==IDOK)
{
pDoc->m_Font.DeleteObject();
pDoc->m_Font.CreateFontIndirect(&pDoc->m_lf);
this->SetFont(&pDoc->m_Font);
}
}
(4)编译连接运行。
10.如何保存前面设置的字体颜色、背景颜色和字体?
回答:
(1)打开TestEditView工程,为文档类添加一公有成员变量
BOOLbOpenFlag;
(2)在文档类的构造函数中初始化
bOpenFlag=FALSE;
(3)修改文档类的Serialize函数,添加如下代码:
voidCTestEditViewDoc:
:
Serialize(CArchive&ar)
{
//CEditViewcontainsaneditcontrolwhichhandlesallserialization
if(ar.IsStoring())
{
//TODO:
addstoringcodehere
ar<ar<ar<ar<ar<ar<ar<ar<ar<ar<ar<ar<ar<ar<ar<CStringFaceName=m_lf.lfFaceName;
ar<}
else
{
//TODO:
addloadingcodehere
ar>>m_bkColor;
ar>>m_txtColor;
ar>>m_lf.lfHeight;
ar>>m_lf.lfWidth;
ar>>m_lf.lfEscapement;
ar>>m_lf.lfOrientation;
ar>>m_lf.lfWeight;
ar>>m_lf.lfItalic;
ar>>m_lf.lfUnderline;
ar>>m_lf.lfStrikeOut;
ar>>m_lf.lfCharSet;
ar>>m_lf.lfOutPrecision;
ar>>m_lf.lfClipPrecision;
ar>>m_lf.lfQuality;
ar>>m_lf.lfPitchAndFamily;
CStringFaceName;;
ar>>FaceName;
strcpy(m_lf.lfFaceName,FaceName);
m_Font.DeleteObject();
m_Font.CreateFontIndirect(&m_lf);
bOpenFlag=TRUE;
}
((CEditView*)m_viewList.GetHead())->Serialize(ar);
}
(4)重载视图类的OnInitialUpdate,添加如下代码:
voidCTestEditViewView:
:
OnInitialUpdate()
{
CEditView:
:
OnInitialUpdate();
//TODO:
Addyourspecializedcodehereand/orcallthebaseclass
CTestEditViewDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
if(pDoc->bOpenFlag==TRUE)
{
pDoc->m_Font.DeleteObject();
pDoc->m_Font.CreateFontIndirect(&pDoc->m_lf);
this->SetFont(&pDoc->m_Font);
pDoc->bOpenFlag=FALSE;
}
}
11.CFindReplaceDialog类的用法:
CFindReplaceDialog类用于实现Find(搜索)和Replace(替换)对话框,这两个对话框都是非模态对话框,用于在正文中搜索和替换指定的字符串。
由于Find和Replace对话框是无模式对话框,它的创建方式稍有不同:
CFindReplaceDialog对象是用new操作符在堆中创建的,而不是象普通对话框那样以变量的形式创建。
要启动Find/Replace对话框,应该调用CFindReplaceDialog:
:
Create函数,而不是DoModal。
Create函数的声明是
BOOLCreate(BOOLbFindDialogOnly,LPCTSTRlpszFindWhat,LPCTSTRlpszReplaceWith=NULL,DWORDdwFlags=FR_DOWN,CWnd*pParentWnd=NULL);
当参数bFindDialogOnly的值为TRUE时,创建的是Find对话框,为FALSE时创建的是Replace对话框。
参数lpszFindWhat指定了要搜索的字符串,lpszReplaceWith指定了用于替换的字符串。
dwFlags用来设置对话框,其缺省值是FR_DOWN(向下搜索),该参数可以是几个FR_XXX常量的组合,用户可以通过该参数来决定诸如是否要显示Matchcase、MatchWholeWord检查框等设置。
参数pParentWnd指明了对话框的父窗口或拥有者窗口。
CFindReplaceDialog类只提供了一个界面,它并不会自动实现搜索和替换功能。
CFindReplaceDialog使用了一种特殊的通知机制,当用户按下了操作的按钮后,它会向父窗口发送一个通知消息,父窗口应在该消息的消息处理函数中实现搜索和替换。
用法示例:
(1)打开课本上的EditScroll工程,添加一查找菜单,ID为ID_FIND,并添加消息处理函数,添加代码如下:
voidCEditScrollView:
:
OnFind()
{
CFindReplaceDialog*dlgFind=newCFindReplaceDialog();
dlgFind->Create(1,"",NULL,FR_HIDEWHOLEWORD|FR_DOWN,this);
}
(2)在视图类实现文件EditScrollView.cpp的头部添加如下代码:
staticUINTWM_FINDREPLACE=:
:
RegisterWindowMessage(FINDMSGSTRING);
//TheRegisterWindowMessagefunctiondefinesanewwindowmessagethatisguaranteedtobeuniquethroughoutthesystem.ThereturnedmessagevaluecanbeusedwhencallingtheSendMessageorPostMessagefunction.
(3)在视图类定义EditScrollView.h中添加消息函数原型:
afx_msgLONGOnFindReplace(WPARAMwParam,LPARAMlParam);
(4)在视图类实现文件EditScrollView.cpp的消息映射中添加消息映射
ON_REGISTERED_MESSAGE(WM_FINDREPLACE,OnFindReplace)
(5)在视图类实现文件EditScrollView.cpp中添加消息处理函数的实现代码:
longCEditScollView:
:
OnFindReplace(WPARAMwParam,LPARAMlParam)
{
CEditScollDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
CFindReplaceDialog*dlgFindGetted=CFindReplaceDialog:
:
GetNotifier(lParam);
if(dlgFindGetted->IsTerminating())
return1;
BOOLbDown=dlgFindGetted->m_fr.Flags&FR_DOWN;
BOOLbMatchCase=dlgFindGetted->MatchCase();
if(dlgFindGetted->FindNext())
{
intn=pDoc->m_Text[pDoc->m_Count].Find(dlgFindGetted->GetFindString());
if(n!
=-1)//如果查找到,则反色显示
{
CDC*pDC=GetDC();
COLORREFOldColor=pDC->SetTextColor(RGB(0,0,0));
pDoc->m_Font.CreateFontIndirect(&pDoc->m_lf);
CFont*pOldFont=pDC->SelectObject(&pDoc->m_Font);
CSizesize=pDC->GetTextExtent(pDoc->m_Text[pDoc->m_Count].Left(n));
pDC->TextOut(pDoc->m_StartPoint[pDo