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_GdiplusULONG_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;即可