CDC中
CDC->StretchBlt(int x,int y,int nWidth,int nHeight,CDC *pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight,DWORD dwRop)
CDC->BitBlt(int x, int y, int nWidth,int nHeight,CDC *pSrcDC, int xSrc, int ySrc,DWORD dwRop)
HDC中
1.
HDC.StretchBlt(HDC hDestDC, int xDest,int yDest,int nDestWidth,int nDestHeight,DWORD dwRop)
2.
HDC.StretchBlt(HDC hDestDC, const RECT &rectDest,DWORD dwRop)
3.
HDC.StretchBlt(HDC hDestDC, int xDest,int yDest,int nDestWidth,int nDestHeight,, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop)
4.
HDC.StretchBlt(HDC hDestDC, const RECT &rectDest,const RECT &rectSrc, DWORD dwRop)
1.
HDC.BitBlt(HDC hDestDC, int xDest,int yDest,DWORD dwRop)
2.
HDC.BitBlt(HDC hDestDC, const POINT &pointDest,DWORD dwRop)
3.
HDC.BitBlt(HDC hDestDC, int xDest,int yDest,int nDestWidth,int nDestHeight,int xSrc, int ySrc, DWORD dwRop)
4.
HDC.BitBlt(HDC hDestDC, const RECT &rectDest, const POINT &pointSrc,DWORD dwRop)
//
pDC 是 类指针
HDC 是 windows句柄
/
通过pDC获得hdc:
HDC hdc=pDC->GetSafeHdc();
/
通过hdc获得pDC:
CDC *pDC=new CDC;
pDC->Attach(hdc);
补充:CImage
CImage image;
CRect m_rcShow;
CDC *pShowDC = m_bmpShow.GetDC(); //m_bmpShow为Picture控件变量
m_bmpShow.GetWindowRect(&m_rcShow);
image.Load(TEXT("e:\1.jpg"));
//在picture控件里显示图片
image.Draw(pShowDC->m_hDC,0,0,m_rcShow.Width(),m_rcShow.Height(),
0,0,image.GetWidth(),image.GetHeight());
m_bmpShow.ReleaseDC(pShowDC);
//*************************
StretchBlt函数缩放图片后图片失真严重,所以要用SetStretchBltMode函数来设置 StretchBlt(或StretchDIBits)函数的伸缩模式。具体用法是
调用StretchBlt前调用:
SetStretchBltMode(pDC->m_hDC,STRETCH_HALFTONE);
//***************************
MFC画图
MFC画图类包含画图设备类和画图对象类
1 画图设备类
CDC类-父类是CObject,封装的是一般的画图设备,比如:显示器,
打印机等。
CWindowDC类-父类是CDC类。封装的是窗体对象,包含客户区和非
客户区。
CClientDC类-父类是CDC类,封装的仍然是窗体。可是仅仅包含客户区。
CPaintDC类-父类是CDC类,封装的是窗体的客户区。可是,它仅仅用
在窗体的WM_PAINT消息处理函数中。
CMetaFileDC类-父类是CDC类,作用保存绘制命令。
2 使用
创建MFC AppWizard(exe)project,加入菜单项。然后使用类向导生成消息命令的函数体框架。
2.1 CDC::CreateDC()-创建画图设备
virtual BOOL CreateDC(
LPCTSTR lpszDriverName,//设备的驱动名称
LPCTSTR lpszDeviceName,//设备名称
LPCTSTR lpszOutput,//接口
const void* lpInitData//设备的初始化參数
);
设备为显示器时,("DISPLAY",NULL,NULL,NULL);
2.2 使用
....
2.3 CDC::DeleteDC()-删除设备
2.4 CDC的子类CWindowDC、CClientDC、CPaintDC,在构造函数中
调用CreateDC(),在析构函数中调用DeleteDC(),所以,子类使用
仅仅须要构造对象就可以。
2.5 CMetaFileDC类的使用
2.5.1 创建
CMetaFileDC::Create
2.5.2 绘制
....
2.5.3 关闭。返回句柄 HMETAFILE
CMetaFileDC::Close
2.5.4 使用
CDC::PlayMetaFile
2.5.5 删除
DeleteMetaFile
3 画图对象类
3.1 CPen-画笔
3.2 CBrush-画刷
3.3 CFont-字体
3.4 CBitmap-位图
3.5 CRgn-区域
3.6 CPalette-调色板
RGB(0~255,0~255,0~255),每一个颜色值占3个字节。
彩色位图,800*600像素,位图大小是:800*600*3 字节
颜色表大小 48*3 +800*600*1
3.7 使用
3.7.1 CPen、CBrush、CFont的使用
3.7.2 CBitmap的使用
3.7.3 CRgn的使用
1 创建
CRgn::CreateXXX
2 将两个CRgn对象进行几何运算
CRgn::CombineRgn
3 填充
CDC::FillRgn
4 填充边框
CDC::FrameRgn
程序演示样例:
在****view类中,定义一个成员变量:
HMETAFILE m_hMetafile;
//功能实现部分主要代码
void CMFCdrawView::OnDcCwindowdc()
{
// TODO: Add your command handler code here
CWindowDC dc(AfxGetMainWnd());
dc.TextOut(0,0,"Hello CWindowDC");
}
void CMFCdrawView::OnDcCmetafiledc()
{
// TODO: Add your command handler code here
//创建
CMetaFileDC dc;
dc.Create();
//绘制命令
dc.TextOut(100,100,"DcCmetafile");
dc.MoveTo(150,150);
dc.LineTo(200,200);
//关闭,并返回句柄
m_hMetafile= dc.Close();
CClientDC dc2(this);
dc2.PlayMetaFile(m_hMetafile);
}
void CMFCdrawView::OnDcCclientdc()
{
// TODO: Add your command handler code here
CClientDC dc(this);
dc.TextOut(0,0,"Hello CClientDC");
}
void CMFCdrawView::OnDcCdc()
{
// TODO: Add your command handler code here
CDC dc;
dc.CreateDC("DISPLAY",NULL,NULL,NULL);//打印到屏幕上
RECT rc={0};
rc.left=0;rc.right=200;rc.top=0;rc.bottom=100;
dc.DrawText("hello cdc",&rc,DT_MODIFYSTRING);
dc.DeleteDC();
}
void CMFCdrawView::OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.TextOut(0,20,"Hell0 Paint");
//使用CMetaFile
if(m_hMetafile) dc.PlayMetaFile(m_hMetafile);
//OnGdiBitmap();
// Do not call CView::OnPaint() for painting messages
}
void CMFCdrawView::OnGdiBitmap()
{
// TODO: Add your command handler code here
CClientDC dc(this);
CDC dcBitmap;//内存dc
dcBitmap.CreateCompatibleDC(&dc);
CBitmap bmp;//位图对象
bmp.LoadBitmap(IDB_BITMAP1);//插入的图片资源
CBitmap*oldbmp=dcBitmap.SelectObject(&bmp);//放入内存dc
//dc.BitBlt(300,300,110,37,&dcBitmap,0,0,SRCCOPY);//成像
RECT rc={0};
GetClientRect(&rc);
//拉伸成像
dc.StretchBlt(0,0,rc.right,rc.bottom,&dcBitmap,0,0,101,37,SRCCOPY);
dcBitmap.SelectObject(oldbmp);
dcBitmap.DeleteDC();//删除内存dc
bmp.DeleteObject();//删除位图对象
}
void CMFCdrawView::OnGdiBrush()
{
// TODO: Add your command handler code here
//CBrush brush(HS_CROSS,RGB(0,255,0));//普通画刷
CBitmap bmp;bmp.LoadBitmap(IDB_BITMAP2);
CBrush brush(&bmp);//位图画刷
CClientDC dc(this);
CBrush*oldbrush=dc.SelectObject(&brush);
dc.RoundRect(50,50,220,220,2,2);
dc.SelectObject(oldbrush);
brush.DeleteObject();
}
void CMFCdrawView::OnGdiFont()
{
// TODO: Add your command handler code here
CFont font;
font.CreatePointFont(500,"黑体");
CClientDC dc(this);
CFont*oldfont=dc.SelectObject(&font);
dc.TextOut(150,150,"OnGdiFont");
dc.SelectObject(oldfont);
font.DeleteObject();
}
void CMFCdrawView::OnGdiPen()
{
// 创建画笔
CPen pen(PS_SOLID,5,RGB(255,0,0));
//将画笔选择当前设备
CClientDC dc(this);
CPen * oldpen=dc.SelectObject(&pen);
dc.TextOut(10,10,"OnGdiPen");
dc.RoundRect(100,100,200,200,2,2);
dc.SelectObject(oldpen);
pen.DeleteObject();
}
void CMFCdrawView::OnGdiRgn()
{
CRgn rgn1,rgn2;
//创建
rgn1.CreateEllipticRgn(100,100,300,300);
rgn2.CreateEllipticRgn(150,100,350,300);
//几何运算
rgn1.CombineRgn(&rgn1,&rgn2,RGN_XOR);
//填充
CClientDC dc(this);
CBrush brush(RGB(255,0,0));
CBrush brush2(RGB(0,0,255));
dc.FillRgn(&rgn1,&brush);
//dc.FillRgn(&rgn2,&brush2);
//填充边框
dc.FrameRgn(&rgn1,&brush2,5,1);
//将窗体的区域设置成rgn1
AfxGetMainWnd()->SetWindowRgn(rgn1,TRUE);
}
效果:
2、
简单的鼠标画图的样例
1 图形数据,1 起点和终点,CPoint;
2 使用整数变量确定当前绘制的图形
UINT m_nType;
m_nType=1;直线
m_nType=2;矩形
m_nType=3;椭圆
m_nType=0;不绘制图形
3 BOOL m_bFlag;//标识是否開始画线
2 绘制过程
2.1 LBUTTONDOWN消息
m_bFlag=TRUE;//開始画图
m_ptBegin=m_ptEnd=point; //确定起点位置
2.2 MOUSEMOVE消息
if(m_bFlag)
{
//擦线
//画线
}
2.3 LBUTTONUP消息
m_bFlag=FALSE;//结束画线
模拟画图软件,鼠标点下进行画图。放开则绘制指定的图形。
新建立 MFC 应用程序,并依照例如以下操作:
在****view 中,增加成员变量:
CPoint m_ptBegin;//起点坐标
CPoint m_ptEnd;//终点坐标
UINT m_nType;//类型:1-直线,2-距形。3-圆
BOOL m_bFlag;//是否開始画线
****view中主要实现代码:
//构造函数
CMFCdraw2View::CMFCdraw2View()
{
// TODO: add construction code here
m_nType=0;
m_bFlag=FALSE;
m_ptBegin=m_ptEnd=0;
}
void CMFCdraw2View::OnDrawElipse()
{
// TODO: Add your command handler code here
m_nType=3;
}
void CMFCdraw2View::OnDrawLine()
{
// TODO: Add your command handler code here
m_nType=1;
}
void CMFCdraw2View::OnDrawRect()
{
// TODO: Add your command handler code here
m_nType=2;
}
void CMFCdraw2View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_bFlag=TRUE;//開始画图
m_ptBegin=m_ptEnd=point; //确定起点位置
CView::OnLButtonDown(nFlags,point);
}
void CMFCdraw2View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_bFlag=FALSE;//结束画线
CView::OnLButtonUp(nFlags, point);
}
void CMFCdraw2View::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
if(m_bFlag)
{
//擦线
DrawShape(&dc,m_ptBegin,m_ptEnd);
//画线
DrawShape(&dc,m_ptBegin,point);
//保存终点位置,为擦线准备
m_ptEnd=point;
}
CView::OnMouseMove(nFlags, point);
}
void CMFCdraw2View::DrawShape(CDC *pDC, CPoint p1, CPoint p2)
{
//设置画图模式,R2_NOT与当前画线处颜色相反
pDC->SetROP2(R2_NOT);
//设置画刷为透明画刷
CBrush *pOldBrush=
(CBrush*)pDC->SelectStockObject(NULL_BRUSH);
switch (m_nType)
{
case 1://直线
pDC->MoveTo(p1);
pDC->LineTo(p2);
break;
case 2://矩形
pDC->Rectangle(p1.x,p1.y,p2.x,p2.y);
break;
case 3://椭圆
pDC->Ellipse(p1.x,p1.y,p2.x,p2.y);
break;
}
//恢复默认画刷
pDC->SelectObject(pOldBrush);
}
void CMFCdraw2View::OnUpdateDrawElipse(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->SetRadio(m_nType==3);//更改选中的状态
}
void CMFCdraw2View::OnUpdateDrawLine(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->SetRadio(m_nType==1);
}
void CMFCdraw2View::OnUpdateDrawRect(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->SetRadio(m_nType==2);
}
//*********************************************
StretchBlt和BitBlt都用在双缓冲视图中,用来显示一幅图像
一、StretchBlt
函数从源矩形中复制一个位图到目标矩形,必要时按目标设备设置的模式进行图像的拉伸或压缩。也即是将内存中的位图拷贝到屏幕上,并且可以根据屏幕画图区的大小来进行伸缩,适应响应的屏幕(或图像控件)
BOOL StretchBlt(
int x,
int y,
int nWidth,
int nHeight,
CDC* pSrcDC,
int xSrc,
int ySrc,
int nSrcWidth,
int nSrcHeight,
DWORD dwRop
);
x :逻辑单元x轴左上角坐标; (获取图像控件的DC后,该值一般设为 0 )
y :逻辑单元y轴左上角坐标; (获取图像控件的DC后,该值一般设为 0 )
nWidth : 设备矩形宽度;(即是图像控件的宽度,通过int rcWidth = rc.right - rc.left;来获得,rc为保存了图像控件矩形区坐标信息)
nHeight :设备矩形高度; (即是图像控件的高度,通过int rcHeight = rc.bottom - rc.top;来获得)
pSrcDC : 源设备上下文; (就是我们定义的内存DC,然后取地址)
xSrc :源矩形x轴左上角坐标; (一般都是整幅图片拷贝,所以该值为 0 )
ySrc : 源矩形y轴左上角坐标; (一般都是整幅图片拷贝,所以该值为 0 )
nSrcWidth:源矩形宽度;(如果我们定义了一个结构体BITMAP类型m_bmp保存位图信息,那么可以用m_bmp.bmWidth获取宽度)
nSrcHeight:源矩形高度 ( 如果我们定义了一个结构体BITMAP类型m_bmp保存位图信息,那么可以用m_bmp.bmHeight获取宽度)
dwRop :指定要进行的光栅操作。(这个有很多选择,我们一般选择SRCCOPY:将源矩形区域直接拷贝到目标矩形区域。)
二、BitBlt函数
该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境。
BOOL BitBlt(
int x,
int y,
int nWidth,
int nHeight,
CDC* pSrcDC,
int xSrc,
int ySrc,
DWORD dwRop
);
BitBlt函数和上面的STretchBlt函数的参数基本上差不多,只是少了倒数第二个和倒数第三个参数:
nSrcWidth:源矩形宽度; 以及,nSrcHeight:源矩形高度
前面四个参数也是和目标矩形(也即是我们的图像控件区域)相关的,如果是图像控件的话,起点坐标也是(0,0),终点坐标就是矩形区的宽度和高度;
对于源矩形区域(指内存DC中的位图),只需要给出拷贝的起点即可,
BitBlt函数不会对原来的位图进行拉伸或压缩,只会根据我们给定的nWidth,nHeight 值来决定该有多少部分进行显示
下面一段代码给出了这两个函数的具体用法:
void CEnvirMonibeta1View::ShowBitmap(CDC *pDC, CString TotalName, const RECT &rc)
{
//显示图片函数LoadImage 根据位图(或图片)的全路径名TotalName加载图片
HBITMAP m_hBitmap;
m_hBitmap = (HBITMAP)
LoadImage(
NULL,
TotalName,
IMAGE_BITMAP,
0,
0,
LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION
);
// 之前在类中定义了一个CBitmap 类的对象m_bitmap,
if(m_bitmap.m_hObject){
m_bitmap.Detach(); // m_bitmap为创建的位图对象
}
m_bitmap.Attach(m_hBitmap); // 让位图对象m_bitmap 和我们加载的位图相关联
//定义并创建一个内存设备环境
CDC m_dcMemory;
if( !m_dcMemory.CreateCompatibleDC(pDC) ) // 创建兼容性的DC
return;
//定义一个位图结构体,将图片信息保存在位图结构体中
BITMAP bitmap;
m_bitmap.GetBitmap(&bitmap);
CBitmap *pbmpOld = NULL;
m_dcMemory.SelectObject(&m_bitmap); // 将位图选入临时内存设备环境
//获取屏幕画图区域(图像控件)的宽度和高度
int rcWidth = rc.right - rc.left;
int rcHeight = rc.bottom - rc.top;
//图片显示调用函数BitBlt
pDC->BitBlt(0,0,rcWidth,rcHeight,&dcBmp,0,0,SRCCOPY);
// 如果希望图片和矩形区域能自动适配,可以用下面的函数
pDC->StretchBlt(0,0,rcWidth,rcHeight,&dcBmp,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
//下面是一些善后工作
dcBmp.SelectObject(pbmpOld); // 恢复临时DC的位图
DeleteObject(&m_bitmap); // 删除位图
dcBmp.DeleteDC(); // 删除后台DC
// Invalidate(); // 一直调用OnDraw显示图片
}