GDI+入門

來源:互聯網
上載者:User

轉載請註明出處

作者:小馬

 

一 介紹
本人對GDI+算不上專家,只是在幾個小項目中應用了一些而已, 算是入門了. 剛好最近有點時間, 把自己掌握的東東做個總結.

 

如果你以前用過GDI, 那麼恭喜你,因為你轉到GDI+易如反掌. 如果你沒用過GDI,那麼也恭喜你, 因為你可以直接學GDI+,不用經曆學習GDI的那種痛苦. 因為GDI+相對於GDI,更加抽象,隱藏了更多底層的東西, 整體架構更加清晰明了.

 

GDI+通過c++ class的形式對外引出介面, 程式員直接調用這些介面來完成相應的功能. 共有40個相關的類, 50個枚舉常量和6個結構體. 它的局限性是只能運行在windows XP和windows server2003的系統上.

 

簡單說幾個GDI+與GDI不同的地方.
1 GDI+很重要一個改進就是增了對多種映像格式的支援.它目前支援下面幾中格式的映像:
BMP
Graphics 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);
也就是在指定位置顯示載入的映像.

 

3 漸層效果

前面說了,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);  }

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.