在使用MFC编写程序时,经常需要显示图像;根据GDI的要求,需要一个DC(设备内容)作为显示的基础;实际上任何Windows的窗口都可以作为一个DC,我们可以通过API或MFC的函数来得到,例如:
HDC GetDC (HWND);---这里的HWND是窗口的句柄
CDC * CWnd::GetDC ();---这里的CWnd实际上是任何从CWnd的类
当我们使用MFC的单文档或多文档框架时,我们可以使用CView作为图像显示的DC,这个时候我们将绘制图像的操作放在OnDraw中就可以了;当窗口无效或更新的时候,框架会自动调用该函数来重新绘制图像;这里没有什么问题,我们主要来谈谈另外一种模式:当你需要在一个基于Dialog程序或一个CDialog控件中显示图像的问题。
实际上什么控件都可以作为图像显示的DC,他们可以是按钮、图片控件、Static控件等,只要有窗口的控件都可以得到DC。这里仅以Static控件作为图像显示的控件来介绍。
首先看我程序的基本逻辑:
源文件后面的按钮是用来选择位图文件的;而下面的图像显示区域是用来显示图像的Static控件;当设置好要显示的图像文件以后,图像就自动在Static中画出来。
l 第一次
一开始,我在CDialog对应的按钮处理程序中调用显示图像的代码,代码如下(IDC_PICVIEW为Static的ID):
然后在CImageCntDlg::OnPaint中也调用ShowImage(TRUE);然后编译运行。一开始还可以,选择BMP文件之后也可以正确选择,但当激活另一个程序(也就是隐藏了该窗口),然后再激活这个程序,这个时候发现Static中图像显示闪烁一下后变成灰色的背景。到底什么发生了?
l 到底什么发生了?
上面的现象告诉我们,即使我们将ShowImage放在CDialog的WM_PAINT处理消息中,在某些情况下仍然不能正确的处理。
从现象看,我们的图像应该是先画出来了,但然后又被清除了;感觉是PAINT的消息处理不正确。
没有办法,自己想不同那么就使用工具。VC自带的Spy++是个很好的工具,打开Spy++;运行程序,然后打开某个图像,这个时候在Spy++中找到对应的窗口,然后观察与该窗口相关的消息;如图:
这个时候我们切换程序窗口,先让其被覆盖,然后再显示;观察Spy++的结果,发现这样几条记录:
可以看到在WM_PAINT消息之后,窗口又收到了很多WM_CTLCOLORBTN和WM_CTLCOLORSTATIC等多条消息,查询MSDN知道这些是主窗体收到的绘制窗口上空间的消息;实际上,主窗体在处理WM_PAINT消息的时候也需要绘制发送消息给各个控件有机会绘制自己;而对应的消息是控件本身的WM_PAINT消息。
好了,终于找到原因了,我们在CDialog的OnPaint中调用ShowImage之后不久,OnPaint也主动通知各控件重绘,结果这个时候Static上的图像给覆盖了。
l 定义自己的Static控件
知道原因就好办了,只需要将ShowImage放到适当的地方就可以了。这里需要自己从CStatic继承一个自己的类,然后重写其OnPaint函数,在其中显示图像。代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0ac3a2d53663ec01c7f7225264eeefae.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0ac3a2d53663ec01c7f7225264eeefae.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
另外CImageWnd头文件如此定义:
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f70a0fde2b51b7dd92a70e712e540cf6.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/4a5daaec04350a363f186a4d2c5ed6ce.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f70a0fde2b51b7dd92a70e712e540cf6.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/4a5daaec04350a363f186a4d2c5ed6ce.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0ac3a2d53663ec01c7f7225264eeefae.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
在原来调用ShowImage(TRUE)的地方这样调用m_picView.ShowImage(filename);(m_picView是Static对应的CImageWnd类型成员)。
好了,编译测试。这次发现切换没有问题了;但当我们打开文件选择对话框,然后在窗口上面覆盖Static左右拖动的时候发现,一会以后图像不在显示了。那么这次又为什么?
实际上上面的写法有问题的,只是赶时间随手写的。
l 追踪最后的凶手
没有办法,我插入了许多日志来观察变量的设置情况,结果发现DrawImage 中的m_hBitmap变量在一段时间后变成0了,那么肯定显示不了图像了。
想了想,GDI资源中HANDLE有一定的数目限制,这里只创建HANDLE,而从没有释放过,所以一段时间之后HANDLE的上限达到,而不能再创建新的HANDLE了。那么就删除不用的HANDLE吧。
l 最后的代码
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
2
![](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
3
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
4
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
5
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
6
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
7
![](https://i-blog.csdnimg.cn/blog_migrate/f70a0fde2b51b7dd92a70e712e540cf6.gif)
8
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
9
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
10
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
11
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
12
![](https://i-blog.csdnimg.cn/blog_migrate/4a5daaec04350a363f186a4d2c5ed6ce.gif)
13
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
14
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
15
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
16
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
17
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
18
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
19
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
20
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
21
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
22
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
23
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
24
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
25
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
26
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
27
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
28
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
29
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
30
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
31
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
32
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
33
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
34
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
35
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
36
![](https://i-blog.csdnimg.cn/blog_migrate/0ac3a2d53663ec01c7f7225264eeefae.gif)
好了,在编译运行。这次一切正常。
通过这个例子,我们了解几个问题:
1. CDialog首先画自己,然后再画控件
2. 选择合适的时候重绘图像
3. GDI对象的有限的,达到一定数目之后就不能创建了,所有需要释放,以免资源浪费
欢迎讨论。
转自:http://www.cppblog.com/windcsn/archive/2006/02/19/3327.aspx