VC中如何在对话框上显示位图

 在用VC开发应用程序的时候,经常要在对话框上显示位图。如果把位图加入资源中,当然是省时省力,但程序却也增肥不少,并且失去了灵活性。而如果你要动态地显示一大堆图片,各个图片大小不一,这岂不…本文就是介绍如何在对话框上显示位图,并且如何让对话框自动适应位图的大小的。 


---- VC对位图的操作比较烦琐,要显示一个位图到对话框上去,很麻烦。我在开发的过程中走通了两条路:一是使用Kodak图象编辑控件;二是利用Microsoft提供的例子中的一个类,并稍加改造。两种方法各有优缺点。我把它写下来,以避免其他人多走弯路。 

    一、利用控件 

   利用 WINDOWS98中带的Kodak图象编辑控件来在对话框上显示一个位图,虽然有点儿杀鸡用牛刀的感觉,但却不失为一个极方便快捷的方法。顾名思义,这个控件不但可以显示,它更强大的功能还是在编辑图象,它可以对图象进行放大、缩小、标注等操作。而且,使用起来很方便。但它毕竟是别人的东东,不太清楚它的底细,用起来就不免…我就吃了它的苦头。在本机上调试通过,安装了其他几台机器也很正常,但是有一台却颜色失真了,变成了水粉画。不知是不是那台机器的显卡有问题。还有就是据我初步实验,在95下好象行不通。不过现在大家都是WIN98,这似乎已经不算一个问题了。下面就把我的过程写下来: 

  首先应该保证系统中有这个控件。注意,它不能单独使用,必须和其他几个控件(特别是Imgcmn.dll)一同使用。如果没有,从别的机器上copy过来即可。这几个文件是Imgadmin.ocx,Imgcmn.dll,Imgedit.ocx,Imgscan.ocx,Imgshl.dll,Imgthumb.ocx,Imgutil.dll,把它们copy到 windows\system目录下,然后用regsvr32.exe将它们分别注册。 

  打开VC,新建一个基于对话框的工程(主要是为了说明方便),删除掉对话框上其他的东西(按钮和LABEL),在对话框上单击右键,单击Insert Activex control… 选择Kodak图象编辑控件,大小任意。 

  在对话框上选中该控件,打开view|classwizard,单击Member Variables,点击Add Variable…按钮,系统会弹出一个对话框,大体上是提示你它要把控件加入工程中了,确定即可。在接下来的对话框上继续点击OK,此时,会出现一个对话框,提示你输入变量名,输入你想要的名字即可。我们输入m_ctrlPicture。单击确定。 

  此时你的工程中已经有了一个名字为m_ctrlPicture的控件,接下来就可以利用它来显示图片了,我们把它加到对话框的初始化中。单击ClassWizard,选择OnInitDialog,单击Edit Code按钮。 

  在OnInitDialog中,找到// TODO: Add extra initialization here,在下面加入如下代码: 
m_ctrlPicture.SetImage("c:\\ windows\Clouds.bmp"); 
m_ctrlPicture.Display(); 


  编译运行,看到了吗?就这么简单。 

  但是它的大小却是固定的,要看全图只能利用滚动条。下面我们再来得到图象的尺寸,然后使对话框自动适应图象的大小。还是在初始化中,代码如下: 
m_ctrlPicture.SetImage("c:\\ windows\\Clouds.bmp"); 
const int nAddConst=40; 
//图象尺寸不会正合适,需要加点增量。 
long lPictureWidth=m_ctrlPicture.GetImageWidth(); 
long lPictureHeight=m_ctrlPicture.GetImageHeight(); 
MoveWindow(0,0,lPictureWidth,lPictureHeight,true); 
    //改变对话框大小 

    //改变控件的大小 
m_ctrlPicture.MoveWindow(0,0,lPictureWidth, 
lPictureHeight+nAddConst,true); 
m_ctrlPicture.Display(); 

成功了。 
注意,这个控件不但只能显示bmp,还可显示许多其他的格式,你可以自己试一下。 
  

   二、利用Cdib类 

  这个方法比较烦琐,并且只能显示bmp,但它不依赖特定的系统,也比较实用。这个类在MSDN提供的例子中有,名字为ex10c.dsw,找到cdib.cpp和cdib.h,加入你的工程即可。如果你找不到,也可以到我的网页去看看http://dlgis.topcool.net或者给我写信ytdl@263.net。 

---- 下面是过程: 

新建一个基于对话框的工程,单击Add Files to Project,加入上面所说的两个文件。 

在对话框的头文件中加入#include "cdib.h",然后给对话框类加入一个成员变量,代码如下: Cdib m_dibFile; 

在对话框的初始化函数中,加入如下代码: 
#ifdef MEMORY_MAPPED_FILES 
if (m_dibFile.AttachMapFile 
("c:\\ windows\\clouds.bmp",TRUE)==TRUE) 
{ // share 
Invalidate(); 

#else 
CFile file; 
file.Open("c:\\ windows\\clouds.bmp", 
Cfile::modeRead); 
if (m_dibFile.Read(&file) == TRUE) 

Invalidate(); 

#endif // MEMORY_MAPPED_FILES 
CClientDC dc(this); 
m_dibFile.SetSystemPalette(&dc); 
在OnPaint函数中,找到else,然后在里面加入如下代码: 
BeginWaitCursor(); 
m_dibFile.UsePalette(GetDC()); 
CSize sizeFileDib = m_dibFile.GetDimensions(); 
m_dibFile.Draw(GetDC() ,CPoint(0,0), sizeFileDib); 
EndWaitCursor(); 

  运行程序,是不是看到蓝天白云了?!下面继续加入让对话框自动适应图片大小的代码,还是在初始化中,紧接这上一次的代码,加入如下两行: 
CSize sizeFileDib = m_dibFile.GetDimensions(); 
MoveWindow(0,0,sizeFileDib.cx,sizeFileDib.cy,true); 

  (3)书籍标准版
在OnPaint()中加入以下代码
//在对话框中直接显示图像
 BITMAP bm;
 CBitmap bmp;//定义CBitmap 类的对象
 bmp.LoadBitmap(IDB_BITMAP1);//装入ID号为IDB_BITMAP1的位图
 CDC memdc;//定义CDC类的对象
 CRect rect;
 memdc.CreateCompatibleDC(&dc);//创建与显示DC相兼容的内存DC
 bmp.GetBitmap(&bm);
 CBitmap *bmpold=memdc.SelectObject(&bmp);//将选定的位图选入内存DC
 this->GetClientRect(&rect);
 //从内存DC向显示DC复制,rect.left,rect.top为图像左上角的坐标,SRCCOPY表示直接将源位图拷贝到目的位图,不作修改
 dc.BitBlt(rect.left,rect.top,bm.bmWidth,bm.bmHeight,&memdc,0,0,SRCCOPY);
 memdc.SelectObject(bmpold);
 memdc.DeleteDC();
 bmp.DeleteObject();
(4)摘自网络

步骤/方法

  1. 1
      //在对话框内显示位图
      CBitmap hbmp;
      HBITMAP hbitmap;
      //装载图片文件MM.bmp
      hbitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"MM.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
      hbmp.Attach(hbitmap);
      //获取图片格式
      BITMAP bm;
      hbmp.GetBitmap(&bm);
      CDC dcMem;
      dcMem.CreateCompatibleDC(GetDC());
      CBitmap * poldBitmap=(CBitmap*)dcMem.SelectObject(hbmp);
      CRect lRect;
      GetClientRect(&lRect);
      lRect.NormalizeRect();
      //显示位图
    MFC显示位图的几种方法
  2. 2
      GetDC()->StretchBlt(lRect.left,lRect.top,lRect.Width(),lRect.Height(),&dcMem,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
      dcMem.SelectObject(&poldBitmap);
      //在Static控件内显示位图
      CBitmap hbmp;
      HBITMAP hbitmap;
      //将pStatic指向要显示的地方
      CStatic *pStatic;
      pStatic=(CStatic*)GetDlgItem(IDC_STATIC); //IDC_STATIC是你的Staic控件名
      //装载图片文件MM.bmp
      hbitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"MM.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
      hbmp.Attach(hbitmap);
    MFC显示位图的几种方法
  3. 3
      //获取图片格式
      BITMAP bm;
      hbmp.GetBitmap(&bm);
      CDC dcMem;
      dcMem.CreateCompatibleDC(GetDC());
      CBitmap * poldBitmap=(CBitmap*)dcMem.SelectObject(hbmp);
      CRect lRect;
      pStatic->GetClientRect(&lRect);
      lRect.NormalizeRect();
      //显示位图
      pStatic->GetDC()->StretchBlt(lRect.left,lRect.top,lRect.Width(),lRect.Height(),&dcMem,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
      dcMem.SelectObject(&poldBitmap);
    MFC显示位图的几种方法
   // 测试可用 PIC control

//弄了半天终于是picturecontrol上能显示位图了,离逻辑bitblt还远

void Ctest1Dlg::OnStnClickedPic()
{  HBITMAP   hBitmap;
  //获得指向静态控件的指针   
  CStatic   *pStatic=(CStatic   *)GetDlgItem(IDC_PIC);   
  //获得位图句柄  
  hBitmap   =   (HBITMAP)LoadImage(   
                  AfxGetInstanceHandle(),     
                  MAKEINTRESOURCE(IDB_BITMAP2),     
                  IMAGE_BITMAP,     
                  0,     
                  0,     
                  LR_LOADMAP3DCOLORS);  

   
  //设置静态控件的样式,使其可以使用位图,并试位标显示使居中   
  pStatic->ModifyStyle(0xF,SS_BITMAP|SS_CENTERIMAGE);   
  //设置静态控件显示位图   
  pStatic->SetBitmap(hBitmap);   
    
 
 // TODO: Add your control notification handler code here
}

     CEDIT类如何实现背景位图

在VC中,标准的WINDOWS控件如TREEVIEW,EDITBOX,COMBOBOX和LISTBOX等控件都不支持选择背景位图的属性,所以如果要使这些标准控件达到这种效果,必须有些非常规的方法。本文介绍一个CEDIT类如何实现背景位图,并且可以更换背景的例子。可能实现的方法还有其它种,如果有兴趣可以大家探讨。

本文程序运行效果图

下面介绍CMYEDITCTRL类几个关键变量和函数。

第一步在该类中增加几个变量;

1. public:
2. CBitmap m_bmp;
3. protected:
4. CBrush m_brHollow;
5. CBitmap *m_pbmCurrent;

第二步 重载部分函数:

1. afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
2. afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
3. afx_msg void OnChange();
4. afx_msg BOOL OnEraseBkgnd(CDC* pDC);

各个函数的具体作用:

2.1 OnChange();

如果没有这个函数,你敲几个字符如 ABCDEDFG,然后删除两个FG,但是EDITBOX并未更新。添加这个函数主要是这个原因。

1. void CMyEditCtrl::OnChange()
2. {
3. Invalidate(); ///强制进行更新
4. }

2.2 OnLButtonUp();

也类似,是你鼠标选择时候的刷新问题,如果你有兴趣,可以先把它注释掉,看看BUG是怎么出现的。

1. void CMyEditCtrl::OnLButtonUp(UINT nFlags, CPoint point)
2. {
3. Invalidate(); ///强制进行更新
4. CEdit::OnLButtonUp(nFlags, point);
5. }

2.3 CtlColor(CDC* pDC, UINT nCtlColor)

一般的文字的默认背底是白色的,这儿选择了透明的形式,所以底图可以显示。

1. HBRUSH CMyEditCtrl::CtlColor(CDC* pDC, UINT nCtlColor)
2. {
3. pDC->SetBkMode(TRANSPARENT); ///选择透明背景模式
4. pDC->SetTextColor(RGB(0xff,0xff,0xff)); ///设置文字颜色为白色
5. return m_brHollow;
6. }

2.4 OnEraseBkgnd(CDC* pDC)

主要把选好的背景位图显示出来。

01. BOOL CMyEditCtrl::OnEraseBkgnd(CDC* pDC)
02. {
03. BITMAP bm;
04. m_bmp.GetBitmap(&bm);
05. m_pbmCurrent = &m_bmp;
06. CDC dcMem;
07. dcMem.CreateCompatibleDC(pDC);
08. CBitmap* pOldBitmap = dcMem.SelectObject(m_pbmCurrent);  ///选择位图
09. pDC->BitBlt(0,0,bm.bmWidth,bm.bmHeight,&dcMem,0,0,SRCCOPY);  ///画出位图
10. dcMem.SelectObject(pOldBitmap);
11. return TRUE;
12. }

说明:其中代码有些部分简化了,有些部分还可以优化。对于底图的选择,在这里我选择是与我EDITBOX一样大小的底图,如果两者不一样大小,需要修改部分OnEraseBkgnd(CDC* pDC)代码。

基本上这个类的功能就这样实现了。


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值