GDI+學習筆記之GDI+環境初始化 收藏
作者:朱金燦
來源:http://blog.csdn.net/clever101/

 


      盡管以前接觸過一下GDI+,但決心從現在開始系統學習GDI+,所用的教材為《精通GDI編程》。在VS 2010以下版本的VS 編譯器使用GDI+都需要對GDI+環境進行初始化操作(VS 2010中的MFC 10依賴GDI+,故不用初始化)。

VS 2003、VS 2005和VS 2008的GDI+環境初始化操作步驟一樣。


      在應用程序類添加一個保護權限的數據成員:

view plaincopy to clipboardprint?
ULONG_PTR m_gdiplusToken; 
ULONG_PTR m_gdiplusToken;

 


在應用程序類的實現文件包含gdi+的頭文件:

 


view plaincopy to clipboardprint?
#include <GdiPlus.h> 
#include <GdiPlus.h>


在工程附加庫加上:GdiPlus.lib

 


然后在應用程序類的InitInstance加上下面初始化代碼:

 


view plaincopy to clipboardprint?
BOOL C***App::InitInstance()  
{  
    Gdiplus::GdiplusStartupInput StartupInput;  
    GdiplusStartup(&m_gdiplusToken,&StartupInput,NULL);  

BOOL C***App::InitInstance()
{
 Gdiplus::GdiplusStartupInput StartupInput;
 GdiplusStartup(&m_gdiplusToken,&StartupInput,NULL);
}
 

 

上面代碼的作用是初始化GDI+資源。

 


  在應用程序類的InitInstance加上下面代碼:

 


view plaincopy to clipboardprint?
int C***App::ExitInstance()  
{  
    // TODO: 在此添加專用代碼和/或調用基類  
      
    Gdiplus::GdiplusShutdown(m_gdiplusToken);  
    return __super::ExitInstance();  

int C***App::ExitInstance()
{
 // TODO: 在此添加專用代碼和/或調用基類
   
 Gdiplus::GdiplusShutdown(m_gdiplusToken);
 return __super::ExitInstance();
}
 

 

上面代碼的作用是銷毀GDI+資源。


VC 6.0中使用GDI+庫,請參考這篇文章:在VC6.0中使用GDI+的兩種辦法

 


     現在測試一下我們初始化GDI+環境是否成功。我們使用GDI+的類接口在視圖客戶區繪制一個字符串,具體代碼如下:

 


view plaincopy to clipboardprint?
CDC *pDC = pView->GetDC();  
Gdiplus::Graphics graphics(pDC->m_hDC);  
Gdiplus::Pen pen(Gdiplus::Color(255,0,0,255));  
Gdiplus::SolidBrush brush(Gdiplus::Color(255,0,0,255));  
Gdiplus::FontFamily fontfm(L"宋體");  
Gdiplus::Font font(&fontfm,24,Gdiplus::FontStyleRegular,Gdiplus::UnitPixel);  
CRect rt;  
pView->GetClientRect(&rt);  
Gdiplus::PointF pointF(rt.Width()/2,rt.Height()/2);  
   graphics.DrawString(L"GDI+程序示意",-1,&font,pointF,&brush);  
   graphics.ReleaseHDC(pDC->m_hDC);  
   pView->ReleaseDC(pDC); 
 CDC *pDC = pView->GetDC();
 Gdiplus::Graphics graphics(pDC->m_hDC);
 Gdiplus::Pen pen(Gdiplus::Color(255,0,0,255));
 Gdiplus::SolidBrush brush(Gdiplus::Color(255,0,0,255));
 Gdiplus::FontFamily fontfm(L"宋體");
 Gdiplus::Font font(&fontfm,24,Gdiplus::FontStyleRegular,Gdiplus::UnitPixel);
 CRect rt;
 pView->GetClientRect(&rt);
 Gdiplus::PointF pointF(rt.Width()/2,rt.Height()/2);
    graphics.DrawString(L"GDI+程序示意",-1,&font,pointF,&brush);
    graphics.ReleaseHDC(pDC->m_hDC);
    pView->ReleaseDC(pDC);
 

 

 

 

效果圖如下:

 


 

 

 

 


使用GDI+一些注意事項:

 


1.在DLL中使用GDI+庫,只需要包含GdiPlus.h和GdiPlus.lib,初始化GDI+環境的工作只需要在主調用程序做,否則在DLL初始化代碼中初始化GDI+環境容易發生DLL重入的錯誤(以前我犯過這樣的錯誤)。

 


2.GDI+接口參數使用的是unicode字符集,因為調用任何GDI+類接口時其字符串參數都必須確保是unicode字符。在多字節字符集環境下開發常量字符串可以通過L宏轉換,變量多字節字符轉unicode字符可以使用Windows API函數MultiByteToWideChar或ATL的A2W宏。

 


3. GDI+的對象和GDI句柄一樣,同樣會占用資源,一次使用過多的GDI+的對象甚至會發生程序崩潰的現象。因此必須隨時將不必要的GDI+的對象占用的資源釋放掉,如上例的:graphics.ReleaseHDC(pDC->m_hDC)。

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/clever101/archive/2010/12/08/6063670.aspx
作者:朱金燦
來源:http://blog.csdn.net/clever101/

 


      我發現使用GDI+來制作畫圖工具的調色板極為方便(這個工作如果讓GDI來做不知要寫多少代碼)。下面我們學習一下GDI+的線性漸變畫刷:LinearGradientBrush類的用法,具體代碼如下:

 


      view plaincopy to clipboardprint?
    CDC *pDC = pView->GetDC();  
     // 定義一個畫圖對象  
    Gdiplus::Graphics graphics(pDC->m_hDC);  
      
     // 獲取視圖客戶區大小  
     CRect rt;  
     pView->GetClientRect(&rt);  
// 定義一個線性漸變畫刷,按紅黃藍綠的順序四種顏色漸變  
     LinearGradientBrush linGrBrush(Point(100,0),Point(100,rt.Height()/2),Color(255,255,0,0),Color(255,0,0,255));  
     Color colors[] = {  
         Color(255, 255, 0, 0),   // red  
         Color(255, 255, 255, 0), //yellow  
         Color(255, 0, 0, 255),   // blue  
         Color(255, 0, 255, 0)};  // green  
         REAL positions[] = {  
             0.0f,     
             0.33f,     
             0.66f,  
             1.0f};    
    linGrBrush.SetInterpolationColors(colors, positions,4);  
    // 填充指定區域矩形  
    graphics.FillRectangle(&linGrBrush,rt.Width()/2,0,80,rt.Height()/2);  
 CDC *pDC = pView->GetDC();
    // 定義一個畫圖對象
 Gdiplus::Graphics graphics(pDC->m_hDC);
    
  // 獲取視圖客戶區大小
  CRect rt;
  pView->GetClientRect(&rt);
// 定義一個線性漸變畫刷,按紅黃藍綠的順序四種顏色漸變
     LinearGradientBrush linGrBrush(Point(100,0),Point(100,rt.Height()/2),Color(255,255,0,0),Color(255,0,0,255));
  Color colors[] = {
   Color(255, 255, 0, 0),   // red
         Color(255, 255, 255, 0), //yellow
   Color(255, 0, 0, 255),   // blue
   Color(255, 0, 255, 0)};  // green
   REAL positions[] = {
    0.0f,  
    0.33f,  
    0.66f,
    1.0f}; 
 linGrBrush.SetInterpolationColors(colors, positions,4);
 // 填充指定區域矩形
 graphics.FillRectangle(&linGrBrush,rt.Width()/2,0,80,rt.Height()/2); 

 


     效果如下:

 


        

 


          這個線性漸變畫刷很簡單,就是按垂直方向(即y軸方向)漸變的。我感興趣的是畫刷的兩個參數Point(100,0),Point(100,rt.Height()/2),書上介紹的起點的顏色和終點顏色的位置和要填充的矩形之間的關系是怎樣的?我們看到上面的畫刷的起點和終點的高度和要填充的矩形的高度是一樣的,都是rt.Height()/2。我們把畫刷的高度縮小為原來的一般,看看有什么效果,即定義為:

 


       view plaincopy to clipboardprint?
LinearGradientBrush linGrBrush(Point(100,0),Point(100,rt.Height()/4),Color(255,255,0,0),Color(255,0,0,255)); 
LinearGradientBrush linGrBrush(Point(100,0),Point(100,rt.Height()/4),Color(255,255,0,0),Color(255,0,0,255));

效果圖如下:

 


 

 


     我們發現上圖等于連續用兩個畫刷填充這個矩形。假如填充的目標矩形的高度小于畫刷的高度,又會是怎樣的效果呢?代碼改為:

 


view plaincopy to clipboardprint?
LinearGradientBrush linGrBrush(Point(100,0),Point(100,rt.Height()/2),Color(255,255,0,0),Color(255,0,255,0));  
     Color colors[] = {  
         Color(255, 255, 0, 0),   // red  
         Color(255, 255, 255, 0), //yellow  
         Color(255, 0, 0, 255),   // blue  
         Color(255, 0, 255, 0)};  // green  
         REAL positions[] = {  
             0.0f,     
             0.33f,     
             0.66f,  
             1.0f};    
    linGrBrush.SetInterpolationColors(colors, positions,4);  
    // 填充指定區域矩形  
    graphics.FillRectangle(&linGrBrush,rt.Width()/2,0,80,rt.Height()/4); 
LinearGradientBrush linGrBrush(Point(100,0),Point(100,rt.Height()/2),Color(255,255,0,0),Color(255,0,255,0));
  Color colors[] = {
   Color(255, 255, 0, 0),   // red
         Color(255, 255, 255, 0), //yellow
   Color(255, 0, 0, 255),   // blue
   Color(255, 0, 255, 0)};  // green
   REAL positions[] = {
    0.0f,  
    0.33f,  
    0.66f,
    1.0f}; 
 linGrBrush.SetInterpolationColors(colors, positions,4);
 // 填充指定區域矩形
 graphics.FillRectangle(&linGrBrush,rt.Width()/2,0,80,rt.Height()/4);
 

 


效果圖如下:

 


 

 

 

    我們看到這時矩形區域的填充只使用了畫刷的一部分。這時或許我們可以得出一個簡單的結論:用畫刷填充多邊形區域,有點類似于鋪地磚,地磚好比畫刷,空地好比要填充的區域區域。

 


思考題:

 


      線性漸變畫刷的起點和終點的坐標值和要填充的矩形之間是什么關系?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/clever101/archive/2010/12/08/6063697.aspx