在C++界面编程中,经常会用到GDI(Graphics Device Interface的缩写,含义是图形设备接口),我在VS2013上,以实现动态数字为例,介绍它的基本使用:
1)下载GDIplus工具包,推荐连接:http://download.csdn.net/detail/yja000/9868700;
2)新建对话框工程,将GDIplus工具包中文件全部复制到工程目录下;
3)在StdAfx.h文件中添加GDIplus连接代码:
#include "../Includes\\GdiPlus.h"
using namespace Gdiplus;
#pragma comment(lib, "../Lib\\GdiPlus.lib")
如果是VS低版本或者是VC++平台,还需要添加以下代码:
#define UNICODE
#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#endif
4)在类行为文件XX.cpp的InitInstance()中添加如下4条代码(注意【】标识的添加位置):
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken,&gdiplusStartupInput, NULL);
【C**Dlg dlg;】
【…】
GdiplusShutdown(gdiplusToken);
【return FALSE;】
5) 在XXDlg.h文件中声明变量和函数:
Image *m_pImageBackground, *m_pImageNum;
BOOL ImageFromIDResource(UINT nID, LPCTSTR sTR, Image *&pImg);//获取图片信息函数
void DrawBackground(HDC hDC);//绘制背景
void DrawTime(HDC hDC);//绘制时钟
6)在XXDlg.cpp文件中添加ImageFromIDResource函数代码:
BOOL Cgraph_testDlg::ImageFromIDResource(UINT nID, LPCTSTR sTR, Image *&pImg)
{
HINSTANCE hInst = AfxGetResourceHandle();
HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nID), sTR); // type
if (!hRsrc)
return FALSE;
// load resource into memory
DWORD len = SizeofResource(hInst, hRsrc);
BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
if (!lpRsrc)
return FALSE;
// Allocate global memory on which to create stream
HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
memcpy(pmem, lpRsrc, len);
IStream* pstm;
CreateStreamOnHGlobal(m_hMem, FALSE, &pstm);
// load from stream
pImg = Gdiplus::Image::FromStream(pstm);
// free/release stuff
GlobalUnlock(m_hMem);
pstm->Release();
FreeResource(lpRsrc);
return TRUE;
}
7)添加PNG背景图和数字编码图,在XXDlg.cpp文件的OnInitDialog()函数中添加代码:
ImageFromIDResource(IDB_PNG1, _T("PNG"), m_pImageBackground);
ImageFromIDResource(IDB_PNG2, _T("PNG"), m_pImageNum);
SetTimer(1, 1000, NULL);
8)在XXDlg.cpp文件中添加DrawBackground(HDC hDC)函数及代码:
void Cgraph_testDlg::DrawTime(HDC hDC)
{
Graphics graph(hDC);
SYSTEMTIME SystemTime; // address of system time structure
GetLocalTime(&SystemTime);
int nx = 30;
//H,从m_pImageClock中剪切指定rect中的像素draw到指定位置
graph.DrawImage(m_pImageNum, nx + 0, 0, 14 * (SystemTime.wHour / 10), 0, 14, 23, UnitPixel);
graph.DrawImage(m_pImageNum, nx + 20, 0, 14 * (SystemTime.wHour % 10), 0, 14, 23, UnitPixel);
//:
graph.DrawImage(m_pImageNum, nx + 20 * 2, 0, 140, 0, 14, 23, UnitPixel);
//M
graph.DrawImage(m_pImageNum, nx + 20 * 3, 0, 14 * (SystemTime.wMinute / 10), 0, 14, 23, UnitPixel);
graph.DrawImage(m_pImageNum, nx + 20 * 4, 0, 14 * (SystemTime.wMinute % 10), 0, 14, 23, UnitPixel);
//:
graph.DrawImage(m_pImageNum, nx + 20 * 5, 0, 140, 0, 14, 23, UnitPixel);
//S
graph.DrawImage(m_pImageNum, nx + 20 * 6, 0, 14 * (SystemTime.wSecond / 10), 0, 14, 23, UnitPixel);
graph.DrawImage(m_pImageNum, nx + 20 * 7, 0, 14 * (SystemTime.wSecond % 10), 0, 14, 23, UnitPixel);
graph.ReleaseHDC(hDC);
}
9)在XXDlg.cpp文件中添加DrawBackground(HDC hDC)函数及代码:
void Cgraph_testDlg::DrawBackground(HDC hDC)
{
CRect rcClient;
GetClientRect(&rcClient);
Graphics graph(hDC);
Point points[] = { Point(0, 0),
Point(rcClient.Width(), 0),
Point(0, rcClient.Height()),
};
graph.DrawImage(m_pImageBackground, points, 3);
graph.ReleaseHDC(hDC);
}
10)在XXDlg.cpp文件中添加MyPaint()函数及代码:
void Cgraph_testDlg::MyPaint()
{
CPaintDC dc(this);
CRect rcClient;
GetClientRect(&rcClient);
CDC dcMem;
CBitmap bmpMem;
dcMem.CreateCompatibleDC(&dc);
if (bmpMem.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height()))
{
CBitmap* pOldBmp = dcMem.SelectObject(&bmpMem);
DrawBackground(dcMem.m_hDC);
DrawTime(dcMem.m_hDC);
dc.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &dcMem, 0, 0, SRCCOPY);
dcMem.SelectObject(pOldBmp);
bmpMem.DeleteObject();
}
dcMem.DeleteDC();
}
11)在XXDlg.cpp文件的OnPaint()函数else分支中添加代码:
MyPaint(); //绘图
12)在XXDlg.cpp文件的OnInitDialog()函数中添加代码:
ImageFromIDResource(IDB_PNG1, _T("PNG"), m_pImageBackground);//装载背景图
ImageFromIDResource(IDB_PNG2, _T("PNG"), m_pImageNum);//装载数字编码图
SetTimer(1, 1000, NULL);
13)在对话框工程中添加定时器响应函数及代码:
void Cgraph_testDlg::OnTimer(UINT_PTR nIDEvent)
{
//UpdateClockDisplay(255);
UpdateWindow();
Invalidate();
CDialogEx::OnTimer(nIDEvent);
}
14)最后在退出时释放资源:
void Cgraph_testDlg::OnDestroy()
{
delete m_pImageBackground;
delete m_pImageNum;
CDialogEx::OnDestroy();
}
保存后运行程序,对话框中就显示背景图,并且刷新当前显示时间,效果如下: