hur.cn - 华软网

 热门搜索

关于CreateCompatibleBitmap的疑问

  作者:未知    来源:网络    更新时间:2011/8/18
书上的东西,我一起粘了过来,是打印图像的代码

void CPrintImageDlg::OnButprint() 
{
CRect m_rect;
//获取图像的大小
m_Image.GetClientRect(m_rect);
CDC* pImageDC = m_Image.GetDC(); //获得控件画布
int formx,formy;
//获得屏幕分辨率
formx = pImageDC->GetDeviceCaps(LOGPIXELSX);
formy = pImageDC->GetDeviceCaps(LOGPIXELSY);
ReleaseDC(pImageDC);
CPrintDialog m_printdlg(FALSE,PD_RETURNDEFAULT); //构造打印对话框
if (m_printdlg.DoModal() == IDOK)
{
CDC pdc;
pdc.Attach(m_printdlg.GetPrinterDC());
//获取打印机与屏幕的分辨率比率
int printerx,printery;
printerx = pdc.GetDeviceCaps(LOGPIXELSX);
printery = pdc.GetDeviceCaps(LOGPIXELSY);
double ratex,ratey;
ratex = (double)printerx/formx;
ratey = (double)printery/formy;
CClientDC dc(this);
CBitmap bmp;
bmp.CreateCompatibleBitmap(&dc,m_rect.Width(),m_rect.Height()); //创建位图
CDC imagedc;
imagedc.CreateCompatibleDC(&dc); //创建兼容的画布
imagedc.SelectObject(&bmp); //选入位图
imagedc.BitBlt(0,0,m_rect.Width(),m_rect.Height(),&dc,0,0,SRCCOPY); //绘制位图
//打印图像
  pdc.StartDoc("printimage");
pdc.StretchBlt(0,0,(int)(m_rect.Width()*ratex),(int)(m_rect.Height()*
ratey),&imagedc,0,0,m_rect.Width(),m_rect.Height(),SRCCOPY);

pdc.EndDoc();
}
}

1.小弟对CreateCompatibleDC这个方法理解不深,用这个新建的DC是否和原来的有一样的控件,尺寸什么的?
2.上面的代码中为什么不直接创建一个DC,选择位图,然后输出到打印机DC里?上面的代码是先创建到imagedc再输出到打印机中的么?
3.bmp.CreateCompatibleBitmap(&dc,m_rect.Width(),m_rect.Height());
光这一句,bmp里有东西么?感觉没有吧,不然dc里有多张图怎么弄、、、
4.imagedc.SelectObject(&bmp);
为什么要这句,直接把dc里的绘制到imagedc里不就好了?



因为我只知道这样的用法

CDC  memDC; //定义一个内存设备上下文
memDC.CreateCompatibleDC(pDC); //创建与pDC兼容的设备上下文
memDC.SelectObject(&bmp); //选中位图对象
//在窗口中绘图
pDC->StretchBlt(0, 0, clientRC.Width(), clientRC.Height(), &memDC, 0, 0, nBmpWidth, nBmpHeight, SRCCOPY);
memDC.DeleteDC(); //释放内存设备上下文


分数不多啦,还有帖没结,各位看在我认真学习的份上帮我看看~~
---华软 网友回答---
网上贴的代码 你就单步调试一下
看看实现流程
---华软网友回复---
1.小弟对CreateCompatibleDC这个方法理解不深,用这个新建的DC是否和原来的有一样的控件,尺寸什么的?
========
它创建一个与原来的DC兼容的DC,DC是没有尺寸这个概念的,尺寸是指它里面的位图对象。

3.bmp.CreateCompatibleBitmap(&dc,m_rect.Width(),m_rect.Height());
光这一句,bmp里有东西么?感觉没有吧,不然dc里有多张图怎么弄、、、
========
默认情况下它会创建一个全黑的位图。
---华软网友回复---
2.上面的代码中为什么不直接创建一个DC,选择位图,然后输出到打印机DC里?上面的代码是先创建到imagedc再输出到打印机中的么?
===========
上面代码的功能是先在窗口中贴图,显示出图片,然后再输出到打印机中。
---华软网友回复---
4.imagedc.SelectObject(&bmp);
为什么要这句,直接把dc里的绘制到imagedc里不就好了?
==========
这个是要的,绘图之前总得要先确实一下画布的大小,调色板格式之类的吧。
---华软网友回复---
引用 2 楼 wltg2001 的回复:
1.小弟对CreateCompatibleDC这个方法理解不深,用这个新建的DC是否和原来的有一样的控件,尺寸什么的?
========
它创建一个与原来的DC兼容的DC,DC是没有尺寸这个概念的,尺寸是指它里面的位图对象。

3.bmp.CreateCompatibleBitmap(&dc,m_rect.Width(),m_rect.Height());
光这一句,bmp里有东……


这我知道,重点是什么叫兼容?这我搞不清。
CreateCompatibleBitmap是创建和这个dc兼容的位图,这个怎样算是兼容?
---华软网友回复---
引用 3 楼 wltg2001 的回复:
2.上面的代码中为什么不直接创建一个DC,选择位图,然后输出到打印机DC里?上面的代码是先创建到imagedc再输出到打印机中的么?
===========
上面代码的功能是先在窗口中贴图,显示出图片,然后再输出到打印机中。


不是的吧,imagedc不是窗口的DC吧,只是内存里的吧?
CClientDC dc(this);
这个得到的dc才是窗口的吧?
---华软网友回复---
引用楼主 kissgoodbye365 的回复:
书上的东西,我一起粘了过来,是打印图像的代码

void CPrintImageDlg::OnButprint() 
{
CRect m_rect;
//获取图像的大小
m_Image.GetClientRect(m_rect);
CDC* pImageDC = m_Image.GetDC(); //获得控件画布
int formx,formy;
//获得屏幕分辨率
formx……


1.小弟对CreateCompatibleDC这个方法理解不深,用这个新建的DC是否和原来的有一样的控件,尺寸什么的?
该函数只创建一个和源DC色彩结构相同的内存DC,只有色彩结构,没有尺寸!

2.上面的代码中为什么不直接创建一个DC,选择位图,然后输出到打印机DC里?上面的代码是先创建到imagedc再输出到打印机中的么?
位图要输出到设备缓冲区,都需要通过内存设备缓冲区!你没办法直接使用SelectObject将位图选人物理设备!

3.bmp.CreateCompatibleBitmap(&dc,m_rect.Width(),m_rect.Height());
光这一句,bmp里有东西么?感觉没有吧,不然dc里有多张图怎么弄、、、
使用和dc兼容的色彩结构和指定宽高,创建位图,bmp是一个VC封装的对象(CBitmap),在API中,是一个内存句柄,一般需要通过LaodBitmap等函数加载实际位图;

4.imagedc.SelectObject(&bmp);
为什么要这句,直接把dc里的绘制到imagedc里不就好了?

dc创建,和位图创建是两个不相关的对象(只是色彩结构相同而已),需要使用SelectObject将位图数据放入到内存DC中


---华软网友回复---
引用 6 楼 kissgoodbye365 的回复:
引用 3 楼 wltg2001 的回复:
2.上面的代码中为什么不直接创建一个DC,选择位图,然后输出到打印机DC里?上面的代码是先创建到imagedc再输出到打印机中的么?
===========
上面代码的功能是先在窗口中贴图,显示出图片,然后再输出到打印机中。


不是的吧,imagedc不是窗口的DC吧,只是内存里的吧?
CClientDC dc(this);
这个得到的d……

imagedc是内存DC啊,没错,dc是窗口DC啊,
imagedc.BitBlt(0,0,m_rect.Width(),m_rect.Height(),&dc,0,0,SRCCOPY); //绘制位图
这个是在窗口中显示图像
---华软网友回复---
2.上面的代码中为什么不直接创建一个DC,选择位图,然后输出到打印机DC里?上面的代码是先创建到imagedc再输出到打印机中的么
==============
我看不明白你这个问题,上面代码本来就是这样做啊,先创建一个内存DC,再选择位图,最后输出到打印DC中去。
---华软网友回复---
参看一下MSDN上这些GDI函数的描述吧~
---华软网友回复---
引用 8 楼 wltg2001 的回复:
引用 6 楼 kissgoodbye365 的回复:
引用 3 楼 wltg2001 的回复:
2.上面的代码中为什么不直接创建一个DC,选择位图,然后输出到打印机DC里?上面的代码是先创建到imagedc再输出到打印机中的么?
===========
上面代码的功能是先在窗口中贴图,显示出图片,然后再输出到打印机中。


不是的吧,imagedc不是窗口的DC吧,只是内存里的吧?
……



BOOL BitBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop );

pSrcDC

Pointer to a CDC object that identifies the device context from which the bitmap will be copied. It must be NULL if dwRop specifies a raster operation that does not include a source.

明明pSrcDC是源设备DC指针啊,是把窗口里的拷贝到内存里啊。


---华软网友回复---
引用 4 楼 wltg2001 的回复:
4.imagedc.SelectObject(&bmp);
为什么要这句,直接把dc里的绘制到imagedc里不就好了?
==========
这个是要的,绘图之前总得要先确实一下画布的大小,调色板格式之类的吧。


可是下面复制到打印机DC里怎么没见他先SelectObject呢?
---华软网友回复---
可是下面复制到打印机DC里怎么没见他先SelectObject呢?
==============
解释一下代码吧,只说主要部分:
CDC imagedc;
imagedc.CreateCompatibleDC(&dc); //创建兼容的画布
imagedc.SelectObject(&bmp); //选入位图
imagedc.BitBlt(0,0,m_rect.Width(),m_rect.Height(),&dc,0,0,SRCCOPY); //绘制位图
这里imagedc是内存DC,CreateCompatilbeDC创建一个兼容的位图,默认是全黑的。选入imagedc中。
imagedc.BitBlt(0,0,m_rect.Width(),m_rect.Height(),&dc,0,0,SRCCOPY); 这句的功能是将源DC的图像复制到imagedc中,这里的源DC是窗口DC,这样的话,imagedc中的位图就有图像了。


pdc.StretchBlt(0,0,(int)(m_rect.Width()*ratex),(int)(m_rect.Height()*
ratey),&imagedc,0,0,m_rect.Width(),m_rect.Height(),SRCCOPY);
这句是将imagedc中的图像输出到打印DC中去。

---华软网友回复---
明明pSrcDC是源设备DC指针啊,是把窗口里的拷贝到内存里啊
==========
我上面说的有的地方可能有点含混,打字过快,没说清。
---华软网友回复---
想了半天,应该还是我对其工作原理了解很模糊。
我把imagedc.SelectObject(&bmp);删了就打不出图像来了。
我是否可以这样理解,复制图像都要先设置一下画布大小,只是复制到内存里的DC时要自己设置
而到屏幕或者打印机时是系统帮你完成的?
---华软网友回复---
我把imagedc.SelectObject(&bmp);删了就打不出图像来了。
==========
删除了这句的话,imagedc中的原有的位图和原来的窗口的位图在格式上不兼容,所以无法工作。
---华软网友回复---
引用 16 楼 wltg2001 的回复:
我把imagedc.SelectObject(&bmp);删了就打不出图像来了。
==========
删除了这句的话,imagedc中的原有的位图和原来的窗口的位图在格式上不兼容,所以无法工作。


都问这么多了,我决定还是问到底了~
1.imagedc没有进行SelectObject时原有的位图指什么?他才创建,没做什么操作,是一个默认的位图吗?

2.还有我上面问的其实重点是为什么同样是复制位图,当屏幕和打印机作为接收方时不需要做SelectObject的工作?
---华软网友回复---
imagedc.CreateCompatibleDC(&dc); //创建兼容的画布
这句是创建兼容的内存设备描述表,但是最初的显示表面非常小,单色,1像素宽,1像素高,只占一位;
通过imagedc.SelectObject(&bmp); 对这个表面进行扩充;
屏幕和打印机得描述表的尺寸是固定的,所以不需要SelectObject了;

---华软网友回复---
豁然开朗!多谢多谢~      
华软声明:本内容来自网络,如有侵犯您版权请来信指出,本站立即删除。