| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2219 人关注过本帖
标题:MFC遇到一个令我困惑的现象,和大家讨论(难度较高)
只看楼主 加入收藏
yongyong
Rank: 1
等 级:新手上路
帖 子:9
专家分:0
注 册:2006-4-26
收藏
 问题点数:0 回复次数:9 
MFC遇到一个令我困惑的现象,和大家讨论(难度较高)

我在theApp的InitInstance()中的return TRUE之前加入这样一句:
((CFrameWnd*)m_pMainWnd)->GetActiveView()->CloseWindow();
也就是初始化结束后把view给closewindow。
运行一下看一看,让这个窗口被别的窗口挡住,再切回这个窗口,我们看到,
窗口的client区域就成了“空心”的,显然,整个client区域没有被重绘。
我觉得很奇怪,于是我写了一个SDK模拟了一下,模仿MFC的做法,
创建一个主窗口(模仿mianframe),一个子窗口(模仿view),子窗口覆盖
在主窗口的client区域,然后把子窗口给closewindow,但并不会出现上述现象。

那么就是说MFC中的mainframe是不重绘自己的客户区的,这一点容易理解,
因为通常客户区被view覆盖,mainframe重绘它是多余的。
MFC是如何做到让mainframe不重绘客户区呢?默认情况下,窗口在产生WM_PAINT
消息的时候一般都是要重绘客户区的呀。
我想知道细节,我看了源代码,但水平有限,没有头绪。
请高手指教!

搜索更多相关主题的帖子: MFC 窗口 难度 现象 困惑 
2006-04-26 12:46
lisypro
Rank: 4
等 级:业余侠客
威 望:3
帖 子:695
专家分:216
注 册:2005-9-25
收藏
得分:0 

不对罢
我的程序怎么运行出错


长期承接管理系统
代做各种vb/ / vc小程序
QQ:82341763
手机:13623290828
群号 11619730
2006-04-27 08:07
yongyong
Rank: 1
等 级:新手上路
帖 子:9
专家分:0
注 册:2006-4-26
收藏
得分:0 

((CFrameWnd*)m_pMainWnd)->GetActiveView()->CloseWindow();
这一句要加在CMFCxxxApp::InitInstance()的最后,return TRUE之前。你如果把这句放的靠前肯定会出错,因为那时候view还没有被创建呢,GetActiveView()得到的肯定是空指针,肯定要出错。

2006-04-27 09:30
aogun
Rank: 5Rank: 5
等 级:贵宾
威 望:17
帖 子:638
专家分:0
注 册:2006-4-5
收藏
得分:0 
是否在创建CFrameWnd窗口的时候注册的窗口类没有用背景刷,即WNDCLASSEX的成员hbrBackground为空,这样的话又不响应WM_PAINT消息那么窗口是不会重绘的,可惜创建主窗口的过程不是用宏写的,不然倒可以看看是不是这样的

世界上总共有 10 种人,一种懂得什么是二进制 ,一种不懂。
2006-04-27 16:01
lisypro
Rank: 4
等 级:业余侠客
威 望:3
帖 子:695
专家分:216
注 册:2005-9-25
收藏
得分:0 
我跟你说的一样可是运行出错
要不把把你程序发给我一份
lisypro@sohu.com

长期承接管理系统
代做各种vb/ / vc小程序
QQ:82341763
手机:13623290828
群号 11619730
2006-04-28 10:19
yongyong
Rank: 1
等 级:新手上路
帖 子:9
专家分:0
注 册:2006-4-26
收藏
得分:0 
to lisypro:已经把程序发给你了,收一下,多谢关注!
我很奇怪你为什么会出错,就这么简单的一句改动,其他都是向导生成的呀,出得什么错呢?
2006-04-28 12:50
西部天狼
Rank: 1
等 级:新手上路
帖 子:95
专家分:0
注 册:2006-2-23
收藏
得分:0 

在MFC中,窗口的绘制要至少要有两个必备的过程,首先是擦除,其次才是绘制。
你可以随便创建一个MFC应用程序,同时添加WM_PAINT和WM_ERASEBKGND 两个消息响应函数,调试一下你会发现首先响应的是擦除消息。因为,清空帧缓存总是比重新绘制它要快。
因此,检验窗口上能不能绘制像素首先要考虑擦除这个过程。因为,没有擦除,将不会正确的绘制。

