MFC文本、图形、图像、GDI+处理

GDI:Graphics Device Interface,图形设备接口

DC:Device Context ,设备上下文

GDI对象:字体CFont,位图CBitmap,画刷CBrush,调色板CPalette,画笔CPen,区域CRgn

一、文本输出

1.BOOL TextOut(int x,int y,const CString&str)

指定坐标输出文本
x:文本未终止的X轴坐标
y:文本未终止的Y轴坐标
str:输出的文本信息
CFont Font;
Font.CreateFont(24,24,0,0,FW_NORMAL,0,TRUE,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,
           CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_ROMAN,"宋体");
CFont *pOldFont = NULL;
pOldFont = pDC->SelectObject(&Font);
pDC->TextOut(10,10,"谁动了我的小熊啊!");
pDC->SelectObject(pOldFont);
Font.DeleteObject();

2.int DrawText(const CString&str,LPRECT lpRect,UINT nFormat)

str:被输出的字符串
lpRect:一个区域对象,字符串将绘制在该区域
nFormat:文本被格式化的方式,即文本在区域的显示方式。
CRect rc(100,20,300,200);
CString str = " 你是年少的欢喜 !";
CBrush brush(RGB(0,0,0,0));
//pDC->FrameRect(rc,&brush);
pDC->DrawText(str,rc,DT_CENTER|DT_SINGLELINE|DT_VCENTER);
brush.DeleteObject();

3.设置字体及文本颜色

(1).CreateFont
HFONT CreateFont(
int nHeight, // logical height of font height
int nWidth, // logical average character width
int nEscapement, // angle of escapement
int nOrientation, // base-line orientation angle
int fnWeight, // font weight
DWORD fdwItalic, // italic attribute flag
DWORD fdwUnderline, // underline attribute flag
DWORD fdwStrikeOut, // strikeout attribute flag
DWORD fdwCharSet, // character set identifier
DWORD fdwOutputPrecision, // output precision
DWORD fdwClipPrecision, // clipping precision
DWORD fdwQuality, // output quality
DWORD fdwPitchAndFamily, // pitch and family
LPCTSTR lpszFace // pointer to typeface name string
);
cHeight是字体的高度。
cWidth是字体的宽度。
cEscapement是字体的倾斜角。
cOrientation是字体的倾斜角。
cWeight是字体的粗细。
bItalic是字体是否斜体。
bUnderline是字体是否有下划线。
bStrikeOut是字体是否有删除线。
iCharSet是字体使用的字符集。
iOutPrecision是指定如何选择合适的字体。
iClipPrecision是用来确定裁剪的精度。
iQuality是怎么样跟选择的字体相符合。
iPitchAndFamily是间距标志和属性标志。
pszFaceName是字体的名称。
(2).BOOL CreatePointFont(int nPointSize,LPCTSTR lpszFaceName,CDC* pDC = NULL);
nPointSize:要求字体高度为这个点的1/10。
lpszFaceName:一个CString 或者一个指向null-terminated(以空为结尾的)字符串指针来标注字体名称。长度不得超过30个字母。函数EnumFontFamilies可列举能够使用的字体。如果lpszFaceName是NULL,那么GDI uses a device-independent typeface.
pDC:指向CDC对象的指针,用来将字体高度转化为逻辑单位,如果是NULL,那么就根据屏幕当前的上下文(context)来转化
CFont Font;//定义一个字体对象
	//创建字体
	Font.CreateFont(12,12,2700,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,
	CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_ROMAN,"黑体");
	CFont *pOldFont = NULL;						//定义一个字体指针
	pOldFont = pDC->SelectObject(&Font);			//选中创建的字体
	pDC->SetTextColor(RGB(255,0,0));
	pDC->TextOut(100,50,"黑色轨迹");			//输出文本信息
	pDC->SelectObject(pOldFont);					//恢复之前选中的字体
	Font.DeleteObject();	
	Font.CreatePointFont(120,"黑体",pDC);
	pOldFont = pDC->SelectObject(&Font);
	pDC->TextOut(120,70, "皮皮虾我们回来");
	pDC->TextOut(120,90, "屁屁猪你快回来");
	pDC->SelectObject(pOldFont);					//恢复之前选中的字体
	Font.DeleteObject();	
(3).空心文字:在路径中输出文本
BeginPath函数用于在当前的设备上下文中打开一个路径
EndPath函数用于关闭一个打开的路径
StrokePath函数用当前的画笔描述路径
CFont mFont;	
	//创建字体
	VERIFY(mFont.CreateFont(
		150, 50, 0, 0, FW_HEAVY, TRUE, FALSE, 
		0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,        
		CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,             
		DEFAULT_PITCH | FF_SWISS, "宋体"));
	CPen pen(PS_SOLID,2,RGB(255,0,0));
	pDC->SelectObject(&pen);
	CFont *pOldFont = pDC->SelectObject(&mFont);
	pDC->SetBkMode(TRANSPARENT);
	pDC->BeginPath();
	pDC->TextOut(30,30,"皮皮虾我们走");
	 pDC->EndPath();
	 pDC->StrokePath();
	mFont.DeleteObject();
	pDC->SelectObject(pOldFont);

