程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 在CB中進行DirectX編程(3)

在CB中進行DirectX編程(3)

編輯:關於C++

2.3 裝入並顯示圖形文件

為了簡明地說明采用DirectDraw圖形文件的顯示技術,我們以示例程序dx2介紹圖面、圖形文件裝入、圖形縮放、圖形在圖面上顯示等的初步概念和實現技術。

2.3.1 DirectDraw顯示圖形的技術

為了顯示圖象,DirectDraw必需首先擁有類似畫布(canvas)的繪圖空間,DirectDraw並不向在DOS下那樣簡單地將顯示緩存作為繪畫的對象,而是通過DirectDraw對象創建各種不同種類的“圖面”(Suerface),圖面上的內容可以被應用程序自由地拷貝、組合,生成千變萬化的圖形。

2.3.1.1圖面分以下幾種類型:

(1)主圖面(Primary圖面):即在屏幕上顯示出來的圖面,就是GDI用於繪制Windows用戶界面的圖面。每個DirectDraw對象只能有一個主圖面,主圖面的尺寸、位置和格式由系統當前的顯示模式決定,不能改動。

(2)後台圖面(Off-screen圖面):此類圖面不能被直接看到。一般來說,後台圖面往往用於作為游戲精靈動畫、背景圖形等部件的存儲緩沖區。後台圖面的尺寸是可以調整的,且可以有多個後台圖面,其大小根據實際情況調整,不要太大或太小。一種典型的例子是:有一個精靈的動畫由4張128點陣圖形組成,那麼可以將後台圖面定義為256點的方陣,將這個動畫序列存儲下來讀者可能認為可以創建一個比主圖面大的後台圖面以便保存游戲背景,這樣可以方便地實現滾屏,但是,DirectDraw限制後台圖面的尺寸不能比主圖面大,除非系統的顯示卡支持。能否實現大的後台圖面我們將在以後敘述。

(3)復合圖面(Complex圖面)和翻轉鏈(Flipping Chain):這種圖面主要用於生成平滑動畫。有關技術待制作動畫時介紹。

(4)覆蓋圖面(Overlay圖面):這是一種由硬件支持的圖面,DirectDraw不能仿真。有關技術在後面介紹。

DirectDraw可以把圖面創建在顯示內存或系統內存中,而顯示內存又分為常規顯示內存和AGP加速圖形接口內存。由於顯示內存容量是有限的,所以每個圖面具體應該創建在哪部分存儲區域中應該統籌規劃,一般將使用頻繁,需要硬件加速或實現功能的圖面安排在顯示內存。如果您不指定圖面創建的位置,DirectDraw將首先在常規顯示內存創建圖面,當常規顯示內存不夠時,若系統支持AGP內存,則先使用AGP內存,最終使用系統內存。

2.3.1.2 圖形文件的裝入

圖形文件裝入到圖面並不象想象的那麼簡單,因為裝入的圖形的點陣可能與、圖面的點陣不同,這就存在圖形的縮放。另外,圖形數據在內存中的移動、復制,也是需要處理的內容。對於Windows的設備無關位圖,我們可以考慮使用Windows的功能實現:

(1)采用LoadImage函數裝入圖形文件

(2)采用圖面的GetDC方法獲得圖面與GDI兼容的設備上下文

(3)采用BitBlt函數將圖形數據拷貝到圖面中

有關GDI編程請參看有關Windows編程資料,這裡讀者只需要知道固定的用法就可以了。

2.3.1.3 圖面的丟失

在DirectDraw應用程序被最小化、屏幕顯示方式改變或用戶按Alt+Tab鍵切換當前應用程序時,圖面將會丟失,因此在重新回到DirectDraw應用程序中時,必需用Restore方法恢復圖面。遺憾的是,雖然圖面被恢復了,但其中圖形數據卻丟失了,需要重新繪制。

2.3.2 dx2運行過程

啟動dx2程序後,只有第一個“執行”按鈕可以使用,按下該按鈕後,系統將創建DirectDraw對象,並設置為800*600全屏幕顯示方式;按順序按下“創建主圖面”、“創建

圖2.2 dx2 裝入並顯示圖形文件程序運行界面

