CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  界面

建立一个单文档的工程,希望能够将本地的一张图片显示在view上做背景图,如何实现(急)

楼主princesshan(小青蛇)2006-03-03 18:15:42 在 VC/MFC / 界面 提问

建立一个单文档的工程,希望能够将本地的一张图片显示在view上做背景图,如何实现(急)  
  图像文件在本地的硬盘上。  
  还有我要在屏幕上绘图,要实时刷新,怎么避免闪烁。图片是bmp或者jpg的  
  我已经试了好写代码,都不行。最好给些可执行的代码。谢谢 问题点数:20、回复次数:21Top

1 楼cpio(备注)回复于 2006-03-03 18:25:11 得分 0

用GDI+吧  
   
  它可以直接从硬盘文件创建Image对象  
   
  Graphics有画Image的方法  
   
  至于闪烁就是用双缓冲,先画在内存DC里,再通过Bitblt复制到实际DC上  
   
  Top

2 楼wawaku(一堆裤衩!)回复于 2006-03-03 18:43:20 得分 0

Ctrl+R  
  插入位图,  
  在xxxxview.h中  
  CBitmap   bitmap;  
  在OnCreate()中  
  bitmap.LoadBitmap(IDB_BITMAP1);  
  在OnDraw()中  
  mdc->SelectObject(&bitmap);  
  pDC->Bitblt(0,0,400,400,&mdc,0,0,SRCCOPY);  
  Top

3 楼wawaku(一堆裤衩!)回复于 2006-03-03 18:45:44 得分 0

想实现没有闪烁很容易,只要都先画在预设的DC上,最后再画在设备DC上就OK了  
   
  即,  
  mdc->BitBlt();  
  mdc->  
  .  
  .  
  .  
  .  
   
   
  pDC->BitBlt(0,0,800,600,&mdc,0,0,SRCCOPY);Top

4 楼princesshan(小青蛇)回复于 2006-03-06 09:49:23 得分 0

to:wawaku  
  你的方法不行,因为我每一次用的图不同  
   
   
  好像没有人实际解决了这个问题,继续找,求告人指点Top

5 楼ggw(格格巫)回复于 2006-03-06 12:33:39 得分 0

前天看到个问题与此类似,显示为背景就是要换窗口类中的那个Brush。是不是可以这样:在view类中重载precreatewindow这函数,将类中的brush换掉?再重新注册新类。Top

6 楼wawaku(一堆裤衩!)回复于 2006-03-06 13:02:15 得分 0

有很多图片么?不太多的话可以全LOAD进来,再通过你想更换背景的设置来个switch就OK呀.  
  要不用户自已想浏览着换的话,可以做一个浏对话框呀Top

7 楼wawaku(一堆裤衩!)回复于 2006-03-06 13:02:55 得分 0

??不太明白你要的功能!Top

8 楼princesshan(小青蛇)回复于 2006-03-06 16:53:40 得分 0

我需要用的是哪一个图片,是可以通过一个列表进行选择的,图像在本地,应该有几万个不同的。Top

9 楼xiao_fang(frank)回复于 2006-03-06 17:19:36 得分 4

在网上搜索一下CBitmapPicture   这个类,用于装载各种本地图片  
   
  然后在OnEraseBkgnd中  
  BOOL   CTestView::OnEraseBkgnd(CDC*   pDC)    
  {  
  CRect   rect;  
  GetClientRect(&rect);  
  CBitmapPicture   bitmap;  
  bitmap.Load(GetDocument()->m_strBackPix);  
   
  BITMAP   bmp;  
  bitmap.GetBitmap(&bmp);  
   
  CDC   dcCompatible;  
  dcCompatible.CreateCompatibleDC(pDC);  
  dcCompatible.SelectObject(&bitmap);  
   
  //   居中显示背景图片  
  pDC->BitBlt((rect.Width()-bmp.bmWidth)/2,   (rect.Height()-bmp.bmHeight)/2,  
  bmp.bmWidth,   bmp.bmHeight,   &dcCompatible,   0,   0,   SRCCOPY);  
   
  return   TRUE;  
  }Top

10 楼princesshan(小青蛇)回复于 2006-03-07 10:27:02 得分 0

多谢楼上的,问题已经解决大部分了  
  还有一点,按照上面的代码,view上面没有图像的部分好像不会自动刷新,怎么办?除了图像的部分,其他的部分现在显示的乱其八糟的东西,是代码编辑界面上的东西,我希望是空白的,怎么办?Top

11 楼paulli_li()回复于 2006-03-07 12:39:46 得分 4

用位图作为背景并且可以在上面画图的思路是这样的:要作到不闪烁就是用内存缓冲的方法,  
  而用位图作为背景就要将位图的影像“映射”到View的Brush中。要综合考虑这两点,如果只是  
  简单的把位图载入而在上面直接画图的话,虽然解决了闪烁的问题,但是不能使鼠标在客户区  
  有点击画图动作时刷新。因此可以考虑把图象作为背景,用Brush实现。  
  具体可以这样:在OnDraw()中定义变量   mdc,然后像下面这样  
   
  CDC     mdc;  
  mdc.CreateCompatibleDC(pDC);           //创建memDC  
   
  CBitmap     backBitmap;  
  backBitmap.LoadBitmap(IDB_***);     //载入位图  
   
  BITMAP       bmp;                                         //计算位图尺寸  
  bmp.GetBitmap(&bmp);  
  int   bmpWidth=   bmp.bmWidth;  
  int   bmpHeight=   bmp.bmHeight;  
   
  CBitmap     memBitmap;                             //创建用于画图的Bitmap  
  memBitmap.CreateCompatibleBitmap(pDC,bmpWidth,   bmpHeight);  
  CBitmap*   pOldBitmap=   mdc.SelectObject(&memBitmap);  
   
  CRect   rect(0,0,bmpWidth,   bmpHeight);         //改写Brush  
  CBrush       bkBrush;  
  bkBrush.CreatePatternBrush(&backBitmap);  
  CBrush*   pOldBrush=mdc.SelectObject(&bkBrush);  
  mdc.FillRect(rect,   &bkBrush);  
   
  pDC->BitBlt(0,0,   bmpWidth,bmpHeight,   &mdc,   0,0,   SRCCOPY);       //Bitblt   to   screen  
   
  mdc.SelectObject(pOldBitmap);  
  mdc.SelectObject(pOldBrush);  
   
  然后在OnEraseBkgnd中将返回语句改成    
  return   TRUE;  
  这样就应该可以了.做背景图不闪烁的方法大抵如此,至于如何列表装载位图的方法,  
  需要用哪个类,我不是很清楚.参考一下其他人的吧.Top

12 楼princesshan(小青蛇)回复于 2006-03-07 17:05:02 得分 0

楼上的,好像不可以,显示的不是背景图片,是一些编码界面乱其八糟的东西,  
  哪位有自己测试通过了的代码阿?谢谢了  
  Top

13 楼denjackson(Harley)回复于 2006-03-07 17:14:44 得分 4

xiao_fang(frank)   (   )   信誉:105   讲的在OnEraseBkgnd(CDC*   pDC)   做是正解,这样才能不闪.  
   
  BOOL   CGraphicView::OnEraseBkgnd(CDC*   pDC)    
  {  
  //   TODO:   Add   your   message   handler   code   here   and/or   call   default  
  CBitmap   bitmap;  
  bitmap.LoadBitmap(IDB_BITMAP1);  
   
  BITMAP   bmp;  
  bitmap.GetBitmap(&bmp);  
   
  CDC   dcCompatible;  
  dcCompatible.CreateCompatibleDC(pDC);  
   
  dcCompatible.SelectObject(&bitmap);  
   
  CRect   rect;  
  GetClientRect(&rect);  
  pDC->StretchBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,  
  0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);  
  return   TRUE;  
   
  }Top

14 楼paulli_li()回复于 2006-03-07 19:19:59 得分 0

抱歉,Bitmap   bmp下面那行应该写成backBitmap.GetBitmap(&bmp);这样的就应该没有问题了。  
  我编译运行后并没有问题.你可以再仔细查看一下,LoadBitmap是不是正确,图片是正常显示的.  
  楼上的也是这个意思,大同小异.Top

15 楼YufengShi(浪子)回复于 2006-03-07 19:45:49 得分 0

1.LoadImage从文件载入bmp图片(jpg图片要用其它手段)  
  2.计算图片的大小,在WM_ERASEBKGND中用刷子刷新背景前,  
  用CDC::SelectClipRgn进行裁减,目的是只刷新除图片区域外的背景  
  3.粘贴图片(先创建兼容DC,再选择bitmap,在bitblt到窗口DC中)Top

16 楼xiao_fang(frank)回复于 2006-03-08 10:06:10 得分 4