(4).在图像背景上输出透明文本

CBitmap bmp;
	bmp.LoadBitmap(IDB_BKBITMAP);
	BITMAP bInfo;
	bmp.GetBitmap(&bInfo);
	int width = bInfo.bmWidth;
	int height = bInfo.bmHeight;
	CDC memDC;
	memDC.CreateCompatibleDC(pDC);
	memDC.SelectObject(&bmp);
	pDC->BitBlt(0,0,width,height,&memDC,0,0,SRCCOPY);
	memDC.DeleteDC();
	bmp.DeleteObject();
	CFont mFont;									//定义一个字体对象
	//创建字体
	VERIFY(mFont.CreateFont(					
		24, 20, 0, 0, FW_HEAVY, FALSE, FALSE, 
		0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, 
		CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, 
		DEFAULT_PITCH | FF_SWISS, "宋体"));
	CFont* pOldFont = pDC->SelectObject(&mFont);
	pDC->SetBkMode(TRANSPARENT);
	pDC->SetTextColor(RGB(0,255,0));
	pDC->TextOut(60,60,"田园生活");
	pDC->SelectObject(pOldFont);
	mFont.DeleteObject();
	// TODO: add draw code for native data here

二、绘制图形

1.CPoint MoveTo(int x,int y)

该方法用于移动当前的坐标点到指定的位置上

2.BOOL LineTo(int x,int y)

从当前的坐标点绘制一条直线到参数指定的位置

3.Arc

该方法以一个外接的矩形为依据绘制一个椭圆的弧线
BOOL Arc(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)
//绘制矩形
	CPen pen(PS_SOLID,2,RGB(255,0,0));
	CPen *pOldPen = pDC->SelectObject(&pen);
	pDC->MoveTo(50,30);
	pDC->LineTo(240,30);//绘制上边框
	pDC->LineTo(240,120);//绘制右边框
	pDC->LineTo(50,120);  //绘制下边框
	pDC->LineTo(50,30);//绘制左边框
	//绘制多变形

	pDC->MoveTo(300,50);//设置当前坐标
	pDC->LineTo(400,50);//绘制上边框
	pDC->LineTo(450,100);//绘制右斜边框
	pDC->LineTo(400,150);//绘制右斜边框
	pDC->LineTo(300,150); //绘制底边框
	pDC->LineTo(250,100);//绘制左上边框
	pDC->LineTo(300,50);//绘制左上边框

	//绘制弧线
	CRect rc(500,50,600,100);
	pDC->Arc(500,50,600,100,520,70,560,30);
	CBrush brush(RGB(255,0,0));
	pDC->FrameRect(rc,&brush);
	pDC->SelectObject(pOldPen);














4.BOOL Rectangle(int x1,int y1,int x2,int y2)

X1、Y1矩形区域的左上角坐标
X2、Y2矩形区域的右下角坐标
lpRect:一个CRect对象指针,表示一个矩形区域

5、BOOL RoundRect(int x1,int y1,int x2,int y2,int x3,int y3)

BOOL RoundRect(LPCRECT lpRect,POINT point)
该方法用于绘制一个圆角矩形
x1,y1:矩形区域的左上角坐标
x2,y2:矩形区域的右上角坐标
x3,y3:圆角的宽度和高度
lpRect:一个CRect对象指针,标识一个矩形区域
point:圆角的宽度和高度

6.Polygon

该方法利用当前的画笔根据列列举的坐标点绘制一个多边形
BOOL Polygon(LPPOINT lpPoints,int nCount)
lpPoints:多边形的各个端点
nCount:lpPoints元素的数量

7.Polyline

利用当前的画笔绘制坐标点中的直线
BOOL Polyline(LPPOINT lpPoints,int nCount)
	CRect rc(20,20,80,80);
	pDC->Rectangle(rc);
	CRect RndRC(20,100,80,160);
	pDC->RoundRect(RndRC,CPoint(10,10));
	CPoint pts[6] = {CPoint(300,50),CPoint(400,50),CPoint(450,100),
		             CPoint(400,150),CPoint(300,150),CPoint(250,100)};
	pDC->Polygon(pts,6);

三、绘制控件外观

1.BOOL DrawFrameControl(LPRECT lpRect,UINT nType,UINT nState)

lpRect:控件所在的矩形区域
nType:控件的类型。
DFC_BUTTON-绘制按钮
DFC_CAPTION-绘制标题栏
DFC_MENU-绘制菜单
DFC_SCROLL-绘制滚动条
/绘制按钮
	CRect rc(50,50,120,80);
	pDC->DrawFrameControl(rc,DFC_BUTTON,DFCS_BUTTONPUSH);
	//绘制标题栏关闭按钮
	CRect CapRC(130,50,160,80);
	pDC->DrawFrameControl(CapRC,DFC_CAPTION,DFCS_CAPTIONHELP);
	//绘制滚动条按钮
	CRect ScrollRC(170,50,200,80);
	pDC->DrawFrameControl(ScrollRC,DFC_SCROLL,DFCS_SCROLLCOMBOBOX);

四、填充图形区域

1.FillRect

该函数用所标识的画刷填充一个矩形区域
void FillRect(LPCRECT lpRect,CBrush* pBrush)
lpRect:需要填充的矩形区域
pBrush:一个画刷对象指针,函数将使用该画刷填充矩形区域。

2.FillSolidRect

该函数用指定的颜色填充一个矩形区域
void FillSolidRect(LPCRECT lpRect,COLORREF clr)
lpRect:需要填充的矩形区域
clr:标识一个RGB颜色值,函数将使用该颜色填充矩形区域

3.FillRgn

该函数所标识的画刷填充一个选区
BOOL FillRgn(CRgn* pRgn,CBrush* pBrush)
pRgn:一个选区对象。选区可以通过系统提供的CreateRectRgn.CreateEllipticRgn和CreatePolygonRgn等API函数创建
pBrush:一个画刷对象指针,函数将使用该画刷填充选区

4.FillPath

该函数用当前的画刷填充路径
BOOL FillPath()

5.CombineRgn

将两个区域组合为一个新区域。
int CombineRgn(
  _In_?HRGN hrgnDest,
  _In_?HRGN hrgnSrc1,
  _In_?HRGN hrgnSrc2,
  _In_?int ?fnCombineMode
);
hrgnDest:包含组合结果的区域句柄
hrgnSrc1:源区域1
hrgnSrc2:源区域2
nCombineMode :组合两区域的方法。可设为下述常数
RGN_AND
hDestRgn被设置为两个源区域的交集(集合中的交集)
RGN_COPY
hDestRgn被设置为hSrcRgn1的拷贝
RGN_DIFF
hDestRgn被设置为hSrcRgn1与hSrcRgn2相减后的区域(集合中的差集)
RGN_OR hDestRgn被设置为两个区域的并集(集合中的并集)
RGN_XOR
hDestRgn被设置为两个区域的异或操作后的区域(集合中的异或操作)

[返回值]
下列常数之一:
COMPLEXREGION:区域有互相交叠的边界
SIMPLEREGION:区域边界没有互相交叠
NULLREGION:区域为空
ERRORAPI:不能创建组合区域
CRect rc(30,40,100,120);//定义一个区域对象
	CBrush brush(RGB(128,128,128));//定义一个颜色画刷
	
	pDC->FillRect(rc,&brush);//使用颜色填充区域
	brush.DeleteObject();//删除画刷杜爱香
	CBitmap bmp;//定义一个位图对象
	bmp.LoadBitmap(IDB_BKBITMAP);//加载位图
	brush.CreatePatternBrush(&bmp);//创建位图画刷
	CRect bmpRC(110,40,200,120);//定义一个区域对象
	
	pDC->FillRect(bmpRC,&brush);//使用位图填充区域
	bmp.DeleteObject();//释放位图对象
	brush.DeleteObject();//释放画刷对象


	//填充选区
	CRect rectrc(210,40,300,120);//定义一个区域对象
	CRect hrc(280,60,350,140);//定义一个区域对象
	pDC->Rectangle(rectrc);//绘制矩形边框
	pDC->Rectangle(hrc);//绘制矩形边框
	HRGN hRect = CreateRectRgn(210,40,300,120);//创建一个矩形选区
	HRGN hrgn = CreateRectRgn(280,60,350,140);//创建一个矩形选区
	HRGN hret = CreateRectRgn(0,0,0,0);//创建选区
	CombineRgn(hret,hRect,hrgn,RGN_AND);//组合选区,获取选区公共部分
	brush.CreateSolidBrush(RGB(255,0,0));//创建一个颜色画刷
	CRgn rgn;//定义一个选区对象
	rgn.Attach(hret);//将选区对象附加一个选区句柄
	pDC->FillRgn(&rgn,&brush);//填充选区
	brush.DeleteObject();//释放画刷对象
	rgn.Detach();//分离选区句柄
	DeleteObject(hRect);//释放选取句柄
	DeleteObject(hrc);//释放选取句柄
	DeleteObject(hret);//释放选取句柄

五、图像显示

1.BitBIt

该函数用于从源设备中复制位图到目标设备
BOOL BitBIt(int x,int y,int nWidth,int nHeight,CDC* pSrcDC,int xSrc,int ySrc,DWORD dwRop)
x:目标矩形区域的左上角X轴坐标点
y:目标矩形区域的左上角y轴坐标点
nWidth:在目标设备中绘制位图的宽度
nHeight:在目标设备中绘制位图的高度
pSrcDC:源设备上下文对象指针
xSrc:源设备上下文的起点x轴坐标,函数从该起点复制位图到目标设备
ySrc:源设备上下文的起点y轴坐标,函数从该起点复制位图到目标设备
dwRop:光栅操作代码


BLACKNESS:表示使用与物理调色板的索引0相关的色彩来填充目标矩形区域,(对缺省的物理调色板而言,该颜色为黑色)。
DSTINVERT:表示使目标矩形区域颜色取反。
MERGECOPY:表示使用布尔型的AND(与)操作符将源矩形区域的颜色与特定模式组合一起。
MERGEPAINT:通过使用布尔型的OR(或)操作符将反向的源矩形区域的颜色与目标矩形区域的颜色合并。
NOTSRCCOPY:将源矩形区域颜色取反,于拷贝到目标矩形区域。
NOTSRCERASE:使用布尔类型的OR(或)操作符组合源和目标矩形区域的颜色值,然后将合成的颜色取反。
PATCOPY:将特定的模式拷贝到目标位图上。
PATPAINT:通过使用布尔OR(或)操作符将源矩形区域取反后的颜色值与特定模式的颜色合并。然后使用OR(或)操作符将该操作的结果与目标矩形区域内的颜色合并。
PATINVERT:通过使用XOR(异或)操作符将源和目标矩形区域内的颜色合并。
SRCAND:通过使用AND(与)操作符来将源和目标矩形区域内的颜色合并。
SRCCOPY:将源矩形区域直接拷贝到目标矩形区域。
SRCERASE:通过使用AND(与)操作符将目标矩形区域颜色取反后与源矩形区域的颜色值合并。
SRCINVERT:通过使用布尔型的XOR(异或)操作符将源和目标矩形区域的颜色合并。
SRCPAINT:通过使用布尔型的OR(或)操作符将源和目标矩形区域的颜色合并。
WHITENESS:使用与物理调色板中索引1有关的颜色填充目标矩形区域。(对于缺省物理调色板来说,这个颜色就是白色)。

2.StretchBIt

该函数复制源设备上下文的内容到目标设备上下文中,与BitBIt不同的是,StretchBIt方法能够延伸或收缩位图以适应目标区域的大小
BOOL StretchBIt(int x,int y,int nWidth,int nHeight,CDC* pSrcDC,int xSrc,int ySrc,int nSrcWidth,int nSrcHeight,DWORD dwRop)
nSrcWidth:需要复制的位图宽度
nSrcHeight:需要复制的位图高度
CDC memDC;//定义一个设备上下文
	memDC.CreateCompatibleDC(pDC);//创建兼容的设备上下文
	CBitmap bmp;//定义位图对象
	bmp.LoadBitmap(IDB_BKBITMAP);//加载位图
	memDC.SelectObject(&bmp);//选中位图对象
	pDC->BitBlt(30,20,180,180,&memDC,1,1,SRCCOPY);//绘制位图
	CRect rc(30,20,210,200);//定义一个区域
	CBrush brush(RGB(0,0,0));//定义一个黑色的画刷
	pDC->FrameRect(rc,&brush);//绘制矩形边框
	
	rc.OffsetRect(220,0);//移动区域

	BITMAP BitInfo;//定义位图结构
	bmp.GetBitmap(&BitInfo);//获取位图信息
	int x = BitInfo.bmWidth;//获取位图宽度
	int y = BitInfo.bmHeight;//获取位图高度
	pDC->StretchBlt(rc.left,rc.top,rc.Width(),rc.Height(),&memDC,0,0,x,y,SRCCOPY);绘制位图
	pDC->FrameRect(rc,&brush);//绘制边框
	brush.DeleteObject();//释放画刷对象
	memDC.DeleteDC();//释放设备上下文
	bmp.DeleteObject();//释放位图对象

3.LoadImage

