回 帖 发 新 帖 刷新版面

主题:[原创]c/c++ 与 Windows 32 图形编程(一)

<为自学者和初学者>     

    标准 C/C++ 没有规定图形函数,因此可以说 C/C++ 没有图形函数.通过 TC 
学习 c/c++ 的初学者,甚至包括一些所谓的 "教员",常常错误的把 graphics 库
当成 c/c++ 的一部分(令人遗憾的是,许多教科书并没有澄清 TC 和标准 c/c++ 
的区别), 当他们改用其他IDE 时往往会对如何绘制图形手足无措.

    在这个论坛上见到许多类似如下的一些问题:

    ● VC (BC++ Builder,Dev-C++ 等) 没有 graphics 库,那它们怎么画图呢?
    ● 我没有 graphics 库,谁能发给我?
    ● 我想绘制曲线,谁能告诉我绘图函数在 C 的哪个头文件里?
    ● c 能编出 Windows 程序吗? 为什么我老是在 "黑屏" 下转悠?
    ● 32 位真彩是怎么回事?
    
    之所以会有上面那些疑问,很大程度上是由于我们教科书的作者们对标准的忽视.
有许多教科书从头到尾没有一句对 ISO/ANSI 标准的介绍( 甚至当它们讲 std 空间时).
有些教材乐于介绍过时的 C "外挂",比如 graphics 库,却根本不谈它是否属于 C 的
范畴.

     由于这类教材的误导,本论坛一位对 C 语法已经相当熟悉的坛友令人费解地耗费大
量时间精力"开发"了一个 256 色图形包.另一位坛友发帖介绍根本不存在的 "c 语言
图形函数".有一位在用了 Dephi 后提问: 为什么要学 C/C++ 这种"低级"的语言? 
还有一位坛友断言 c 语言本身不支持 Windows 程序.

    看了上面的一段话,可能会有很多人会产生如下的疑问和感叹:
    
    ● 都说 C 功能强大,没想到居然不能绘图
    ● 为什么 C 没有图形函数呢? 这是否是 C 的一个巨大缺陷呢?
    ● 原来 C 不支持图形,难怪我们老是在黑屏下转悠了
    
    为澄清上述疑问,首先要指出的是:
    
    [color=000080][size=5]c 没有图形函数并不表明 c 不支持图形处理.[/size][/color]

    打个简单的比方: 机械制造厂需要的是机械制造设备而不是矿山设备,但它能生产
矿山设备.
    
    [color=000080][size=5]c 虽然没有图形函数,但 c 能生产图形函数.[/size]
[/color]
    
     对操作系统和图形设备驱动程序的开发者来说,他使用的语言是否有图形处理函数
是无关紧要的,因为他的目的是设计并编写新的图形处理函数而不是使用已有的图形处理
函数.
    为了充分发挥图形处理设备的处理能力,图形处理硬件需要与自己配套的驱动程序,
为了使这个驱动程序能和操作系统有机的结合在一起,驱动程序还需要按照操作系统的要
求来编写.新的图形处理设备的性能较旧型号一般都有一定提高,加入了新的特性.由于
图形硬件种类型号繁多,程序语言不可能把各种硬件的各种不同操作系统的驱动程序集成
到语言内,因此程序语言所集成的图形函数一般只是与设备无关的图形函数,为了使这些
与设备无关的图形函数能正常工作,就必须依赖操作系统把这些与设备无关的图形函数
转化为与设备有关的图形函数.也就是说,操作系统必须提供一个与设备无关的图形接口
供程序语言使用,操作系统必须提供一种机制使这些与设备无关的图形函数转化为与设备
有关的图形函数.由于操作系统的种类繁多,它们所提供的与设备无关的图形接口千差万
别,因而指望程序语言包含所有的操作系统的与设备无关的图形接口是不现实的.对需要
跨越多种软硬件平台的程序语言来说,合理的选择是让这种语言具备生产各种平台的图形
函数的能力而不是去集成,也就是说,让它具有编写操作系统和设备驱动程序的能力.这样
,我们就不需要把某种具体平台\具体设备的图形处理函数集成到语言内.这正是标准 c 
的做法.

    在 DOS 编程时代,由于 DOS 没有提供一个与设备无关的图形接口( 这在 16 位的系
统下也确实很难作到),因此为了在应用程序中绘制图象就不得不直接和各种硬件或直接
和它们的驱动程序打交道.由于硬件的多样性,DOS 时代的图形编程是一件极其痛苦的事.
你必须有广泛的知识,了解硬件的各种选项和控制方法.可为应用程序购买的图形库极少,
而且这些图形库只能在特定的设备上工作,不能完全发挥硬件的能力. TC 的 graphics
库是 DOS 时代 C 语言的最优秀的 "外挂" 之一, 它是 C 的 "外挂",不属于标准 C 的
范畴.即便如此, TC 的 graphics 库所提供的设备驱动数量极其有限,不能充分发挥硬件
性能,无法处理象绘图仪\照排设备等图形输出设备.

    Windows 简化了这项工作,因为 Windows 向用户提供了 GDI ( 图形设备接口) 这个
