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