从磁盘动态加载一副图像到窗口
HANDLE LoadImage(HINSTANCE hinst,LPCTSTR lpszName,UINT uType,int cxDesired,int cyDesired,UINT fuload)
hinst:表示包含图像的实例句柄,可以为NULL
lpszName:表示图像的资源名称,如果从磁盘加载,该参数表示图像的名称,包含完整路径
uType:表示加载的图像类型IMAGE_BITMAP位图, IMAGE_CURSOR,鼠标指针, IMAGE_ICON图标
cxDesired:表示图标或鼠标指针的宽度,如果是位图,参数为0
cyDesired:表示图标或鼠标指针的高度,如果是位图,参数为0
fuload:表示加载的类型,如果为LR_LOADFROMFILE,表示从磁盘加载位图
	m_hBmp = LoadImage(NULL, "Demo.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
	CBitmap bmp;//定义位图对象
	bmp.Attach(m_hBmp);//将位图关联到位图句柄上
	CDC memDC;//定义设备上下文
	memDC.CreateCompatibleDC(pDC);//创建兼容的设备上下文
	memDC.SelectObject(&bmp);//选中位图对象
	BITMAP BitInfo;		//定义位图结构							//定义位图结构
	bmp.GetBitmap(&BitInfo);//获取位图信息								//获取位图信息
	int x = BitInfo.bmWidth;								//获取位图宽度
	int y = BitInfo.bmHeight;								//获取位图高度
	pDC->BitBlt(0,0,x,y,&memDC,0,0,SRCCOPY);
	bmp.Detach();//分离位图句柄
	memDC.DeleteDC();//释放设备上下文

案例:

1.画笔
void CSDI_PenView::OnDraw(CDC* pDC)
{
	CSDI_PenDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	CPen RedPen(PS_SOLID, m_PenWidth, RGB(255, 0, 0));//定义时直接创建

	CPen GreenPen;
    GreenPen.CreatePen(PS_DASHDOT, 1, RGB(0, 255, 0));//定义CPen对象,再调用CreatePen()函数
	
	CPen *pOldPen = pDC->SelectObject(&RedPen);//选择画笔
	pDC->MoveTo(30, 30);
	pDC->LineTo(300, 30);

	pDC->SelectObject(GreenPen);//选择画笔
	pDC->MoveTo(30, 80);
	pDC->LineTo(300, 80);

	pDC->SelectObject(pOldPen);//还原画笔
}

2.画刷

void CSDI_BrushView::OnDraw(CDC* pDC)
{
	CSDI_BrushDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	CBrush RedBrush;
    RedBrush. CreateSolidBrush(RGB(255, 0, 0));
	//选择画刷
	CBrush *pOldBrush = pDC->SelectObject(&RedBrush);
	pDC->Rectangle(10, 10, 80, 80);

	CBrush GreenBrush(HS_DIAGCROSS, RGB(0,255,0));
	//选择画刷
	pDC->SelectObject(&GreenBrush);
	pDC->Rectangle(10, 90, 80, 160);

	CBitmap bmp;
    // Load a resource bitmap.
    bmp.LoadBitmap(IDB_BITMAP1);
    CBrush BMPBrush(&bmp);
	pDC->SelectObject(&BMPBrush);
	pDC->Rectangle(90, 10, 260, 160);


	还原画刷
	pDC->SelectObject(&pOldBrush);

}
3.基本图形
void CSDI_GraphicView::OnDraw(CDC* pDC)
{
	CSDI_GraphicDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	//在(10,10)位置画一个红点
	pDC->SetPixel(CPoint(10,10), RGB(255,0,0));

	pDC->MoveTo(20,20);//设置起点为(10,10)
    pDC->LineTo(80,20);//从起点(10,10)到终点(80,80)画一条直线

	CRect rect(90,20,150,100);
    pDC->Rectangle(&rect);//画长宽均为200的矩形
	
    CRect rect1(170,20,230,80);
	pDC->Ellipse(&rect1);//在矩形内部画圆
	CRect rect2(240,20,300,200);
	pDC->Ellipse(&rect2);//在矩形内部画椭圆

	CPoint pt[3];
	pt[0] = CPoint(310,90);
	pt[1] = CPoint(360,80);
	pt[2] = CPoint(380,100);
	pDC->Polygon(pt, 3);//画多边形
}
CDC::Pie//画饼状图
CDC::Chord//画炫
CDC::FillRect//用指定颜色填充矩形并且不画边线
CDC::Draw3dRect//绘制3D边框
CDC::RoundRect//画圆角矩形
4.列表视图list control
//设置列表视图的扩展风格
	m_Grid.SetExtendedStyle(LVS_EX_FLATSB			//扁平风格显示滚动条
		|LVS_EX_FULLROWSELECT					//允许整行选中
		|LVS_EX_HEADERDRAGDROP				//允许整列拖动
		|LVS_EX_ONECLICKACTIVATE				//单击选中项
		|LVS_EX_GRIDLINES);						//画出网格线
	//设置表头
	m_Grid.InsertColumn(0,"书名",LVCFMT_LEFT,200,0); 	//设置书名列
	m_Grid.InsertColumn(1,"作者",LVCFMT_LEFT,130,1); 	//设置作者列
	m_Grid.InsertColumn(2,"出版社",LVCFMT_LEFT,130,2); 	//设置出版社列

	m_Grid.InsertItem(0,"Visual C++开发技术大全(第2版)");						//插入第0行
	m_Grid.SetItemText(0,1,"明日科技");				//向第1列插入数据
	m_Grid.SetItemText(0,2,"人民邮电出版社");				//向第2列插入数据
	m_Grid.InsertItem(1,"Visual C++从入门到精通(第2版)");						//插入第1行
	m_Grid.SetItemText(1,1,"明日科技");				//向第1列插入数据
	m_Grid.SetItemText(1,2,"清华大学出版社");				//向第2列插入数据
	m_Grid.InsertItem(2,"Visual C++开发实战宝典");						//插入第2行
	m_Grid.SetItemText(2,1,"明日科技");				//向第1列插入数据
	m_Grid.SetItemText(2,2,"清华大学出版社");				//向第2列插入数据
5.组合框combo Box
CString str[]={"钱夫人","小丹尼","卡卡罗特","琪琪","特兰克斯","贝吉塔","天津饭"};
	m_ImageList.Create(16,16,ILC_COLOR24|ILC_MASK,1,0);		//创建列表视图窗口
	m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON1));		//向图像列表中添加图标
	m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON2)); 		//向图像列表中添加图标
	m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON3)); 		//向图像列表中添加图标
	m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON4)); 		//向图像列表中添加图标
	m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON5)); 		//向图像列表中添加图标
	m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON6)); 		//向图像列表中添加图标
	m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON7)); 		//向图像列表中添加图标
	m_Combo.SetImageList(&m_ImageList);
	for(int i=0;i<7;i++)
	{
		COMBOBOXEXITEM cbi;
		cbi.mask = CBEIF_IMAGE|CBEIF_INDENT|CBEIF_OVERLAY|
					CBEIF_SELECTEDIMAGE|CBEIF_TEXT;
		cbi.iItem 			= i;
		cbi.pszText 		= str[i].GetBuffer(0);	//设置列表项文本
		cbi.cchTextMax		= str[i].GetLength();	//设置文本最大长度
		cbi.iImage 			= i;
		cbi.iSelectedImage	= i;
		cbi.iOverlay 		= 0;
		cbi.iIndent 		= (0 & 0x03); 
		m_Combo.InsertItem(&cbi);					//插入数据

6.列表框list box
















六、位图文件分析

BITMAPFILEHEADER、BITMAPINFOHEADER及BMP结构详解

1.StretchDIBits

根据位图的数据将图像显示在窗口中
int StretchDIBits(HDC hdc, int XDest , int YDest , int nDestWidth, int nDestHeight, int XSrc, int Ysrc, int nSrcWidth, int nSrcHeight, CONST VOID *lpBits, CONST BITMAPINFO * lpBitsInfo, UINT iUsage, DWORD dwRop);
hdc:指向目标设备环境的句柄。
XDest:指定目标矩形左上角位置的X轴坐标,按逻辑单位来表示坐标。
YDest:指定目标矩形左上角的Y轴坐标,按逻辑单位表示坐标。
nDestWidth:指定目标矩形的宽度。
nDestHeight:指定目标矩形的高度。
XSrc:指定DIB中源矩形(左上角)的X轴坐标,坐标以像素点表示。
YSrc:指定DIB中源矩形(左上角)的Y轴坐标,坐标以像素点表示。
nSrcWidth:按像素点指定DIB中源矩形的宽度。
nSrcHeight:按像素点指定DIB中源矩形的高度。
lpBits:指向DIB位的指针,这些位的值按字节类型数组存储,有关更多的信息,参考下面的备注一节。
lpBitsInfo:指向BITMAPINFO结构的指针,该结构包含有关DIB方面的信息。
iUsage:表示是否提供了BITMAPINFO结构中的成员bmiColors,如果提供了,那么该bmiColors是否包含了明确的RGB值或索引。参数iUsage必须取下列值,这些值的含义如下:
DIB_PAL_COLORS:表示该数组包含对源设备环境的逻辑调色板进行索引的16位索引值。
DIB_RGB_COLORS:表示该颜色表包含原义的RGB值,若想了解更多的信息,请参考下面备注一节。
dwRop:指定源像素点、目标设备环境的当前刷子和目标像素点是如何组合形成新的图像。若想了解更多信息,请参考下面的备注一节。


2.显示JPEG图像

思路是将JPEG文件加载到堆中,然后在堆中创建一个数据流,接着调用OleLoadPicture函数加载流中的数据到IPicture接口中,最后
调用IPicture接口的Render方法输出图像信息 
1.添加成员变量
IStream *m_pStream;					//定义流对象
	IPicture *m_pPicture;				//定义接口对象
	OLE_XSIZE_HIMETRIC m_JPGWidth;		//图像宽度
	OLE_YSIZE_HIMETRIC m_JPGHeight;		//图像高度
	HGLOBAL hMem;						//堆句柄
2.构造函数中从磁盘加载JPEG图像到流中
CFile file;//定义文件对象
	file.Open("angell.jpg",CFile::modeReadWrite);//打开文件
	DWORD len = file.GetLength();//获取文件长度
	hMem = GlobalAlloc(GMEM_MOVEABLE,len);//在堆中分配内存
	LPVOID pData = NULL; //定义一个指针对象
	pData = GlobalLock(hMem);//锁定内存区域
	//file.ReadHuge(pData,len);
	file.Read(pData, len);//读取图像数据到堆中
	file.Close();//关闭文件
	GlobalUnlock(hMem);//解除对堆得锁定
	CreateStreamOnHGlobal(hMem,TRUE,&m_pStream);//在堆中创建流
	OleLoadPicture(m_pStream,len,TRUE,IID_IPicture,(LPVOID*)&m_pPicture);//加载图像
	m_pPicture->get_Height(&m_JPGHeight);//获取图像高度
	m_pPicture->get_Width(&m_JPGWidth);//获取图像宽度
3.OnDaw绘制JPEG图像
m_pPicture->Render(pDC->m_hDC,0,0,(int)(m_JPGWidth/26.45),(int)(m_JPGHeight/26.45)
		              ,0,m_JPGHeight,m_JPGWidth,-m_JPGHeight,NULL);	

七、GDI+图像编程

1.流程

(1)、下载GDI+包文件
(2)、引用Gdiplus.h
#include "Gdiplus//Gdiplus.h" 
(3)、引用Gdiplus命名空间
using namespace Gdiplus 
(4)、在程序中链接gdiplus.lib库文件
#pragma comment(lib,"gdiplus.lib")
(5)、定义两个全局变量
GdiplusStartupinput m_Gdiplus
ULONG_PTR m_pGdiToken
(6)、在应用程序或对话框初始化时加载GDI+
GdiplusStartup(&m_pGdiToken,&m_Gdiplus,NULL)
(7)、在应用程序结束时卸载GDI+
GdiplusShutdown(m_pGdiToken)




2.GDI+实现图像格式BMP、JPEG、GIF转换

(1).创建对话框工程ConverImage
(2).引用GDI+
//ConvertImageDlg.h
#include "Gdiplus//Gdiplus.h"
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus//gdiplus.lib")
(3).添加成员变量
GdiplusStartupInput m_Gdiplus;
ULONG_PTR m_pGdiToken;
CString m_FileName;//记录文件名称
(4).初始化GDI+,OnInitDialog()函数添加
	GdiplusStartup(&m_pGdiToken,&m_Gdiplus,NULL);	
	CButton *pButton = NULL;
	pButton = (CButton*)GetDlgItem(IDC_JPEG);
	if (pButton != NULL)
	{
		pButton->SetCheck(BST_CHECKED);
	}

(5).添加OnCancel方法函数卸载GDI+
void CConvertImageDlg::OnCancel()
{
	GdiplusShutdown(m_pGdiToken);
	CDialog::OnCancel();
}

(6).添加getCodecClsid方法,根据图像格式获取其CLSID
int GetCodecClsid(const WCHAR* format, CLSID* pClsid)
{
   UINT  num = 0;		//记录图像编码的数量
   UINT  size = 0;		//记录编码数组大小
   ImageCodecInfo* pImageCodecInfo = NULL;	//定义图像编码信息
   GetImageEncodersSize(&num, &size);		//获取图像编码的数量和编码数组大小
   if(size == 0)
      return -1; 
   pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
   if(pImageCodecInfo == NULL)
      return -1;  
   GetImageEncoders(num, size, pImageCodecInfo);	//获取图像编码
   for(UINT j = 0; j < num; ++j)					//匹配图像格式,
   {
      if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
      {
         *pClsid = pImageCodecInfo[j].Clsid;


         return j;  
      }    
   } 
   return -1; 
} 
(7).处理按钮的单击事件,选择待转换的图像
void CConvertImageDlg::OnOK() 
{
	CFileDialog flDlg(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		              "图像文件|*.bmp;*.jpeg;*.jpg;*.gif|所有文件|*.*||",this);
	if (flDlg.DoModal()==IDOK)
	{
		m_FileName = flDlg.GetPathName();//获取文件名和路径
		m_ImageName.SetWindowText(m_FileName);	//设置编辑框文本
	}
}

(8).添加TestButtonState方法,根据按钮的命令ID判断按钮是否被选中
BOOL CConvertImageDlg::TestButtonState(UINT BTNID)
{
	CButton *pButton = NULL;//定义按钮指针
	pButton = (CButton*)GetDlgItem(BTNID);//获取按钮对象
	if (pButton != NULL)//哦判断指针是否为空
	{
		if (pButton->GetCheck()==BST_CHECKED)//判断单选按钮是否被选中
			return TRUE;	
	}
	return FALSE;
}

(9).处理转换按钮的单击事件,将源图像转换为指定的图像格式
void CConvertImageDlg::OnConvert() 
{
	if (TestButtonState(IDC_JPEG))//判断JPEG单选按钮是否被选中
	{
		CFileDialog flDlg(FALSE,"jpeg","convert",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"所有文件|*.*||",this);
		if (flDlg.DoModal()==IDOK)//判断是否单击OK
		{
			CString svname = flDlg.GetPathName();//获取文件名及路径
			Bitmap bmp(m_FileName.AllocSysString());//定义一个文图对象
			CLSID clsid;//定义一个CLSID
			GetCodecClsid(L"image/jpeg", &clsid);//获取JPEG图像CLSID
			bmp.Save(svname.AllocSysString(),&clsid);
		}//保存为JPEG图像格式
	}
	else if (TestButtonState(IDC_BMP))
	{
		CFileDialog flDlg(FALSE,"bmp","convert",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"所有文件|*.*||",this);
		if (flDlg.DoModal()==IDOK)
		{
			CString svname = flDlg.GetPathName();
			Bitmap bmp(m_FileName.AllocSysString());
			CLSID clsid ;
			GetCodecClsid(L"image/bmp", &clsid);
			bmp.Save(svname.AllocSysString(),&clsid);	
		}
	}
	else
	{
		CFileDialog flDlg(FALSE,"gif","convert",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"所有文件|*.*||",this);
		if (flDlg.DoModal()==IDOK)
		{
			CString svname = flDlg.GetPathName();
			Bitmap bmp(m_FileName.AllocSysString());
			CLSID clsid = ImageFormatGIF;
			GetCodecClsid(L"image/gif", &clsid);
			bmp.Save(svname.AllocSysString(),&clsid);	
		}
	}
}

3、使用GDI+显示GIF图像

GDI+提供一个Image类,使用该类的GetFrameDimensionsCount方法可以获取GID文件中
帧的维数,通过GetFrameDimensionsList方法获取图像帧的GUID,通过GetFrameCount方法根据GUID
获取图像的帧数,通过SelectActiveFrame方法设置图像显示的当前帧,最后使用Graphice类的DrawImage方法显示当前帧的图像即可显示
GIF动画

(1). 引用
#include "Gdiplus//Gdiplus.h"
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus//gdiplus.lib")
(2).成员变量
DECLARE_DYNCREATE(CShowGIFView)
	GdiplusStartupInput m_Gdiplus;	//定义GDI+初始化变量
	ULONG_PTR m_pGdiToken;			//定义GID+标识
	Bitmap *m_pBmp;			//定义位图对象,派生于Image类
	UINT m_Count;			//记录维数
	UINT m_FrameCount;		//帧数
	PropertyItem* pItem ;	//定义图像属性
	int fcount;				//定义一个临时整型变量
	UINT delay;				//第一帧的延时
(3).构造函数中初始化
GdiplusStartup(&m_pGdiToken,&m_Gdiplus,NULL);//初始化GUI+
	m_pBmp = Bitmap::FromFile(L"query.gif");//加载GIF图像
	m_Count = m_pBmp->GetFrameDimensionsCount();//获取帧维度
	GUID *pGuids = new GUID[m_Count];//定义GUID数组
	m_pBmp->GetFrameDimensionsList(pGuids,m_Count);//获取图像帧的GUID


	m_FrameCount = m_pBmp->GetFrameCount(pGuids);//或缺GIF帧数
	UINT size;//定义一个整型变量
	m_Count = 0;//初始化成员变量
	m_pBmp->GetPropertySize(&size,&delay);//获取属性大小
	PropertyItem *pItem = NULL;//定义属性指针
	pItem = (PropertyItem*)malloc(size);//为属性指针分配合适的空间
	Status status= m_pBmp->GetAllPropertyItems(size,delay,pItem);//或缺属性信息
	delay = ((long*)pItem->value)[0];//或缺第一帧的延时
	free(pItem);//释放属性对象
	delete [] pGuids;//释放GUID
	fcount = 0;//初始化成员变量
(4).定义一个内存画布类,放置图像闪烁
class CMemDC : public CDC //定义一个CMenDC类
{
private:
	CBitmap*	m_bmp;//定义一个位图对象
	CBitmap*	m_oldbmp;
	CDC*		m_pDC;//定义一个设备上下文指针
	CRect		m_Rect;//定义一个区域对象
public:
	CMemDC(CDC* pDC, const CRect& rect) : CDC()//定义构造函数
	{
		CreateCompatibleDC(pDC);//创建一个兼容的设备上下文
		m_bmp = new CBitmap;//为位图对象分配空间
		m_bmp->CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());//创建位图对象
	
		m_oldbmp = SelectObject(m_bmp);//选中创建的位图


		m_pDC = pDC;//设置成员变量
		m_Rect = rect;//设置区域对象
		this->BitBlt(m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height(), 
			pDC, m_Rect.left, m_Rect.top,WHITENESS);绘制白色背景		
	}
	~CMemDC() //析构函数
	{
		
		m_pDC->BitBlt(m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height(), 
				this, m_Rect.left, m_Rect.top,SRCCOPY);//绘制图像
		SelectObject(m_oldbmp);//选中原来的位图对象
		
		if (m_bmp != NULL) //判断位图对象是否为空
			delete m_bmp;//删除位图对象
		DeleteObject(this);//释放设备上下文
	}
};
(5).处理WM_TIMER信息,按照一定时间间隔绘制不同图像帧
::OnTimer(UINT nIDEvent) 
{
	GUID Guid = FrameDimensionTime;//定义GUID
	CDC* pDC = GetDC();//获取视图窗口的设备上下文	
	CMemDC dc(pDC,CRect(0,0,m_pBmp->GetWidth(),m_pBmp->GetHeight()));//定义一个内存画布
	Graphics gh(dc.m_hDC); //定义一个图像对象
	gh.DrawImage(m_pBmp,0,0,m_pBmp->GetWidth(),m_pBmp->GetHeight());//向设备上下文绘制图像
	m_pBmp->SelectActiveFrame(&Guid,fcount++);//设置下一帧
	if(fcount == m_FrameCount) //判断当前帧是否为尾帧
	   fcount = 0; 	//将当前帧设置为第一帧
	CView::OnTimer(nIDEvent);
}
(6).处理WM_CAEATE消息
::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)//调用父类的方法
		return -1;
	SetTimer(0,delay*10,NULL);//开始一个计时器
	return 0;
}
(7).析构函数中卸载GDI+
GdiplusShutdown(m_pGdiToken);


GDI+源码: http://download.csdn.net/detail/greless/9863471


注:VC6.0才需要下载GDI+包,VS后已经集成GDI+了,直接 #include <Gdiplus.h>
using namespace Gdiplus;即可


















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值