• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 42  文章 - 3  trackbacks - 0
            <2009年7月>
            2829301234
            567891011
            12131415161718
            19202122232425
            2627282930311
            2345678

            常用鏈接

            留言簿(2)

            隨筆檔案

            文章檔案

            網頁收藏

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            1.位圖和調色板的概念
            如今Windows(3.x以及95,NT)系列已經成為決大多數用戶使用的操作系統。它比DOS成功的一個重要因素是它可視化的漂亮界面,例如你可以在桌面上鋪上你喜歡的墻紙。那么Windows是如何顯示圖象的呢?這就要談到位圖(Bitmap)。
            我們知道,普通的顯示器屏幕是由許許多多的點構成的,我們稱之為象素。顯示時采用掃描的方法:電子槍每次從左到右掃描一行,為每個象素著色,然后從上到下這樣掃描若干行,就掃過了一屏。為了防止閃爍,每秒要重復上述過程幾十次。例如我們常說的屏幕分辨率為640*480,刷新頻率為70Hz,意思是說每行要掃描640個象素,一共有480行,每秒重復掃描屏幕70次。我們稱這種顯示器為位映象設備。所謂位映象,就是指一個二維的象素矩陣,而位圖就是采用位映象方法顯示和存儲的圖象。舉個例子,下圖1是一幅普通的黑白位圖,圖2是被放大后的圖,圖中每個方格代表了一個象素,我們可以看到:整個骷髏就是由這樣一些黑點和白點組成的。

                                         
            圖1.骷髏(左) 圖2.放大后的骷髏位圖(右)

            那么,彩色圖是怎么回事呢?
            我們先來說說三元色RGB概念。我們知道,自然界中的所有顏色都可以由紅,綠,藍(R,G,B)組合而成。有的顏色含有紅色成分多一些,如深紅;有的含有紅色成分少一些,如淡紅。針對含有紅色成分的多少,可以分成0到255共256個等級,0級表示不含紅色成分,255級表示含有100%的紅色成分。同樣,綠色和藍色也被分成256級。這種分級的概念被稱作量化。這樣,根據紅,綠,藍各種不同的組合我們就能表示出256*256*256,約1千6百萬種顏色。這么多顏色對于我們人眼來已經足夠了。
            下表是常見的一些顏色的RGB組合值。
            顏色RGB
            紅25500
            藍00255
            綠02550
            黃2552550
            紫2550255
            青0255255
            白255255255
            黑000
            灰128128128
            你大概已經明白了,當一幅圖中每個象素賦予不同的RGB值時,就能呈現出五彩繽紛的顏色了,這樣就形成了彩色圖。對,是這樣的,但實際上的做法還有些差別。
            讓我們來看看下面的例子。
            有一個長寬各為200個象素,顏色數為16色的彩色圖,每一個象素都用R,G,B三個分量表示,因為每個分量有256個級別,要用8位(bit),即一個字節(byte)來表示,所以每個象素需要用3個字節。整個圖象要用200*200*3,約120k字節,可不是一個小數目呀!如果我們用下面的方法,就能省的多。 因為是一個16色圖,也就是說這幅圖中最多只有16種顏色,我們可以用一個表:表中的每一行記錄一種顏色的R,G,B值。這樣當我們表示一個象素的顏色時,只需要指出該顏色是在第幾行,即該顏色在表中的索引值。舉個例子,如果表的第0行為255,0,0(紅色),那么當某個象素為紅色時,只需要標明0即可。 讓我們再來計算一下:16種狀態可以用4位(bit)表示,所以一個象素要用半個字節。整個圖象要用200*200*0.5,約20k字節,再加上表占用的字節為3*16=48字節.整個占用的字節數約為前面的1/6,省很多吧。
            這張RGB的表,即是我們常說的調色板(Palette),另一種叫法是顏色查找表LUT(LookUpTable),似乎更確切一些。Windows位圖中便用到了調色板技術.其實是不光是Windows位圖,許多圖象文件格式如pcx,tif,gif等都用到了。所以很好地掌握調色板的概念是十分重要的.
            有一種圖,它的顏色數高達256*256*256種,也就是說包含我們上述提到的R,G,B顏色表示方法中所有的顏色,這種圖叫做真彩色圖(TrueColor)。真彩色圖并不是說一幅圖包含了所有的顏色,而是說它具有顯示所有顏色的能力,即最多可以包含所有的顏色。表示真彩色圖時,每個象素直接用R,G,B三個分量字節表示,而不采用調色板技術,原因很明顯:如果用調色板,表示一個象素也要用24位,這是因為每種顏色的索引要用24位(因為總共有2的24次方種顏色,即調色板有2的24次方行),和直接用R,G,B三個分量表示用的字節數一樣,不但沒有任何便宜,還要加上一個256*256*256*3個字節的大調色板。所以真彩色圖直接用R,G,B三個分量表示,它又叫做24位色圖。

            2.Bmp文件格式
            介紹完位圖和調色板的概念,下面就讓我們來看一看Windows的位圖文件(.bmp文件)的格式是什么樣子的。 bmp文件大體上分成四個部分,如圖3所示。
             

            位圖文件頭BITMAPFILEHEADER

            位圖信息頭BITMAPINFOHEADER

            調色板Palette

            實際的位圖數據ImageDate


            圖3.Windows位圖文件結構示意圖
            第一部分為位圖文件頭BITMAPFILEHEADER,是一個結構,其定義如下:
            typedefstructtagBITMAPFILEHEADER{
            WORD bfType;
            DWORD bfSize;
            WORD bfReserved1;
            WORD bfReserved2;
            DWORD bfOffBits;
            } BITMAPFILEHEADER;
            這個結構的長度是固定的,為14個字節(WORD為無符號16位整數,DWORD為無符號32位整數),各個域的說明如下:
            bfType
            指定文件類型,必須是0x424D,即字符串"BM",也就是說所有.bmp文件的頭兩個字節都是"BM"
            bfSize
            指定文件大小,包括這14個字節
            bfReserved1,bfReserved2
            為保留字,不用考慮
            bfOffBits
            為從文件頭到實際的位圖數據的偏移字節數,即圖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個字節(WORD為無符號16位整數,DWORD無符號32位整數,LONG為32位整數),各個域的說明如下:
            biSize
            指定這個結構的長度,為40
            biWidth
            指定圖象的寬度,單位是象素
            biHeight
            指定圖象的高度,單位是象素
            biPlanes
            必須是1,不用考慮
            biBitCount
            指定表示顏色時要用到的位數,常用的值為1(黑白二色圖),4(16色圖),8(256色),24(真彩色圖)(新的.bmp格式支持32位色,這里就不做討論了)。
            biCompression
            指定位圖是否壓縮,有效的值為BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS(都是一些Windows定義好的常量)。要說明的是,Windows位圖可以采用RLE4,和RLE8的壓縮格式,但用的不多。我們今后所討論的只有第一種不壓縮的情況,即biCompression為BI_RGB的情況。
            biSizeImage
            指定實際的位圖數據占用的字節數,其實也可以從以下的公式中計算出來:
            biSizeImage=biWidth'*biHeight
            要注意的是:上述公式中的biWidth'必須是4的整倍數(所以不是biWidth,而是biWidth',表示大于或等于biWidth的,離4最近的整倍數。舉個例子,如果biWidth=240,則biWidth'=240;如果biWidth=241,biWidth'=244)如果biCompression為BI_RGB,則該項可能為零
            biXPelsPerMeter
            指定目標設備的水平分辨率,單位是每米的象素個數,關于分辨率的概念,我們將在打印部分詳細介紹。
            biYPelsPerMeter
            指定目標設備的垂直分辨率,單位同上。
            biClrUsed
            指定本圖象實際用到的顏色數,如果該值為零,則用到的顏色數為2的biBitCount次方。
            biClrImportant
            指定本圖象中重要的顏色數,如果該值為零,則認為所有的顏色都是重要的。
            第三部分為調色板(Palette),當然,這里是對那些需要調色板的位圖文件而言的。有些位圖,如真彩色圖,前面已經講過,是不需要調色板的,BITMAPINFOHEADER后直接是位圖數據。
            調色板實際上是一個數組,共有biClrUsed個元素(如果該值為零,則有2的biBitCount次方個元素)。數組中每個元素的類型是一個RGBQUAD結構,占4個字節,其定義如下:
            typedef struct tagRGBQUAD{
            BYTE rgbBlue; //該顏色的藍色分量
            BYTE rgbGreen; //該顏色的綠色分量
            BYTE rgbRed; //該顏色的紅色分量
            BYTE rgbReserved; //保留值
            } RGBQUAD;
            第四部分就是實際的圖象數據了。對于用到調色板的位圖,圖象數據就是該像素顏在調色板中的索引值,對于真彩色圖,圖象數據就是實際的R,G,B值。下面就2色,16色,256色位圖和真彩色位圖分別介紹。
            對于2色位圖,用1位就可以表示該像素的顏色(一般0表示黑,1表示白),所以一個字節可以表示8個像素。
            對于16色位圖,用4位可以表示一個像素的顏色,所以一個字節可以表示2個像素。
            對于256色位圖,一個字節剛好可以表示1個像素。
            對于真彩色圖,三個字節才能表示1個像素。
            要注意兩點:
            1.每一行的字節數必須是4的整倍數,如果不是,則需要補齊。這在前面介紹biSizeImage時已經提到了。
            2.一般來說,.BMP文件的數據從下到上,從左到右的。也就是說,從文件中最先讀到的是圖象最下面一行的左邊第一個像素,然后是左邊第二個像素…接下來是倒數第二行左邊第一個像素,左邊第二個像素…依次類推,最后得到的是最上面一行的最右一個像素。
            好了,終于介紹完bmp文件結構了,是不是覺得頭有些大?別著急,對照著下面的程序,你就會很清楚了.

            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; //文件句柄
            LPBITMAPINFOHEADER lpImgData; //指向BITMAPINFOHEADER結構的指針
            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,"Filec:\\test.bmpnotfound!","ErrorMessage",
            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)
            NumColors=(DWORD)bi.biClrUsed;//如果bi.biClrUsed不為零,就是本圖象實際
            //用到的顏色數
            else//否則,用到的顏色數為2的biBitCount次方。
            switch(bi.biBitCount){
            case1:
            NumColors=2;
            break;
            case4:
            NumColors=16;
            break;
            case8:
            NumColors=256;
            break;
            case24:
            NumColors=0;//對于真彩色圖,沒用到調色板
            break;
            default:
            //不處理其它的顏色數,認為出錯。
            MessageBox(hWnd,"Invalidcolornumbers!","ErrorMessage",
            MB_OK|MB_ICONEXCLAMATION);
            _lclose(hf);
            return FALSE;//關閉文件,返回FALSE
            }
            if(bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)
            +sizeof(BITMAPINFOHEADER)))
            {
            //計算出的偏移量與實際偏移量不符,一定是顏色數出錯
            MessageBox(hWnd,"Invalidcolornumbers!","ErrorMessage",
            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,"Errorallocmemory!","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不為零,說明用到了調色板
            {
            //為邏輯調色板分配局部內存,大小為邏輯調色板結構長度加NumColors個
            //PALETTENTRY大小
            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; //成功返回
            }

            上面的程序中,要說明的有兩點:
            第一,對于需要調色板的圖,要想正確的顯示,必須根據.bmp文件,產生邏輯調色板。產生的方法是:1.為邏輯調色板指針分配內存,大小為邏輯調色板結構(LOGPALETTE)長度加NumColors個PALETTENTRY大小。(調色板的每一項都是一個PALETTEENTRY結構),2.填寫邏輯調色板結構的頭pPal->palNumEntries=NumColors;pPal->palVersion=0x300;3.從文件中讀取調色板的RGB值,填寫到每一項中。4,產生邏輯調色板:hPalette=CreatePalette(pPal)
            第二,產生位圖(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消息時使用,這樣才能在屏幕上顯示出來,處理過程如下面的程序。

            StaticHDC 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坐標,在上面的程序中,2和3為(0,0),表示顯示在窗口的左上角;4.目標矩形的寬度;5.目標矩形的高度;6.源設備上下文,在上面的程序里,為內存設備上下文;7.源矩形左上角點x坐標;8.源矩形左上角點y坐標;9.操作方式,在這里為SRCCOPY,表示直接將源矩形拷貝到目標矩形。還可以是反色,擦除,做"與"運算等操作,具體細節見VC++幫助。你可以試著改改第2,3,4,5,7,8,9項參數,就能體會到它們的含義了。
            終于講完了。是不是覺得有點枯燥?這一講是有點兒枯燥,特別是當你對Windows的編程并不很清楚時,就更覺得如此。不過,當一幅漂亮的bmp圖顯示在屏幕上時,你還是會興奮的大叫"Yeah",至少當年我是這樣。

            最后,再介紹一個命令行編譯的竅門。為什么要用命令行編譯呢?主要有兩個好處:
            第一,不用進入IDE(集成開發環境),節省了時間,而且編譯速度也比較快。
            第二,對于簡單的程序,不用生成項目文件.mdp或.mak,直接就能生成.exe文件,這一點,在下面的例子中可以看到。
            在安裝VisualC++完畢時,在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目錄就可以了。在DOSPROMPT下執行該批處理文件,執行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;
            現在我們就可以進行命令行編譯了。(當然,你也可以使用IDE,先new一個project,然后把.c和.rc文件插入到project中,編譯運行。)
            首先編譯資源文件,輸入rc bmp.rc,將生成bmp.res文件,接著輸入cl bmp.c bmp.res user32.lib gdi32.lib,就生成bmp.exe了。可以看到,我們并沒有用到項目文件,所以,對于這種簡單的程序來說,使用命令行編譯還是非常方便的。好了,運行bmp.exe,欣賞一下你今天的勞動成果。

            注意事項:
            命令行編譯過程如下:
            vcvars32
            rc bmp.rc
            cl bmp.c bmp.res user32.lib gdi32.lib

             ========
            后來發現原文出自
            http://vipbase.net/ipbook/此書是清華學生寫的,做圖像編程的入門教材很不錯!

            posted on 2009-07-10 22:59 鷹擊長空 閱讀(1173) 評論(0)  編輯 收藏 引用
            99久久99久久精品国产片果冻| 久久亚洲精品无码播放| 亚洲熟妇无码另类久久久| 色综合久久中文字幕无码| 亚洲va久久久噜噜噜久久狠狠| 色偷偷88888欧美精品久久久| 大伊人青草狠狠久久| 麻豆久久久9性大片| 久久国产成人精品麻豆| 国产精品一区二区久久精品涩爱| 久久久女人与动物群交毛片| 国产一区二区三精品久久久无广告 | 国产精品美女久久久久久2018| 国产精品视频久久| 久久久久人妻一区二区三区 | 欧美精品乱码99久久蜜桃| 国产亚洲美女精品久久久久狼| 中文成人无码精品久久久不卡| 亚洲国产精品久久| www.久久99| 久久精品国产亚洲av高清漫画| 色欲综合久久躁天天躁| 久久久中文字幕| 国内精品人妻无码久久久影院| 伊人久久亚洲综合影院| 无码人妻少妇久久中文字幕 | 狠狠精品干练久久久无码中文字幕 | 女人高潮久久久叫人喷水| 久久有码中文字幕| 欧美久久一区二区三区| 久久中文娱乐网| 国产午夜精品理论片久久| 国产精品久久久久久久午夜片| 色综合久久久久网| 999久久久国产精品| 丰满少妇人妻久久久久久4| 久久久久久久99精品免费观看| 91精品久久久久久无码| 久久国产福利免费| 久久青青草原精品国产软件| 久久人妻少妇嫩草AV蜜桃|