国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Windows+GDI和GDI+編程實(shí)例剖析

1.基本概念

GDI
Windows中定義為Graphics Device Interface,即圖形設(shè)備接口,是Windows API(Application Programming Interface)的一個(gè)重要組成部分。它是Windows圖形顯示程序與實(shí)際物理設(shè)備之間的橋梁,GDI使得用戶無需關(guān)心具體設(shè)備的細(xì)節(jié),而只需在一 個(gè)虛擬的環(huán)境(即邏輯設(shè)備)中進(jìn)行操作。它的橋梁作用體現(xiàn)在:

(1)
用戶通過調(diào)用GDI函數(shù)將邏輯空間的操作轉(zhuǎn)化為具體針對設(shè)備驅(qū)動(dòng)程序的調(diào)用。

為實(shí)現(xiàn)圖形設(shè)備無關(guān)性,Windows的繪圖操作在一個(gè)設(shè)備描述表上進(jìn)行。用戶擁有自己的"邏輯坐標(biāo)"系統(tǒng),它獨(dú)立于實(shí)際的物理設(shè)備,與"設(shè)備坐標(biāo)"相對應(yīng)。開發(fā)Windows應(yīng)用程序時(shí),程序員關(guān)心的是邏輯坐標(biāo),我們在邏輯坐標(biāo)系上繪圖,利用GDI將邏輯窗口映射到物理設(shè)備上。

(2)GDI
能檢測具體設(shè)備的能力,并依據(jù)具體的設(shè)備以最優(yōu)方式驅(qū)動(dòng)這些設(shè)備,完成真實(shí)的顯示。

GDI
函數(shù)大致可分類為:設(shè)備上下文函數(shù)(GetDC、CreateDC、DeleteDC)、 畫線函數(shù)(LineTo、PolylineArc)、填充畫圖函數(shù)(Ellipse、FillRectPie)、畫圖屬性函數(shù)( SetBkColor、SetBkMode、SetTextColor)、文本、字體函數(shù)(TextOut、GetFontData)、位圖函數(shù)( SetPixel、BitBlt、StretchBlt)、坐標(biāo)函數(shù)(DPtoLP、LPtoDP、ScreenToClient、 ClientToScreen)、映射函數(shù)(SetMapModeSetWindowExtEx、SetViewportExtEx)、元文件函數(shù) (PlayMetaFile、SetWinMetaFileBits)、區(qū)域函數(shù)(FillRgn、FrameRgn、InvertRgn)、路徑函 數(shù)(BeginPath、EndPath、StrokeAndFillPath)、裁剪函數(shù)(SelectClipRgn、 SelectClipPath)等。

GDI
雖然使程序員得到了一定程度的解脫,但是其編程方式仍很麻煩。譬如,顯示一張位圖,程序員需要進(jìn)行"裝入位圖讀取位圖文件頭信息啟用設(shè)備場景調(diào)色板變換"等一連串操作。而有了GDI+,這些問題便迎刃而解了。

顧名思義,GDI+GDI的增強(qiáng)版。它是微軟在Windows 2000以后操作系統(tǒng)中提供的新接口,其通過一套部署為托管代碼的類來展現(xiàn),這套類被稱為GDI+"托管類接口"。GDI+主要提供了以下三類服務(wù):

(1)
二維矢量圖形:GDI+提供了存儲圖形基元自身信息的類(或結(jié)構(gòu)體)、存儲圖形基元繪制方式信息的類以及實(shí)際進(jìn)行繪制的類;

(2)
圖像處理:大多數(shù)圖片都難以劃定為直線和曲線的集合,無法使用二維矢量圖形方式進(jìn)行處理。因此,GDI+為我們提供了Bitmap、Image等類,它們可用于顯示、操作和保存BMP、JPG、GIF等圖像格式。

(3)
文字顯示:GDI+支持使用各種字體、字號和樣式來顯示文本。

GDI
接口是基于函數(shù)的,而GDI+是基于C++類的對象化的應(yīng)用程序編程接口,因此使用起來比GDI要方便。

2.
例程簡述

單擊此處下載本文例程源代碼。

本文后續(xù)的講解都基于這樣的一個(gè)例子工程(例程的開發(fā)環(huán)境為Visual C++6.0,操作系統(tǒng)為Windows XP),它是一個(gè)基于對話框的MFC應(yīng)用程序,包括2個(gè)父菜單:

(1) GDI

GDI
父菜單下包括一個(gè)子菜單:

ID
IDM_GDI_DRAW_LINE caption:畫線

單擊事件:在窗口繪制正旋曲線

(2) GDI+

DIB
位圖父菜單下包括兩個(gè)子菜單:

a. ID
IDM_GDIP_DRAW_LINE caption:畫線

單擊事件:在窗口繪制正旋曲線

b. caption
:新增功能,其下又包括下列子菜單:

(ⅰ)ID
IDM_Gradient_Brush caption:漸變畫刷

單擊事件:在窗口演示GDI+的漸變畫刷功能

(ⅱ)ID
IDM_Cardinal_Spline caption:基數(shù)樣條

單擊事件:在窗口演示GDI+的基數(shù)樣條函數(shù)功能

(ⅲ)ID
IDM_Transformation_Matrix caption:變形和矩陣對象

單擊事件:在窗口演示GDI+的變形和矩陣對象功能

(ⅳ)ID
IDM_Scalable_Region caption:可伸縮區(qū)域

單擊事件:在窗口演示GDI+的可伸縮區(qū)域功能

(ⅴ)ID
IDM_IMAGE caption:圖像

單擊事件:在窗口演示GDI+的多種圖像格式支持功能

(ⅵ)ID
IDM_Alpha_Blend captionAlpha混合

單擊事件:在窗口演示GDI+Alpha混合功能

(ⅶ)ID
IDM_TEXT caption:文本

單擊事件:在窗口演示GDI+的強(qiáng)大文本輸出能力

后續(xù)篇章將集中在對上述菜單單擊事件消息處理函數(shù)的講解,下面的代碼是整個(gè)對話框類CGdiexampleDlg的消息映射:

BEGIN_MESSAGE_MAP(CGdiexampleDlg, CDialog)
//{{AFX_MSG_MAP(CGdiexampleDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_COMMAND(IDM_GDI_DRAW_LINE, OnGdiDrawLine)
ON_COMMAND(IDM_GDIP_DRAW_LINE, OnGdipDrawLine)
ON_COMMAND(IDM_Gradient_Brush, OnGradientBrush)
ON_COMMAND(IDM_Cardinal_Spline, OnCardinalSpline)
ON_COMMAND(IDM_Transformation_Matrix, OnTransformationMatrix)
ON_COMMAND(IDM_Scalable_Region, OnScalableRegion)
ON_COMMAND(IDM_IMAGE, OnImage)
ON_COMMAND(IDM_Alpha_Blend, OnAlphaBlend)
ON_COMMAND(IDM_TEXT, OnText)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


3.GDI
編程

頭文件:#include  "math.h "

#define PI 3.1415926


"GDI"
菜單下的"畫線"子菜單單擊事件消息處理函數(shù)的代碼如下:

void CGdiexampleDlg::OnGdiDrawLine()
{
// TODO: Add your command handler code here
CClientDC dc(this);
//
邏輯坐標(biāo)與設(shè)備坐標(biāo)變換
CRect rect;
GetClientRect(&rect);
dc.SetMapMode(MM_ANISOTROPIC);
dc.SetWindowOrg(0, 0);
dc.SetWindowExt(rect.right, rect.bottom);
dc.SetViewportOrg(0, rect.bottom / 2);
dc.SetViewportExt(rect.right, - rect.bottom);
//
創(chuàng)建繪制正旋曲線的pen并將其選入設(shè)備上下文
CPen pen(PS_SOLID, 1, RGB(255, 0, 0));
HGDIOBJ oldObject = dc.SelectObject(pen.GetSafeHandle());
//
繪制正旋曲線
dc.MoveTo(0, 0);
for (int i = 0; i < rect.right; i++)
{
dc.LineTo(i, 100 *sin(2 *(i / (rect.right / 5.0)) *PI));
}
//
創(chuàng)建繪制x軸的pen并將其選入設(shè)備上下文
CPen penx(PS_SOLID, 1, RGB(0, 0, 255));
dc.SelectObject(penx.GetSafeHandle());
//
繪制X
dc.MoveTo(0, 0);
dc.LineTo(rect.right, 0);
//
恢復(fù)原先的pen
dc.SelectObject(oldObject);
}


單擊這個(gè)按鈕,會出現(xiàn)如圖1所示的效果,我們來對此進(jìn)行解讀。

 


1 繪制正旋曲線


前文提到,GDI編程需進(jìn)行設(shè)備坐標(biāo)和邏輯坐標(biāo)的轉(zhuǎn)化。而屏幕上的設(shè)備坐標(biāo)通常會按客戶坐標(biāo)給出,客戶坐標(biāo)依賴于窗口的客戶區(qū)域,其起始位置位于客戶區(qū)域的左上角。為示區(qū)別,圖2給出了設(shè)備坐標(biāo)和用戶邏輯坐標(biāo)的示例。


2 設(shè)備坐標(biāo)與邏輯坐標(biāo)


設(shè)備坐標(biāo)與邏輯坐標(biāo)的轉(zhuǎn)換關(guān)系如下:


公式中的<Xvorg, Yvorg>是設(shè)備空間中視口的原點(diǎn),而< Xworg, Yworg >是邏輯空間中窗口的原點(diǎn)。 Xwext/XvextYwext/Yvext分別是窗口與視口水平和垂直范圍的比例。

因此,經(jīng)過程序中的dc.SetWindowOrg (0,0) dc.SetViewportOrg (0,rect.bottom/2)語句我們設(shè)置了視口和窗口的原點(diǎn);而經(jīng)過程序中的dc.SetWindowExt (rect.right,rect.bottom) dc.SetViewportExt (rect.right,-rect.bottom) 語句我們設(shè)置了視口和窗口的范圍。由于視口和窗口的縱坐標(biāo)方向相反,設(shè)置視口的垂直范圍為負(fù)值。這樣我們得到了一個(gè)邏輯坐標(biāo)原點(diǎn)為客戶區(qū)水平方向最左邊和垂直方向居中的坐標(biāo)系,我們在這個(gè)坐標(biāo)系上直接繪制正旋曲線,不需要再理睬Windows對話框客戶區(qū)坐標(biāo)了。

void CGdiexampleDlg::OnGdiDrawLine()
函數(shù)中未指定邏輯設(shè)備和物理設(shè)備的映射模式,則為缺省的MM_TEXT。在這種模式下,一個(gè)邏輯單位對應(yīng)于一個(gè)像素點(diǎn)。映射模式是GDI中的一個(gè)重要概念,其它的映射模式還有MM_LOENGLlSH、MM_HIENGLISH、 MM_LOMETRICMM_HIMETRIC等。我們可以通過如下語句指定映射模式為MM_TEXT

dc.SetMapMode(MM_TEXT);


值得一提的是,從上述代碼可以看出:在GDI編程中,幾乎所有的操作都圍繞設(shè)備上下文dc展開。的確,這正是GDI編程的特點(diǎn)!設(shè)備上下文是Windows 使用的一種結(jié)構(gòu),所有GDI操作前都需取得特定設(shè)備的上下文,函數(shù)中的CClientDC dc (this) 語句完成這一功能。

歸納可得,利用GDI進(jìn)行圖形、圖像處理的一般操作步驟為:
1.
取得指定窗口的DC;
2.
確定使用的坐標(biāo)系及映射方式;
3.
進(jìn)行圖形、圖像或文字處理;
4.
釋放所使用的DC。
5. GDI+
編程

 


"GDI+"
菜單下的"畫線"子菜單單擊事件消息處理函數(shù)的代碼如下:

void CGdiexampleDlg::OnGdipDrawLine()
{
// TODO: Add your command handler code here
CClientDC dc(this);
//
邏輯坐標(biāo)與設(shè)備坐標(biāo)變換
CRect rect;
GetClientRect(&rect);
dc.SetMapMode(MM_ANISOTROPIC);
dc.SetWindowOrg(0, 0);
dc.SetWindowExt(rect.right, rect.bottom);
dc.SetViewportOrg(0, rect.bottom / 2);
dc.SetViewportExt(rect.right, - rect.bottom);

//
創(chuàng)建Graphics對象
Graphics graphics(dc);
//
創(chuàng)建pen
Pen myPen(Color::Red);
myPen.SetWidth(1);
//
畫正旋曲線
for (int i = 0; i < rect.right; i++)
{
graphics.DrawLine(&myPen, i, 100 *sin(2 *(i / (rect.right / 5.0)) *PI), i+1, 100 *sin(2 *((i + 1)/(rect.right / 5.0)) *PI));
}
//
X
myPen.SetColor(Color::Blue);
graphics.DrawLine(&myPen, 0, 0, rect.right, 0);
}


由于我們使用的是Visual C++6.0而非VS.Net,我們需要下載微軟的GDIPLUS支持包。在微軟官方網(wǎng)站下載時(shí)需認(rèn)證Windows為正版,我們可從這個(gè)地址下載: http://www.codeguru.com/code/legacy/gdi/GDIPlus.zip。一個(gè)完整的GDI+支持包至少包括如下文 件:

(1)
頭文件:gdiplus.h

(2)
動(dòng)態(tài)鏈接庫的.lib文件:gdiplus.lib

(3)
動(dòng)態(tài)鏈接庫的.dll文件:gdiplus.dll

少了(1)、(2)程序不能編譯,少了(3)程序能以共享DLL的方式編譯但是不能運(yùn)行,運(yùn)行時(shí)找不到.dll文件。


為使得Visual C++6.0支持GDI+,我們需要在使用GDI+對象的文件的開頭添加如下代碼:

#define UNICODE
#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#endif
#include "c:\gdiplus\includes\gdiplus.h"
using namespace Gdiplus;
#pragma comment(lib, "c:\\gdiplus\\lib\\gdiplus.lib")


Visual C++中使用GDI+必須先進(jìn)行GDI+的初始化,我們在CWinApp派生類的InitInstance函數(shù)中進(jìn)行此項(xiàng)工作是最好的:

/////////////////////////////////////////////////////////////////////////////
// CGdiexampleApp initialization

BOOL CGdiexampleApp::InitInstance()
{
AfxEnableControlContainer();

// Standard initialization

#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif

//
初始化gdiplus的環(huán)境
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
//
初始化GDI+.
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);


CGdiexampleDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK){}
else if (nResponse == IDCANCEL){}

//
關(guān)閉gdiplus的環(huán)境
GdiplusShutdown(gdiplusToken);

return FALSE;
}


單擊"GDI+"菜單下的"畫線"子菜單,也會出現(xiàn)如圖1所示的效果。觀察void CGdiexampleDlg::OnGdipDrawLine() 函數(shù),我們發(fā)現(xiàn)用GDI+進(jìn)行圖形、圖像操作的步驟為:

(1)
創(chuàng)建 Graphics 對象:Graphics 對象表示GDI+繪圖表面,是用于創(chuàng)建圖形圖像的對象;

(2)
使用 Graphics 對象繪制線條和形狀、呈現(xiàn)文本或顯示與操作圖像。
Graphics
對象是GDI+的核心,GDI中設(shè)備上下文dcGraphics 對象的作用相似,但在GDI中使用的是基于句柄的編程模式,而GDI+中使用的則是基于對象的編程模式。Graphics封裝了GDI+ 繪圖面,而且此類無法被繼承,它的所有成員函數(shù)都不是虛函數(shù)。

下面,我們來逐個(gè)用實(shí)際代碼實(shí)現(xiàn)GDI+的新增功能,這些新增功能包括:漸變的畫刷(Gradient Brushes)、基數(shù)樣條函數(shù)(Cardinal Splines)、持久的路徑對象(Persistent Path Objects)、變形和矩陣對象(Transformations &Matrix Object)、可伸縮區(qū)域(Scalable Regions)Alpha混合(Alpha Blending)和豐富的圖像格式支持等。

漸變的畫刷

GDI+
提供了用于填充圖形、路徑和區(qū)域的線性漸變畫刷和路徑漸變畫刷。

線性漸變畫刷使用漸變顏色來填充圖形。

當(dāng)用路徑漸變畫刷填充圖形時(shí),可指定從圖形的一部分移至另一部分時(shí)畫刷顏色的變化方式。例如,我們可以只指定圖形的中心顏色和邊緣顏色,當(dāng)畫刷從圖形中間向外邊緣移動(dòng)時(shí),畫刷會逐漸從中心顏色變化到邊緣顏色。

