第十一章 显示位图
在窗口中显示位图(*.bmp文件)的需要是经常会发生的。本章介绍如何把位图文件加入到工程的资源中,如何在对话框中显示出来。因为图片是在设计阶段加入的,成为静态加入图片。VC的资源管理只能够加入BMP格式的图片,因此要使用GIF和JPG格式等其他的图片和想动态地加入图片,还需要使用别的控件,这在以后专门介绍。
本章要点
1 在工程中添加位图资源
2 把图片读入内存和屏幕显示
11.1 MyBmp.exe程序的界面和功能
本程序打开后在窗口显示一幅图——小猫,上面有一个简单的菜单,没有其他控件。File菜单中有Open, Save和Exit三项。Open菜单项没有加入代码,点击后没有反应;Save菜单项连消息映射都没有加入;点击[Exit]则可以退出程序。[Help]菜单项会打开About消息框。但是,窗口是可以改变大小的,当鼠标拖动右下角时,图片总是充满整个用户区域。
11.2 添加资源和设计界面
1 加入位图资源
事先找好小猫的图片文件cat.bmp,我这是在WINDOWS目录中的,也可以用其它的BMP格式的图片,别的格式不行。右击工作区资源页的Bitmap分支,选“导入或Import”;在打开的文件对话框中位图的文件名;这就在Bitmap分支上增加了一个位图,你还需要用右键菜单设置属性,把ID改为IDB_MYBMP。双击它还可以对它进行图片加工。
2 添加菜单
参考第四章叙述的方法添加菜单IDR_MENU1,它包含FIEL和HELP两个菜单。FIEL菜单包括三个菜单项,HELP菜单就只有Help菜单项。打开类向导,将菜单IDR_MENU1与类CMyBmpDlg项关联。
3 设置主窗口
打开主对话框的属性页,设置ID = IDD_MYBMP_DIALOG,标题 = MyBmp-显示位图,并把MENU1加入进去。在Styles页设置窗口是可以改变大小的,加上系统菜单。
11.3 编写代码
为了在屏幕上显示图片,需要给出区域的左上角座标和区域的宽度和长度。因为要使显示区域是可变的,所以引进两个全局变量
int m_Width, m_Height ;
定义在构造函数中。
显示图片就是先创建一个内存对象(HDC),把图片读入到这个内存对象这个内存,再用函数StretchBlt()把它映射到指定的屏幕区域。我们在OnPaint()函数中加入如下代码:
else
{
//My code startup here
//Create 环境设备
CPaintDC dc(this);
//创建一个位图对象
HBITMAP hbitmap = ::LoadBitmap(
::AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_MYBMP));
//Create a memory dc
HDC hMemDC = ::CreateCompatibleDC(NULL);
//put the bitmap into memory dv
SelectObject(hMemDC,hbitmap);
//Copy the memory dc into the screen
::StretchBlt(dc.m_hDC, //Draw
on screen field
0,0, m_Width, m_Height, //Place
of the screen
hMemDC, //Memory
DC map into screen
0,0,113,133, //Size
of this pictrue
SRCCOPY); //Copy
Mode
//My code END
......
当对话框的窗口大小被改变时系统会发送消息,因此我们需要添加消息映射WM_SIZE,并且在响应函数OnSize中把窗口的大小值传递给m_Width和m_Height,并让窗口重画。这函数为:
void CMyBmpDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
m_Width = cx;
m_Height= cy;
Invalidate();
}
OnSize()中的变量cx,cy就是当前窗口(客户区)的宽度和高度。
要在HELP菜单中打开About对话框,就在OnHelpAbout()函数中加入代码:
CAboutDlg dlg;
dlg.DoModal();
给Open菜单项添加消息映射但不加代码,给EXIT菜单项加入退出代码OnOK()。编码结束,编译和运行。
11.4 代码解析
HBITMAP hbitmap = ::LoadBitmap(
::AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_MYBMP));
创建一个HBITMAP类的对象hbitmap,双冒号表示调用一个SDK的函数LoadBitmap(),它返回一个HBITMAP类的对象。它有两个参数。第一个由:AfxGetInstanceHandle()函数提供,它是这个对象的句柄。第二个由宏MAKEINTRESOURCE()生成,它对应位图资源。
下一行
HDC hMemDC = ::CreateCompatibleDC(NULL);
定义了一个HDC类型的对象,它表示一块内存区域,由函数CreateCompatibleDC()创建。然后,让内存区域和位图对象hbitmap联系起来,这项任务由函数SelectObject()来实现。
现在,就可以用StretchBlt()函数来显示图形了。这项任务是由StretchBlt()函授来实现的,它有11个参数,列举如下:
::StretchBlt(dc.m_hDC, //环境设备dc的可画的对象
0,0, m_Width, m_Height, //屏幕区域
hMemDC, //内存对象源,它已经含有图片信息。
0,0,113,133, //原图片的大小
SRCCOPY); //Copy模式
dc.m_hDC是dc的一个数据成员,是“可画图”的对象。原图片的大小必须事先查好。0