c/c++ 与 Windows 32 图形编程(一)

 
作者:tianyuan008      发表时间:2006-3-13 23:51:00

楼主  

<为自学者和初学者>     

    标准 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 不支持图形,难怪我们老是在黑屏下转悠了
    
    为澄清上述疑问,首先要指出的是:
    
    c 没有图形函数并不表明 c 不支持图形处理.

    打个简单的比方: 机械制造厂需要的是机械制造设备而不是矿山设备,但它能生产
矿山设备.
    
    c 虽然没有图形函数,但 c 能生产图形函数.

    
     对操作系统和图形设备驱动程序的开发者来说,他使用的语言是否有图形处理函数
是无关紧要的,因为他的目的是设计并编写新的图形处理函数而不是使用已有的图形处理
函数.
    为了充分发挥图形处理设备的处理能力,图形处理硬件需要与自己配套的驱动程序,
为了使这个驱动程序能和操作系统有机的结合在一起,驱动程序还需要按照操作系统的要
求来编写.新的图形处理设备的性能较旧型号一般都有一定提高,加入了新的特性.由于
图形硬件种类型号繁多,程序语言不可能把各种硬件的各种不同操作系统的驱动程序集成
到语言内,因此程序语言所集成的图形函数一般只是与设备无关的图形函数,为了使这些
与设备无关的图形函数能正常工作,就必须依赖操作系统把这些与设备无关的图形函数
转化为与设备有关的图形函数.也就是说,操作系统必须提供一个与设备无关的图形接口
供程序语言使用,操作系统必须提供一种机制使这些与设备无关的图形函数转化为与设备
有关的图形函数.由于操作系统的种类繁多,它们所提供的与设备无关的图形接口千差万
别,因而指望程序语言包含所有的操作系统的与设备无关的图形接口是不现实的.对需要
跨越多种软硬件平台的程序语言来说,合理的选择是让这种语言具备生产各种平台的图形
函数的能力而不是去集成,也就是说,让它具有编写操作系统和设备驱动程序的能力.这样
,我们就不需要把某种具体平台/具体设备的图形处理函数集成到语言内.这正是标准 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 的描述.
 
<BC++Builder6>
  点击 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 库不同,我们不需要初始化
图形环境.

<VC++6>

选文件 -> 新建 -> 工程, 在打开的新工程窗口中选 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 接口的各种图形对象和常见的图形函数.

 

 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值