void CGdiexampleDlg::OnGradientBrush()
{
// TODO: Add your command handler code here
CClientDC dc(this);
CRect rect;
GetClientRect(&rect);
//
創(chuàng)建Graphics對象
Graphics graphics(dc);
//
創(chuàng)建漸變畫刷
LinearGradientBrush lgb(Point(0, 0), Point(rect.right, rect.bottom), Color::Blue, Color::Green);
//
填充
graphics.FillRectangle(&lgb, 0, 0, rect.right, rect.bottom);
}


本程序使用線性漸變畫刷,當(dāng)畫刷從客戶區(qū)左上角移向客戶區(qū)右下角的過程中,顏色逐漸由藍(lán)色轉(zhuǎn)變?yōu)榫G色。


3 GDI+漸變畫刷


基數(shù)樣條函數(shù)

GDI+
支持基數(shù)樣條,基數(shù)樣條指的是一連串單獨(dú)的曲線,這些曲線連接起來形成一條較大的曲線。樣條由點(diǎn)(Point結(jié)構(gòu)體)的數(shù)組指定,并通過該數(shù)組中的每一個(gè)點(diǎn)。基數(shù)樣條平滑地穿過數(shù)組中的每一個(gè)點(diǎn)(不出現(xiàn)尖角),因此比用直線連接創(chuàng)建的路徑精確。

void CGdiexampleDlg::OnCardinalSpline()
{
// TODO: Add your command handler code here
CClientDC dc(this);
//
創(chuàng)建Graphics對象
Graphics graphics(dc);
Point points[] =

{
Point(0, 0), Point(100, 200), Point(200, 0), Point(300, 200), Point(400, 0)
};
//
直接畫線
for (int i = 0; i < 4; i++)
{
graphics.DrawLine(&Pen(Color::Blue, 3), points[i], points[i + 1]);
}
//
利用基數(shù)樣條畫線
graphics.DrawCurve(&Pen(Color::Red, 3), points, 5);
}


4演示了直接連線和經(jīng)過基數(shù)樣條平滑擬合后的線條的對比,后者的曲線(Curve)沒有尖角。這個(gè)工作我們在中學(xué)的數(shù)學(xué)課上把離散的點(diǎn)連接成曲線時(shí)做過。


4 GDI+基數(shù)樣條

持久的路徑對象

GDI中,路徑隸屬于一個(gè)設(shè)備上下文,一旦設(shè)備環(huán)境指針超過它的生存期,路徑也會被刪除。利用GDI+,可以創(chuàng)建并維護(hù)與Graphics對象分開的GraphicsPath 對象,它不依賴于Graphics對象的生存期。

變形和矩陣對象

GDI+
提供了Matrix對象,它是一種可以使變形(旋轉(zhuǎn)、平移、縮放等) 簡易靈活的強(qiáng)大工具,Matrix對象需與要被變形的對象聯(lián)合使用。對于GraphicsPath類,我們可以使用其成員函數(shù)Transform接收Matrix參數(shù)用于變形。

void CGdiexampleDlg::OnTransformationMatrix()
{
// TODO: Add your command handler code here
CClientDC dc(this);
//
創(chuàng)建Graphics對象
Graphics graphics(dc);
GraphicsPath path;
path.AddRectangle(Rect(250, 20, 70, 70));
graphics.DrawPath(&Pen(Color::Black, 1), &path); //
在應(yīng)用變形矩陣之前繪制矩形
//
路徑變形
Matrix matrix1, matrix2;

matrix1.Rotate(45.0f); //
旋轉(zhuǎn)順時(shí)針45
path.Transform(&matrix1); //
應(yīng)用變形
graphics.DrawPath(&Pen(Color::Red, 3), &path);

matrix2.Scale(1.0f, 0.5f); //
轉(zhuǎn)化成為平行四邊形法則
path.Transform(&matrix2); //
應(yīng)用變形
graphics.DrawPath(&Pen(Color::Blue, 3), &path);
}


5演示了正方形經(jīng)過旋轉(zhuǎn)和拉伸之后的效果:黑色的為原始圖形,紅色的為旋轉(zhuǎn)45度之后的圖形,藍(lán)色的為經(jīng)過拉伸為平行四邊形后的圖形。


5 GDI+變形和矩陣對象


可伸縮區(qū)域

GDI+
通過對區(qū)域(Region)的支持極大地?cái)U(kuò)展了GDI。在GDI 中,區(qū)域存儲在設(shè)備坐標(biāo)中,可應(yīng)用于區(qū)域的唯一變形是平移。但是在GDI +中,區(qū)域存儲在全局坐標(biāo)(世界坐標(biāo))中,可對區(qū)域利用變形矩陣進(jìn)行變形(旋轉(zhuǎn)、平移、縮放等)。

void CGdiexampleDlg::OnScalableRegion()
{
// TODO: Add your command handler code here
CClientDC dc(this);
//
創(chuàng)建Graphics對象
Graphics graphics(dc);
//
創(chuàng)建GraphicsPath
GraphicsPath path;
path.AddLine(100, 100, 150, 150);
path.AddLine(50, 150, 150, 150);
path.AddLine(50, 150, 100, 100);
//
創(chuàng)建Region
Region region(&path);
//
填充區(qū)域
graphics.FillRegion(&SolidBrush(Color::Blue), &region);
//
區(qū)域變形
Matrix matrix;
matrix.Rotate(10.0f); //
旋轉(zhuǎn)順時(shí)針20
matrix.Scale(1.0f, 0.3f); //
拉伸
region.Transform(&matrix); //
應(yīng)用變形
//
填充變形后的區(qū)域
graphics.FillRegion(&SolidBrush(Color::Green), &region);
}


上述程序中以藍(lán)色填充一個(gè)三角形區(qū)域,接著將此區(qū)域旋轉(zhuǎn)和拉伸,再次顯示,其效果如圖6


6 GDI+區(qū)域變形

豐富的圖像格式支持

GDI +
提供了Image、Bitmap Metafile 類,方便用戶進(jìn)行圖像格式的加載、操作和保存。GDI+支持的圖像格式有BMPGIF、JPEG、EXIFPNG、TIFFICON、WMF、EMF等,幾乎涵蓋了所有的常用圖像格式。

void CGdiexampleDlg::OnImage()
{
// TODO: Add your command handler code here
CClientDC dc(this);
//
創(chuàng)建Graphics對象
Graphics graphics(dc);
Image image(L "d:\\1.jpg");
//
在矩形區(qū)域內(nèi)顯示jpg圖像
Point destPoints1[3] =
{
Point(10, 10), Point(220, 10), Point(10, 290)
};
graphics.DrawImage(&image, destPoints1, 3);
//
在平行四邊形區(qū)域內(nèi)顯示jpg圖像
Point destPoints2[3] =
{
Point(230, 10), Point(440, 10), Point(270, 290)
};
graphics.DrawImage(&image, destPoints2, 3);
}


上述程序?qū)?span lang="EN-US">D盤根目錄下文件名為"1.jpg"jpg圖像以矩陣和平行四邊形兩種方式顯示,效果如圖7。


7 GDI+多種圖像格式支持


由此我們可以看出,GDI+在圖像顯示和操作方面的確比GDI簡單許多。回憶我們在《Visual C++DDBDIB位圖編程全攻略》一文中所介紹的用GDI顯示位圖的方式,其與GDI+圖像處理的難易程度真是有天壤之別。

Alpha
混合

Alpha
允許將兩個(gè)物體混合起來顯示,在3D氣氛和場景渲染等方面有廣泛應(yīng)用。它能"霧化"圖像,使得一個(gè)圖像著色在另一個(gè)半透明的圖像上,呈現(xiàn)一種朦朧美。我們知道,一個(gè)像素可用 R,G,B三個(gè)維度來表示,我們可以再加上第4個(gè)即:Alpha維度(channel),表征透明程度。

void CGdiexampleDlg::OnAlphaBlend()
{
// TODO: Add your command handler code here
CClientDC dc(this);
//
創(chuàng)建Graphics對象
Graphics graphics(dc);
//
創(chuàng)建ColorMatrix
ColorMatrix ClrMatrix =
{
1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.5f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f
};
//
ColorMatrix賦給ImageAttributes
ImageAttributes ImgAttr;
ImgAttr.SetColorMatrix(&ClrMatrix, ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);
//
在矩形區(qū)域內(nèi)顯示jpg圖像
Image img1(L "d:\\1.jpg");
Point destPoints1[3] =
{
Point(10, 10), Point(220, 10), Point(10, 290)
};
graphics.DrawImage(&img1, destPoints1, 3);
//Alpha
混合
Image img2(L "d:\\2.jpg");
int width, height;
width = img2.GetWidth();
height = img2.GetHeight();
graphics.DrawImage(&img2, RectF(10, 10, 210, 280), 0, 0, width, height,UnitPixel, &ImgAttr);
//
在平行四邊形區(qū)域內(nèi)顯示jpg圖像
Point destPoints2[3] =
{
Point(230, 10), Point(440, 10), Point(270, 290)
};
graphics.DrawImage(&img1, destPoints2, 3);
//Alpha
混合
graphics.DrawImage(&img2, destPoints2, 3, 0, 0, width, height, UnitPixel,&ImgAttr);
}


