Visual C++中的圖形特技 (轉)

worldblog發表於2007-12-11
Visual C++中的圖形特技 (轉)[@more@]隨著資訊表示及實現的多化,在許多學習、遊戲軟體,以及多媒體課件製作軟體中,經常使用各種圖形顯示技巧,如圖形的推拉、交錯、雨滴狀、百頁窗、積木隨機堆疊等顯示。這樣使畫面變得更為生動活潑,更能吸引,也為更好地發揮軟體的功能奠定了基礎。本文就Visual C++ 6.0中實現圖形的各種顯示技巧的原理及具體方法做些探討。

基本原理

在Visual C++6.0中,顯示點陣圖的方法及過程如下:

1. 顯示資源中的點陣圖(點陣圖的所有資料均存在於可中)

(1)從資源中裝入點陣圖

● 定義點陣圖資料成員CBitmap m_Bitmap;

● CBitmap成員Loaitmap(),如m_Bitmap.LoadBitmap(IDB_BITMAP1);

● 傳入LoadBitmap的引數是點陣圖在圖形編輯器中生成或從位件中引入時賦予的識別符。

(2)生成與點陣圖相聯絡的裝置情境物件

CDC MemDC;

MemDC.CreateCompatibleDC(NULL);

MemDC.(&m_Bitmap);

(3)顯示點陣圖

CClientDC ClientDC(this);

BITMAP BM;

m_Bitmap.GetObject(sizeof(BM),&BM);

ClientDC.BitBlt

( X,Y, //目標裝置邏輯橫、縱座標

BM.bmWidth, BM.bmHeight, //顯示點陣圖的畫素寬、高度

&MemDC,

//待顯示點陣圖資料的裝置情境物件

0,0, //源資料中的橫、縱座標

SRCCOPY); //位操作方式

這種方法顯示點陣圖速度快,但不是很靈活,而且會使可執行檔案增大。

2. 顯示獨立檔案方式的點陣圖(點陣圖的所有資料獨立於可執行檔案)

HBITMAP *hBitmap; //定義點陣圖物件控制程式碼

BITMAP BM;

CDC MemDC;

CClientDC ClientDC(this);

MemDC.CreateCompatibleDC(&ClientDC);

hBitmap=(HBITMAP*):: LoadImage

( AfxGetInstanceHandle(),

//取得應用程式控制程式碼

“demo1.bmp”,

//點陣圖檔名

IMAGE_BITMAP,

//型別為點陣圖

0,0,

LR_LOADFROMFILE);

//從檔案中取點陣圖資料

MemDC.SelectObject(hBitmap);

:: GetObject(hBitmap,sizeof(BM),&BM);

ClientDC.BitBlt(……)

//使用格式與方法一同

這種方法顯示點陣圖速度較之前一種慢了一點,但其靈活性較大,可以任意變換點陣圖檔案,而無需重新編譯源程式, 也減小了可執行檔案的大小。

實現方法

下面介紹各種圖形顯示技巧的具體實現原理及方法。以下所有程式演算法的實現均可放在視類(CView,也可視自己的需要放在其他類)中處理,且有必要進行如下的相關操作:

增加如下類成員變數:

BITMAP m_Bm;

//儲存點陣圖的寬、高度等資料

HBITMAP *m_hBitmap;

//儲存點陣圖資料控制程式碼

CDC m_MemDC; //記憶體裝置情境物件

在類建構函式中加入如下程式碼:

m_MemDC.CreateCompatibleDC(NULL); //產生記憶體裝置情境物件

m_hBitmap=(HBITMAP *)::LoadImage(

//從檔案中裝入點陣圖資料

AfxGetInstanceHandle(),

“demo1.bmp”,

IMAGE_BITMAP,

0,0,

LR_LOADFROMFILE );

m_MemDC.SelectObject(m_hBitmap); //將點陣圖選入記憶體裝置情境物件

::GetObject(m_hBitmap,sizeof(m_Bm),&m_Bm);

1. 水平交錯效果

原理:將記憶體裝置情境物件(如MemDC)中的點陣圖資料拆分成奇、偶掃描線兩部分,其中奇數條掃描線由上往下移動,偶數條掃描線則由下往上移動,且兩者同時進行。螢幕上的效果為分別由上下兩端出現的較淡柵欄圖形,逐漸相互靠近,直至整個點陣圖完全清楚。垂直交錯效果的實現原理與之類似。

程式演算法:

int i,j;

for ( i=0; i<=m_Bm.bmHeight; i+=2 )

{j = i;

while ( j>0 )

{ClientDC.StretchBlt(

//奇數,由上至下

0,j-1,

//目標裝置邏輯橫、縱座標

m_Bm.bmWidth,1,

//顯示點陣圖的畫素寬、高度

&m_MemDC,

//源點陣圖裝置情境物件

0,m_Bm.bmHeight-(i-j-1),

//源點陣圖的起始橫、縱座標

m_Bm.bmWidth,1,

//源點陣圖的畫素寬、高度

SRCCOPY);

ClientDC.StretchBlt(

//偶數,由下至上

0,m_Bm.bmHeight-j,

//目標裝置邏輯橫、縱座標

m_Bm.bmWidth,1,

//顯示點陣圖的畫素寬、高度

&m_MemDC,

//源點陣圖裝置情境物件

0,i-j,

//源點陣圖的起始橫、縱座標

m_Bm.bmWidth,1,

//源點陣圖的畫素寬、高度

SRCCOPY);

j-=2; }

// while ( j>0 )

Sleep(10);

}

//for ( i=0; i<=m_Bm.bmHeight; i+ =2 )

2. 雨滴效果

原理:將記憶體裝置情境物件(如MemDC)中點陣圖資料的最後一條掃描線,順序地從目標裝置(如ClientDC)中待顯示點陣圖的第一條掃描線所在位置移動至最後一條處,並保留此條掃描線在螢幕上移動時留下的軌跡。接著再把MemDC中點陣圖資料的倒數第二條掃描線,順序地從目標裝置(如ClientDC)中待顯示點陣圖的第一條掃描線所在位置移動至倒數第二條處。其餘的掃描線依此類推。

程式演算法:

int i,j;

for ( i=0; i<=m_Bm.bmHeight; i++ )

{for ( j=0; j<=m_Bm.bmHeight-i; j++ )

ClientDC.StretchBlt(

0,j,

//目標裝置邏輯橫、縱座標

m_Bm.bmWidth,1,

//顯示點陣圖的畫素寬、高度

&m_MemDC,

//源點陣圖裝置情境物件

0,m_Bm.bmHeight-i,

//源點陣圖的起始橫、縱座標

m_Bm.bmWidth,1,

//源點陣圖的畫素寬、高度

SRCCOPY);

Sleep(20);

}

//for ( i=0; i<=m_Bm.bmHeight; i++ )

3. 百葉窗效果

原理:將記憶體裝置情境物件(如MemDC)中的點陣圖資料分成若干組,然後分別從第一組到最後一組進行搬移,第一次搬移每組中第一條掃描線到目標裝置(如ClientDC)中待顯示點陣圖的相應位置,第二次搬移每組中第二條掃描線,接著第三條、第四條掃描線。

程式演算法:

int i,stepi,j;

stepi=m_Bm.bmHeight/10;

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

{for ( j=0; j<10; j++ )

ClientDC.StretchBlt(

0,j*stepi+i,

//目標裝置邏輯橫、縱座標

m_Bm.bmWidth,1,

//顯示點陣圖的畫素寬、高度

&m_MemDC,

//源點陣圖裝置情境物件

0,j*stepi+i,

//源點陣圖的起始橫、縱座標

m_Bm.bmWidth,1,

//源點陣圖的畫素寬、高度

SRCCOPY);

Sleep(20);

} //for ( i=0; i<=stepi; i++ )

4. 隨機積木效果

原理:將記憶體裝置情境物件(如MemDC)中的點陣圖資料分成縱橫十等份共一百組資料,然後隨機地取出這一百組資料中的某一組顯示到目標裝置(如ClientDC)中待顯示點陣圖的相應位置,如此反覆直到所有一百組資料均顯示完畢為止。

程式演算法:

int i,j,stepx,stepy,dispnum,x,y;

int pxy[10][10];

//使用本陣列記錄已顯示過的資料組

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

for ( j=0; j<10; j++ )

pxy[i][j]=0;

stepx=m_Bm.bmWidth/10;

stepy=m_Bm.bmHeight/10;

srand( (unsigned)time( NULL ) );

dispnum=0;

//記錄已顯示過的資料組的個數

while(1)

{ x=rand() % 10;

y=rand() % 10;

if ( pxy[x][y] )

//本組x,y所代表的資料組是否已顯示過?

continue;

pxy[x][y]=1;

//表明本組x,y所代表的資料組已顯示過

ClientDC.StretchBlt(

x*stepx, y*stepy,

//目標裝置邏輯橫、縱座標

stepx,stepy,

//顯示點陣圖的畫素寬、高度

&m_MemDC,

//源點陣圖裝置情境物件

x*stepx, y*stepy,

//源點陣圖的起始橫、縱座標

stepx,stepy,

//源點陣圖的畫素寬、高度

SRCCOPY);

dispnum++;

if ( dispnum >=100 )

break;

Sleep(30);

} // while(1)

結 語

以上程式程式碼均在Visual C++ 6.0中透過,所有片斷均可編寫成獨立的函式,靈活使用。如果對以上幾種顯示效果進行變換,我們還可以實現多種其他特技效果。 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991328/,如需轉載,請註明出處,否則將追究法律責任。

相關文章