後台圖面”按鈕,分別創建對應屏幕顯示的主圖面和100*100點陣的後台圖面;按下“後台圖面裝入圖形”按鈕,則圖形文件view.bmp被一100*100點陣裝入到後台圖面,屏幕上看不見圖形;再按下“主圖面裝入圖形”按鈕,view.bmp以200*100點陣縮放後裝入到主圖面(屏幕)的(0,0)位置,此時圖形顯示在屏幕左上角;繼續按“拷貝後台圖面到主圖面”,將把後台圖面的100*100圖形顯示在屏幕的(200,0)位置,我們可以看到兩副同樣的圖形以不同的縮放比例並排顯示在屏幕左上方;按下“圖面丟失”後,屏幕被設置成640*480的顯示方式,屏幕上顯示出的圖形消失了;用“恢復丟失的圖面”按鈕重新設置顯示方式為800*600(必需恢復顯示方式,否則圖面恢復將會失敗)並恢復圖面,此時,失去的圖形在屏幕上仍然看不見;最後,按“重新顯示圖形”來重新繪制view.bmp,屏幕重新展現原有的圖形。

2.3.3 dx2程序的編程實現

2.2.2 dx1編程實現

啟動C++ Builder後在窗口Form1中設計如圖2.2的操作界面,各對象相關屬性設置如表2.3:

控件對象類型 控件對象名稱 相關屬性  屬性值

TForm     Form1     Caption   DirectX 練習程序1

TLabel    Label1    Caption   運行狀態:

TLabel    Label2    Caption   設備的枚舉

Tlabel    Label3    Caption   顯示模式DDraw2

TEdit     Edit1     Text    (空)

ReadOnly  True

TGroupBox   GroupBox1   Caption   狀態

TCheckBox   CheckBox6   Caption   DDSCL_NOWINDOWCHANGES

Checked   true

TButton    Button1    Caption   執行

TButton    Button2    Caption   創建主圖面

Enabled   False

TButton    Button3    Caption   創建後台圖面

Enabled   False

TButton    Button4    Caption   後台圖面裝入圖形

Enabled   False

TButton    Button5    Caption   主圖面裝入圖形

Enabled   False

TButton    Button6    Caption   拷貝後台圖面到主圖面

Enabled   False

TButton    Button7    Caption   圖面丟失:設置640*480方式

Enabled   False

TButton    Button8    Caption   恢復已丟失的圖面

Enabled   False

TButton    Button9    Caption   重新顯示圖形

Enabled   False

表2.3 dx2控件對象屬性設置一覽表

2.3.3.1 創建主圖面

用HRESULT IDirectDraw::CreateSurface來創建圖面:

lpDD2->CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc,

LPDIRECTDRAWSURFACE FAR *lpDDSurface,

Iunknown FAR *pUnkOuter)

(1)參數lpDDSurfaceDesc是一個志向DDSURFACEDESC結構的指針,DDSURFACEDESC結構的定義比較復雜,幸好一般只需要使用其中很少的一部分。結構DDSURFACEDESC的部分描述如表2.4所示:

結構成員

描述

DOWRD dwSize

DDSURFACE結構的尺寸。在使用此結構之前,此項數據必需用sizeof函數設置

DWORD dwFlags

控制標志。主要可以設置的標志為:

DDSD_CAPS、

DDSD_HEIGHT、

DDSD_WIDTH、

DDSD_BACKBUFFERCOUNT、

DDSD_PIXELFORMATDENG 等

DWORD dwHeight

圖面高度。主圖面不需要設置

DWORD dwWidth

圖面寬度。主圖面不需要設置

DDSCAPS ddsCaps

圖面能力。DDSCAPS也是一個結構,在創建圖面時需要設置其成員dwCaps的值,以便確定所建圖面的性質。

DwCaps的取值主要有:

DDSCAPS_PRIMARYSURFACE:主圖面

DDSCAPS_OFFSCREENPLAIN:後台圖面

DDSCAPS_COMPLEX:復合圖面

DDSCAPS_FLIP:圖面翻轉鏈

DDSCAPS_OVERLAY:覆蓋圖面

DDSCAPS_VIDEOMEMORY:圖面創建在顯示內存

DDSCAPS_LOCALVIDMEM:使用常規顯示內存

DDSCAPS_NONLOCALVIDMEM:使用AGP內存

DDSCAPS_SYSTEMMEMORY:圖面創建在系統內存

