1.GDI+ 常用方法詳解
作為Windows圖形系統基準的GDI存在諸多不足:Alpha通道支援較弱,不支援高階影象功能,抗鋸齒能力差等等。為了解決這鞋問題,微軟推出GDI+,使用非常方便,滿足大多數場合需求。
需要指明的是,GDI+是構建於GDI上的基於CPU渲染的圖形系統,所以儘管微軟一直在優化,它的效能是比不上GDI的且實測發現XP上GDI+有一定概率崩潰,另外,GDI可以藉助[GDI DDI驅動程式和顯示卡實現]完成硬體加速而GDI+不行。對於遊戲等效能要求高的需求,微軟推薦使用Direct2D和Direct3D,他們很好支援抗抗鋸齒等高階特性且支援硬體加速。
下面詳細說下GDI+ 常用方法的使用。
1.環境初始化
GDI+使用需要連結對應的連結庫,使用完成後要反初始化環境。這裡封裝一個類,建構函式中完成初始化,解構函式中完成反初始化,使用時作為全域性變數或類成員,即可自動完成這些過程,如下:
#pragma once
//GDI+
#include <GdiPlus.h>
#include <GdiplusGraphics.h>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;
class CGdiplusInitHelper
{
public:
CGdiplusInitHelper()
{
//gdi+初始化
m_nGidToken = 0;
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&m_nGidToken, &gdiplusStartupInput, NULL);
}
~CGdiplusInitHelper()
{
//gdi+解除安裝
if ( 0 != m_nGidToken )
{
GdiplusShutdown( m_nGidToken );
m_nGidToken = 0;
}
}
private:
ULONG_PTR m_nGidToken;
};
2.常見影象繪製
和GDI 中dc對應的是GDI+中的Graphics。但是:
1.GDI是有狀態的,GDI+是無狀態的,比如GDI中要把當前畫筆、畫刷等選進dc,然後使用這些GDI圖元來工作,GDI+中不一樣,畫筆、畫刷、字型等等都是物件,我們只需要Graphics繪製時將物件作為引數傳遞即可。
2.GDI畫矩形、圓等圖形的副作用是會填充區域,要不填充區域必須使用NULL_BRUSH,GDI+中繪製邊緣和填充是兩個概念,另外GDI+支援的圖形種類更多也更靈活
演示如下:
void DrawLines(HDC &hdc)
{
Graphics g(hdc);
Pen redP(Color(255,0,0), 2);
g.DrawLine(&redP, 20, 20, 40, 60);
redP.SetDashStyle(DashStyle::DashStyleDashDotDot);//線條樣式
g.DrawLine(&redP, 1, 10, 300, 20);
Pen cyanP(Color::DarkCyan);
g.DrawRectangle(&cyanP, 60,30,20,100);
g.DrawEllipse(&cyanP, 60,30,20,100);
Point pts[] = {Point(10,120), Point(60,200), Point(80,200), Point(90,90)};
g.DrawPolygon(&cyanP, pts, 4);
Pen pinkP(Color::HotPink);
PointF pts2[] = {PointF(10.0f,220.0f), PointF(60.0f, 230.0f), PointF(50.0f, 250.0f)};
g.DrawCurve(&pinkP, pts2, 3);
Point pt1(10,300);
Point pt2(50,400);
Point pt3(100,350);
Point pt4(30,250);
g.DrawBezier(&pinkP, pt1, pt2, pt3, pt4);
}
//填充和繪製分開
void FillShape()
{
Graphics g(m_hWnd);
SolidBrush redB(Color(255,0,0));
g.FillRectangle(&redB, 100,400,200,250);
}
可以看到:
1.這裡繪製時我們建立一個Pen物件,設定他的屬性,然後Graphics繪製時作為引數
2.填充區域是Fill*函式,繪製圖形是Draw*函式
3.路徑和區域
void DrawPathAndRegion(HDC &hdc)
{
PointF data[] = {
PointF(40,140),
PointF(275,200),
PointF(105,255),
PointF(50,350),
PointF(20,180)
};
BYTE typeline[] = {
PathPointTypeLine,
PathPointTypeLine,
PathPointTypeLine,
PathPointTypeLine,
PathPointTypeLine
};
GraphicsPath path1(data, typeline, 5);
Graphics g(hdc);
g.SetSmoothingMode(SmoothingModeAntiAlias);//繪製時反走樣來消除鋸齒
g.TranslateTransform(400., 0.);
g.FillPath(&SolidBrush(Color::Red), &path1);
g.TranslateTransform(300., 0.);
GraphicsPath path2;
FontFamily fontFamily(L"Arial");
path2.AddString(L"Add String", -1,
&fontFamily, FontStyleRegular, 100, PointF(0,0),
NULL);
Pen pen(Color::Black);
g.DrawPath(&pen, &path2);
GraphicsState s = g.Save();
g.SetClip(&path2);//path做剪下區域
for (int i=0; i<100; i+=2)
{
g.DrawLine(&pen, 0, i, 600, i);
}
Region rgn(&path2); //路徑轉區域
g.Restore(s); //取消剪下區域
g.TranslateTransform(0., 100.);
g.FillRegion(&SolidBrush(Color::Black), &rgn);
}
4.文字繪製
void DrawText(HDC &hdc)
{
Graphics g(hdc);
Font myFont(L"Arial", 50, FontStyleItalic, UnitPixel);
RectF layoutRect(10.0f, 10.0f, 197.0f, 50.0f);
StringFormat format;
format.SetAlignment(StringAlignmentCenter); //水平對齊
format.SetLineAlignment(StringAlignmentCenter); //垂直對齊
format.SetFormatFlags(StringFormatFlagsNoClip); //不截斷
format.SetHotkeyPrefix(HotkeyPrefixShow); //&前導符
SolidBrush blackBrush(Color(255,0,0,0));
LPCWSTR pszText = L"Out&putx Text";
g.DrawString(pszText, -1, &myFont, layoutRect, &format, &blackBrush);
g.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit); //抗鋸齒
format.SetTrimming(StringTrimmingEllipsisCharacter); //結尾...
layoutRect.Offset(0, 100);
LPCWSTR pszText2 = L"Output Text Output Text Output Text Output Text";
g.DrawString(pszText2, -1, &myFont, layoutRect, &format, &blackBrush);
//測量指定文字大小
RectF boundRect;
g.MeasureString(pszText2, -1, &myFont, PointF(0,0), &boundRect);
CString str;
str.Format(L"W:%d-H:%d", boundRect.Width, boundRect.Height);
OutputDebugString(str);
//測量指定layoutRect寬度內,文字顯示的個數、行數和包圍框大小
INT codepointsFitted = 0;
INT linesFilled = 0;
RectF layoutRect2(10.0f, 10.0f, 197.0f, 0.f);//高度必須為0才能自適應計算
g.MeasureString(pszText2, -1, &myFont,
layoutRect2, &format,
&boundRect, &codepointsFitted, &linesFilled);
}
可以看到類似GDI,這裡我們使用StringFormat控制輸出文字的格式。g.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);指明字型抗鋸齒輸出。5.影象繪製
GDI中影象功能有很多確定,只支援載入bmp格式,Alpha通道支援有限,影象處理功能較弱。GDI+很好的彌補了這一切。
GDI+支援BMP/TIFF/JPG/PNG/GIF等,且支援透明,GDI的AlphaBlend函式縮放時不支援抗鋸齒,GDI+的DrawImage彌補了這些,如下:
void DrawImages(HDC &hdc)
{
Graphics g(hdc);
g.Clear(Color::WhiteSmoke);//清空當前背景
Image img1(L".\\pop_bk.png");
PointF pt1(0.f, 0.f);
g.DrawImage(&img1, pt1);
g.SetInterpolationMode(InterpolationModeHighQualityBicubic);//設定插值模式,處理影象縮放
RectF rcDest(400.f,400.f,REAL(img1.GetWidth()), REAL(img1.GetHeight()));
g.DrawImage(&img1, rcDest, 20.f,20.f,40.f,40.f, UnitPixel);
}
g.SetInterpolationMode(InterpolationModeHighQualityBicubic)設定影象縮放時的插值方式,保證高質量顯示。這裡主要演示DrawImage使用,影象的載入和處理下一節再細述。
可在DrawImage時傳入Attr引數,指定影象的色彩變換,具體參考API使用。
6.雙緩衝繪製
GDI中我們都是通過建立一個相容DC,一個相容BMP,相容BMP選入相容DC繪製完成後,再將BMP一次性貼到實際DC上。
在GDI+中不用這麼麻煩,GDI+將一切表面抽象,如果想在點陣圖上繪製,直接將Graphics的表面選成點陣圖即可,如下:
//雙緩衝
void DrawImages5(HDC &hdc)
{
Bitmap bmp1(L".\\pop_bk.png");
//記憶體繪圖
Bitmap bmpMem(bmp1.GetWidth(), bmp1.GetHeight());
Graphics gMem(&bmpMem);//以記憶體Bitmap為表面繪圖
gMem.DrawImage(&bmp1, 0, 0);
gMem.DrawRectangle(&Pen(Color::Black), 0,0,40,40);
//一次性繪製到DC
Graphics g(hdc);
g.DrawImage(&bmpMem, 0, 0);
}
測試程式下載連結
參考書籍《精通GDI+》,很多示例,可以當做手冊查詢
原創,轉載請註明來自http://blog.csdn.net/wenzhou1219
相關文章
- 【Java集合】單列集合Collection常用方法詳解Java
- JAVA中StringBuffer類常用方法詳解Java
- Selenium用法詳解 -- Selenium3 常用方法
- Day33:String類及其常用方法詳解
- PyTorch常用引數初始化方法詳解PyTorch
- mysql常用函式詳解MySql函式
- Ftp - 常用的命令詳解FTP
- ES常用引數詳解
- SpringMVC--常用註解(詳解)SpringMVC
- Android AlterDialog 常用對話方塊使用方法詳解Android
- 經典:詳解IP地址盜用常用方法及防範(轉)
- super()方法詳解
- java方法詳解Java
- springmvc常用註解標籤詳解SpringMVC
- Git 常用命令詳解Git
- Flutter常用Widget詳解(三)Flutter
- Flutter常用Widget詳解(二)Flutter
- Flutter常用Widget詳解(一)Flutter
- npm 常用命令詳解NPM
- Java常用jar包用途詳解JavaJAR
- hive sql 常用語法詳解HiveSQL
- 常用Excel圖表型別詳解Excel型別
- Python語言進行程式碼換行常用的方法詳解!Python行程
- canvas arc()方法詳解Canvas
- canvas closePath()方法詳解Canvas
- toJSON()方法詳解JSON
- API模板方法詳解API
- linux常用命令詳解Linux
- Oracle GoldenGate常用引數詳解OracleGo
- java刷題時常用容器詳解Java
- 常用的 wget 引數詳解wget
- curl常用引數詳解及示例
- 常用網路命令及命令詳解
- SQLmap常用命令使用詳解SQL
- 詳解equals()方法和hashCode()方法
- 詳解Spring MVC 4常用的那些註解SpringMVC
- Pandas中resample方法詳解
- $AJAX方法詳解(轉載)