首先明确声明,单文档CTestView继承CRichEditView,在此基础上研究分析所遇到的问题。
1、关于OnDraw函数:
2、关于Serialize函数:(带一笔OnNewDocument
1、关于OnDraw:不知道有没有提及过,其实是在OnPaint中调用的OnDraw,也就是消息WM_PAINT,即WM_PAINT->OnPaint->OnDraw;在OnDraw中进行绘制,显示数据。

 此处有两个函数:UpdateAllViews() 与 Invalidate()--------UpdateAllViews()通知所有视图做出相应改变,Invalidate()使窗口无效,这里个人理解一般,参考链接:UpdateAllViews() 与 Invalidate()   也就是下图:(此外,这里额外给一个链接,写的不错:令人生疑的Windows窗口消息WM_PAINT详解 )

回到CRichEditView中来,继承它的类是CTestView,可以发现,在CTestView中初始是不带OnDraw的,这个需要主动去类向导中添加虚函数OnDraw,观察OnDraw函数还是会发现这和继承CView得到的OnDraw不一样,其函数内不会自带任何东西

在此处用一些语句测试一下:pDC->TextOut(200, 200, _T("输出试一下"));       // 绘制一行文本

发现并没有出现这行文本,问题何在?可以发现,程序运行过程中根本不会来到这里,也就是完全不会调用函数OnDraw,可以尝试改变窗口大小,发现仍然不会输出文本,不禁思考,此处应该是连OnPaint都不会调用,难道是屏蔽了WM_PAINT消息?尝试添加OnPaint函数,并在其中加上一个消息框提示,用以表明调用这个函数;见下面结果,发现WM_PAINT消息还是正常被处理,那为什么这里在没有主动添加OnPaint函数时,没有响应?追溯到源头,CWnd中有函数OnPaint,按照继承这一套CTestView应该是可以调用OnPaint处理的,但却没有任何反应(暂时没能解决这个问题,也不知道怎么查找资料,其实这个问题简单,我是有猜测的,只不过没能证实,简单来说就是CRichEditView(也可能是CCtrlView类)重写了OnPaint,禁止它去实现重绘功能,因为文本编辑不需要重绘,也就是在OnPaint函数中不调用OnDraw,函数里什么也不做)------这里的解决方案是:如果你想实现绘制,那就重写OnDraw,写OnPaint函数,然后在OnPaint函数中手动调用OnDraw,即可。

              

通过上面一番处理,是不是发现现在可以在OnDraw中绘制了,但是,这可能恰恰违背了CRichEditView的使用方式,你可以尝试输入,发现现在根本无法正常输入了(如下图),完全打乱了CRichEditView的使用。(这是不是能解释为什么在CTestView中没有默认给出OnPaint和OnDraw这两个函数的呢?可能就是为了屏蔽WM_PAINT引起的重绘,(当然我不知道怎么证实我的想法,但是八九不离十)

(插补一条,这里虽然不能正常输入,也就是显示问题,但是存进去的内容还是对的。。。也是写完后面Serialize后发现竟然还是能够把文字正常存入--->>>: 显示和数据接收完全是两码事,这里是不是也体现了Doc/View呢?)

 此外补充一点,我之前也是想在OnDraw中使用SetWindowText的(虽然没成功,导致我从不在OnDraw里使用),不过找到了这其中的问题,(在OnDraw()函数中,利用for循环更新SetWindowText,为什么CEdit不能实时显示-CSDN社区 )(mfc中SetWindowText()导致程序卡死)(还好不是我问的问题,不然我也被骂,哈哈哈哈)提示一下,SetWindowText会引发消息WM_SETTEXT,下图就是问题答案了,(大致可以理解为,发了一个WM_PAINT消息,然后在OnDraw中又发了一个WM_SETTEXT消息,导致又需要发送一个WM_PAINT消息,然后就一直然后了)(我要是理解错了,。。。。。记得骂我,)

问题解决,搞明白了,记得删掉OnDraw、OnPaint函数,还原到原来的程序,毕竟人家本来就不想你用。(主要是后面用不到,嫌它碍事)


2、关于Serialize函数:(带一笔OnNewDocument

当建立一个单文档之后,发现,他都是可以在一定程度上实现某些功能的,比如新建、打开、保存这些通用功能,确实在点击这些菜单项之后能够做出对应的操作,虽然可能做的不够好。它是怎么实现这些功能的呢?

探寻生成的代码,终于在CTestAPP类中找到了一点蛛丝马迹:不过显然能够响应的菜单不止这几个,其他的菜单响应函数又被写在了哪里?(知道踢我)(2022-10-11,最后补充)

 (看孙鑫那本书学的)知道,新建文件,执行过程会调用到Doc中的函数BOOL CTestDoc::OnNewDocument(),MFC实现了这个功能,我们可以做的是,在这个基础上增加内容,做一些修改。运行程序,发现一开始这个标题就被设置为(我是新建),以此发现在程序启动或单击新建的时候,都会调用这个函数。(OnFileNew)

(OnFileNew)新建函数找不到,却能够响应,实现功能,这显然是写在内部,不希望我们做改动,或者说,这就是单文档自带功能,已经给予提供。同样,可以发现(OnFileOpen)函数也是如此,而函数OnFileOpen在执行过程中则是调用了函数void CTestDoc::Serialize(CArchive& ar),实现内容的读取。

这里首先测试一下CTestView继承CRichEditView,程序自动生成的代码到底能够实现哪些功能:

1.能够正常输入文本;

2.新建/保存/打开/另存为/退出菜单项均可响应;

3.可以实现文本保存,需手动添加文件后缀.txt,默认保存utf-8;

4.可以打开刚刚保存的文件,但是无法打开其他Txt文本,保存的txt文本如下;

--->>>:它自己内部实现了读写,但是这种格式不是我们想要的,

(阅读孙鑫那本书),知道,函数OnFileOpen调用了Serialize,当我们去Doc找Serialize函数时,发现它的结构如下所示:(CTestDoc -> CRichEditDoc->COleServerDoc->COleLinkingDoc->COleDocument->CDocument);下面提示:如果作为文本进行序列化,则设置 CRichEditDoc::m_bRTF = FALSE,我们把这句话加入到CRichEditDoc::Serialize(ar);前面,(也就是加在 返回值前面)。

再次运行,发现程序可以正常运行,即完全实现了MFC实现Txt的若干功能,能够像一个正常txt一样,读写保存,保存下来的内容也是正常的字符形式,以ANSI编码,不禁感叹,之前写了那么多,其实只需要一句话就可以实现Txt的功能,这也算是CRichEditView帮我们实现的功能。(其实我写Serialize就是为了这一块内容,CRichEditView可以直接实现txt功能,同时也了解一下串行化问题


(2022-10-11):前面提到,只找到了部分菜单的处理程序,像Save,SaveAs等并没有找到,此处进行补充;
处理事件由View到Doc,View没有,虽然继承下来的Doc中没有(CTestDoc),但是可以发现,其实基类CDocument中存在,毫无疑问,已经帮我们写好了,甚至可以直接保存数据,是一个可以直接使用的功能(参考文中直接实现CRichEditView的保存)。
反观之前在View中写OnFileSave(MFC实现Txt02之当然是CRichEditView了),即在View中处理了这一事件,若不写OnFileSave,则会爬到CDocument::OnFileSave,由此实现;


 2022-11-23:回头看,侯捷的深入浅出MFC中有详细分析序列化Serialize,更容易明白;

 

2022-08-22

posted on 2022-08-19 17:12  夜_归_人  阅读(270)  评论(0编辑  收藏  举报