WNDCLASS中的成员hbrBackground设置了窗口用于擦除背景的颜色值。如果该值取0,则意味着系统不为应用程序执行窗口擦除操作。
按照楼主说的方法创建工程,并调试跟踪,如下序列:
从APP的ProcessShellCommand(cmdInfo)开始往下走
AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)
_AfxDispatchCmdMsg(。。。。)
CreateNewFrame(pDocument, NULL)
LoadFrame(。。。。。) // CFrameWnd
在上面这个函数中有
LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
该调用是返回一个WNDCLASS名,用于在创建窗口时使用。
其值为:Afx:4000000:b:10011:6:145b06cd
MFC为向导生成的窗口定义的窗口类名规范有如下形式:
Afx:%x:%x:%x:%x:%x
其中每个&x代表以下参数的值:
WNDCLASS.hInstance
WNDCLASS.style
WNDCLASS.hCursor
WNDCLASS.hbrBackground
WNDCLASS.hIcon
对应可以看出在当前这个程序中hbrBackground 的值为系统颜色COLOR_WINDOW,不为零。也就是说,系统为窗口要执行擦除操作,擦除的颜色是COLOR_WINDOW。
那么为什么会出现楼主说的现象呢?
我们知道,该程序支持文档/视图模型,也就是框架的客户区由视图填充,可能的情况是,当存在一个活动视图时,框架窗口的擦除被视图所取代了。
为此,跟踪主窗口对象的消息响应函数OnEraseBkgnd
在该函数中,该响应函数调用的是其基类的OnEraseBkgnd,进入到CFrameWnd类中的OnEraseBkgnd我们可以看到如下实现:
BOOL CFrameWnd::OnEraseBkgnd(CDC* pDC)
{
if (m_pViewActive != NULL)
return TRUE; // active view will erase/paint itself
// for view-less frame just use the default background fill
return CWnd::OnEraseBkgnd(pDC);
}
从注释我们可以看出当存在一个激活的视图时,窗口的擦除与绘制是由视图完成的。否则,才会由系统完成。因此,当前程序有视图,并且虽然关闭了,但仍生于激活状态。因此,不会调用系统的擦除,但又由于关闭的窗口并没有被清除,只是其矩形区域大小为0而已,因此,视图所占的那部分的窗口就成了真空的,没有谁去在那里执行擦除和绘制操作,从而导致了楼主所说的现象。
在这里我顺便跟踪了一下CWnd::OnEraseBkgnd(pDC);发现最终调用的是WIN32API的 ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam)函数,其中m_pfnSuper指的是该窗口的父窗口的窗口处理函数,由于框架窗口的父窗口是桌面窗口,因此,一般情况下的擦除是由桌面窗口来处理的。

这是我的一点浅见,请路过的高人多指教。

参考:MFC源码 MSDN


学习-->编程-->交流-->再学习-->再编程-->再交流
2006-04-28 18:37
西部天狼
Rank: 1
等 级:新手上路
帖 子:95
专家分:0
注 册:2006-2-23
收藏
得分:0 
补充一点:
用语句
((CMainFrame *)m_pMainWnd)->SetActiveView(NULL);将视图置非激活状态,从而代替关闭视图,这样就不会出现楼主所说的现象了。因为,其擦除操作由框架窗口来完成。

学习-->编程-->交流-->再学习-->再编程-->再交流
2006-04-28 18:48
西部天狼
Rank: 1
等 级:新手上路
帖 子:95
专家分:0
注 册:2006-2-23
收藏
得分:0 
以下是引用aogun在2006-4-27 16:01:00的发言:
是否在创建CFrameWnd窗口的时候注册的窗口类没有用背景刷,即WNDCLASSEX的成员hbrBackground为空,这样的话又不响应WM_PAINT消息那么窗口是不会重绘的,可惜创建主窗口的过程不是用宏写的,不然倒可以看看是不是这样的

即便是背景刷为空值,程序也会响应WM_PAINT消息的。我个认为WINDOWS的图形绘制是采用单缓存进行的,因此,如果帧缓存中的内容没有清除,将不会重新绘制新的像素。
窗口的创建关键在于WNDCLASS的创建,MFC向导用了一些默认的设置,你可以参考MSDN中的TN001和TN070两个条目。


学习-->编程-->交流-->再学习-->再编程-->再交流
2006-04-28 18:58
yongyong
Rank: 1
等 级:新手上路
帖 子:9
专家分:0
注 册:2006-4-26
收藏
得分:0 
非常感谢西部天狼,分析的可谓透彻之极,让我长了知识,非常感谢!
2006-04-30 08:47
快速回复:MFC遇到一个令我困惑的现象,和大家讨论(难度较高)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.029731 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved