win7下自绘窗口, 被遮挡后窗口绘图变了

Sandrer 2014-09-26 12:49:26
第一次在win7下开发程序,配置环境:win7x64旗舰版,vs2010

我自己做了个工具栏和状态栏的类(继承自CWnd),都是全自绘
现在发现了个问题,当窗口被其它遮挡了一部分后,窗口里面原本所话的内容就只现实被遮挡的那部分了
而且我发现,阻挡在上面的窗口移开后,自绘的窗口是没有收到 WM_PAINT 消息的

下图是正常状态:

现在用个“计算器”挡住一部分:

把“计算器”移开后:

同样的一个类,在 winxp 下面编译是不会这样的啊,被遮挡移开后也会收到 WM_PAINT 消息的
现在在 win7 下,只有当整个窗口被遮挡,然后移开才会收到 WM_PAINT 消息
这是怎么回事?
...全文
302 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
Sandrer 2014-10-14
  • 打赏
  • 举报
回复
问题解决了,是 OnNcPaint 里面的处理出了问题 我对照了 win7 和 xp 中的代码,发现 xp 里没有处理边框,所以没有调用 OnNcPaint,也就没有发生闪烁的现象 而导致闪烁的根本问题,是在 OnNcPaint 里面获得的窗口坐标没处理好导致的
schlafenhamster 2014-10-02
  • 打赏
  • 举报
回复
void CSanStatusBar::OnPaint() { static int nIndex = 0; TRACE1("%04d: Painting client area.\n", ++nIndex); CRect rect; GetClientRect(&rect); // CPaintDC dc(this); 调 CStatusBar:: OnPaint(); 试试
Sandrer 2014-10-01
  • 打赏
  • 举报
回复
引用 17 楼 schlafenhamster 的回复:
void CSanStatusBar::OnPaint() { static int nIndex = 0; TRACE1("%04d: Painting client area.\n", ++nIndex); CRect rect; GetClientRect(&rect); CPaintDC dc(this); CClientDC dc2(this); DrawBackground(&dc2, &rect); } 如果有效说明 ; EraseBackground 有问题?
默认处理试了,直接返回 true 也试了,都一样
schlafenhamster 2014-10-01
  • 打赏
  • 举报
回复
void CSanStatusBar::OnPaint() { static int nIndex = 0; TRACE1("%04d: Painting client area.\n", ++nIndex); CRect rect; GetClientRect(&rect); CPaintDC dc(this); CClientDC dc2(this); DrawBackground(&dc2, &rect); } 如果有效说明 ; EraseBackground 有问题?
Sandrer 2014-10-01
  • 打赏
  • 举报
回复
引用 13 楼 tixisong 的回复:
你这个问题有没有解决,我也遇到类似的问题,自绘了button listctrl static,挡住窗口移开后没有刷新。
看我10楼的帖子,有个临时性的方法
tixisong 2014-09-30
  • 打赏
  • 举报
回复
你这个问题有没有解决,我也遇到类似的问题,自绘了button listctrl static,挡住窗口移开后没有刷新。
  • 打赏
  • 举报
回复
无论是XP还是win7,被遮挡后移开都会发WM_PAINT消息,但,为了提高效率,它不是窗口的所有区域都会去重绘,而是,只重绘窗口无效区(被遮挡的部分),其它区域保持原样!
xiongkw 2014-09-30
  • 打赏
  • 举报
回复
曾经遇到过,不过现在还是觉得XP的系统好用,就没有管了
schlafenhamster 2014-09-29
  • 打赏
  • 举报
回复
当然也可能 toolbar 部分 自绘 有问题。
Sandrer 2014-09-26
  • 打赏
  • 举报
回复
太夸张了,刚刚才发的帖,在百度里搜索了一下相关的关键字,居然这个帖子排首位
Sandrer 2014-09-26
  • 打赏
  • 举报
回复
还有,在 win7 下用 vs2010 编译后的程序,放到 winxp 的模拟机上面运行 也会发生同样的情况 但是我把代码独立出来拿到 winxp(vs2005)下面编译,就不会发生这种情况了 是不是 win7 自己把绘图接管了?
schlafenhamster 2014-09-26
  • 打赏
  • 举报
回复
"操作系统在内存的某个地方记录了刚刚窗口的样子, 系统在将它显示到屏幕之前创建了一个"复合"了所有当前屏幕窗口的视图. 因为系统一直跟踪每个窗口的上下文, 所以 dwm.exe 能在窗口按层次排布的时候添加一些效果, 比如我们常用的透明度, 还有动态的缩略图预览功能."
Sandrer 2014-09-26
  • 打赏
  • 举报
回复
void CSanStatusBar::OnPaint()
{
    static int nIndex = 0;
    TRACE1("%04d: Painting client area.\n", ++nIndex);

    CRect rect;
    GetClientRect(&rect);

    CPaintDC dc(this);
    CClientDC dc2(this);

    DrawBackground(&dc2, &rect);
}
上面是 OnPaint 的代码,DrawBackground 里面其实就一句代码,画背景的 现在加了个 CClientDC 上去,然后用 CClientDC 来绘图 画面会非常快的闪烁了一下(肉眼很难看到,不排除后期内容多了会看得清楚这个闪烁),后面没遮挡的部分也画上了
hhhh63 2014-09-26
  • 打赏
  • 举报
回复
引用 楼主 Sandrer 的回复:
现在在 win7 下,只有当整个窗口被遮挡,然后移开才会收到 WM_PAINT 消息 这是怎么回事?
实测了一下,全部盖上也不会重画,放大缩小会重画。
Sandrer 2014-09-26
  • 打赏
  • 举报
回复
引用 6 楼 schlafenhamster 的回复:
win7 是 DWM 管理窗口。 与 xp 大不同。
那是不是连 mfc 里面的代码也有所不同了? 因为编译出来的程序,放到 winxp 中运行也发生同样的问题 但如果是在 winxp 上面编译的话,就不会
hhhh63 2014-09-26
  • 打赏
  • 举报
回复
引用 楼主 Sandrer 的回复:
而且我发现,阻挡在上面的窗口移开后,自绘的窗口是没有收到 WM_PAINT 消息的
Win7会自动保存被覆盖的窗口图像,移动上层窗口时直接把保存的图像补上,而不发送wm_paint消息,提高效率。看上面的截图,好象在WM_PAINT消息外绘制了背景,所以Win7补回来的一块正确,其它部分变成了背景色。 lz可参考http://download.csdn.net/detail/hhhh63/7710711,MFC全自绘界面。
schlafenhamster 2014-09-26
  • 打赏
  • 举报
回复
win7 是 DWM 管理窗口。 与 xp 大不同。
Sandrer 2014-09-26
  • 打赏
  • 举报
回复
引用 3 楼 bojie5744 的回复:
onerasebkgnd return true操作后,需要自己刷新界面
你没看清楚咯,都说了同样的代码在 winxp 下没这个问题 是 win7 背后不知在搞什么鬼
  • 打赏
  • 举报
回复
很基础的东西,没什么好说的
  • 打赏
  • 举报
回复
onerasebkgnd return true操作后,需要自己刷新界面
可以作为课程设计的程序,实现简单的绘图,移动图形的功能。 使用vc框架实现。 GHpaint程序的几个重点 程序的基本功能: 程序提供绘图、删除已绘图形、移动已绘图形。 可以选择绘图颜色、形状、线粗。 重点问题: 1、 程序设计基于面向对象。 程序中所有图形都从基类CShapebase派生,大部分工作(例如:删除、移动等)都在这个基类中完成。此类中的两个纯需函数: //纯需函数DrawShape,每个基类都必须实现的函数。 //指定不同图形的绘制方法。 virtual void DrawShape(CDC* pdc) = 0; //橡皮筋效果的算法函数 virtual void ZoomShape(CDC *pdc) = 0; 这两个函数需要在派生类中重载。这两个函数中主要实现不同图形的绘制方法。 也就是说,不同图形的不同点只有绘制方法不同,其他所有属性和行为都可以统一处理。 这里的继承体现了面向对象的设计,论文中可以体现这一点。 2、 动态模板库对象CPtList的使用,动态模板库基础知识。 CPtList是动态模板库的一个实例化类。功能是以链表形式保存指针,至于指针类型不做要求,需要程序员自己设计。 本程序CPtList对象中保存所有图形对象指针,由于所有图形都从CShapebase派生,所以所有图形指针都可以转化为基类CShapebase指针后保存在CPtList中。以后再遍历列表,调用图形对象函数时出现了多态调用。这里体现面向对象程序的多态,论文中可以说明。 至于CPtList的使用,可以在网上查查,可以看看程序代码,比较简单。 多态:是一种函数调用形式。出现在类继承情况下。详细的多态定义到网上查查。 程序中的多态体现在CShapebase类的虚函数,在使用CShapebase指针调用这两个虚函数,实际调用的使子类的重载函数体。这里实际上是不知道函数怎样工作,但是知道函数功能。 例如:使用CShapebase指针调用DrawShape函数,因为不知道子类是什么图形,所以不知道DrawShape怎样画这个图,但是直到DrawShape函数会把这个图画好,这就达到了要求。 3、 Windows窗口绘图基本知识。 3.1 Windows GUI绘图基本知识。使用MFC类库之后,每个窗口都有一个CDC指针量。这个量提供图形绘制。CDC类说明查查网络,内容比较多。CDC及提供图形绘制算法,也提供各种绘制模式(单色、异或色等),提供画笔和画刷的功能。 3.2 窗口绘图基本思想: 图形绘制在窗口中,windows不会帮助程序员让图形“长在”窗口上,当窗口遮挡,最小化后,图形绘消失。程序需要在合适的时机把图形重新画在窗口上。所以窗口上画的内容需要程序员自己思考怎样保存。在本程序中所有图形保存在CPtList对象中。 3.2 Windows为窗口提供了一个重绘消息:OnPaint,在winxp系统中,这个消息会在窗口遮挡部分从新出现、窗口从最小化恢复时调用。在win7种只有窗口从屏幕外移动进屏幕时调用。具体情况可以查查网络,这里是我的发现,并不是主要内容。 在OnPaint消息中重新绘制所有图形是一个保证图形不消失的好办法。 4、 Windows颜色控制基本知识。 4.1 windows使用RGB三原色(红绿蓝)提供颜色控制,本程序使用24位颜色,在内存中占用4字节,所以用int型表示,但是int型的最高位字节不使用,这样每一种颜色就有一个字节表示,每种颜色级别从0-255。系统提供RGB宏帮助定义颜色,例如:RGB(255,0,0)是红色,RGB(0,0,0)黑色,RGB(255,255,255)白色。 4.2 windows绘图提供多种颜色混合模式,本程序中使用异或模式实现图形的“橡皮筋”效果和移动效果,使用纯色模式定位图形。

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