上述程序中將D盤根目錄下文件名為"1.jpg"的圖像以矩陣和平行四邊形兩種方式顯示,然后將文件名為為"2.jpg"的圖像與之進(jìn)行混合,其效果如圖8


8 GDI+ Alpha混合


為了能進(jìn)行Alpha混合,我們需要使用ImageAttributes類和ColorMatrix矩陣,ImageAttributes可以進(jìn)行顏色、灰度等調(diào)整從而達(dá)到控制圖像著色方式的目的。ColorMatrixImageAttributes類大多數(shù)函數(shù)的參數(shù),它包含了Alpha Red、Green、Blue維度的值,以及另一維w,順序?yàn)?span lang="EN-US">RGBaw

CGdiexampleDlg:: OnAlphaBlend()
函數(shù)中ColorMatrix的實(shí)例ClrMatrix中元素(4,4)的值為0.5,表示Alpha度的值為0.5(即半 透明)。在ColorMatrix中,元素(5,5)的值恒定為1.0。我們把ClrMatrix的元素(0,0)修改為0.0,就是使得圖像2.jpg的 紅色維度全不顯示,再看效果,為圖9。列位讀者,我們以前在豪杰超級解霸中調(diào)整R,GB值從而控制圖像輸出顏色的時(shí)候,調(diào)的就是這個(gè)東東!圖9的效果很 像破舊彩色電視機(jī),紅色電子槍""了。剛大學(xué)畢業(yè)時(shí),俺那個(gè)叫窮啊,就買了這么個(gè)電視機(jī),還看得很爽,真是往事不堪回首!


9 GDI+中的ColorMatrix


強(qiáng)大的文字輸出

GDI+
擁有極其強(qiáng)大的文字輸出處理能力,輸出文字的顏色、字體、填充方式都可以直接作為GraphicsDrawString成員函數(shù)的參數(shù)進(jìn)行設(shè)置,其功能遠(yuǎn)勝過GDI設(shè)備上下文的TextOut函數(shù)。

void CGdiexampleDlg::OnText()
{
// TODO: Add your command handler code here
CClientDC dc(this);
//
創(chuàng)建Graphics對象
Graphics graphics(dc);
//
創(chuàng)建20"楷體"字體
FontFamily fontFamily1(L"
華文行楷"); // 定義"楷體"字樣
Font font1(&fontFamily1, 20, FontStyleRegular, UnitPoint);
//
定義輸出UNICODE字符串
WCHAR string[256];
wcscpy(string, L"
天極網(wǎng)的讀者朋友,您好!");
//
以藍(lán)色畫刷和20"楷體"顯示字符串
graphics.DrawString(string, (INT)wcslen(string), &font1, PointF(30, 10),&SolidBrush(Color::Blue));
//
定義字符串顯示畫刷
LinearGradientBrush linGrBrush(Point(30, 50), Point(100, 50), Color(255, 255,0, 0), Color(255, 0, 0, 255));
//
以線性漸變畫刷和創(chuàng)建的20"楷體"顯示字符串
graphics.DrawString(string, (INT)wcslen(string), &font1, PointF(30, 50),&linGrBrush);
//
創(chuàng)建20"華文行楷"字體
FontFamily fontFamily2(L"
華文行楷"); // 定義"楷體"字樣
Font font2(&fontFamily2, 20, FontStyleRegular, UnitPoint);
//
以線性漸變畫刷和20"華文行楷"顯示字符串
graphics.DrawString(string, (INT)wcslen(string), &font2, PointF(30, 90),&linGrBrush);
//
以圖像創(chuàng)建畫刷
Image image(L"d:\\3.jpg");
TextureBrush tBrush(&image);
//
以圖像畫刷和20"華文行楷"顯示字符串
graphics.DrawString(string, (INT)wcslen(string), &font2, PointF(30, 130),&tBrush);
//
創(chuàng)建25"華文中宋"字體
FontFamily fontFamily3(L"
華文中宋"); // 定義"楷體"字樣
Font font3(&fontFamily2, 25, FontStyleRegular, UnitPoint);
//
以圖像畫刷和20"華文行楷"顯示字符串
graphics.DrawString(string, (INT)wcslen(string), &font3, PointF(30, 170),&tBrush);
}


上述代碼的執(zhí)行效果如圖10所示,字體、顏色和填充都很豐富!


10 GDI+文本輸出


5.GDI
GDI+的比較

GDI+
相對GDI而言主要在編程方式上發(fā)生了巨大的改變。

GDI
的核心是設(shè)備上下文,GDI函數(shù)都依賴于設(shè)備上下文句柄,其編程方式是基于句柄的;GDI+無需時(shí)刻依賴于句柄或設(shè)備上下文,用戶只需創(chuàng)建一個(gè)Graphics 對象,就可以用面向?qū)ο蟮姆绞秸{(diào)用其成員函數(shù)進(jìn)行圖形操作,編程方式是基于對象的。

GDI
在使用設(shè)備上下文繪制線條之前,必須先調(diào)用SelectObject 以使鋼筆對象和設(shè)備上下文關(guān)聯(lián)。其后,在設(shè)備上下文中繪制的所有線條均使用該鋼筆,直到選擇另一支不同的鋼筆為止。CGdiexampleDlg:: OnGdiDrawLine函數(shù)中的下列語句完成的就是這個(gè)功能:

//創(chuàng)建繪制正旋曲線的pen并將其選入設(shè)備上下文
CPen pen(PS_SOLID,1,RGB(255,0,0));
HGDIOBJ oldObject = dc.SelectObject(pen.GetSafeHandle());

//
創(chuàng)建繪制x軸的pen并將其選入設(shè)備上下文
CPen penx(PS_SOLID,1,RGB(0,0,255));
dc.SelectObject(penx.GetSafeHandle());

//
恢復(fù)原先的pen
dc.SelectObject(oldObject);


但是,在GDI+中,只需將Pen對象直接作為參數(shù)傳遞給Graphics類的DrawLine等方法即可,而不必使Pen對象與Graphics對象關(guān)聯(lián),例如CGdiexampleDlg::OnGdipDrawLine函數(shù)中的下列語句:

Pen myPen(Color::Red);
myPen.SetWidth(1);

graphics.DrawLine(&myPen,i,100*sin(2*(i/(rect.right/5.0))*PI),
i+1,100*sin(2*((i+1)/(rect.right/5.0))*PI));

graphics.DrawLine(&myPen,0,0,rect.right,0);


GDI
中有當(dāng)前位置的概念,所以在使用GDI繪制線條前應(yīng)該先使用MoveTo移動(dòng)當(dāng)前位置,再使用LineTo畫線,例如:

//繪制正旋曲線
dc.MoveTo(0,0) ;
for(int i=0;i<rect.right;i++)
{
dc.LineTo(i,100*sin(2*(i/(rect.right/5.0))*PI));
}


GDI+中則沒有當(dāng)前位置的概念,畫線函數(shù)中可以直接指定起點(diǎn)和終點(diǎn),例如:

graphics.DrawLine(&myPen,0,0,rect.right,0);


6.
結(jié)論

鑒于GDI+良好的易用性和其具有的強(qiáng)大功能,我們建議盡快拋棄GDI編程方式,因?yàn)槲覀儧]有必要將時(shí)間浪費(fèi)在無意義的重復(fù)代碼的設(shè)計(jì)上。GDI+ GDI的增強(qiáng),某種意義上類似于MFCWindows API的整理和封裝。作為一種良好的"生產(chǎn)工具",它必將大大地促進(jìn)開發(fā)時(shí)的"生產(chǎn)力"。

 

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Windows GDI和GDI+編程實(shí)例剖析 (8)
文本和字體
GDI 編程小結(jié)
Windows GDI與GDI+
在窗口中繪圖
Metafiles
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服