數字圖像處理編程入門—第1章 Windows位圖和調色板

<iframe name="google_ads_frame" marginwidth="0" marginheight="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-0496393683895860&dt=1190078602171&lmt=1190078602&prev_fmts=728x90_as%2C728x90_as&format=468x15_0ads_al_s&output=html&correlator=1190078600937&url=http%3A%2F%2Fwww.sheji8.net%2FanArticlelist.asp%3FArticleID%3D544%26ArticlePage%3D1&cc=226&ga_vid=1205560419.1190078601&ga_sid=1190078601&ga_hid=1817377489&flash=9&u_h=1050&u_w=1680&u_ah=1020&u_aw=1680&u_cd=32&u_tz=480&u_java=true" frameborder="0" width="468" scrolling="no" height="15" allowtransparency="allowtransparency"></iframe>

1.1 位圖和調色板的概念

如今Windows(3.x以及9598NT)系列已經成爲絕大多數用戶使用的操作系統,它比DOS成功的一個重要因素是它可視化的漂亮界面。那麼Windows是如何顯示圖象的呢?這就要談到位圖(bitmap)

我們知道,普通的顯示器屏幕是由許許多多點構成的,我們稱之爲象素。顯示時採用掃描的方法:電子槍每次從左到右掃描一行,爲每個象素着色,然後從上到下這樣掃描若干行,就掃過了一屏。爲了防止閃爍,每秒要重複上述過程幾十次。例如我們常說的屏幕分辨率爲640×480,刷新頻率爲70Hz,意思是說每行要掃描640個象素,一共有480行,每秒重複掃描屏幕70次。

我們稱這種顯示器爲位映象設備。所謂位映象,就是指一個二維的象素矩陣,而位圖就是採用位映象方法顯示和存儲的圖象。舉個例子,圖1.1是一幅普通的黑白位圖,圖1.2是被放大後的圖,圖中每個方格代表了一個象素。我們可以看到:整個骷髏就是由這樣一些黑點和白點組成的。

1.1    骷髏

1.2     放大後的骷髏位圖

那麼,彩色圖是怎麼回事呢?

我們先來說說三元色RGB概念。

我們知道,自然界中的所有顏色都可以由紅、綠、藍(RGB)組合而成。有的顏色含有紅色成分多一些,如深紅;有的含有紅色成分少一些,如淺紅。針對含有紅色成分的多少,可以分成0255256個等級,0級表示不含紅色成分;255級表示含有100%的紅色成分。同樣,綠色和藍色也被分成256級。這種分級概念稱爲量化。

這樣,根據紅、綠、藍各種不同的組合我們就能表示出256×256×256,約1600萬種顏色。這麼多顏色對於我們人眼來說已經足夠豐富了。

1.1     常見顏色的RGB組合值

顏色

R

G

B

255

0

0

0

255

0

0

0

255

255

255

0

255

0

255

0

255

255

255

255

255

0

0

0

128

128

128

你大概已經明白了,當一幅圖中每個象素賦予不同的RGB值時,能呈現出五彩繽紛的顏色了,這樣就形成了彩色圖。的確是這樣的,但實際上的做法還有些差別。

讓我們來看看下面的例子。

有一個長寬各爲200個象素,顏色數爲16色的彩色圖,每一個象素都用RGB三個分量表示。因爲每個分量有256個級別,要用8(bit),即一個字節(byte)來表示,所以每個象素需要用3個字節。整個圖象要用200×200×3,約120k字節,可不是一個小數目呀!如果我們用下面的方法,就能省的多。

因爲是一個16色圖,也就是說這幅圖中最多隻有16種顏色,我們可以用一個表:表中的每一行記錄一種顏色的RGB值。這樣當我們表示一個象素的顏色時,只需要指出該顏色是在第幾行,即該顏色在表中的索引值。舉個例子,如果表的第0行爲25500(紅色),那麼當某個象素爲紅色時,只需要標明0即可。

讓我們再來計算一下:16種狀態可以用4(bit)表示,所以一個象素要用半個字節。整個圖象要用200×200×0.5,約20k字節,再加上表佔用的字節爲3×16=48字節.整個佔用的字節數約爲前面的1/6,省很多吧?

這張RGB的表,就是我們常說的調色板(Palette),另一種叫法是顏色查找表LUT(Look Up Table),似乎更確切一些。Windows位圖中便用到了調色板技術。其實不光是Windows位圖,許多圖象文件格式如pcxtifgif等都用到了。所以很好地掌握調色板的概念是十分有用的。

