GdiPlus使用方法

GDI是Graphics Device Interface的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。

在Windows操作系统下,绝大多数具备图形界面的应用程序都离不开GDI,我们利用GDI所提供的众多函数就可以方便的在屏幕、打印机及其它输出设备上输出图形,文本等操作。GDI的出现使程序员无需要关心硬件设备及设备驱动,就可以将应用程序的输出转化为硬件设备上的输出,实现了程序开发者与硬件设备的隔离,大大方便了开发工作。

GDI+是Windows XP中的一个子系统,它主要负责在显示屏幕和打印设备输出有关信息,它是一组通过C++类实现的应用程序编程接口。顾名思义,GDI+是以前版本GDI的继承者,出于兼容性考虑,Windows XP仍然支持以前版本的GDI,但是在开发新应用程序的时候,开发人员为了满足图形输出需要应该使用GDI+,因为GDI+对以前的Windows版本中GDI进行了优化,并添加了许多新的功能。

作为图形设备接口的GDI+使得应用程序开发人员在输出屏幕和打印机信息的时候无需考虑具体显示设备的细节,他们只需调用GDI+库输出的类的一些方法即可完成图形操作,真正的绘图工作由这些方法交给特定的设备驱动程序来完成,GDI+使得图形硬件和应用程序相互隔离.从而使开发人员编写设备无关的应用程序变得非常容易。

GdiPlus使用方法:

开发工具:VS2008

1.新建对话框应用程序

2.拷贝 GdiPlus_Includes文件夹、Lib文件、gdiplus.dll文件 到应用程序中

3.在StdAfx.h文件中添加如下代码

//GDI+
#define UNICODE
#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#endif
//#include "c:\gdi+\includes\gdiplus.h"   ////请修改为你的头文件路径
//using namespace Gdiplus;
//#pragma comment(lib, "c:\\gdi+\\lib\\gdiplus.lib") ////请修改为你的.lib文件路径
#include "../GdiPlus_Includes\\gdiplus.h"
using namespace Gdiplus;
#pragma comment(lib, "../GdiPlus_Lib\\gdiplus.lib")

4.在C**App.cpp文件的InitInstance()函数中

在C**Dlg dlg之前,添加如下代码:

	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR           gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

在dlg后,return前,添加如下代码:

	//关闭gdiplus的环境
	GdiplusShutdown(gdiplusToken);

如:

BOOL CGdiPlusDemoApp::InitInstance()
{
	// 如果一个运行在 Windows XP 上的应用程序清单指定要
	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
	//则需要 InitCommonControlsEx()。否则,将无法创建窗口。
	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwSize = sizeof(InitCtrls);
	// 将它设置为包括所有要在应用程序中使用的
	// 公共控件类。
	InitCtrls.dwICC = ICC_WIN95_CLASSES;
	InitCommonControlsEx(&InitCtrls);

	CWinApp::InitInstance();

	AfxEnableControlContainer();

	// 标准初始化
	// 如果未使用这些功能并希望减小
	// 最终可执行文件的大小,则应移除下列
	// 不需要的特定初始化例程
	// 更改用于存储设置的注册表项
	// TODO: 应适当修改该字符串,
	// 例如修改为公司或组织名
	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR           gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	CGdiPlusDemoDlg dlg;
	m_pMainWnd = &dlg;
	INT_PTR nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: 在此放置处理何时用
		//  “确定”来关闭对话框的代码
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: 在此放置处理何时用
		//  “取消”来关闭对话框的代码
	}

	//关闭gdiplus的环境
	GdiplusShutdown(gdiplusToken);

	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
	//  而不是启动应用程序的消息泵。
	return FALSE;
}

5.C**Dlg操作

OnInitDialog:设置对话框位置和大小,获取资源信息

OnPaint:画图

头文件

private:
	Image *m_pImageBackground;
	int m_nBackgroundWidth, m_nBackgroundHeight;

	Image *m_pImagePic;
	int m_nPicWidth, m_nPicHeight;

private:
	void MyInitDialog();
	void InitUi();//设置界面初始化信息
	void GetImageSource();//获取图片信息

	void MyPaint();
	void DrawBackground(HDC hDC);//绘制背景
	void DrawPic(HDC hDC);//绘制图片

	//获取图片信息
	BOOL ImageFromIDResource(UINT nID, LPCTSTR sTR, Image *&pImg);
	BOOL ImageFromIDResource(CString sFilePathName, Image *&pImg);

源文件

void CGdiPlusDemoDlg::MyInitDialog()
{
	InitUi();
	GetImageSource();
}

void CGdiPlusDemoDlg::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);
		CWnd::DefWindowProc(WM_PAINT,(WPARAM)dcMem.m_hDC,0);

		DrawBackground(dcMem.m_hDC);
		DrawPic(dcMem.m_hDC);

		dc.BitBlt(0,0,rcClient.right,rcClient.bottom,&dcMem,0,0,SRCCOPY);
		dcMem.SelectObject(pOldBmp);
		bmpMem.DeleteObject();
	}
	dcMem.DeleteDC();
}

void CGdiPlusDemoDlg::InitUi()
{
	//对话框背景图片宽和高
	const int nBkBmpWidth  = 800;
	const int nBkBmpHeight = 450;
	//获得电脑显示器的像素宽度和像素高度
	int ax = GetDC()->GetDeviceCaps(HORZRES) - nBkBmpWidth;
	int ay = GetDC()->GetDeviceCaps(VERTRES) - nBkBmpHeight;

	int nWidth = 0;
	int nHeight = 0;
	if(ax <= 0)
	{		ax =0;	}
	else
	{		ax = ax/2;	}
	if(ay <=0 )
	{		ay =0;	}
	else
	{		ay = ay/2;	}

	RECT clientRect;
	clientRect.left = ax;
	clientRect.top = ay;
	clientRect.right = clientRect.left + nBkBmpWidth;
	clientRect.bottom = clientRect.top + nBkBmpHeight;
	MoveWindow(&clientRect);
}

void CGdiPlusDemoDlg::GetImageSource()
{
	ImageFromIDResource(IDB_PNG_BG,_T("PNG"),m_pImageBackground);
	m_nBackgroundWidth  = m_pImageBackground->GetWidth();
	m_nBackgroundHeight = m_pImageBackground->GetHeight();

	CString sPath = _T("res\\hd.png");
	ImageFromIDResource(sPath,m_pImagePic);
	//ImageFromIDResource(IDB_PNG_HD,_T("PNG"),m_pImagePic);
	m_nPicWidth  = m_pImagePic->GetWidth();
	m_nPicHeight = m_pImagePic->GetHeight();
}

void CGdiPlusDemoDlg::DrawBackground(HDC hDC)
{
	RECT rct;
	GetWindowRect(&rct);
	POINT ptWinPos={rct.left,rct.top};
	Graphics graph(hDC);

	Point points[] = { Point(0, 0),
		Point(m_nBackgroundWidth, 0),
		Point(0, m_nBackgroundHeight),
	};
	graph.DrawImage(m_pImageBackground, points, 3);
	graph.ReleaseHDC(hDC);
}

void CGdiPlusDemoDlg::DrawPic(HDC hDC)
{
	RECT rct;
	GetWindowRect(&rct);
	POINT ptWinPos={rct.left,rct.top};
	Graphics graph(hDC);

	int nHorOffset = 50;
	int nVerOffset = 50;

	Point points[] = { Point(nHorOffset, nVerOffset),
		Point(nHorOffset+m_nPicWidth, nVerOffset),
		Point(nHorOffset, nVerOffset+m_nPicHeight),
	};
	graph.DrawImage(m_pImagePic, points, 3);
	graph.ReleaseHDC(hDC);
}

BOOL CGdiPlusDemoDlg::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;
}

BOOL CGdiPlusDemoDlg::ImageFromIDResource(CString sFilePathName, Image *&pImg)
{
	// load file into memory
	DWORD len = 0;
	HANDLE hFile;
	DWORD  size1,readbyte;
	hFile=CreateFile(sFilePathName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
	if(INVALID_HANDLE_VALUE == hFile)
	{
		return FALSE;
	}
	len=GetFileSize(hFile,&size1);
	if(0xFFFFFFFF == len)
	{
		CloseHandle(hFile);
		return FALSE;
	}

	// Allocate global memory on which to create stream
	HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
	BYTE* pmem = (BYTE*)GlobalLock(m_hMem);

	ReadFile(hFile,pmem,len,&readbyte,NULL);
	IStream* pstm;
	CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);

	// load from stream
	pImg=Gdiplus::Image::FromStream(pstm);

	// free/release stuff
	GlobalUnlock(m_hMem);
	pstm->Release();

	return TRUE;
}

工程

  

运行效果

源码下载

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 10:42:38

GdiPlus使用方法的相关文章

vc++加载透明png图片方法——GDI+和CImage两种

vc++加载透明png图片方法——GDI+和CImage两种 在加载png时遇到了麻烦,后来用了两个方法解决了.一个是用GDI+,另外就是用vs.net MFC自带的CImage. 先看看GDI+的方法 方法1: 1.GDI+画透明图层(alpha)的png图片 stdafx加入如下: #include <comdef.h>//初始化一下com口 #include "GdiPlus.h" using namespace Gdiplus; #pragma comment(li

[ATL/WTL]_[中级]_[使用GDIPlus剪切和缩放图片]

场景: 1. 缩放图片,不用多说,就是需要缩略图和画在界面上这类. 2. 剪切,不用多说,就是剪切一部分图片用于绘制控件背景之类. 3. wxWidget的wxImage都是自带这些功能的直接方法的. Gdiplus::Bitmap* CutImage(Gdiplus::Image* source,int x,int y,int width,int height) { Gdiplus::Rect zoomRect(0, 0, width,height); Gdiplus::Bitmap* pIm

一种使用GDI+对图片尺寸和质量的压缩方法

今天同事向我询问图片压缩的算法,我想起大概两三年前做过的一个项目.其中包含了尺寸和质量两种压缩算法,并且支持JPEG.bmp.PNG等格式.今天把这段逻辑贴出来,供大家参考.(转载请指明来源于breaksoftware的CSDN博客) 尺寸压缩 bool CompressImagePixel( const WCHAR* pszOriFilePath, const WCHAR* pszDestFilePah, UINT ulNewHeigth, UINT ulNewWidth ) { // Ini

【gdiplus.h问题】

之前用GUI+的时候一直都是用的 #include <gdiplus.h> #pragma comment(lib, "gdiplus.lib") using namespace Gdiplus; 但是偶发现当多个文件包含的时候,会报很多错误~~ 1>f:\vs2013\vc\include\gdiplusenums.h(29): error C2146: 语法错误: 缺少";"(在标识符"GraphicsState"的前面)

使用GDI+的RotateFlip方法 旋转图像并保存图片

使用GDI+旋转图像并保存图片的方法,代码如下: 1 #pragma once 2 class CGDIImageFile 3 { 4 public: 5 CGDIImageFile(void); 6 ~CGDIImageFile(void); 7 8 String TypeToFormat(TCHAR cType); 9 bool GetImageCLSID(const TCHAR* mformat,CLSID *pClsid); 10 11 void CreateRotateImage(St

【CITE】DrawImage方法详解(转)

Image和Bitmap类概述 GDI+的Image类封装了对BMP.GIF.JPEG.PNG.TIFF.WMF(Windows元文件)和EMF(增强WMF)图像文件的调入.格式转换以及简单处理的功能.而Bitmap是从Image类继承的一个图像类,它封装了Windows位图操作的常用功能.例如,Bitmap::SetPixel和Bitmap::GetPixel分别用来对位图进行读写像素操作,从而可以为图像的柔化和锐化处理提供一种可能. DrawImage方法 DrawImage是GDI+的Gr

vc++加载透明png图片方法-GDI+和CImage两种

转载自:http://blog.csdn.net/zhongbin104/article/details/8730935 先看看GDI+的方法方法1: 1.GDI+画透明图层(alpha)的png图片 stdafx加入如下: #include //初始化一下com口 #include "GdiPlus.h" using namespace Gdiplus; #pragma comment(lib,"gdiplus.lib") 开始初始化:在app类的声明里(.h)加

GDIPlus绘制桌面歌词

功能介绍 採用GDIPlus绘制桌面歌词,相似酷狗.QQ音乐等软件.歌词支持纯色.两色渐变.三色渐变:支持高亮歌词. 实现方法 窗体部分:桌面歌词是个独立的背景透明窗体.能够移动位置,能够鼠标穿透.透明採用WS_EX_LAYERED.UpdateLayeredWindow.鼠标穿透能够增加WS_EX_TRANSPARENT样式.歌词部分:用Graphics::MeasureString取出文字的宽度/高度.把文字增加GDIPlus的路径(GraphicsPath),然后绘制边框(Graphics

Unity 崩溃问题解决方法——之一

友情提示:工作随记,不喜勿喷 注意:文艺青年可以略过,暴力青年欢迎采纳 Library文件夹 Unity每次编译都会生成这个东西,不用担心丢失的问题.所以,干掉他! 选中 + Delete   或者  选中 + Shift  + Delete 网上看了很多方法,就觉得这个简单,粗暴,是我喜欢的类型. 优点:上面说了 缺点:如果工程过大,重新编译时间会比较长.(但是对于查Log日志来说,相对快点)