与设备无关的编程接口,另外一个最常用的编程接口就是著名的 DirectX, DirectX 几乎
是现代 3D 游戏的唯一图形编程接口.
    我们首先来看看如何使用 GDI 接口,附带几个小程序来说明如何作图.C/C++ 的各种
著名的 Win32 IDE 都提供了相应的头文件供用户使用这个接口.这个接口的实现部分是
Windows 系统的一个组成部分: GDI . DLL
     GDI 接口屏蔽了硬件的具体细节,它提供一个虚拟的图形设备供用户使用,这使得用
户可以用同样的函数集来操作不同的图形硬件.不管这个硬件是显示卡\打印机\绘图仪
\照排系统还是其他图形设备,用户都按照相同的方式来操作它们.
    利用 GDI 接口,用户可以把所有设备都视为某个窗口的"设备场境"(Device Context,简记为 DC),实际上这允许用户把各种图形设备都看成窗口,你只要获得这个
"窗口"的设备场境句柄,就能在这个窗口上自由的作图.所有的硬件共同使用同一个函数集,这意味着你为某种硬件编写的程序只需修改一下设备场境所关联的对象就可以正常
在另一种硬件上工作.这就是"设备无关性"的好处.
    先解释一下设备场境的概念.设备场境是一个定义了图形对象集,这些对象的属性
以及影响输出的图形模式的结构.
    为了在指定设备上作图,首先应该获得该设备场境的句柄.我们举几个例子.我们要在
控制台程序(Console)的运行窗口上绘制一系列点,一根线和一个圆.我们给出 BC++Buider 6 / VC++6  两种 IDE 的描述.
 
[size=3][color=000080]<BC++Builder6>[/color][/size]
  点击 file 菜单,选 new 菜单, 然后选 other 命令,在打开的 New Items 对话框中选 new 标签下的 console wizard, 点击 OK 打开 Console Wizard 对话框, 在 Console Wizard 对话框的 source type 中选 c (语言) 选项, 然后勾中 Console Application复选框.单击 OK,打开代码页.在代码页中我们看见 Wizard 已经为我们创建了 main 函数框架.我们的代码如下:

#pragma hdrstop
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
//---------------------------------------------------------------------------

#pragma argsused

 int main(int argc, char* argv[])
{

        HWND hWnd=FindWindow(NULL,argv[0]); //找到程序运行窗口的句柄
        HDC hDC=GetDC(hWnd);//通过窗口句柄得到该窗口的设备场境句柄
        HPEN hPen,hOldPen; //画笔
        int i=0;

        for(;i<500;++i)
            SetPixel(hDC,10+i,10+i,0x0000ff);//用画点的办法画一根线,最后一个参数是颜色(32位)

        hPen=CreatePen(PS_SOLID,2,0x00ff00);//生成绿色画笔
        hOldPen=SelectObject(hDC,hPen);//把画笔引入设备场境


        MoveToEx(hDC,20,50,NULL); //设置画线起点
        LineTo(hDC,520,550);      //画到终点

        Arc(hDC,100,100,300,300,350,500,350,500);//画圆

        SelectObject(hDC,hOldPen);//复原

        //下面是对比,表明它确实是控制台程序

        printf("hello console");
        system("pause");
        return 0;
}

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

点击运行菜单就可以看见效果了,应当注意的是,和 graphics 库不同,我们不需要初始化
图形环境.

[color=000080][size=3]<VC++6>[/size][/color]

选文件 -> 新建 -> 工程, 在打开的新工程窗口中选 Win32 Console Application , 起名后单击确定后保存工程,然后选"一个简单的程序".向导给我们生成了 main 函数的框架填加对 windows.h 的包含,然后写入如下代码:

#include "stdafx.h"
#include <windows.h>
#include <string.h>
#include <stdio.h>

 int main(int argc, char* argv[])
{
        char arg[200]={0};
        arg[0]='\"';
        strcpy(arg+1,argv[0]);
        int len=int(strlen(arg));
        arg[len]='\"';
        

        HWND hWnd=FindWindow(NULL,arg); //找到程序运行窗口的句柄
        HDC hDC=GetDC(hWnd);//通过窗口句柄得到该窗口的设备场境句柄
        HPEN hPen,hOldPen; //画笔
        int i=0;

        for(;i<500;++i)
            SetPixel(hDC,10+i,10+i,0x0000ff);//用画点的办法画一根线,最后一个参数是颜色(32位)

        hPen=CreatePen(PS_SOLID,2,0x00ff00);//生成绿色画笔
        hOldPen=(HPEN)SelectObject(hDC,hPen);//把画笔引入设备场境


        MoveToEx(hDC,20,50,NULL); //设置画线起点
        LineTo(hDC,520,550);      //画到终点

        Arc(hDC,100,100,300,300,350,500,350,500);//画圆

        SelectObject(hDC,hOldPen);

        //下面是对比,表明它确实是控制台程序

        printf("hello console");
        system("pause");
        return 0;

}

我们看到, 两种 IDE 下我们用的代码是基本一致的, 也就是 gdi 接口和 IDE 无关,因为它是操作系统的一个部分.

下一篇将介绍 GDI 接口的各种图形对象和常见的图形函数.

回复列表 (共14个回复)

沙发

楼主辛苦了。
当初我用TurboC的时候还嫌着graphics.h里面的东西太烦没去学,后来学了点汇编,不知怎么的又热衷于在16位子系统中修改显存了,在前进中中确实走了些弯路。
回头看看,以前的问题现在虽然弄懂了一点,但我都没有拿到这里来跟别人分享。确实现在很多书对初学者有误导,我这个副斑竹也没有站出来讲两句,实在是有点对不住大家了。
再次感谢楼主的辛勤劳动!

板凳

顶一下!

3 楼

当时就是因为在VC中没法用graphics.h所以才去学了windows api.
楼主辛苦了~~~~~

4 楼

顶.

5 楼

哦,原来是这样
但是我们现在正在学计算机图形学,老师要求必须用C语言画图
那我该怎办呢?

6 楼

[quote]哦,原来是这样
但是我们现在正在学计算机图形学,老师要求必须用C语言画图
那我该怎办呢?[/quote]

学了你就懂了

7 楼

用c_free怎么两个都运行不通呀 ??
请问适合什么编译器的

8 楼

厉害啊
楼主 
一定好好学习C语言
其实我也有这样的疑惑
现在你一说我就更加明白了
打好基础是关键!

9 楼

图形库有很多,比如opengl,allegro,还有其他一些自由软件,只要从网上把它们的库下载然后加到/lib中就好了,比GDI好,还有源码。更适合学习。最近我想学allegro,有没有人跟我一起学哈?[em2]

10 楼

为楼主的努力感动。

楼主的话也是本人蓄谋已久的话,只是觉得论坛里都是学生, 中国教育也很落后,
导致这种总体错误认识,一两个人说了也是白说,大量的错误疑问仍旧接踵而来。


==============================================
本论坛一位对 C 语法已经相当熟悉的坛友令人费解地耗费大
量时间精力"开发"了一个 256 色图形包
====================================

没有什么费解的,应支持原创,我以为,不过不要以为这就是所谓的C语言图形包,C语言根本没有什么图形库, 所有图形库都是第三方,自己也可以开发。

我来回复

您尚未登录,请登录后再回复。点此登录或注册