有一種圖,它的顏色數高達256×256×256種,也就是說包含我們上述提到的RGB顏色表示方法中所有的顏色,這種圖叫做真彩色圖(true color)。真彩色圖並不是說一幅圖包含了所有的顏色,而是說它具有顯示所有顏色的能力,即最多可以包含所有的顏色。表示真彩色圖時,每個象素直接用RGB三個分量字節表示,而不採用調色板技術。原因很明顯:如果用調色板,表示一個象素也要用24位,這是因爲每種顏色的索引要用24(因爲總共有224種顏色,即調色板有224),和直接用RGB三個分量表示用的字節數一樣,不但沒有任何便宜,還要加上一個256×256×256×3個字節的大調色板。所以真彩色圖直接用RGB三個分量表示,它又叫做24位色圖。

1.2 bmp文件格式

介紹完位圖和調色板的概念,下面就讓我們來看一看Windows的位圖文件(.bmp文件)的格式是什麼樣子的。

bmp文件大體上分成四個部分,如圖1.3所示。

位圖文件頭BITMAPFILEHEADER

位圖信息頭BITMAPINFOHEADER

調色板Palette

實際的位圖數據ImageDate

1.3     Windows位圖文件結構示意圖

第一部分爲位圖文件頭BITMAPFILEHEADER,是一個結構,其定義如下:

typedef struct tagBITMAPFILEHEADER {

WORD           bfType;

DWORD bfSize;

WORD           bfReserved1;

WORD           bfReserved2;

DWORD bfOffBits;

} BITMAPFILEHEADER;

這個結構的長度是固定的,爲14個字節(WORD爲無符號16位整數,DWORD爲無符號32位整數),各個域的說明如下:

bfType

指定文件類型,必須是0x424D,即字符串“BM”,也就是說所有.bmp文件的頭兩個字節都是“BM”。

bfSize

指定文件大小,包括這14個字節。

bfReserved1bfReserved2     

爲保留字,不用考慮

bfOffBits

爲從文件頭到實際的位圖數據的偏移字節數,即圖1.3中前三個部分的長度之和。

第二部分爲位圖信息頭BITMAPINFOHEADER,也是一個結構,其定義如下:

typedef struct tagBITMAPINFOHEADER{

DWORD  biSize;

LONG            biWidth;

LONG            biHeight;

WORD           biPlanes;

WORD           biBitCount

DWORD  biCompression;

DWORD  biSizeImage;

LONG            biXPelsPerMeter;

LONG            biYPelsPerMeter;

DWORD  biClrUsed;

DWORD  biClrImportant;

} BITMAPINFOHEADER;

這個結構的長度是固定的,爲40個字節(LONG32位整數),各個域的說明如下:

biSize

指定這個結構的長度,爲40

biWidth

指定圖象的寬度,單位是象素。

biHeight

指定圖象的高度,單位是象素。

biPlanes

必須是1,不用考慮。

biBitCount

指定表示顏色時要用到的位數,常用的值爲1(黑白二色圖), 4(16色圖), 8(256), 24(真彩色圖)(新的.bmp格式支持32位色,這裏就不做討論了)

biCompression

指定位圖是否壓縮,有效的值爲BI_RGBBI_RLE8BI_RLE4BI_BITFIELDS(都是一些Windows定義好的常量)。要說明的是,Windows位圖可以採用RLE4,和RLE8的壓縮格式,但用的不多。我們今後所討論的只有第一種不壓縮的情況,即biCompressionBI_RGB的情況。

biSizeImage

指定實際的位圖數據佔用的字節數,其實也可以從以下的公式中計算出來:

biSizeImage=biWidth’ × biHeight

要注意的是:上述公式中的biWidth’必須是4的整倍數(所以不是biWidth,而是biWidth’,表示大於或等於biWidth的,最接近4的整倍數。舉個例子,如果biWidth=240,則biWidth’=240;如果biWidth=241biWidth’=244)

如果biCompressionBI_RGB,則該項可能爲零

biXPelsPerMeter

指定目標設備的水平分辨率,單位是每米的象素個數,關於分辨率的概念,我們將在第4章詳細介紹。

biYPelsPerMeter

指定目標設備的垂直分辨率,單位同上。

biClrUsed

指定本圖象實際用到的顏色數,如果該值爲零,則用到的顏色數爲2biBitCount

biClrImportant

指定本圖象中重要的顏色數,如果該值爲零,則認爲所有的顏色都是重要的。

第三部分爲調色板Palette,當然,這裏是對那些需要調色板的位圖文件而言的。有些位圖,如真彩色圖,前面已經講過,是不需要調色板的,BITMAPINFOHEADER後直接是位圖數據。

調色板實際上是一個數組,共有biClrUsed個元素(如果該值爲零,則有2biBitCount個元素)。數組中每個元素的類型是一個RGBQUAD結構,佔4個字節,其定義如下:

typedef struct tagRGBQUAD {

BYTE    rgbBlue; //該顏色的藍色分量

BYTE    rgbGreen; //該顏色的綠色分量

BYTE    rgbRed; //該顏色的紅色分量

BYTE    rgbReserved; //保留值

} RGBQUAD;

第四部分就是實際的圖象數據了。對於用到調色板的位圖,圖象數據就是該象素顏在調色板中的索引值。對於真彩色圖,圖象數據就是實際的RGB值。下面針對2色、16色、256色位圖和真彩色位圖分別介紹。

對於2色位圖,用1位就可以表示該象素的顏色(一般0表示黑,1表示白),所以一個字節可以表示8個象素。

對於16色位圖,用4位可以表示一個象素的顏色,所以一個字節可以表示2個象素。

對於256色位圖,一個字節剛好可以表示1個象素。

對於真彩色圖,三個字節才能表示1個象素,哇,好費空間呀!沒辦法,誰叫你想讓圖的顏色顯得更亮麗呢,有得必有失嘛。

要注意兩點:

(1)    每一行的字節數必須是4的整倍數,如果不是,則需要補齊。這在前面介紹biSizeImage時已經提到了。

(2)    一般來說,.bMP文件的數據從下到上,從左到右的。也就是說,從文件中最先讀到的是圖象最下面一行的左邊第一個象素,然後是左邊第二個象素……接下來是倒數第二行左邊第一個象素,左邊第二個象素……依次類推 ,最後得到的是最上面一行的最右一個象素。

好了,終於介紹完bmp文件結構了,是不是覺得頭有些大?彆着急,對照着下面的程序,你就會很清楚了(我最愛看源程序了,呵呵)

1.3 顯示一個bmp文件的C程序

下面的函數LoadBmpFile,其功能是從一個.bmp文件中讀取數據(包括BITMAPINFOHEADER,調色板和實際圖象數據),將其存儲在一個全局內存句柄hImgData中,這個hImgData將在以後的圖象處理程序中用到。同時填寫一個類型爲HBITMAP的全局變量hBitmap和一個類型爲HPALETTE的全局變量hPalette。這兩個變量將在處理WM_PAINT消息時用到,用來顯示位圖。該函數的兩個參數分別是用來顯示位圖的窗口句柄,和.bmp文件名(全路徑)。當函數成功時,返回TRUE,否則返回FALSE

BITMAPFILEHEADER  bf;

BITMAPINFOHEADER bi;

BOOL LoadBmpFile (HWND hWnd,char *BmpFileName)

{  

HFILE                      hf; //文件句柄

//指向BITMAPINFOHEADER結構的指針

LPBITMAPINFOHEADER    lpImgData;

LOGPALETTE                           *pPal; //指向邏輯調色板結構的指針

LPRGBQUAD                            lpRGB; //指向RGBQUAD結構的指針

HPALETTE                               hPrevPalette; //用來保存設備中原來的調色板

HDC                                         hDc; //設備句柄

HLOCAL                                   hPal; //存儲調色板的局部內存句柄

DWORD                                   LineBytes;  //每一行的字節數

DWORD                                   ImgSize;   //實際的圖象數據佔用的字節數

//實際用到的顏色數 ,即調色板數組中的顏色個數

DWORD                                   NumColors;

DWORD                                   i;

if((hf=_lopen(BmpFileName,OF_READ))==HFILE_ERROR){

MessageBox(hWnd,"File c://test.bmp not found!","Error Message",

MB_OK|MB_ICONEXCLAMATION);

return FALSE; //打開文件錯誤,返回

}

//BITMAPFILEHEADER結構從文件中讀出,填寫到bf

_lread(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER));

//BITMAPINFOHEADER結構從文件中讀出,填寫到bi

_lread(hf,(LPSTR)&bi,sizeof(BITMAPINFOHEADER));

//我們定義了一個宏 #define WIDTHBYTES(i)    ((i+31)/32*4)上面曾經

//提到過,每一行的字節數必須是4的整倍數,只要調用

//WIDTHBYTES(bi.biWidth*bi.biBitCount)就能完成這一換算。舉一個例

//子,對於2色圖,如果圖象寬是31,則每一行需要31位存儲,合3

//字節加7位,因爲字節數必須是4的整倍數,所以應該是4,而此時的

//biWidth=31,biBitCount=1,WIDTHBYTES(31*1)=4,和我們設想的一樣。

//再舉一個256色的例子,如果圖象寬是31,則每一行需要31個字節存

//儲,因爲字節數必須是4的整倍數,所以應該是32,而此時的

//biWidth=31,biBitCount=8,WIDTHBYTES(31*8)=32,我們設想的一樣。你可

//以多舉幾個例子來驗證一下

//LineBytes爲每一行的字節數

LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount);

//ImgSize爲實際的圖象數據佔用的字節數

ImgSize=(DWORD)LineBytes*bi.biHeight;

//NumColors爲實際用到的顏色數 ,即調色板數組中的顏色個數

if(bi.biClrUsed!=0)

//如果bi.biClrUsed不爲零,即爲實際用到的顏色數

NumColors=(DWORD)bi.biClrUsed;

else //否則,用到的顏色數爲2biBitCount

switch(bi.biBitCount){

case 1:

NumColors=2;

                     break;

                      case 4:

NumColors=16;

                    break;

       case 8:

           NumColors=256;

           break;

       case 24:

           NumColors=0; //對於真彩色圖,沒用到調色板

           break;

default: //不處理其它的顏色數,認爲出錯。

MessageBox(hWnd,"Invalid color numbers!","Error Message",

MB_OK|MB_ICONEXCLAMATION);

_lclose(hf);

                     return FALSE; //關閉文件,返回FALSE

}

if(bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD)+

sizeof(BITMAPFILEHEADER)+

sizeof(BITMAPINFOHEADER)))

{

//計算出的偏移量與實際偏移量不符,一定是顏色數出錯

   MessageBox(hWnd,"Invalid color numbers!","Error Message",

MB_OK|MB_ICONEXCLAMATION);

_lclose(hf);

return FALSE; //關閉文件,返回FALSE

}

bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+

NumColors*sizeof(RGBQUAD)+ImgSize;

//分配內存,大小爲BITMAPINFOHEADER結構長度加調色板+實際位圖

if((hImgData=GlobalAlloc(GHND,(DWORD)

(sizeof(BITMAPINFOHEADER)+

NumColors*sizeof(RGBQUAD)+

ImgSize)))==NULL)

{

//分配內存錯誤

MessageBox(hWnd,"Error alloc memory!","ErrorMessage",MB_OK|

                 MB_ICONEXCLAMATION);

_lclose(hf);

return FALSE; //關閉文件,返回FALSE

}

//指針lpImgData指向該內存區

lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);

//文件指針重新定位到BITMAPINFOHEADER開始處

_llseek(hf,sizeof(BITMAPFILEHEADER),SEEK_SET);

//將文件內容讀入lpImgData

_hread(hf,(char *)lpImgData,(long)sizeof(BITMAPINFOHEADER)

+(long)NumColors*sizeof(RGBQUAD)+ImgSize);

_lclose(hf); //關閉文件

if(NumColors!=0) //NumColors不爲零,說明用到了調色板

{

//爲邏輯調色板分配局部內存,大小爲邏輯調色板結構長度加

//NumColorsPALETTENTRY

hPal=LocalAlloc(LHND,sizeof(LOGPALETTE)+

NumColors* sizeof(PALETTEENTRY));

//指針pPal指向該內存區

pPal =(LOGPALETTE *)LocalLock(hPal);

   //填寫邏輯調色板結構的頭

pPal->palNumEntries = NumColors;

   pPal->palVersion = 0x300;

//lpRGB指向的是調色板開始的位置

lpRGB = (LPRGBQUAD)((LPSTR)lpImgData +

(DWORD)sizeof(BITMAPINFOHEADER));

//填寫每一項

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

   {

pPal->palPalEntry[i].peRed=lpRGB->rgbRed;

pPal->palPalEntry[i].peGreen=lpRGB->rgbGreen;

pPal->palPalEntry[i].peBlue=lpRGB->rgbBlue;

pPal->palPalEntry[i].peFlags=(BYTE)0;

lpRGB++; //指針移到下一項

}

//產生邏輯調色板,hPalette是一個全局變量

hPalette=CreatePalette(pPal);

//釋放局部內存

LocalUnlock(hPal);

LocalFree(hPal);

}

//獲得設備上下文句柄

hDc=GetDC(hWnd);

if(hPalette) //如果剛纔產生了邏輯調色板

{

//將新的邏輯調色板選入DC,將舊的邏輯調色板句柄保存在//hPrevPalette

hPrevPalette=SelectPalette(hDc,hPalette,FALSE);

RealizePalette(hDc);

}

//產生位圖句柄

hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpImgData,

(LONG)CBM_INIT,

(LPSTR)lpImgData+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD),

(LPBITMAPINFO)lpImgData, DIB_RGB_COLORS);

//將原來的調色板(如果有的話)選入設備上下文句柄

if(hPalette && hPrevPalette)

{

SelectPalette(hDc,hPrevPalette,FALSE);

RealizePalette(hDc);

}

ReleaseDC(hWnd,hDc); //釋放設備上下文

GlobalUnlock(hImgData); //解鎖內存區

return TRUE; //成功返回

}

對上面的程序要說明兩點:

(1)    對於需要調色板的圖,要想正確地顯示,必須根據bmp文件,產生邏輯調色板。產生的方法是:①爲邏輯調色板指針分配內存,大小爲邏輯調色板結構(LOGPALETTE)長度加NumColorsPALETTENTRY大小(調色板的每一項都是一個PALETTEENTRY結構);②填寫邏輯調色板結構的頭pPal->palNumEntries = NumColors; pPal->palVersion = 0x300;③從文件中讀取調色板的RGB值,填寫到每一項中;④產生邏輯調色板:hPalette=CreatePalette(pPal)

(2)    產生位圖(BITMAP)句柄,該項工作由函數CreateDIBitmap來完成。

hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpImgData,

(LONG)CBM_INIT,

(LPSTR)lpImgData+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD),

(LPBITMAPINFO)lpImgData, DIB_RGB_COLORS);

CreateDIBitmap的作用是產生一個和Windows設備無關的位圖。該函數的第一項參數爲設備上下文句柄。如果位圖用到了調色板,要在調用CreateDIBitmap之前將邏輯調色板選入該設備上下文中,產生hBitmap後,再把原調色板選入該設備上下文中,並釋放該上下文;第二項爲指向BITMAPINFOHEADER的指針;第三項就用常量CBM_INI,不用考慮;第四項爲指向調色板的指針;第五項爲指向BITMAPINFO(包括BITMAPINFOHEADER,調色板,及實際的圖象數據)的指針;第六項就用常量DIB_RGB_COLORS,不用考慮。

上面提到了設備上下文,相信編過Windows程序的讀者對它並不陌生,這裏再簡單介紹一下。Windows操作系統統一管理着諸如顯示,打印等操作,將它們看作是一個個的設備,每一個設備都有一個複雜的數據結構來維護。所謂設備上下文就是指這個數據結構。然而,我們不能直接和這些設備上下文打交道,只能通過引用標識它的句柄(實際上是一個整數),讓Windows去做相應的處理。

產生的邏輯調色板句柄hPalette和位圖句柄hBitmap要在處理WM_PAINT消息時使用,這樣才能在屏幕上顯示出來,處理過程如下面的程序。

Static      HDC              hDC,hMemDC;

PAINTSTRUCT            ps;

case WM_PAINT:

{

hDC = BeginPaint(hwnd, &ps); //獲得屏幕設備上下文

if (hBitmap) //hBitmap一開始是NULL,當不爲NULL時表示有圖

{

hMemDC = CreateCompatibleDC(hDC); //建立一個內存設備上下文

if (hPalette) //有調色板

{

//將調色板選入屏幕設備上下文

SelectPalette (hDC, hPalette, FALSE);

//將調色板選入內存設備上下文

SelectPalette (hMemDC, hpalette, FALSE);

RealizePalette (hDC);

}

//將位圖選入內存設備上下文

SelectObject(hMemDC, hBitmap);

//顯示位圖

BitBlt(hDC, 0, 0, bi.biWidth, bi.biHeight, hMemDC, 0, 0, SRCCOPY);

//釋放內存設備上下文

DeleteDC(hMemDC);

}

//釋放屏幕設備上下文

EndPaint(hwnd, &ps);

break;

}

在上面的程序中,我們調用CreateCompatibleDC創建一個內存設備上下文。SelectObject函數將與設備無關的位圖選入內存設備上下文中。然後我們調用BitBlt函數在內存設備上下文和屏幕設備上下文中進行位拷貝。由於所有操作都是在內存中進行,所以速度很快。

BitBlt函數的參數分別爲:1.目標設備上下文,在上面的程序裏,爲屏幕設備上下文,如果改成打印設備上下文,就不是顯示位圖,而是打印;2.目標矩形左上角點x座標;3. 目標矩形左上角點y座標,在上面的程序中,23(00),表示顯示在窗口的左上角;4.目標矩形的寬度;5. 目標矩形的高度;6. 源設備上下文,在上面的程序裏,爲內存設備上下文;7. 源矩形左上角點x座標;8. 源矩形左上角點y座標;9.操作方式,在這裏爲SRCCOPY,表示直接將源矩形拷貝到目標矩形。還可以是反色,擦除,做“與”運算等操作,具體細節見VC++幫助。你可以試着改改第2345789項參數,就能體會到它們的含義了。

哇,終於講完了。是不是覺得有點枯燥?這一章是有點兒枯燥,特別是當你對Windows的編程並不清楚時,就更覺得如此。不過,當一幅漂亮的bmp圖顯示在屏幕上時,你還是會興奮地大叫“Yeah!”,至少當年我是這樣。

在本書的附盤中包含所有的源程序,包括頭文件和資源文件和例圖。特別要注意的是,退出時,別忘了釋放內存和資源,這是每個程序員應該養成的習慣。這些個程序並不是很完善,例如,如果一幅圖很大,屏幕顯示不下怎麼辦?你可以試着自己加上滾動條。另外,爲了節省篇幅,.bmp文件名被固定爲c:/test.bmp,可以自己加入打開文件對話框,任意選擇你要顯示的文件。圖1.4爲程序運行時的畫面。

1.4     運行時的畫面

最後,再介紹一個命令行編譯的竅門。爲什麼要用命令行編譯呢?主要有兩個好處:第一,不用進入IDE(集成開發環境),節省了時間,而且編譯速度也比較快;第二,對於簡單的程序,不用生成項目文件.mdp.mak,直接就能生成.exe文件,這一點,在下面的例子中可以看到。

在安裝完Visual C++時,在bin目錄下會產生一個VCVARS32.BAT文件,它的作用是在命令行編譯時設置正確的環境變量,如存放頭文件的INCLUDE目錄,存放庫文件的LIB目錄等。如果你沒找到這個批處理文件,可以參考下面的例子,自己做一個批處理。

@echo off

set MSDevDir=d:/MSDEV

set VcOsDir=WIN95

set PATH="%MSDevDir%/BIN";"%MSDevDir%/BIN/%VcOsDir%";"%PATH%"

set INCLUDE=%MSDevDir%/INCLUDE;%MSDevDir%/MFC/INCLUDE;

%INCLUDE%

set LIB=%MSDevDir%/LIB;%MSDevDir%/MFC/LIB;%LIB%

set VcOsDir=

只要把上面的“d:/MSDEV”改成你自己的VC目錄就可以了。在DOS PROMPT下執行該批處理文件,執行set命令,你就能看到新設置的環境變量了。如下所示:

PATH=D:/MSDEV/BIN;D:/MSDEV/BIN/WIN95;C:/WIN95;C:/WIN95/COMMAND;C:/WIN95/SYSTEM;

INCLUDE=d:/msdev/INCLUDE;d:/msdev/MFC/INCLUDE;

LIB=d:/msdev/LIB;d:/msdev/MFC/LIB;

現在我們就可以進行命令行編譯了。首先編譯資源文件,輸入rc bmp.rc,將生成bmp.res文件,接着輸入cl bmp.c bmp.res user32.lib gdi32.lib,就生成bmp.exe 了。可以看到,我們並沒有用到項目文件,所以,對於這種簡單的程序來說,使用命令行編譯還是非常方便的。

有時命令行編譯會出現“Out of enviroment space”的錯誤,那是因爲command.com缺省的初始環境變量內存太小,首先執行command /e:2048 (或更大)命令即可解決改問題。

使用ide的方法是:new project,類型是win32 application->empty project,然後把.h,.rc,.c文件add to project編譯即可。

 
發佈了12 篇原創文章 · 獲贊 2 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章