浪子说的有道理,在图片比客户区域小时,一般我们应设置裁剪区域来避免闪烁。  
  因为在OnEraseBkgnd中我们只是将图片BitBlt到视图上去了,就返回TRUE,这意味着其它区域不会自动刷新,所以应该:  
  //   get   client   rectangle  
  CRect   rcClient;  
  GetClientRect(&rcClient);  
  CRect   rc   =   rcClient;  
   
  //   get   image   rectangle  
  CRect   rcImage;  
  GetImageRect(rcImage);  
  rc   =   rcImage;  
   
  //   create   clipping   region  
  CRgn   clipRgn;  
  clipRgn.CreateRectRgnIndirect(&rcClient);  
  pDC->SelectClipRgn(&clipRgn);  
  pDC->ExcludeClipRect(&rcImage);   //   exclude   the   image   region!!!  
   
  CBrush   brush(RGB(0,0,0));   //   fill   with   black   brush  
  pDC->FillRect(&rcClient,   &brush);  
   
  pDC->SelectClipRgn(NULL);  
  但这样也太麻烦了:)  
   
  在画图前判断一下图片大小,直接填充一次不就行了:  
  //   客户区比图片面积大,先清除客户区为黑色  
  if((rect.Width()   >   bmp.bmWidth)   ||   (rect.Height()   >   bmp.bmHeight))  
  {  
  pDC->BitBlt(0,   0,   rect.Width(),   rect.Height(),  
  NULL,   0,   0,   BLACKNESS   );  
  }  
   
  将以上三行加在我前面提供的代码的dcCompatible.SelectObject(&bitmap)的后面即可。  
  好好看看MSDN中CWnd::OnEraseBkgnd,会问还要多思考才能进步更快:)  
  hope   help:)Top

17 楼denjackson(Harley)回复于 2006-03-08 10:21:37 得分 4

CWnd::OnEraseBkgnd是正解.  
  光用背景图还不行,如果你用FORMVIEW,还得修改控件背景,不然也是不好看的.Top

18 楼wawaku(一堆裤衩!)回复于 2006-03-08 10:38:32 得分 0

这贴可以去当精华了,UPTop

19 楼paulli_li()回复于 2006-03-08 13:41:31 得分 0

我觉得需要分析一下所需问题的意思。如果要让在客户区画图时不闪烁,传统的方法就是  
  兼容DC这种方法,我写的代码和上面讨论的在OnEraseBkgnd中的写法最终都是要BitBlt.  
  princesshan   的意思不仅是要以一个位图当作背景,而且还要在背景图的上面进行绘图,  
  并且绘出的图形和背景图此时都不能闪烁。大家是如何考虑这个问题的?在OnEraseBkgnd  
  return   TRUE,   就是通知框架每次在调用OnDraw之前不要用Brush刷新。刷新是闪烁的根本  
  原因。我没有考虑过图片的大小、客户区、剪裁区之间的关系,我只是让图片大小直接成  
  为绘图客户区大小。希望有人能系统总结一下考虑了诸如楼上提出情况下解决问题的方法。  
  大家多多提供想法和讨论,向精华贴努力!^_^Top

20 楼princesshan(小青蛇)回复于 2006-03-11 10:26:43 得分 0

to:xiao_fang(frank)    
   
  用了下面的代码,屏幕上拖动闪烁的很厉害,怎么办?  
  在画图前判断一下图片大小,直接填充一次不就行了:  
  //   客户区比图片面积大,先清除客户区为黑色  
  if((rect.Width()   >   bmp.bmWidth)   ||   (rect.Height()   >   bmp.bmHeight))  
  {  
  pDC->BitBlt(0,   0,   rect.Width(),   rect.Height(),  
  NULL,   0,   0,   BLACKNESS   );  
  }  
   
   
  如果不用上面的代码,没有画像的部分的区域不会刷新。继续求好的解决办法,我要在view上拖动鼠标画线,闪的太厉害肯定不行。  
  Top

21 楼xiao_fang(frank)回复于 2006-03-18 21:39:56 得分 0

use   your   head,   boy!Top

相关问题

  • 如何在单文档的view中显示一个背景图片(jpg)(急)
  • 基于view的单文档转化成LISTVIEW的单文档?
  • 关于屏蔽基于单文档的view的系统菜单
  • 求助!在单文档的view中画图。
  • 单文档应用(CScroolView),view为什么没有滚动条
  • 单文档方案中MainFrame类中取得View类的句柄?
  • 关于单文档的多个view的切换
  • 单文档问题
  • 单文档 问题!
  • 我的powerpoint文档已经做好, 现在想在背景上加公司名字, 文档很多,如何以简单的方式更改急

关键词

  • mdc
  • 代码
  • view
  • 客户
  • dccompatible
  • bmp
  • 图片
  • pdc
  • 背景
  • onerasebkgnd

得分解答快速导航

  • 帖主:princesshan
  • xiao_fang
  • paulli_li
  • denjackson
  • xiao_fang
  • denjackson

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo