GDI+入门
来源:互联网 发布:mp3加背景音乐软件 编辑:程序博客网 时间:2024/05/18 17:41
转载请注明出处
作者:小马
一 介绍
本人对GDI+算不上专家,只是在几个小项目中应用了一些而已, 算是入门了. 刚好最近有点时间, 把自己掌握的东东做个总结.
如果你以前用过GDI, 那么你转到GDI+易如反掌. 如果你没用过GDI,那么你可以直接学GDI+,不用经历学习GDI的那种痛苦. 因为GDI+相对于GDI,更加抽象,隐藏了更多底层的东西, 整体架构更加清晰明了.
GDI+通过c++ class的形式对外引出接口, 程序员直接调用这些接口来完成相应的功能. 共有40个相关的类, 50个枚举常量和6个结构体. 它的局限性是只能运行在windows XP和windows server2003的系统上.
简单说几个GDI+与GDI不同的地方.
1 GDI+很重要一个改进就是增了对多种图像格式的支持.它目前支持下面几中格式的图像:
BMPGraphics Interchange Format (GIF)JPEG Exif PNG TIFF ICON WMF EMF
2 DC(设备环境内容)的概念变得模糊,基本对程序员是透明了.
用GDI的人都知道, 不懂DC可不行, 这个DC保存着显示设备的属性和功能信息, 每当你想要drawing时, 你得先获取DC的句柄, 然后把这个句柄作为参数传给GDI的API, 另外还要考虑关于”选到设备(selectObjec),释放设备”等繁琐的操作.
GDI+对方简化了这方面的处理,它有一个Graphics类,一个Graphics的对象就类似于DC的角色, 而且它跟pen,brush等的关系也变得独立, 不用再”选来选去”, 在GDI+里,像pen,brush这些东西都是独立的对象,用的时候只需把它们的实例作为参数传给Graphics的接口就可以了(在下面的示例中会看到).
3 增加了对渐变颜色效果的支持.
原来在GDI里做渐变效果, 那叫一复杂呀. 下面的示例中会具体说说GDI+里的渐变.
二 应用
前期准备
使用GDI+, 首先要包含相关的头文件, 只有一个,如下:
#include <gdiplus.h>
vs2005的include目录下有这个头文件, 所以在vs2005环境下, 直接以”<>”的形式包含即可.
还需要用到一个lib, Gdiplus.lib, 你可以在源文件中通过
#pragma comment (lib,"Gdiplus.lib")
的形式链接进来, 也可以直接在”项目属性-linker-input里添加, 效果是一样的.
为了不使GDI+专用的相关类,常量,结构体与其它应用混淆,GDI+有自己的命名空间, 叫Gdiplus, 当你要用到GDI+的相关API时,就要用到下面的语句:
using namespace Gdiplus;
最后, GDI+有个应用开关, GdiplusStartup和GdiplusShutdown, 一个开,一个关, 使用GDI+任何功能前,先调用GdiplusStartup,程序结束时,调用GdiplusShutdown关闭. 比如在基于mfc的对话框应用中, 我一般这样做, 假设我的工程为MyGDIPlusTest, 首先在MyGDIPlusTest.cpp的InitInstance函数中打开GDI+,如下:
CWinApp::InitInstance();GdiplusStartup(&m_gdiPlusToken, &m_gdiPlusStartupInput, NULL);
然后重载ExitInstance函数, 在这个函数里关闭GDI+
GdiplusShutdown(m_gdiPlusToken);//程序退出时关闭return CWinApp::ExitInstance();
示例
1 先看一个msdn中的示例
#include <stdafx.h>#include <windows.h>#include <objidl.h>#include <gdiplus.h>using namespace Gdiplus;#pragma comment (lib,"Gdiplus.lib")VOID OnPaint(HDC hdc){ Graphics graphics(hdc); Pen pen(Color(255, 0, 0, 255)); graphics.DrawLine(&pen, 0, 0, 200, 100);}LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow){ HWND hWnd; MSG msg; WNDCLASS wndClass; GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; // Initialize GDI+. GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = TEXT("GettingStarted"); RegisterClass(&wndClass); hWnd = CreateWindow( TEXT("GettingStarted"), // window class name TEXT("Getting Started"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters ShowWindow(hWnd, iCmdShow); UpdateWindow(hWnd); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } GdiplusShutdown(gdiplusToken); return msg.wParam;} // WinMainLRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ HDC hdc; PAINTSTRUCT ps; switch(message) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); OnPaint(hdc); EndPaint(hWnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; default: return DefWindowProc(hWnd, message, wParam, lParam); }} // WndProc
这个示例是画线的,如果是打印字符串, 只用修改OnPaint中的内容,如下:
VOID OnPaint(HDC hdc){ Graphics graphics(hdc); SolidBrush brush(Color(255, 0, 0, 255)); FontFamily fontFamily(L"Times New Roman"); Font font(&fontFamily, 24, FontStyleRegular, UnitPixel); PointF pointF(10.0f, 20.0f); graphics.DrawString(L"Hello World!", -1, &font, pointF, &brush);}
2 自己写的一个显示图片的简单示例
基于mfc的对话框应用,点一下按钮,显示一张图片. 只显示关键代码
void CGDI_Plus_TestDlg::OnBnClickedButtonPen(){ // TODO: Add your control notification handler code here HDC hdc = this->GetDC()->m_hDC; Graphics graphics(hdc); Image image(L"c:\\image\\ip.jpg"); graphics.DrawImage(&image, 200, 200);}
注意以下几点:
第一, Image只支持通过路径和流的形式提供实例初始化,不支持资源句柄, 如果要用资源句柄的形式,可以先把资源数据读到流里,这里不说了.
第二, 关于DrawImage,有很多重载函数, 提供了几乎你能想到的所有功能,我这里用了下面这个重载
Status DrawImage( Image *image,INT x,INT y);
也就是在指定位置显示加载的图像.
渐变效果
前面说了,GDI+支持渐变, 分为两种, linear gradient和path gradient, 这里讨论第一种.
linear gradient又分为
Horizontal Linear Gradients,Customizing Linear Gradients,Diagonal Linear Gradients三种.
这些比较好理解. 下面的代码示例来自msdn,我做了一些修改.
void CGDI_Plus_TestDlg::OnBnClickedButtonPen(){ // TODO: Add your control notification handler code here HDC hdc = this->GetDC()->m_hDC; Graphics graphics(hdc); LinearGradientBrush linearBrush(Point(0, 10), Point(200, 10), Color(255,255,0,0),Color(255,0,0,255)); Pen pen(&linearBrush, 4); graphics.DrawLine(&pen, 100,100, 200, 100); graphics.FillEllipse(&linearBrush, 100, 150, 200, 100); graphics.FillRectangle(&linearBrush, 100, 255, 500, 30);}
程序运行的效果如下图
附: GDI+与GDI混合编程
GDI+提供了一种机制, 可以和GDI混合使用, 主要是利用Graphics中的ReleaseHDC和GetHDC, 下面的代码示例来自msdn:
VOID Example_GetReleaseHDC(Graphics* g){ Pen pen(Color(255, 0, 0, 255)); g->DrawEllipse(&pen, 10, 10, 100, 50); // GDI+ HDC hdc = g->GetHDC(); // Make GDI calls, but don't call any methods // on g until after the call to ReleaseHDC. Rectangle(hdc, 120, 10, 220, 60); // GDI g->ReleaseHDC(hdc); // Ok to call methods on g again. g->DrawLine(&pen, 240, 10, 340, 60); }
- GDI&GDI+程序入门
- GDI+入门
- GDI+入门
- GDI+入门
- GDI+入门
- GDI+入门
- GDI+入门
- GDI+入门(Starting with GDI+)
- GDI+ 简单入门学习
- GDI+入门01
- GDI+入门(总结)
- GDI+ 基础知识入门
- GDI+入门(总结)
- GDI+ 入门编程
- GDI简明入门
- Gdi+实用入门
- 《GDI/GDI+从入门到精通》视频教程
- Window GDI入门初阶
- fedora 15 安装opencv2.2时出现undefined reference to `cvCreateCameraCapture_V4L(int)'问题及其解决方法
- hideFocus(小技巧)
- css overflow
- 10种ADC软件滤波方法及程序
- 微软等面试经典100题
- GDI+入门
- HTC G7 卸载自带软件(刷Root)
- 常见浏览器兼容问题
- 浏览器兼容解决方案一
- C++Primer读书笔记(六)
- 内存不足 java.lang.OutOfMemoryError: Java heap space
- linux中的apachectl是什么命令
- 删除重复记录
- How does Template Monster Work - Preface