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




