在VC中加了坐标映射,为什么BitBlt()函数就画不出图了?
我在VC++的OnDraw()函数中加了坐标映射,为什么BitBlt()函数就画不出图了?去掉坐标映射就又可以画图了,但是我又需要坐标映射来放大客户区,来绘图。代码如下v...
我在VC++的OnDraw()函数中加了坐标映射,为什么BitBlt()函数就画不出图了?去掉坐标映射就又可以画图了,但是我又需要坐标映射来放大客户区,来绘图。
代码如下
void CCyshetextView::OnDraw(CDC* pDC)
{
CCyshetextDoc* pDoc=GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//创建关于屏幕的内存DC
CDC mDC;
mDC.CreateCompatibleDC(pDC);
//创建一副关于屏幕DC的图画
CRect rect;
GetClientRect(rect); //得到客户区大小
CBitmap MemBitmap;
MemBitmap.CreateCompatibleBitmap(pDC,rect.right,rect.bottom );
//保留以前内存,并将这幅图选入到内存DC中
CBitmap *pOldBitmap=mDC.SelectObject(&MemBitmap);
//以下为设置坐标映射
mDC.SetMapMode(MM_ANISOTROPIC); //X、Y单位长度都自定义的映射模式
mDC.SetWindowOrg(0,0);//设置窗口左上角的坐标为
mDC.SetWindowExt(500,50);//设置窗口度量
mDC.SetViewportOrg(0,0);
mDC.SetViewportExt(rect.right,rect.bottom);
//以下为画直线
CPen PenWave(PS_SOLID,5,RGB(255,0,255));//创建紫色的画笔PenWave
mDC.SelectObject(PenWave);
mDC.MoveTo(0,0);
mDC.LineTo(50,50);
//下面将内存DC上所绘内容一次性拷贝到当前DC
pDC->StretchBlt(0,0,rect.right,rect.bottom,&mDC,0,0,SRCCOPY);
//资源回收
mDC.SelectObject(pOldBitmap);
MemBitmap.DeleteObject();
}
希望路过的VC爱好者不吝指教,本人现在分不多,如问题解决,回头再最加50分.
谢谢你的问答,我已经找到图画不出来的问题了,是因为StretchBlt函数,把它改成BitBlt()函数就好了。
但是问题并没有解决,
其一、正如你的附图一样,我并没有把背景设置为黑色,怎么会变成黑色的呢?客户区应该是白色背景。
其二、如果背景为黑色,那为什么没有把整个客户区都填充成黑色背景?
其三、为什么紫色的直线只出现在黑色的背景里?
我认为,是我的坐标映射和BitBlt()函数有问题,内存DC和屏幕DC没有协调好,正确的效果应该是客户区内有一条紫色的直线,随着调节客户去的大小,直线的大小也会改变,还希望大家指教。
intehel,谢谢你的回答,但是你调试过了么,直线画的不对。 展开
代码如下
void CCyshetextView::OnDraw(CDC* pDC)
{
CCyshetextDoc* pDoc=GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//创建关于屏幕的内存DC
CDC mDC;
mDC.CreateCompatibleDC(pDC);
//创建一副关于屏幕DC的图画
CRect rect;
GetClientRect(rect); //得到客户区大小
CBitmap MemBitmap;
MemBitmap.CreateCompatibleBitmap(pDC,rect.right,rect.bottom );
//保留以前内存,并将这幅图选入到内存DC中
CBitmap *pOldBitmap=mDC.SelectObject(&MemBitmap);
//以下为设置坐标映射
mDC.SetMapMode(MM_ANISOTROPIC); //X、Y单位长度都自定义的映射模式
mDC.SetWindowOrg(0,0);//设置窗口左上角的坐标为
mDC.SetWindowExt(500,50);//设置窗口度量
mDC.SetViewportOrg(0,0);
mDC.SetViewportExt(rect.right,rect.bottom);
//以下为画直线
CPen PenWave(PS_SOLID,5,RGB(255,0,255));//创建紫色的画笔PenWave
mDC.SelectObject(PenWave);
mDC.MoveTo(0,0);
mDC.LineTo(50,50);
//下面将内存DC上所绘内容一次性拷贝到当前DC
pDC->StretchBlt(0,0,rect.right,rect.bottom,&mDC,0,0,SRCCOPY);
//资源回收
mDC.SelectObject(pOldBitmap);
MemBitmap.DeleteObject();
}
希望路过的VC爱好者不吝指教,本人现在分不多,如问题解决,回头再最加50分.
谢谢你的问答,我已经找到图画不出来的问题了,是因为StretchBlt函数,把它改成BitBlt()函数就好了。
但是问题并没有解决,
其一、正如你的附图一样,我并没有把背景设置为黑色,怎么会变成黑色的呢?客户区应该是白色背景。
其二、如果背景为黑色,那为什么没有把整个客户区都填充成黑色背景?
其三、为什么紫色的直线只出现在黑色的背景里?
我认为,是我的坐标映射和BitBlt()函数有问题,内存DC和屏幕DC没有协调好,正确的效果应该是客户区内有一条紫色的直线,随着调节客户去的大小,直线的大小也会改变,还希望大家指教。
intehel,谢谢你的回答,但是你调试过了么,直线画的不对。 展开
3个回答
展开全部
映射模式:MM_ANISOTROPIC
横坐标:往右递增
纵坐标:往下递减
当原点坐标为(0,0)时,
Y坐标如果为正,就跑到窗口上边去了,画的任何东西都是在窗口外面。
-------------------------------------------------------------------------------------
内存DC设置了映射模式,设备DC没有设置映射模式。当BitBlt时,需要使用内存DC的每一个点画到设备DC的对应点中,由于两个DC的映射模式不同,所以无法正确对应每一个点。例如坐标为100,50的点,对于内存DC和设备DC而言,不是同一个坐标点。
正确的逻辑和序列是:
设置设备DC的映射模式,
创建内存DC,
画图,
把内存DC中的图片COPY到设备DC中:
尽量使用BitBlt,不要使用StretchBlt进行COPY。原因是:
1)StretchBlt进行拉伸需要使用算法,执行速度肯定没BitBlt快
2)StretchBlt的拉伸会使图形失真,仔细看下一幅800*600的图片,用StretchBlt拉伸至全屏后,和用Windows自带的图片查看器进行拉伸后比对,就会发现StretchBlt很傻的。
3)图片拉伸算法有几个需要考量的指标:第一是尽可能使图片不失真第二是尽可能提高算法的执行速度。一和二之间是此消彼长的关系。要保真就失速度!StretchBlt不如一些专业图像软件做的拉伸效果就是因为StretchBlt并不是专业的图像处理函数,主要为了提高该函数的执行速度,因此会失真。要想不失真,自己写图像算法。
因此,基本上没有什么理由使用StretchBlt。
附上源代码:
//以下为设置坐标映射
pDC->SetMapMode(MM_ANISOTROPIC); //X、Y单位长度都自定义的映射模式
pDC->SetWindowOrg(0,0);//设置窗口左上角的坐标为
pDC->SetWindowExt(500,50);//设置窗口度量
pDC->SetViewportOrg(0,0);
pDC->SetViewportExt(rect.right,rect.bottom);
mDC.CreateCompatibleDC(pDC);
//创建一副关于屏幕DC的图画
CBitmap MemBitmap;
MemBitmap.CreateCompatibleBitmap(pDC,500, 50); //注意内存位图的大小尺寸设置
//保留以前内存,并将这幅图选入到内存DC中
CBitmap *pOldBitmap=mDC.SelectObject(&MemBitmap);
//以下为画直线
CPen PenWave(PS_SOLID,5,RGB(255,0,255));//创建紫色的画笔PenWave
mDC.SelectObject(PenWave);
mDC.MoveTo(0,0);
mDC.LineTo(50,50);
//下面将内存DC上所绘内容一次性拷贝到当前DC
pDC->BitBlt(0,0,500, 50,&mDC,0,0,SRCCOPY);
//资源回收
mDC.SelectObject(pOldBitmap);
//MemBitmap.DeleteObject();这行没必要,CBitmap析构函数会做的
横坐标:往右递增
纵坐标:往下递减
当原点坐标为(0,0)时,
Y坐标如果为正,就跑到窗口上边去了,画的任何东西都是在窗口外面。
-------------------------------------------------------------------------------------
内存DC设置了映射模式,设备DC没有设置映射模式。当BitBlt时,需要使用内存DC的每一个点画到设备DC的对应点中,由于两个DC的映射模式不同,所以无法正确对应每一个点。例如坐标为100,50的点,对于内存DC和设备DC而言,不是同一个坐标点。
正确的逻辑和序列是:
设置设备DC的映射模式,
创建内存DC,
画图,
把内存DC中的图片COPY到设备DC中:
尽量使用BitBlt,不要使用StretchBlt进行COPY。原因是:
1)StretchBlt进行拉伸需要使用算法,执行速度肯定没BitBlt快
2)StretchBlt的拉伸会使图形失真,仔细看下一幅800*600的图片,用StretchBlt拉伸至全屏后,和用Windows自带的图片查看器进行拉伸后比对,就会发现StretchBlt很傻的。
3)图片拉伸算法有几个需要考量的指标:第一是尽可能使图片不失真第二是尽可能提高算法的执行速度。一和二之间是此消彼长的关系。要保真就失速度!StretchBlt不如一些专业图像软件做的拉伸效果就是因为StretchBlt并不是专业的图像处理函数,主要为了提高该函数的执行速度,因此会失真。要想不失真,自己写图像算法。
因此,基本上没有什么理由使用StretchBlt。
附上源代码:
//以下为设置坐标映射
pDC->SetMapMode(MM_ANISOTROPIC); //X、Y单位长度都自定义的映射模式
pDC->SetWindowOrg(0,0);//设置窗口左上角的坐标为
pDC->SetWindowExt(500,50);//设置窗口度量
pDC->SetViewportOrg(0,0);
pDC->SetViewportExt(rect.right,rect.bottom);
mDC.CreateCompatibleDC(pDC);
//创建一副关于屏幕DC的图画
CBitmap MemBitmap;
MemBitmap.CreateCompatibleBitmap(pDC,500, 50); //注意内存位图的大小尺寸设置
//保留以前内存,并将这幅图选入到内存DC中
CBitmap *pOldBitmap=mDC.SelectObject(&MemBitmap);
//以下为画直线
CPen PenWave(PS_SOLID,5,RGB(255,0,255));//创建紫色的画笔PenWave
mDC.SelectObject(PenWave);
mDC.MoveTo(0,0);
mDC.LineTo(50,50);
//下面将内存DC上所绘内容一次性拷贝到当前DC
pDC->BitBlt(0,0,500, 50,&mDC,0,0,SRCCOPY);
//资源回收
mDC.SelectObject(pOldBitmap);
//MemBitmap.DeleteObject();这行没必要,CBitmap析构函数会做的
展开全部
void CCyshetextView::OnDraw(CDC* pDC)
{
//创建一副关于屏幕DC的图画
CRect rect;
GetClientRect(rect); //得到客户区大小
//以下为设置坐标映射
int mode = pDC->SetMapMode(MM_ANISOTROPIC); //X、Y单位长度都自定义的映射模式
pDC->SetWindowOrg(0,0); //设置窗口左上角的坐标为
pDC->SetWindowExt(50,50); //设置窗口度量
pDC->SetViewportOrg(0,0);
pDC->SetViewportExt(rect.right,rect.bottom);
//创建关于屏幕的内存DC
CDC mDC;
mDC.CreateCompatibleDC(pDC);
CBitmap MemBitmap;
MemBitmap.CreateCompatibleBitmap(pDC,rect.right,rect.bottom);
//保留以前内存,并将这幅图选入到内存DC中
CBitmap *pOldBitmap=mDC.SelectObject(&MemBitmap);
//以下为画直线
//先画背景
mDC.FillSolidRect(0,0,50,50,GetSysColor(COLOR_WINDOW));
CPen PenWave(PS_SOLID,5,RGB(255,0,255));//创建紫色的画笔PenWave
mDC.SelectObject(PenWave);
mDC.MoveTo(0,0);
mDC.LineTo(50,50);
//下面将内存DC上所绘内容一次性拷贝到当前DC
pDC->BitBlt(0,0,rect.right,rect.bottom,&mDC,0,0,SRCCOPY);
//资源回收
mDC.SelectObject(pOldBitmap);
pDC->SetMapMode(mode);
}
//这才是正确的。
//compatible bitmap默认是黑白两色的,你没画过的地方就是黑的,用fillsolidrect或其他方法画即可。
//应该为pDC改变映射模式。
你要画成什么样子至少的说出来噻
{
//创建一副关于屏幕DC的图画
CRect rect;
GetClientRect(rect); //得到客户区大小
//以下为设置坐标映射
int mode = pDC->SetMapMode(MM_ANISOTROPIC); //X、Y单位长度都自定义的映射模式
pDC->SetWindowOrg(0,0); //设置窗口左上角的坐标为
pDC->SetWindowExt(50,50); //设置窗口度量
pDC->SetViewportOrg(0,0);
pDC->SetViewportExt(rect.right,rect.bottom);
//创建关于屏幕的内存DC
CDC mDC;
mDC.CreateCompatibleDC(pDC);
CBitmap MemBitmap;
MemBitmap.CreateCompatibleBitmap(pDC,rect.right,rect.bottom);
//保留以前内存,并将这幅图选入到内存DC中
CBitmap *pOldBitmap=mDC.SelectObject(&MemBitmap);
//以下为画直线
//先画背景
mDC.FillSolidRect(0,0,50,50,GetSysColor(COLOR_WINDOW));
CPen PenWave(PS_SOLID,5,RGB(255,0,255));//创建紫色的画笔PenWave
mDC.SelectObject(PenWave);
mDC.MoveTo(0,0);
mDC.LineTo(50,50);
//下面将内存DC上所绘内容一次性拷贝到当前DC
pDC->BitBlt(0,0,rect.right,rect.bottom,&mDC,0,0,SRCCOPY);
//资源回收
mDC.SelectObject(pOldBitmap);
pDC->SetMapMode(mode);
}
//这才是正确的。
//compatible bitmap默认是黑白两色的,你没画过的地方就是黑的,用fillsolidrect或其他方法画即可。
//应该为pDC改变映射模式。
你要画成什么样子至少的说出来噻
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
1、最好将mDC.SetViewportExt(rect.right,rect.bottom);该为
mDC.SetViewportExt(rect.Width(),rect.Height());因为,是SIZE.当然你以right,bottom等为宽度和高度也没有问题。
2、最重要的画不出来的原因是:
mDC.MoveTo(0,0);
mDC.LineTo(50,50);
两句话还是以CCyshetextView的客户区的0,0开始计算的。既然要映射的话就干脆修改:
CPoint pt(mDC.GetWindowOrg());
mDC.MoveTo(pt.x,pt.y);
mDC.LineTo(pt.x+50,pt.y+50);
都以映射后的坐标为依据吧。看下截图是不是你要的效果。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询