關於C、C++的圖形函數庫問題


原文:http://blog.sina.com.cn/s/blog_5c91824f0101ggon.html

 

標准 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 的描述.


點擊 file 菜單,選 new 菜單, 然后選 other 命令,在打開的 New Items 對話框中選 new 標簽下的 console wizard, 點擊 OK 打開 Console Wizard 對話框, 在 Console Wizard 對話框的 source type 中選 c (語言) 選項, 然后勾中 Console Application復選框.單擊 OK,打開代碼頁.在代碼頁中我們看見 Wizard 已經為我們創建了 main 函數框架.我們的代碼如下:

 

#pragma hdrstop
#include
#include
#include
//---------------------------------------------------------------------------

 

#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 庫不同,我們不需要初始化
圖形環境.

 

選文件 -> 新建 -> 工程, 在打開的新工程窗口中選 Win32 Console Application , 起名后單擊確定后保存工程,然后選"一個簡單的程序".向導給我們生成了 main 函數的框架填加對 windows.h 的包含,然后寫入如下代碼:

 

#include "stdafx.h"
#include
#include
#include

 

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 無關,因為它是操作系統的一個部分.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM