精华内容
下载资源
问答
  • 初学C++,GDI入门基础

    2009-10-09 15:38:28
    GDI入门基础,适合c++初学者,这是我老师的一个课件,希望对新人有所帮助
  • WindowsAPI-GDI入门基础知识详解1CC++WindowsAPI-GDI入门基础知识详解1CC++
  • Windows API-GDI入门基础知识详解
  • 引言:鉴于网上关于GDI+的教程都是.Net的,基本上没有VB6.0的,而这方面又很多人有需要,所以我就写一个Visual Basic 6 GDI+ 入门教程。 目标人群:所有能够较熟练使用VB的,对GDI+感兴趣或有GDI+编程需要的人。 1....

    引言:鉴于网上关于GDI+的教程都是.Net的,基本上没有VB6.0的,而这方面又很多人有需要,所以我就写一个Visual Basic 6 GDI+ 入门教程。
    目标人群:所有能够较熟练使用VB的,对GDI+感兴趣或有GDI+编程需要的人。

    1.What’s GDI+

    官方解释:GDI+是Windows XP中的一个子系统,它主要负责在显示屏幕和打印设备输出有关信息,它是一组通过C++类实现的应用程序编程接口。顾名思义,GDI+是以前版本GDI的继承者,出于兼容性考虑,Windows XP仍然支持以前版本的GDI,但是在开发新应用程序的时候,开发人员为了满足图形输出需要应该使用GDI+,因为GDI+对以前的Windows版本中GDI进行了优化,并添加了许多新的功能。
    作为图形设备接口的GDI+使得应用程序开发人员在输出屏幕和打印机信息的时候无需考虑具体显示设备的细节,他们只需调用GDI+库输出的类的一些方法即可完成图形操作,真正的绘图工作由这些方法交给特定的设备驱动程序来完成,GDI+使得图形硬件和应用程序相互隔离,从而使开发人员编写设备无关的应用程序变得非常容易。

    我的解释:GDI+其实就是一个绘图模块,用于在屏幕上输出各种需要的内容。

    2.GDI+ DLL

    GDI+的Dll在Windows XP+中默认存在,如果Windows XP以下系统需要使用GDI+,那么需要从微软网站上下载安装包。

    3.使用GDI+

    GDI+在.net Framework中默认集成,只要添加它的命名空间(System.Drawing.Drawing2D)就能够使用了;而GDI+在其它上面就没有那么容易了,例如VB6就需要添加GDI+的API。对于初学者,写一堆API可能比学GDI+用时还要长,不过我整理好了API到了一个模块,使用时候呢 只要在VB里面加载一下就可以啦!

    展开全文
  • GDI是Graphics Device Interface的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。  在Windows操作系统下,绝大多数具备图形界面的应用程序都离不开...
    GDI是Graphics Device Interface的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。

      在Windows操作系统下,绝大多数具备图形界面的应用程序都离不开GDI,我们利用GDI所提供的众多函数就可以方便的在屏幕、打印机及其它输出设备上输出图形,文本等操作。GDI的出现使程序员无需要关心硬件设备及设备驱动,就可以将应用程序的输出转化为硬件设备上的输出,实现了程序开发者与硬件设备的隔离,大大方便了开发工作。

    GDI是如何实现输出的?

      要想在屏幕或者其它输出设备上输出图形或者文字,那么我们就必须先获得一个称为设备描述表( DC:Device Context)的对象的句柄,以它为参数,调用各种GDI函数实现各种文字或图形的输出。
    设备描述表是GDI内部保存数据的一种数据结构,此结构中的属性内容与特定的输出设备(显示器,打印机等)相关,属性定义了GDI函数的工作细节,在稍后我们将看到如何使用TextOut函数输出文字,在这里属性确定了文字的颜色,x坐标和y坐标映射到窗口显示区域的方式等。

      设备描述表句柄一旦获得,那么系统将使用默认的属性值填充设备描述表结构。

      如果有必要,我们可以使用一些GDI函数获取和改变设备描述表中的属性值。

    什么是有效矩形什么是无效矩形?

      当应用程序接受到WM_PAINT消息后通常就准备更新正个显示区域,但是通常只需要更新一个比较小的区域而不是整个区域,这种情况通常出现在当应用程序的主窗口的一部分被一个对话框覆盖,需要重画的只是被覆盖的矩形区域(见下图)。

     

      EXE示例程序下载:点击这里下载(90K, winzip压缩文件)

      阴影以下的部分就是需要更新的矩形区域,该区域就是我们所说的无效区域,正是因为此区域的存在,系统才会向消息队列中放入一个WM_PAINT消息。

      Windows内部为每个窗口都保留了一个绘图结构(PAINTSTRUCT),它包含了包围无效区域的最小矩形的坐标和一些其它信息,需要注意的是当窗口消息处理函数在处理WM_PAINT消息之前显示区域中出现了另一个无效区域,那么Windows会计算出一个包围两个无效区域的新无效区域,并把这种变化保存在绘图结构(PAINTSTRUCT)中,Windows是不会同时把多个WM_PAINT消息同时放到消息队列中的。

      窗口消息处理函数是通过调用InvalidateRect函数使窗口显示区域内的矩形变为无效的,如果消息队列中已经存在一个WM_PAINT消息,那么Windows将计算出新的无效矩形,在接收到WM_PAINT消息的时候,窗口消息处理函数可以获得无效矩形的座标,通过调用GetUpdateRect,可以在任何时候获得这些坐标。

     

    如何获取或释放设备描述表句柄?

       当应用程序需要绘图的时候,必须先获取设备描述表句柄,绘图操作结束后必须释放设备描述表句柄。我们有两种方法获取和释放设备描述表句柄。

    1. 使用BeginPaint和Endpaint函数

      通常是在应用程序接收到WM_PAINT消息,也就是需要更新窗口的显示区域的时候调用BeginPaint函数获取设备描述表句柄的,使用完后调用Endpaint函数释放设备描述表句柄。

    他们的函数原型为:

    HDC BeginPaint(
    HWND hwnd,,             // handle to window
    LPPAINTSTRUCT pPaint   // paint information
    );
    BOOL EndPaint(
      HWND hWnd,                   // handle to window
      CONST PAINTSTRUCT *pPaint   // paint data
    );

      从上面BeginPaint函数的原形中我们可以看到需要一个PAINTSTRUCT结构对象的内存地址,PAINTSTRUCT结构包含在WinUser.h头文件中。

      定义如下:

    typedef struct tagPAINTSTRUCT {
      HDC         hdc; //设备描述表句柄
      BOOL        fErase; //擦除状态
      RECT        rcPaint; //无效矩形座标
      BOOL        fRestore;
      BOOL        fIncUpdate;
      BYTE        rgbReserved[32];
    }
    PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT;

      事实上当程序调用BeginPaint函数的时候,Windows会自动的填写此结构的各个属性,而程序作者只需要关心前三个属性。

      第一个属性hdc表示当前的设备描述表句柄。

      第二个属性fErase来说,多数情况下它是被标记成FALSE(0)的,这表示Windows已经擦除了无效矩形的背景,这个擦除动作是是在BeginPaint函数中发生的,而擦除背景用的画刷则是WNDCLASS结构中的hbrBackground属性指定的画刷来擦除背景的,在很多情况下可能程序作者想自己定义一些插除行为,那么可以通过响应消息队列中的WM_ERASEBKGND消息来完成。

      第三个属性rcPaint则表示无效矩形座标,它定义了无效矩形的边界。

      RECT结构可以在WinDef.h头文件中找到。

      定义如下:

    typedef struct tagRECT
    {
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
    } RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;

      注意,我们在前面提到了InvalidateRect函数,并已经清楚了调用它可以让窗口显示区域内的矩形变为无效,那么我们就可以在处理WM_PAINT消息的时候通过调用它实现在无效矩形外绘图,该调用是在调用BegingPaint函数之前调用的。

      使用方法:

    InvalidateRect(hwnd,NULL,TRUE);

      通过上面代码的调用我们让整个显示区域变为了无效,并擦除背景,要注意的是,最后一个参数如果为FALSE,则不擦除背景,原有的东西将保留在原处,这通常是在接受到WM_PAINT消息的时候而不考虑rcPaint属性的情况下简单的重绘整个显示区域最方便的方法,例如,在显示区域内我们输出了一个图形,这个图形的一小部分落在了无效矩形区域内,而这就让绘制这个图形的无效部分变的没有意义,这时就需要重绘整个图形,因为在调用BeginPaint函数传回设备描述表句柄的时候,Windows不会绘制rcPaint也就是无效矩形以外的任何部分。

      对于InvalidateRect函数的详细举例,我们将在以后的章节中看到。

    2. 使用GetDC和ReleaseDC函数

      在很多情况下我们可能需要在接收到非WM_PAINT消息的时候获取设备描述表句柄,通过调用GetDC函数我们可以获得设备描述表句柄,因为程序作者可能要使用设备描述表句柄完成其它工作,例如获得设备描述表属性,或者修改设备描述表属性值等,在最后我们与第一种方法一样要释放句柄,通过调用ReleaseDC函数完成工作。

      他们的函数原型为:

    HDC GetDC(
      HWND hWnd    // handle to window
    );
    int ReleaseDC(
            HWND hWnd,  // handle to window
            HDC hDC      // handle to DC
    );

      两种方法的区别:

      <1> 使用BeginPaint函数获得的的操作区域是显示区域中的无效矩形区域,接下来绘图操作只能在窗口的无效区域范围内进行,无效区域以外的区域将被忽略不能进行操作,而GetDC函数获得的操作区域则是整个窗口的显示区域,之后的操作可以在任何部分进行,而不只限制在无效区域。

      <2> BeginPaint函数会自动把无效区域变成有效的区域,而GetDC函数则不会将任何无效区域变得有效,必须强行调用ValidateRect函数,并把第二个参数设置为NULL来完成。

      最后我们给出一个可执行程序的例子,当应用程序执行的时候会有一个对话框出现,当你拉动这个对话框的时候又会出现同样的另一个对话框,这就证明了窗口的覆盖会造成无效矩形的出现,系统将会发送WM_PAINT消息。

    转自(http://blog.chinaunix.net/uid-9563036-id-352140.html

    转载于:https://www.cnblogs.com/Fightingbirds/archive/2013/01/16/2862140.html

    展开全文
  • GDI GDI+从入门到精通

    2018-06-25 14:56:53
    GDI GDI+从入门到精通,课件PPT,包含一、二、三、四、五讲。
  • 在 VC++6.0 中将 JPG 格式图片转换成 BMP 格式思路:利用 GDI+来完成 难点: (1)配置 GDI 开发环境,添加配置代码 (2)在当文档程序中添加转换代码 注意:本文档由 ybdesire 参考网上资料撰写完成,代码已经做过...
    在 VC++6.0 中将 JPG 格式图片转换成 BMP 格式

    思路:利用 GDI+来完成
    难点: (1)配置 GDI 开发环境,添加配置代码
    (2)在当文档程序中添加转换代码
    注意:本文档由 ybdesire 参考网上资料撰写完成,代码已经做过测试,可直接复制张贴


    实现过程:

    一、 配置 GDI 开发环境
    (1) 下载 GDI+ SDK for Visual C++ 6.0
    http://www.codeguru.com/code/legacy/gdi/GDIPlus.zip
    下载的GDIPlus文件夹中有Includes,Lib文件夹和gdiplus.dll文件。
    将Includes和Lib中的文件分别拷到VC6安装目录中的VC98\include和lib文件夹下。

    (2) 新建 MFC 单文档应用程序 show:

    [cpp]  view plain copy
    1. #include <afxdtctl.h>  
    2. #define ULONG_PTR ULONG  
    3. #include <gdiplus.h>  
    4. using namespace Gdiplus;  
    5. #pragma comment(lib, “gdiplus.lib”)  

    2、如(1)中所说,将gdiplus.dll拷贝到本工程的Debug或Release目录下

    3、在show.h中的class CShowApp : public CWinApp中添加

    [cpp]  view plain copy
    1. private:  
    2.     GdiplusStartupInput m_gdiplusStartupInput;  
    3.     ULONG_PTR m_pGdiToken;  

    4、在show.cpp中的BOOL CShowApp::InitInstance()中添加
    [cpp]  view plain copy
    1. GdiplusStartup(&m_pGdiToken,&m_gdiplusStartupInput,NULL);  

    5、 CShowApp添加名字为ExitInstance的虚函数的,中添加如下退出GDI+的代码
    [cpp]  view plain copy
    1. GdiplusShutdown(m_pGdiToken);  

    (3) 测试 GDI+是否配置成功
    [cpp]  view plain copy
    1. void CShowView::OnDraw(CDC* pDC)  
    2. {  
    3.     CShowDoc* pDoc = GetDocument();  
    4.     ASSERT_VALID(pDoc);  
    5.     Graphics graphics(pDC->m_hDC);  
    6.     Pen pen(Color(255, 0, 255));  
    7.     graphics.DrawLine(&pen, 0, 0, 200, 100);  
    8. }  

    若能成功运行,表明GDI+配置成功


    二、 添加转换代码,实现将打开的 JPG 格式文件保存成 BMP 格式文件


    (1)在 CSshowView 中添加如下成员变量

    [cpp]  view plain copy
    1. CString strOpenFileName;  

    (2)在 CSshowView 中添加如下成员函数
    1、在 CSshowView 中添加 ToWChar 函数

    [cpp]  view plain copy
    1. WCHAR* CShowView::ToWChar(char *str)  
    2. {  
    3.     //在 GDI+中,有关字符的参数类型全部都是 WCHAR 类型的  
    4.     //该函数是将传统字符串进行转换  
    5.     static WCHAR buffer[1024];  
    6.     wcsset(buffer,0);  
    7.     MultiByteToWideChar(CP_ACP,0,str,strlen(str),buffer,1024);  
    8.     return buffer;  
    9. }  

    2、在 CSshowView 中添加 GetImageCLSID 函数

    [cpp]  view plain copy
    1. int CShowView::GetImageCLSID(const WCHAR *format, CLSID *pCLSID)  
    2. {  
    3.     UINT num=0;  
    4.     UINT size=0;  
    5.     ImageCodecInfo* pImageCodecInfo=NULL;  
    6.     GetImageEncodersSize(&num,&size);  
    7.     if(size==0)  
    8.         return FALSE; // 编码信息不可用  
    9.     // 分配内存  
    10.     pImageCodecInfo=(ImageCodecInfo*)(malloc(size));  
    11.     if(pImageCodecInfo==NULL)  
    12.         return FALSE; // 分配失败  
    13.     // 获得系统中可用的编码方式的所有信息  
    14.     GetImageEncoders(num,size,pImageCodecInfo);  
    15.     // 在可用编码信息中查找 format 格式是否被支持  
    16.   
    17.     for(UINT i=0;i<num;++i)  
    18.     {  
    19.         //MimeType: 编码方式的具体描述  
    20.         if (wcscmp(pImageCodecInfo[ i] .MimeType,format)==0)  
    21.         {  
    22.             *pCLSID=pImageCodecInfo[i].Clsid;  
    23.             free(pImageCodecInfo);  
    24.             return TRUE;  
    25.         }  
    26.     }  
    27.     free(pImageCodecInfo);  
    28.     return FALSE;  
    29. }  

    3、在 MFC ClassWixard 中重载 OnFileOpen()

    [cpp]  view plain copy
    1. void CShowView::OnFileOpen()  
    2. {  
    3.     static char szFilter[ ]=“常见图像格式文件(*.*)|*.*|”;  
    4.     CFileDialog dlgChoseImage(1,NULL,NULL,NULL,szFilter);  
    5.     if(dlgChoseImage.DoModal() ==IDOK)  
    6.     {  
    7.         strOpenFileName=dlgChoseImage.GetPathName();  
    8.         // 打开文件后立即在窗口中显示 (重绘客户窗口)  
    9.         this->Invalidate() ;  
    10.     }  
    11. }  

    4、在 MFC ClassWixard 中重载 OnFileSave()

    [cpp]  view plain copy
    1. void CShowView::OnFileSave()  
    2. {  
    3.     if( strOpenFileName.IsEmpty() )  
    4.     {  
    5.         AfxMessageBox(”当前没有打开图像文件, 不能进行保存!”);  
    6.         return;  
    7.     }  
    8.   
    9.     // 建立图形对象  
    10.     Graphics graphics(GetDC()->m_hDC);  
    11.   
    12.     // 装入当前已经打开的图像文件  
    13.     Image image(ToWChar(strOpenFileName.GetBuffer(strOpenFileName.GetLength())));  
    14.   
    15.     CString strFileSave;  
    16.     // 将其他格式的图像全部另存为 BMP 文件  
    17.     static char szFilter[ ]= “位图(*.BMP)|*.BMP|”;  
    18.   
    19.     CFileDialog dlgChoseImage(0,”BMP”,strOpenFileName,NULL,szFilter);  
    20.   
    21.     if(dlgChoseImage.DoModal() ==IDOK)  
    22.   
    23.     {  
    24.   
    25.         strFileSave=dlgChoseImage.GetPathName();  
    26.   
    27.         CLSID clsid;  
    28.   
    29.         if(GetImageCLSID(L“image/bmp”, &clsid))  
    30.         {  
    31.             image.Save(ToWChar(strFileSave.GetBuffer(strFileSave.GetLength())), &clsid, NULL);  
    32.             // 将保存后的图像进行显示  
    33.             strOpenFileName=strFileSave;  
    34.             this->Invalidate() ;  
    35.         }  
    36.     }  
    37. }  

    参考资料

    [1]http://blog.csdn.NET/poonjun/archive/2009/01/04/3701724.aspx
    [2]http://www.cnblogs.com/DavidHu/articles/1191635.html
    [3]http://www.smth.edu.cn/bbsgcon.PHP?board=VisualC&num=785
    [4]《图像格式转换在数字仪表识别系统中的应用》 刘 娜, 汪仁煌, 庞 然

    扩展知识阅读

        [3] 色彩鲜艳漂亮的高品质图像,一个个形象的Windows图标,高速运动、活灵活现的三维动画,这些生动的图形无一不显示着程序设计者的艺术才华。在程序设计中,图像处理已经成了每个程序员的必修课,所以,对于每个程序员来说,熟悉“BMP”、“GIF”、“JPEG”图像格式及具体应用、调色板、图像文件头格式、图像压缩算法等概念似乎已经成了工作中不可缺少的基础知识。面对如此多的图像格式,如果要全部掌握其具体细节,好像这对程序员有些不公。在VC中编程显示一幅位图,下列的步骤是不可少的:装入位图、获得位图的大小信息、启用设备环境、位传输,所需的程序代码显得千篇一律的冗长。如果想要装入的位图另存为其他格式的图像文件……?两个字:头疼!而这一 切都是因为GDI本身的局限性所造成。

        随着Windows 2000的推出,上面的情况有了大大的改观:你可以不必了解每种图像格式的具体含义,照样可以写出多格式图像浏览或转换程序,这一切,全部都依赖于Windows 2000及后继版中所使用的GDI+技术。首先来看看GDI+的具体技术细节及GDI+编程特点。

        Windows 2000在用户界面方面包括了几个重大的改进,可能你已经注意到了有阴影的鼠 标、渐入的工具条快速提示、透明的窗口、平滑地窗口变化等。Windows 2000在界面上之所以有这么大的改进,完全是因为Windows2000采用了一种GDI(graphics device interface :图形设备接口)。GDI+是一种新型的图形设备接口,它的主要特点在于它能够创建全新的用户桌面 体系、能够轻易地完成二维或三维的图形处理,为桌面带来一种数字化的图片。 GDI+同时也提供了增强的图形处理技术,如常见的:alpha blending、 纹理、贴图、增强的文本及图片显示技术。实际上,GDI+主要的特色就在于强调通过硬件加速来达到良好的 视觉感受!

        同传统的GDI不同,GDI+中引入了对COM(组件对象模型)技术的支持,通过COM技术,GDI+简化了对图像文件的访问(打开、保存)程序:通过调用COM组件来实现的,GDI+扮演的只是指挥者,而非操作员。对于图像文件,GDI+所关心的不是图像文件的文件头信息,不论欲打开的文件格式是什么类型,GDI+首先要做的是在注册中查看该图像格式的编码(或解码)信息是否已经注册(HKEY_CLASSES_ROOT\MIME\Database\Content Type)

        在微软的其他软件中已经使用了,如IE。“体验”过NIMDA病毒的朋友可能对“audio/wav”这段代码并不陌生,NIMDA就是靠它来伪装自己的:让IE认为附件是WAV文件而自动打开可执行程序。这其实也是IE使用COM技术的一个突出表现。
    配合GDI+的推出,微软也同时发布了相应的SDK,如果你已经安装了最新的Microsoft PlatForm SDK或已经开始使用VS .NET,GDI+ SDK已经在你的系统中了。如果没有的话,可以到http://noner.top263.Net/progtool上去下载GDI+的头文件和库文件。在使用GDI+之后,, 再有没有必要去考虑什么句柄、设备环境这样的概念了。你只需要简单地创建一个图形对象(Graphics object)绘图即可。图形对象是GDI+中核心,正如DC之于GDI那样。图形对象和DC有许多相似的地方,在使用上遵循着相同的使用规则,但是两者在本质上已经有很大的区别。一个是基于句柄的GDI,一个是基于组件对象模型的GDI+。使用GDI+的SDK编程,必须得按照下面的规范来进行:使用GDI+的名空间(namespace Gdiplus)进行GDI+的初始化,使用完毕之后也得销毁GDI+,这种规范在下面所列的程序中有详细的说明。前面说到了GDI+是通过在注册中查看编码信息来访问图像文件的,在GDI+的SDK中,编码信息是储存在 ImageCodecInfo类中的,在这个类中,有编码的CLSID(COM组件的GUID标识码)

        数来实现:

        1、查看系统中可用的图像编码信息(数量及大小)

    [cpp]  view plain copy
    1. Status GetImageEncodersSize(  
    2.     UINT* numEncoders, //存储编码器数量的地址  
    3.     UINT* size //存储编码信息所需内存大小  
    4.     );  

    2、得到所有的编码信息
    [cpp]  view plain copy
    1. Status GetImageEncoders(  
    2.     UINT numEncoders,//可用编码器数量  
    3.     UINT size,//储存编码器信息所需内存(由ImageCodecInfo类组成的数组的大小)  
    4.     ImageCodecInfo* encoders//编码器信息指针  
    5.     );  

    在GetImageEncoders函数中,参数numEncoders和size都是由GetImageEncodersSize所返回的。下面的代码就能够在注册表中查找具体格式图像的编码方式:

    [cpp]  view plain copy
    1. int GetImageCLSID(const WCHAR* format, CLSID* pCLSID)  
    2. {//得到格式为format的图像文件的编码值,访问该格式图像的COM组件的  
    3.     //GUID值保存在pCLSID中  
    4.     UINT num = 0;  
    5.     UINT size = 0;  
    6.     ImageCodecInfo* pImageCodecInfo = NULL;  
    7.     GetImageEncodersSize(&num, &size);  
    8.   
    9.     if(size == 0)  
    10.         return FALSE; // 编码信息不可用  
    11.   
    12.     //分配内存  
    13.     pImageCodecInfo = (ImageCodecInfo*)(malloc(size));  
    14.     if(pImageCodecInfo == NULL)  
    15.         return FALSE; // 分配失败  
    16.   
    17.     //获得系统中可用的编码方式的所有信息  
    18.     GetImageEncoders(num, size, pImageCodecInfo);  
    19.   
    20.     //在可用编码信息中查找format格式是否被支持  
    21.     for(UINT i = 0; i < num; ++i)  
    22.     { //MimeType:编码方式的具体描述  
    23.         if( wcscmp(pImageCodecInfo[i].MimeType, format) == 0 )  
    24.         {  
    25.             *pCLSID = pImageCodecInfo[i].Clsid;  
    26.             free(pImageCodecInfo);  
    27.             return TRUE;  
    28.         }  
    29.     }  
    30.     free(pImageCodecInfo);  
    31.     return FALSE;  
    32. }  

    有了这种认识,实现多格式的图像的浏览与转换就并不是什么难事了。为了讲述的方便,首先在VC中建立一个SDI项目ImageShow,首先对使用GDI+申明和初始化及销毁进行代码编制,具体代码如下:

    [cpp]  view plain copy
    1. #include “Gdiplus.h”  
    2. using namespace Gdiplus;  
    3.   
    4. CImageShowView::CImageShowView()  
    5. {  
    6.     //初始化GDI+  
    7.     GdiplusStartupInput gdiplusStartupInput;  
    8.     ULONG_PTR gdiplusToken;  
    9.     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);  
    10. }  
    11.   
    12.   
    13. CImageShowView::~CImageShowView()  
    14. {  
    15.     //销毁GDI+  
    16.     ULONG_PTR gdiplusToken;  
    17.     GdiplusShutdown(gdiplusToken);  
    18. }  

    接着通过类向导(Class Wizard),重载“文件”菜单中的“打开”和“另存为”两项,为了编程的简单,本程序只将当前打开的图像文件直接存为BMP文件(实际上保存成其他格式的文件也很简单,只不过是对文件名进行分析而已)进行文件名的传递,首先应在CImageShowView类中加入一全局变量“CString strOpenFileName”。“打开”和“另存为”两项的响应代码如下,大家通过代码中的注释部份理解编程思路,应该不会有什么问题:
    [cpp]  view plain copy
    1. WCHAR* ToWChar(char * str)  
    2. {  
    3.     //在GDI+中,有关字符的参数类型全部都是WCHAR类型的  
    4.     //该函数是将传统字符串进行转换  
    5.     static WCHAR buffer[1024];  
    6.     wcsset(buffer,0);  
    7.     MultiByteToWideChar(CP_ACP,0,str,strlen(str),buffer,1024);  
    8.     return buffer;  
    9. }  

    [cpp]  view plain copy
    1. void CImageShowView::OnFileOpen()  
    2. {  
    3.     //本程序能够打开各类常见格式的图像文件  
    4.     static char szFilter[]=“常见格式图形文件(*.*)|*.*|”;  
    5.     CFileDialog dlgChoseImage(1,NULL,NULL,NULL,szFilter);  
    6.   
    7.     if(dlgChoseImage.DoModal()==IDOK)  
    8.     {  
    9.         strOpenFileName=dlgChoseImage.GetPathName();  
    10.         //打开文件后立即在窗口中显示(重绘客户窗口)  
    11.         this->Invalidate();  
    12.     }  
    13. }  
    14.   
    15.   
    16. void CImageShowView::OnFileSaveAs()  
    17. {  
    18.     if(strOpenFileName.IsEmpty())  
    19.     {  
    20.         AfxMessageBox(”当前没有打开图像文件,不能进行保存!”);  
    21.         return;  
    22.     }  
    23.   
    24.   
    25.     //建立图形对像  
    26.     Graphics graphics(GetDC()->m_hDC);  
    27.   
    28.     //装入当前已经打开的图形文件  
    29.     Image image(ToWChar(strOpenFileName.GetBuffer(strOpenFileName.GetLength())));  
    30.     CString strFileSave;  
    31.   
    32.     //当其他格式的图像全部另存为BMP文件  
    33.     static char szFilter[]=“位图(*.BMP)|*.BMP|”;  
    34.     CFileDialog dlgChoseImage(0,”BMP”,NULL,NULL,szFilter);  
    35.     if(dlgChoseImage.DoModal()==IDOK)  
    36.     {  
    37.         strFileSave=dlgChoseImage.GetPathName();  
    38.         CLSID clsid;  
    39.   
    40.         if(GetImageCLSID(L“image/bmp”, &clsid))  
    41.         {  
    42.             image.Save(ToWChar(strFileSave.GetBuffer(strFileSave.GetLength())), &clsid,NULL);  
    43.   
    44.             //将保存后的图像进行显示  
    45.             strOpenFileName=strFileSave;  
    46.             this->Invalidate();  
    47.         }  
    48.     }  
    49. }  

    最后,为了显示浏览图像转换前后的效果,还应该在窗口中分另绘制转换前后的图像,这很容易,只需要在OnDraw函数中添加绘制代码,如下所述:
    [cpp]  view plain copy
    1. void CImageShowView::OnDraw(CDC* pDC)  
    2. {  
    3.     CImageShowDoc* pDoc = GetDocument();  
    4.     ASSERT_VALID(pDoc);  
    5.     //如果没有选择显示图形文件,则不用重绘  
    6.     if(strOpenFileName.IsEmpty())  
    7.         return;  
    8.     //显示当前打开的图像文件的全名  
    9.     this->GetParent()->SetWindowText(strOpenFileName);  
    10.   
    11.     //建立图形对象  
    12.     Graphics graphics(pDC->m_hDC);  
    13.   
    14.     //装入图形文件  
    15.     Image image(ToWChar(strOpenFileName.GetBuffer(strOpenFileName.GetLength())));  
    16.     Point destPoints[3] =  
    17.     {  
    18.         Point(0, 0),  
    19.         Point(image.GetWidth(), 0),  
    20.         Point(0, image.GetHeight())  
    21.     };  
    22.     Point* pdestPoints = destPoints;  
    23.     //在指定区域pdestPoints显示图像  
    24.     graphics.DrawImage(&image, pdestPoints, 3);  
    25. }  
    在编译上面的程序之前,应该将Gdiplus.lib文件连编到项目中去,否则将会出现“LINK 2001”编译错误。该程序在Visual Studio 6.0、Windows2000/XP下调试通过,它能够显示或转换的图像格式有BMP、GIF、JPEG 、Exif 、PNG 、TIFF 、ICON、WMF 、EMF等等。需要说明的是,本文只就GDI+编程的基本原理进行阐述,其实,GDI+的应用远不止于此。在GDI+的背后,有你意想不到的惊奇!瞧,这程序运行起来是不是有些象ACDSee之类的图像浏览程序?如果对本程序进行些改进,你也以做出功能更加强劲的图像处理程序。本文中所提到的程序,在我的主页“国税之家”(http://nationaltax.home.chinaren.com)的“个人世界”中可以下下载到。有关GDI+的编程序帮助信息,大家可以到微软的MSDN网站去查阅。如果你有VisualStudio .NET,这就最好,因为所附的MSDN for Visual Studio.NET 7.0中有GDI+编程所需的全部信息
    展开全文
  • Windows API-GDI入门基础知识详解

    千次阅读 2013-11-17 00:38:54
     GDI是Graphics Device Interface的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。  在Windows操作系统下,绝大多数具备图形界面的应用程序都

     

     

    转自:http://blog.csdn.net/daichanglin/article/details/1676097

     

     

    什么是GDI?

      GDI是Graphics Device Interface的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。

      在Windows操作系统下,绝大多数具备图形界面的应用程序都离不开GDI,我们利用GDI所提供的众多函数就可以方便的在屏幕、打印机及其它输出设备上输出图形,文本等操作。GDI的出现使程序员无需要关心硬件设备及设备驱动,就可以将应用程序的输出转化为硬件设备上的输出,实现了程序开发者与硬件设备的隔离,大大方便了开发工作。

    GDI是如何实现输出的?

      要想在屏幕或者其它输出设备上输出图形或者文字,那么我们就必须先获得一个称为设备描述表( DC:Device Context)的对象的句柄,以它为参数,调用各种GDI函数实现各种文字或图形的输出。

      设备描述表是GDI内部保存数据的一种数据结构,此结构中的属性内容与特定的输出设备(显示器,打印机等)相关,属性定义了GDI函数的工作细节,在稍后我们将看到如何使用TextOut函数输出文字,在这里属性确定了文字的颜色,x坐标和y坐标映射到窗口显示区域的方式等。

      设备描述表句柄一旦获得,那么系统将使用默认的属性值填充设备描述表结构。

      如果有必要,我们可以使用一些GDI函数获取和改变设备描述表中的属性值。

    什么是有效矩形什么是无效矩形?

      当应用程序接受到WM_PAINT消息后通常就准备更新正个显示区域,但是通常只需要更新一个比较小的区域而不是整个区域,这种情况通常出现在当应用程序的主窗口的一部分被一个对话框覆盖,需要重画的只是被覆盖的矩形区域(见下图)。

      EXE示例程序下载:点击这里下载(90K, winzip压缩文件)

      阴影以下的部分就是需要更新的矩形区域,该区域就是我们所说的无效区域,正是因为此区域的存在,系统才会向消息队列中放入一个WM_PAINT消息。

      Windows内部为每个窗口都保留了一个绘图结构(PAINTSTRUCT),它包含了包围无效区域的最小矩形的坐标和一些其它信息,需要注意的是当窗口消息处理函数在处理WM_PAINT消息之前显示区域中出现了另一个无效区域,那么Windows会计算出一个包围两个无效区域的新无效区域,并把这种变化保存在绘图结构(PAINTSTRUCT)中,Windows是不会同时把多个WM_PAINT消息同时放到消息队列中的。

      窗口消息处理函数是通过调用InvalidateRect函数使窗口显示区域内的矩形变为无效的,如果消息队列中已经存在一个WM_PAINT消息,那么Windows将计算出新的无效矩形,在接收到WM_PAINT消息的时候,窗口消息处理函数可以获得无效矩形的座标,通过调用GetUpdateRect,可以在任何时候获得这些坐标。

    如何获取或释放设备描述表句柄?

       当应用程序需要绘图的时候,必须先获取设备描述表句柄,绘图操作结束后必须释放设备描述表句柄。我们有两种方法获取和释放设备描述表句柄。

    1. 使用BeginPaint和Endpaint函数

      通常是在应用程序接收到WM_PAINT消息,也就是需要更新窗口的显示区域的时候调用BeginPaint函数获取设备描述表句柄的,使用完后调用Endpaint函数释放设备描述表句柄。

    他们的函数原型为:

    HDC BeginPaint(
    HWND hwnd,,             // handle to window
    LPPAINTSTRUCT pPaint   // paint information
    );


    BOOL EndPaint(
      HWND hWnd,                   // handle to window
      CONST PAINTSTRUCT *pPaint   // paint data
    );

      从上面BeginPaint函数的原形中我们可以看到需要一个PAINTSTRUCT结构对象的内存地址,PAINTSTRUCT结构包含在WinUser.h头文件中。

      定义如下:

    typedef struct tagPAINTSTRUCT {
      HDC         hdc; //设备描述表句柄
      BOOL        fErase; //擦除状态
      RECT        rcPaint; //无效矩形座标
      BOOL        fRestore;
      BOOL        fIncUpdate;
      BYTE        rgbReserved[32];
    }
    PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT;

      事实上当程序调用BeginPaint函数的时候,Windows会自动的填写此结构的各个属性,而程序作者只需要关心前三个属性。

      第一个属性hdc表示当前的设备描述表句柄。

      第二个属性fErase来说,多数情况下它是被标记成FALSE(0)的,这表示Windows已经擦除了无效矩形的背景,这个擦除动作是是在BeginPaint函数中发生的,而擦除背景用的画刷则是WNDCLASS结构中的hbrBackground属性指定的画刷来擦除背景的,在很多情况下可能程序作者想自己定义一些插除行为,那么可以通过响应消息队列中的WM_ERASEBKGND消息来完成。

      第三个属性rcPaint则表示无效矩形座标,它定义了无效矩形的边界。

      RECT结构可以在WinDef.h头文件中找到。

      定义如下:

    typedef struct tagRECT
    {
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
    } RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;

      注意,我们在前面提到了InvalidateRect函数,并已经清楚了调用它可以让窗口显示区域内的矩形变为无效,那么我们就可以在处理WM_PAINT消息的时候通过调用它实现在无效矩形外绘图,该调用是在调用BegingPaint函数之前调用的。

      使用方法:

    InvalidateRect(hwnd,NULL,TRUE);

      通过上面代码的调用我们让整个显示区域变为了无效,并擦除背景,要注意的是,最后一个参数如果为FALSE,则不擦除背景,原有的东西将保留在原处,这通常是在接受到WM_PAINT消息的时候而不考虑rcPaint属性的情况下简单的重绘整个显示区域最方便的方法,例如,在显示区域内我们输出了一个图形,这个图形的一小部分落在了无效矩形区域内,而这就让绘制这个图形的无效部分变的没有意义,这时就需要重绘整个图形,因为在调用BeginPaint函数传回设备描述表句柄的时候,Windows不会绘制rcPaint也就是无效矩形以外的任何部分。

      对于InvalidateRect函数的详细举例,我们将在以后的章节中看到。

    2. 使用GetDC和ReleaseDC函数

      在很多情况下我们可能需要在接收到非WM_PAINT消息的时候获取设备描述表句柄,通过调用GetDC函数我们可以获得设备描述表句柄,因为程序作者可能要使用设备描述表句柄完成其它工作,例如获得设备描述表属性,或者修改设备描述表属性值等,在最后我们与第一种方法一样要释放句柄,通过调用ReleaseDC函数完成工作。

      他们的函数原型为:

    HDC GetDC(
      HWND hWnd    // handle to window
    );


    int ReleaseDC(
            HWND hWnd,  // handle to window
            HDC hDC      // handle to DC
    );

      两种方法的区别:

      <1> 使用BeginPaint函数获得的的操作区域是显示区域中的无效矩形区域,接下来绘图操作只能在窗口的无效区域范围内进行,无效区域以外的区域将被忽略不能进行操作,而GetDC函数获得的操作区域则是整个窗口的显示区域,之后的操作可以在任何部分进行,而不只限制在无效区域。

      <2> BeginPaint函数会自动把无效区域变成有效的区域,而GetDC函数则不会将任何无效区域变得有效,必须强行调用ValidateRect函数,并把第二个参数设置为NULL来完成。

      最后我们给出一个可执行程序的例子,当应用程序执行的时候会有一个对话框出现,当你拉动这个对话框的时候又会出现同样的另一个对话框,这就证明了窗口的覆盖会造成无效矩形的出现,系统将会发送WM_PAINT消息。

      现在我们对GDI的基础概念有了一定的了解,下面我们将对GDI一些常用的函数进行学习。

    TextOut函数

      TextOut函数的作用是把指定的字符串输出在我们指定的屏幕位置上。

    函数原型:

     BOOL TextOut(
          HDC hdc,                    // 设备描述表句柄
          int nXStart,                  // 输出的x轴水平位置
          int nYStart,                  // 输出的y轴垂直位置
          LPCTSTR lpString,   // 指向要输出字符串的长指针
          int cbString                // 字符串长度
        );

      第一参数是设备描述表句柄,它既可以是通过BeginPaint函数获得的,也可以是通过GetDC函数获得的,需要提一下的是,设备描述表中的属性控制了显示的字符串的一些细节特征,比如字体、字体颜色、文字背景等,但要注意的是保存在设备描述表属性中的文字背景颜色和WNDCLASS结构中的屏幕背景是有区别的,文字背景指的是紧靠字符周围的矩形空间,又叫做字符框。而窗口背景则是一个画刷,Windows用它来擦除显示区域,它不是设备描述表结构中的一部分。

      第二和第三个参数定义了显示区域内字符串的开始位置,x是水平位置,y是垂直位置,字符串第一个字符位于坐标点(x,y),在设备描述表属性中,原点(x,y)均为为0,是显示区域的左上角,对于坐标来说,坐标的映射方式的不同决定了单位的不同,在通常情况下传递给函数的坐标被称为逻辑坐标,Windows有许多坐标映射方式,它们是用来控制GDI函数指定的逻辑坐标转换为显示器的实际像素坐标的方式。映射方式在设备描述表的属性中定义,默认的映射方式是MM_TEXT,我们可以在WinGdi.h头文件中找到。在MM_TEXT映射模式下,逻辑单位于实际单位都相同,都是像素,对于坐标来说,x的值从左向右递增,y的值则从上向下递增(见下图),MM_TEXT坐标系与Windows在PAINTSTURCT结构中定义的无效矩形所使用的坐标系相同。

      第四个参数是指向要输出字符串的长指针。

      第五个参数是要输出的字符串的实际长度。

      在Windows下输出文字并不如我们所想象的那么容易,在前面我们已经知道输出文字和坐标有关,我们为了精确的输出文字,就必须对系统的字体和字符大小有进一步的认识。

    系统字体

      对于输出字符串的函数TextOut来说,在默认情况下设备描述表属性中使用的是系统字体(SYSTEM_FONT),系统字体是Windows用来在标题栏,功能表和对话框中显示字符串所使用的默认字体。

      但值得注意的是,字体如果按宽度来区分的话,大致可以分为两类:

      1. 等宽字体
      2. 变宽字体

      等宽字体意味着所有的字符宽度都是一致的,但随着计算技术的不断发展和推广,这种等宽字体就不再能够满足需要,于是变宽字体出现了,变宽字体不同的字符宽度都不一定相同。

      系统字体是一种点阵字体,字体被定义成了一个个的像素点,字体的确切大小取决于显示器的大小(分辨率的大小)。 

    字符大小

      如果要使用TextOut函数显示多行文字,那么就必须确定字体字符的大小,字体的高度确定了下一行字符的显示位置,字体的宽度确定了下一列的显示位置。

      屏幕的分辨率和字符大小是确定如何显示字符的主要依据,为了获得当前系统上各种与视觉属性相关的信息,我们可以调用GetSystemMetrics函数获取,调用GetTextMetrics函数可以获取字体大小。

      以下是这两个函数的原形以及参数的详细定义:

    int GetSystemMetrics(
      
      int nIndex  // 索引
    );

      GetSystemMetrics函数是完成Windows图形输出的重要函数,它返回Windows中各种与视觉属性相关的信息,该函数需要只需要一个参数,它是一个索引,这些索引是在Windows头文件中定义的一些常量,这些常量分别指定了不同的与视觉相关的设备属性,这些索引的多少取决与Windows的版本。

      以下是这些索引的含义:

    Value Meaning
    SM_ARRANGE Flags specifying how the system arranged minimized windows. For more information about minimized windows, see the following Remarks section.
    SM_CLEANBOOT Value that specifies how the system was started: 0 Normal boot
    1 Fail-safe boot
    2 Fail-safe with network boot
    Fail-safe boot (also called SafeBoot, Safe Mode, or Clean Boot) bypasses the user's startup files.
    SM_CMONITORS Number of display monitors on the desktop. See Remarks for more information. Windows NT, Windows 95:  This value is not supported.
    SM_CMOUSEBUTTONS Number of buttons on mouse, or zero if no mouse is installed.
    SM_CXBORDER, SM_CYBORDER Width and height of a window border, in pixels. This is equivalent to the SM_CXEDGE value for windows with the 3-D look.
    SM_CXCURSOR, SM_CYCURSOR Width and height of a cursor, in pixels. The system cannot create cursors of other sizes.
    SM_CXDLGFRAME, SM_CYDLGFRAME Same as SM_CXFIXEDFRAME and SM_CYFIXEDFRAME.
    SM_CXDOUBLECLK, SM_CYDOUBLECLK Width and height of the rectangle around the location of a first click in a double-click sequence, in pixels. The second click must occur within this rectangle for the system to consider the two clicks a double-click. (The two clicks must also occur within a specified time.) To set the width and height of the double-click rectangle, call SystemParametersInfo with the SPI_SETDOUBLECLKHEIGHT and SPI_SETDOUBLECLKWIDTH flags.
    SM_CXDRAG, SM_CYDRAG Width and height of a rectangle centered on a drag point to allow for limited movement of the mouse pointer before a drag operation begins. These values are in pixels. It allows the user to click and release the mouse button easily without unintentionally starting a drag operation.
    SM_CXEDGE, SM_CYEDGE Dimensions of a 3-D border, in pixels. These are the 3-D counterparts of SM_CXBORDER and SM_CYBORDER.
    SM_CXFIXEDFRAME, SM_CYFIXEDFRAME Thickness of the frame around the perimeter of a window that has a caption but is not sizable, in pixels. SM_CXFIXEDFRAME is the height of the horizontal border and SM_CYFIXEDFRAME is the width of the vertical border. Same as SM_CXDLGFRAME and SM_CYDLGFRAME.
    SM_CXFOCUSBORDER, SM_CYFOCUSBORDER Width of the left and right edges and the height of the top and bottom edges of the focus rectangle drawn by DrawFocusRect. These values are in pixels. Windows 2000/NT, Windows Me/98/95:  This value is not supported.
    SM_CXFRAME, SM_CYFRAME Same as SM_CXSIZEFRAME and SM_CYSIZEFRAME.
    SM_CXFULLSCREEN, SM_CYFULLSCREEN Width and height of the client area for a full-screen window on the primary display monitor, in pixels. To get the coordinates of the portion of the screen not obscured by the system taskbar or by application desktop toolbars, call the SystemParametersInfo function with the SPI_GETWORKAREA value.
    SM_CXHSCROLL, SM_CYHSCROLL Width of the arrow bitmap on a horizontal scroll bar, in pixels; and height of a horizontal scroll bar, in pixels.
    SM_CXHTHUMB Width of the thumb box in a horizontal scroll bar, in pixels.
    SM_CXICON, SM_CYICON Default width and height of an icon, in pixels. The LoadIcon function can load only icons of these dimensions.
    SM_CXICONSPACING, SM_CYICONSPACING Dimensions of a grid cell for items in large icon view, in pixels. Each item fits into a rectangle of this size when arranged. These values are always greater than or equal to SM_CXICON and SM_CYICON.
    SM_CXMAXIMIZED, SM_CYMAXIMIZED Default dimensions, in pixels, of a maximized top-level window on the primary display monitor.
    SM_CXMAXTRACK, SM_CYMAXTRACK Default maximum dimensions of a window that has a caption and sizing borders, in pixels. This metric refers to the entire desktop. The user cannot drag the window frame to a size larger than these dimensions. A window can override these values by processing the WM_GETMINMAXINFO message.
    SM_CXMENUCHECK, SM_CYMENUCHECK Dimensions of the default menu check-mark bitmap, in pixels.
    SM_CXMENUSIZE, SM_CYMENUSIZE Dimensions of menu bar buttons, such as the child window close button used in the multiple document interface, in pixels.
    SM_CXMIN, SM_CYMIN Minimum width and height of a window, in pixels.
    SM_CXMINIMIZED, SM_CYMINIMIZED Dimensions of a minimized window, in pixels.
    SM_CXMINSPACING SM_CYMINSPACING Dimensions of a grid cell for a minimized window, in pixels. Each minimized window fits into a rectangle this size when arranged. These values are always greater than or equal to SM_CXMINIMIZED and SM_CYMINIMIZED.
    SM_CXMINTRACK, SM_CYMINTRACK Minimum tracking width and height of a window, in pixels. The user cannot drag the window frame to a size smaller than these dimensions. A window can override these values by processing the WM_GETMINMAXINFO message.
    SM_CXSCREEN, SM_CYSCREEN Width and height of the screen of the primary display monitor, in pixels. These are the same values obtained by calling GetDeviceCaps(hdcPrimaryMonitor, HORZRES/VERTRES).
    SM_CXSIZE, SM_CYSIZE Width and height of a button in a window's caption or title bar, in pixels.
    SM_CXSIZEFRAME, SM_CYSIZEFRAME Thickness of the sizing border around the perimeter of a window that can be resized, in pixels. SM_CXSIZEFRAME is the width of the horizontal border, and SM_CYSIZEFRAME is the height of the vertical border. Same as SM_CXFRAME and SM_CYFRAME.
    SM_CXSMICON, SM_CYSMICON Recommended dimensions of a small icon, in pixels. Small icons typically appear in window captions and in small icon view.
    SM_CXSMSIZE SM_CYSMSIZE Dimensions of small caption buttons, in pixels.
    SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN Width and height of the virtual screen, in pixels. The virtual screen is the bounding rectangle of all display monitors. The SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN metrics are the coordinates of the top-left corner of the virtual screen. Windows NT, Windows 95:  This value is not supported.
    SM_CXVSCROLL, SM_CYVSCROLL Width of a vertical scroll bar, in pixels; and height of the arrow bitmap on a vertical scroll bar, in pixels.
    SM_CYCAPTION Height of a caption area, in pixels.
    SM_CYKANJIWINDOW For double byte character set versions of the system, this is the height of the Kanji window at the bottom of the screen, in pixels.
    SM_CYMENU Height of a single-line menu bar, in pixels.
    SM_CYSMCAPTION Height of a small caption, in pixels.
    SM_CYVTHUMB Height of the thumb box in a vertical scroll bar, in pixels.
    SM_DBCSENABLED TRUE or nonzero if User32.dll supports DBCS; FALSE or zero otherwise. Windows Me/98/95:   TRUE or nonzero if the double-byte character-set (DBCS) version of User.exe is installed; FALSE or zero otherwise.
    SM_DEBUG TRUE or nonzero if the debug version of User.exe is installed; FALSE or zero otherwise.
    SM_IMMENABLED TRUE or nonzero if Input Method Manager/Input Method Editor features are enabled; FALSE or zero otherwise. Windows NT, Windows Me/98/95:  This value is not supported. SM_IMMENABLED indicates whether the system is ready to use a Unicode-based IME on a Unicode application. To ensure that a language-dependent IME works, check SM_DBCSENABLED and the system ANSI code page. Otherwise the ANSI-to-Unicode conversion may not be performed correctly, or some components like fonts or registry setting may not be present.
    SM_MENUDROPALIGNMENT TRUE or nonzero if drop-down menus are right-aligned with the corresponding menu-bar item; FALSE or zero if the menus are left-aligned.
    SM_MIDEASTENABLED TRUE if the system is enabled for Hebrew and Arabic languages.
    SM_MOUSEPRESENT TRUE or nonzero if a mouse is installed; FALSE or zero otherwise.
    SM_MOUSEWHEELPRESENT TRUE or nonzero if a mouse with a wheel is installed; FALSE or zero otherwise. Windows 3.51 and earlier, Windows 95:  This value is not supported.
    SM_NETWORK Least significant bit is set if a network is present; otherwise, it is cleared. The other bits are reserved for future use.
    SM_PENWINDOWS TRUE or nonzero if the Microsoft Windows for Pen computing extensions are installed; FALSE or zero otherwise.
    SM_REMOTECONTROL This system metric is used in a Terminal Services environment. Its value is TRUE if the current session is remotely controlled; FALSE otherwise. Windows 2000/NT, Windows Me/98/95:  This value is not supported.
    SM_REMOTESESSION This system metric is used in a Terminal Services environment. If the calling process is associated with a Terminal Services client session, the return value is TRUE or nonzero. If the calling process is associated with the Terminal Server console session, the return value is zero. Windows NT 4.0 SP3 and earlier, Windows Me/98/95:  This value is not supported.
    SM_SECURE TRUE if security is present; FALSE otherwise.
    SM_SAMEDISPLAYFORMAT TRUE if all the display monitors have the same color format, FALSE otherwise. Note that two displays can have the same bit depth, but different color formats. For example, the red, green, and blue pixels can be encoded with different numbers of bits, or those bits can be located in different places in a pixel's color value. Windows NT, Windows 95:  This value is not supported.
    SM_SHOWSOUNDS TRUE or nonzero if the user requires an application to present information visually in situations where it would otherwise present the information only in audible form; FALSE, or zero, otherwise.
    SM_SHUTTINGDOWN TRUE if the current session is shutting down; FALSE otherwise. Windows 2000/NT, Windows Me/98/95:  This value is not supported.
    SM_SLOWMACHINE TRUE if the computer has a low-end (slow) processor; FALSE otherwise.
    SM_SWAPBUTTON TRUE or nonzero if the meanings of the left and right mouse buttons are swapped; FALSE or zero otherwise.
    SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN Coordinates for the left side and the top of the virtual screen. The virtual screen is the bounding rectangle of all display monitors. The SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN metrics are the width and height of the virtual screen. Windows NT, Windows 95:  This value is not supported.


    BOOL GetTextMetrics(
        
      HDC hdc,                        // 当前的设备描述表句柄
        
      LPTEXTMETRIC lptm   // 指向TEXTMETRICS结构对象的指针
    );

      GetTextMetrics函数利用当前选择字体的各种度量值来填充由lptm参数所指向的缓冲区,函数如果运行成功则返回TURE,失败则返回FALSE。

      TEXTMETRIC结构定义在WinGdi.h头文件中。

      结构如下:

    typedef struct tagTEXTMETRICA
    {
        LONG        tmHeight;
        LONG        tmAscent;
        LONG        tmDescent;
        LONG        tmInternalLeading;
        LONG        tmExternalLeading;
        LONG        tmAveCharWidth;
        LONG        tmMaxCharWidth;
        LONG        tmWeight;
        LONG        tmOverhang;
        LONG        tmDigitizedAspectX;
        LONG        tmDigitizedAspectY;
        BYTE         tmFirstChar;
        BYTE        tmLastChar;
        BYTE        tmDefaultChar;
        BYTE        tmBreakChar;
        BYTE        tmItalic;
        BYTE        tmUnderlined;
        BYTE        tmStruckOut;
        BYTE        tmPitchAndFamily;
        BYTE        tmCharSet;
    } TEXTMETRICA, *PTEXTMETRICA, NEAR *NPTEXTMETRICA, FAR *LPTEXTMETRICA;

    typedef struct tagTEXTMETRICW
    {
        LONG        tmHeight;
        LONG        tmAscent;
        LONG        tmDescent;
        LONG        tmInternalLeading;
        LONG        tmExternalLeading;
        LONG        tmAveCharWidth;
        LONG        tmMaxCharWidth;
        LONG        tmWeight;
        LONG        tmOverhang;
        LONG        tmDigitizedAspectX;
        LONG        tmDigitizedAspectY;
        WCHAR      tmFirstChar;
        WCHAR      tmLastChar;
        WCHAR      tmDefaultChar;
        WCHAR      tmBreakChar;
        BYTE        tmItalic;
        BYTE        tmUnderlined;
        BYTE        tmStruckOut;
        BYTE        tmPitchAndFamily;
        BYTE        tmCharSet;
    } TEXTMETRICW, *PTEXTMETRICW, NEAR *NPTEXTMETRICW, FAR *LPTEXTMETRICW;

      该结构拥有大约20个属性,这些属性的值的单位取决于设备描述表的映射方式,默认情况下是MM_TEXT,对于TextOut输出来说我们只需要用到前7个,他们的单位是像素。

    LONG        tmHeight;           // 字符基准线上下最大纵向高度,是tmAscenttmDescent之和。
    LONG        tmAscent;       // 字符基准线以上所占的高度。
    LONG        tmDescent;          // 字符基准线以下所占的高度。
    LONG        tmInternalLeading;   // 内部间距,也是重音符号出现的地方。
    LONG        tmExternalLeading;  // 行距
    LONG        tmAveCharWidth;    // 小写字母的加权平均宽度,对于大写字母来说可以用小写字母的加权平均宽度乘以150%计算出来。
    LONG        tmMaxCharWidth;    // 字符中字宽字符的宽度。

      字符的纵向大小是由TEXTMETRIC结构的前五个属性决定的。

      具体情况见下图:

      字体的大小是取决于当前屏幕的分辨率或是所选字体本身的默认大小的,在编写应用程序的时候不要把字体的大小以猜想的方式固定了,因为字体的大小是可变化的,利用GetTextMetrics函数动态的获取它们才是正确的。

    格式化输出

      如果要使用TextOut函数在Windows应用程序中输出多行文字,我们就必须先取得字符的宽度和高度,通常我们在窗口消息处理函数中处理WM_CREATE消息的时候调用GetTextMetrics函数来获取他们,之所以放到WM_CREATE的部分调用,是因为当系统启动后,系统字体的大小就不会发生改变,我们只需要调用一次GetTextMetrics就可以了。

    具体方法如下:

      大家可能对上面代码中的,tm.tmPitchAndFamily & 1 ? 3 : 2,这样的写法感到疑惑,TEXTMETRICS结构的tmPitchAndFamily属性是用来判断字体是否为变宽字体的,如果是等宽字体那么它的低位就为0,如果为变宽字体那么它的低位就为1,所以通过位运算我们可以判断是否为变宽字体,如果是就进行乘以150%的操作。

      看到这里,我们已经了解了TextOut函数输出所需要的所有知识,下面我们将以一个完整的例子对它进一步的学习。

    实例练习

      例子目的是要将GetSystemMetrics函数所需要的参数以及这些参数的含义和返回值,以字符串的方式并格式化后循环输出在屏幕上。

      该例程我们分为两个文件,一个是用来保存GetSystemMetrics函数所需索引的头文件,另一个则是程序的主文件,代码的详细解释见代码的注释部分。

    代码如下:  

    /* sysmetrics.h 头文件 */

    #define NUMLINES ((int) (sizeof sysmetrics / sizeof sysmetrics [0]))       

    struct 

    {

             int Index; // 索引

             TCHAR* szLabel;// 索引的字符串表示

             TCHAR* szDesc;// 索引含义       

    } 

    sysmetrics [ ] =

    {

             SM_CXSCREEN, TEXT("SM_CXSCREEN"), TEXT("Screen width in pixels"), 

             SM_CYSCREEN, TEXT("SM_CYSCREEN"), TEXT("Screen height in pixels"),  

    SM_CXVSCROLL, TEXT("SM_CXVSCROLL"), TEXT("Vertical scroll width"), 

             SM_CYHSCROLL, TEXT("SM_CYHSCROLL"), TEXT("Horizontal scroll height"), 

             SM_CYCAPTION, TEXT("SM_CYCAPTION"), TEXT("Caption bar height"), 

    SM_CXBORDER, TEXT("SM_CXBORDER"), TEXT("Window border width"), 

    SM_CYBORDER, TEXT("SM_CYBORDER"), TEXT("Window border height"),   

    SM_CXFIXEDFRAME, TEXT("SM_CXFIXEDFRAME"), TEXT("Dialog window frame width"), 

    SM_CYFIXEDFRAME, TEXT("SM_CYFIXEDFRAME"), TEXT("Dialog window frame height"),  

    SM_CYVTHUMB, TEXT("SM_CYVTHUMB"), TEXT("Vertical scroll thumb height"), 

             SM_CXHTHUMB, TEXT("SM_CXHTHUMB"), TEXT("Horizontal scroll thumb width"), 

    SM_CXICON, TEXT("SM_CXICON"), TEXT("Icon width"),       

    SM_CYICON, TEXT("SM_CYICON"), TEXT("Icon height"),       

    SM_CXCURSOR, TEXT("SM_CXCURSOR"), TEXT("Cursor width"),       

    SM_CYCURSOR, TEXT("SM_CYCURSOR"), TEXT("Cursor height"),       

    SM_CYMENU, TEXT("SM_CYMENU"), TEXT("Menu bar height"),       

    SM_CXFULLSCREEN, TEXT("SM_CXFULLSCREEN"), TEXT("Full screen client area width"),       

    SM_CYFULLSCREEN, TEXT("SM_CYFULLSCREEN"), TEXT("Full screen client area height"),       

    SM_CYKANJIWINDOW,TEXT("SM_CYKANJIWINDOW"), TEXT("Kanji window height"),       

    SM_MOUSEPRESENT, TEXT("SM_MOUSEPRESENT"), TEXT("Mouse present flag"),       

    SM_CYVSCROLL, TEXT("SM_CYVSCROLL"), TEXT("Vertical scroll arrow height"),       

    SM_CXHSCROLL, TEXT("SM_CXHSCROLL"), TEXT("Horizontal scroll arrow width"),       

    SM_DEBUG, TEXT("SM_DEBUG"), TEXT("Debug version flag"),       

    SM_SWAPBUTTON,TEXT("SM_SWAPBUTTON"), TEXT("Mouse buttons swapped flag"),       

    SM_CXMIN, TEXT("SM_CXMIN"), TEXT("Minimum window width"),       

    SM_CYMIN, TEXT("SM_CYMIN"), TEXT("Minimum window height"),       

    SM_CXSIZE, TEXT("SM_CXSIZE"), TEXT("Min/Max/Close button width"),       

    SM_CYSIZE, TEXT("SM_CYSIZE"), TEXT("Min/Max/Close button height"),       

    SM_CXSIZEFRAME, TEXT("SM_CXSIZEFRAME"), TEXT("Window sizing frame width"),       

    SM_CYSIZEFRAME, TEXT("SM_CYSIZEFRAME"), TEXT("Window sizing frame height"),       

    SM_CXMINTRACK, TEXT("SM_CXMINTRACK"), TEXT("Minimum window tracking width"),       

    SM_CYMINTRACK, TEXT("SM_CYMINTRACK"), TEXT("Minimum window tracking height"),       

    SM_CXDOUBLECLK, TEXT("SM_CXDOUBLECLK"), TEXT("Double click x tolerance"),       

    SM_CYDOUBLECLK, TEXT("SM_CYDOUBLECLK"), TEXT("Double click y tolerance"),       

    SM_CXICONSPACING, TEXT("SM_CXICONSPACING"), TEXT("Horizontal icon spacing"),       

    SM_CYICONSPACING, TEXT("SM_CYICONSPACING"), TEXT("Vertical icon spacing"),       

    SM_MENUDROPALIGNMENT, TEXT("SM_MENUDROPALIGNMENT"), TEXT("Left or right menu drop"),       

    SM_PENWINDOWS, TEXT("SM_PENWINDOWS"), TEXT("Pen extensions installed"),       

    SM_DBCSENABLED, TEXT("SM_DBCSENABLED"), TEXT("Double-Byte Char Set enabled"),       

    SM_CMOUSEBUTTONS, TEXT("SM_CMOUSEBUTTONS"), TEXT("Number of mouse buttons"),       

    SM_SECURE, TEXT("SM_SECURE"), TEXT("Security present flag"),       

    SM_CXEDGE, TEXT("SM_CXEDGE"), TEXT("3-D border width"),       

    SM_CYEDGE, TEXT("SM_CYEDGE"), TEXT("3-D border height"),       

    SM_CXMINSPACING, TEXT("SM_CXMINSPACING"), TEXT("Minimized window spacing width"),       

    SM_CYMINSPACING, TEXT("SM_CYMINSPACING"), TEXT("Minimized window spacing height"),       

    SM_CXSMICON, TEXT("SM_CXSMICON"), TEXT("Small icon width"),       

    SM_CYSMICON, TEXT("SM_CYSMICON"), TEXT("Small icon height"),       

    SM_CYSMCAPTION, TEXT("SM_CYSMCAPTION"), TEXT("Small caption height"),       

    SM_CXSMSIZE, TEXT("SM_CXSMSIZE"), TEXT("Small caption button width"),       

    SM_CYSMSIZE, TEXT("SM_CYSMSIZE"), TEXT("Small caption button height"),       

    SM_CXMENUSIZE, TEXT("SM_CXMENUSIZE"), TEXT("Menu bar button width"),       

    SM_CYMENUSIZE, TEXT("SM_CYMENUSIZE"), TEXT("Menu bar button height"),       

    SM_ARRANGE, TEXT("SM_ARRANGE"), TEXT("How minimized windows arranged"),       

    SM_CXMINIMIZED, TEXT("SM_CXMINIMIZED"), TEXT("Minimized window width"),       

    SM_CYMINIMIZED, TEXT("SM_CYMINIMIZED"), TEXT("Minimized window height"),       

    SM_CXMAXTRACK, TEXT("SM_CXMAXTRACK"), TEXT("Maximum draggable width"),       

    SM_CYMAXTRACK, TEXT("SM_CYMAXTRACK"), TEXT("Maximum draggable height"),       

    SM_CXMAXIMIZED, TEXT("SM_CXMAXIMIZED"), TEXT("Width of maximized window"),       

    SM_CYMAXIMIZED, TEXT("SM_CYMAXIMIZED"), TEXT("Height of maximized window"),       

    SM_NETWORK, TEXT("SM_NETWORK"), TEXT("Network present flag"),       

    SM_CLEANBOOT, TEXT("SM_CLEANBOOT"), TEXT("How system was booted"),       

    SM_CXDRAG, TEXT("SM_CXDRAG"), TEXT("Avoid drag x tolerance"),       

    SM_CYDRAG, TEXT("SM_CYDRAG"), TEXT("Avoid drag y tolerance"),       

    SM_SHOWSOUNDS, TEXT("SM_SHOWSOUNDS"), TEXT("Present sounds visually"),       

    SM_CXMENUCHECK, TEXT("SM_CXMENUCHECK"), TEXT("Menu check-mark width"),       

    SM_CYMENUCHECK, TEXT("SM_CYMENUCHECK"), TEXT("Menu check-mark height"),       

    SM_SLOWMACHINE, TEXT("SM_SLOWMACHINE"), TEXT("Slow processor flag"),       

    SM_MIDEASTENABLED, TEXT("SM_MIDEASTENABLED"), TEXT("Hebrew and Arabic enabled flag"),       

    SM_MOUSEWHEELPRESENT, TEXT("SM_MOUSEWHEELPRESENT"), TEXT("Mouse wheel present flag"),       

    SM_XVIRTUALSCREEN, TEXT("SM_XVIRTUALSCREEN"), TEXT("Virtual screen x origin"),       

    SM_YVIRTUALSCREEN, TEXT("SM_YVIRTUALSCREEN"), TEXT("Virtual screen y origin"),       

    SM_CXVIRTUALSCREEN, TEXT("SM_CXVIRTUALSCREEN"), TEXT("Virtual screen width"),       

    SM_CYVIRTUALSCREEN, TEXT("SM_CYVIRTUALSCREEN"), TEXT("Virtual screen height"),       

    SM_CMONITORS, TEXT("SM_CMONITORS"), TEXT("Number of monitors"),       

    SM_SAMEDISPLAYFORMAT, TEXT("SM_SAMEDISPLAYFORMAT"), TEXT("Same color format flag")

    }; 

    /* main.cpp 主文件 */

    #include <windows.h>

    #include <stdio.h>

    #include "system.h" 

    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); 

    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) 

    static char szAppName[] = TEXT("HelloWin");

    // 预先定义一个c风格字符串,稍后用于设置窗口类名称。

             WNDCLASS wndclass; // 定义窗口类对象。

             wndclass.style          = CS_HREDRAW | CS_VREDRAW;

             wndclass.lpfnWndProc   = WndProc ;

    // 指定窗口的处理函数为WndProcWndProc将处理windows消息。

             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 = szAppName; // 窗口类对象的名称。

    //-----------------------------------------------------------------------------------------

             RegisterClass (&wndclass); 

    //--------------------------  实例化过程  -------------------------------------------------

    HWND   hwnd ;

    //创建用于保存窗口句柄的对象,窗口句柄是系统识别不同窗口的依据,它只是个代号。

        hwnd = CreateWindow(

                                                                     szAppName,          // 窗口类名称。

                                                                     "GDI 入门",           // 窗口标题。

                                                                     WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL,  // 窗口样式。

                                                                     CW_USEDEFAULT,    // 初始的窗口x轴位置。

                                                                     CW_USEDEFAULT,    // 初始的窗口y轴位置。

                                                                     CW_USEDEFAULT,     // 初始的窗口x轴大小。

                                                                     CW_USEDEFAULT,     // 初始的窗口y轴大小。

                                                                     NULL,                 // 父窗口句柄。

                                                                     NULL,                 // 窗口功能表句柄。

                                                                     hInstance,              // 应用程序实例句柄。

                                                                     NULL                  // 建立参数,这个参数可以存取后面程序中可能引用到的资料。

                                                            );

        ShowWindow(hwnd, iCmdShow);

        UpdateWindow (hwnd);

    //-----------------------------------------------------------------------------------------

    //----------------------------  消息循环  -------------------------------------------------

        MSG    msg ; // 建立消息对象。

        while (GetMessage (&msg, NULL, 0, 0))

        {

                                TranslateMessage (&msg);

                                //把虚拟键盘消息转换到字符消息,满足键盘输入的需要,参数为msg消息对象的地址。

                                DispatchMessage (&msg);

                                //把当前的消息发送到消息处理函数中去。

        }

    //----------------------------------------------------------------------------------------

        return msg.wParam;//返回消息结构中的wParam成员信息。

    }   

    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

    // 窗口消息处理函数。

    {

    static int  iLFx, iCFx, iFy ;

    HDC hdc; // 创建设备描述句柄对象。

    PAINTSTRUCT ps; // 创建绘制结构对象。

             int i;

             TCHAR szBuffer [10]; // 创建字符数组用于保存GetSystemMetrics函数返回的值。

             TEXTMETRIC  tm; // 创建TEXTMETRIC结构对象。

             char szChar[200];

             switch (message)

             {

                       case WM_CREATE: // 当窗口创建的时候获得WM_CREATE消息。

                                hdc = GetDC (hwnd); // 获取设备描述表句柄。

                                GetTextMetrics (hdc, &tm);// 调用GetTextMetrics函数获取字符大小相关信息。

                                iLFx = tm.tmAveCharWidth;

                                // 获得小写字符的平均宽度,小写字母的加权平均值就是字符的平均宽度。

                                iCFx = (tm.tmPitchAndFamily & 1 ? 3 : 2) * iLFx / 2;

    // 获得大写字符的平均宽度,对于变宽字体而言,大写字符的平均宽度是iLFx乘以150%,而如果是等宽字体,那么iCFx就等于iLFx

                                iFy = tm.tmHeight + tm.tmExternalLeading;

                                // 字符高度等于字符准线上下最大纵向高度加行距。

                                ReleaseDC (hwnd, hdc) ;

                                return 0 ;

                       case WM_PAINT://通知窗口更新显示区域的信息

                                hdc = BeginPaint (hwnd, &ps);

                                SetTextColor(hdc,RGB(255,0,0));

                                for (i = 0; i<NUMLINES; i++)

                                //通过获取的define定义的NUMLINES进行迭代,以循环输出字符串。

                                {

                                         TextOut (hdc, 0, iFy*i, sysmetrics[i].szLabel,lstrlen (sysmetrics[i].szLabel));

                                         /*

                                                第一个输出由于是从0位置开始,所以x轴为0y轴高度使用字符高度乘以循环次数获得。

                                         */

                                         TextOut (hdc, 22*iCFx, iFy*i, sysmetrics[i].szDesc, lstrlen(sysmetrics[i].szDesc));

                                         /*

                                                   第二个输出由于字符串的起始点有了变化所以必须空出第一列字符串的宽度。

    22*iCFx的是由第一列最长字符串长度加上两个空位得来,空位只是为了美观而多加上的。

                                         */

                                         SetTextAlign (hdc, TA_RIGHT | TA_TOP);

                                         TextOut (hdc, 22*iCFx+40*iLFx, iFy*i, szBuffer,wsprintf (szBuffer, TEXT("%5d"),GetSystemMetrics (sysmetrics[i].Index)));

                                         SetTextAlign (hdc, TA_LEFT | TA_TOP);

                                         /*

    第三个输出主要是输出GetSystemMetrics函数返回的数值,但其中的确有些微妙。

    由于变宽字符由左向右对齐数值的很难实现,所以我们换个思维而选择从右向左的方式对齐。

    调用SetTextAlign (hdc, TA_RIGHT | TA_TOP);可以让对齐方式转变为右向左对齐。

    22*iCFx+40*iLFx,包含了前两列的宽度,它的值成为了第三列字符串的x轴结束位置。

    输出完成后调用SetTextAlign (hdc, TA_LEFT | TA_TOP);让对齐方式恢复默认,以便下一行的输出。

                                         */

                                }

                EndPaint (hwnd, &ps);

                MessageBox(NULL,"此对话框以下遮盖的部分需要更新!","覆盖区域",0);

                return 0;

                       case WM_DESTROY:

    // 当窗口销毁的时候会返回此信息,比如ALT+F4或关闭窗口的时候,系统默认调用DestroyWindow()函数撤消窗口。

                                PostQuitMessage (0);

                                return 0;

             }

      return DefWindowProc (hwnd, message, wParam, lParam);//处理不于处理的消息

    }

     


     

    case WM_CREATE:

             hdc = GetDC (hwnd);         // 取得设备描述表句柄。

             GetTextMetrics (hdc, &tm);  // 调用GetTextMetrics函数将获得的信息保存在缓冲区中。

             iLFx = tm.tmAveCharWidth;

    // 获得小写字符的平均宽度,小写字母的加权平均值就是字符的平均宽度。

             iCFx = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;

    // 获得大写字符的平均宽度,对于变宽字体而言,大写字符的平均宽度是iLFx乘以150%,而如果是等宽字体,那么iCFx就等于iLFx

             iFy = tm.tmHeight + tm.tmExternalLeading; // 字符高度等于字符准线上下最大纵向高度加行距。

             ReleaseDC (hwnd, hdc) ; // 释放设备描述表句柄。

             return 0;

    展开全文
  • GDI/GDI+从入门到精通》视频教程

    千次阅读 2013-03-11 19:50:43
    第一、二、三讲都是打基础的,第四讲开始实战演练,一个小时把前面提到的函数统统运用了一遍,这讲看完基本上就掌握了GDI/GDI+。 第五讲的内容最为精彩了,是高级进阶篇,非常适合继续提高编程能力的网友。不过...
  • Gdi+实用入门

    2014-11-25 09:10:24
    首先下载GDI+文件包,一个动态链接库,使用GDI+就是调用那个动态链接库里的函数。类似画图什么的,了解这个主要是想把bmp图片转换成jpg的,然后做个简单屏幕监控,几个月前尝试做了一下,差不多是半分钟才传过来一张...
  • GDI+入门教程.....

    2018-11-01 14:52:54
    文档包含简单的程序代码和一个调用类demo和GDI+二维绘制说明
  • 1回顶部 格式化输出  如果要使用TextOut函数在Windows应用程序中输出多行文字,我们就必须先取得字符的宽度和高度,通常我们在窗口消息处理函数中处理WM_CREATE消息的时候调用GetTextMetrics函数来获取他们,之...
  • 之前我了解了BeginPaint和EndPaint,这两个函数能找到需要重绘的部分,并重绘之,什么是重绘的部分呢? 这个概念以及后面的validate,invalidate的概念书中介绍得有点模糊,下面是我的一点理解: ...
  • GDI+_入门教程【一】

    2019-02-06 21:51:00
    GDI For VisualBasic6.0 【一】文件下载:GDI+ For VB6【一】 简单绘图实例演示百度网盘 1 '以下为作者【vIsiaswx】的教程 2 '(该教程发布的原地址已无法访问,此版是流散网络的电子书版复制过来的。如果声明...
  • GDI+编程入门

    2018-07-10 09:27:00
    GDI+编程入门完整教程文档,可以通过该文档学习GDI+编程。
  • 用于记录GDI开发所用的基础知识,可以用于以后遇到相关问题时用于查看。
  • 1 ... 在Windows操作系统下,绝大多数具备图形界面的应用程序都离不开GDI,我们利用GDI所提供的众多函数就可以方便的在屏幕、打印机及其它输出设备上输出图形,文本等操作。GDI的出现使程序员无需
  • Windows Gdi入门初级应用(VC SDK) 好久没发贴了,今天手痒痒,发一个。GDI的绘图函数基本上都是有状态的,所有的函数都要求一个HDC类型的句柄。这个HDC的获得有几个途径BeginPaint,GetWindowDC, GetDC.他们的参数...
  •  现在我们对GDI的基础概念有了一定的了解,下面我们将对GDI一些常用的函数进行学习。 TextOut函数  TextOut函数的作用是把指定的字符串输出在我们指定的屏幕位置上。 函数原型: BOOL TextOut(  HDC hdc, /...
  • Windows Gdi入门初级应用(VC SDK) GDI的绘图函数基本上都是有状态的,所有的函数都要求一个HDC类型的句柄。这个HDC的获得有几个途径BeginPaint,GetWindowDC, GetDC.他们的参数都只需要一个HWND就差不多了。记得...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,102
精华内容 1,640
关键字:

gdi入门