表2.4 DDSURFACEDESC結構的部分成員說明

(2)參數lpDDSurface返回一個指向所創建圖面的指針。

(3)參數pUnkOuter未使用,必需為NULL。

創建主圖面需要以下步驟:

(1)獲得並設置DDSURFACEDESC結構的尺寸dwSize:ddsd.dwSize=sizeof(ddsd);

(2)簡單地設置ddsd.dwFlags=DDSD_CAPS;

(3)設置主圖面標志:ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;

(4)調用CreateSurface方法創建圖面。

2.3.3.2 創建後台圖面

後台圖面的創建與創建主圖面基本相同,只是在DDDURFACEDESC結構中多給出一些信息。創建後台圖面需要以下步驟:

(1) 獲得並設置DDSURFACEDESC結構的尺寸dwSize:ddsd.dwSize=sizeof(ddsd);

(2) 設置ddsd.dwFlags=DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;

(3) 設置後台表面的寬和高(dx2中設為100):ddsd.dwHeight=100; ddsd.dwWidth=100;

(4) 設置後台圖面標志:ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;

(5)調用CreateSurface方法創建圖面。

2.3.3.3 圖形文件的裝入後台圖面和圖形文件的裝入主圖面

圖形文件的裝入主要采用Windows的函數,雖然使用C++Builder的TCavas對象打開圖形文件要方便一些,但是在BitBlt時不夠穩定,因此dx2還是選擇了前者。

dx2在實現圖形內存數據復制時采用了GDI,在DirectDrawSurface對象中有GetDC和ReleaseDC兩個方法,以便取得HDC並調用GDI。

HRESULT IDirectDrawSurface::GetDC(HDC FAR *hdc)

HRESULT IDirectDrawSurface::ReleaseDC(HDC hdc)

參數hdc是一個設備句柄。

BitBlt雖然速度比較慢,但是兼容性好,能夠支持不同的顯示模式,而且能夠自動進行格式轉換。

2.3.3.4 後台圖面圖形拷貝到主圖面顯示

這裡同樣使用了BitBlt,將後台圖面的數據復制到主圖面並顯示出來。

2.3.3.5 丟失圖面及恢復初始顯示方式和圖面

在dx2中我們演示了當改變屏幕顯示方式時,圖面丟失的現象,並且說明了在圖面丟失後可以用HRESULT IDirectDrawSurface::Restore()方法來恢復圖面,同時必需重新繪制圖面上的圖形。

Restore方法沒有參數,但是若要成功恢復已丟失的圖面,必需屏幕顯示方式重新恢復到其初始的狀態。

為了判斷圖面是否已經丟失,也可以使用HRESULT IDirectDrawSurface::IsLost()方法來進行檢測,若返回值為DDERR_SURFACELOST則說明圖面確實丟失了。在dx2中沒有進行此判斷,讀者可以根據自己的理解修改dx2,實現恢復圖面前首先進行圖面是否丟失的判斷。

2.3.4 dx2源程序

2.3.4.1 dx2主要文件的組成為:工程文件(dx2.bpr)、窗口文件(main.cpp)、頭文件(main.h)、view.bmp。

2.3.4.2 頭文件main.h

#ifndef mainH
#define mainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Dialogs.hpp>
#include "d:\tools\dx5sdk\sdk\inc\ddraw.h"
//---------------------------------------------------------------------------
char CR[]={13,10,0};
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TLabel *Label1;
TGroupBox *GroupBox1;
TMemo *Memo1;
TButton *Button2;
TButton *Button3;
TButton *Button4;
TButton *Button5;
TButton *Button6;
TButton *Button7;
TButton *Button8;
TButton *Button9;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall Button3Click(TObject *Sender);
void __fastcall Button4Click(TObject *Sender);
void __fastcall Button5Click(TObject *Sender);
void __fastcall Button6Click(TObject *Sender);
void __fastcall Button7Click(TObject *Sender);
void __fastcall Button8Click(TObject *Sender);
void __fastcall Button9Click(TObject *Sender);
private: // User declarations
LPDIRECTDRAW FAR lpDD;
LPDIRECTDRAW2 FAR lpDD2;
DDSURFACEDESC ddsd;
LPDIRECTDRAWSURFACE FAR lpDDPrimary,lpDDOffScreen;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved