T°φdu CSurface ji₧ mßme zcela naimplementovanou, dnes nßm tedy zb²vß t°φdy CDisplay, abychom dokonΦili knihovnu Display.dll. ╚lßnek op∞t bude trochu delÜφ ne₧ je obvyklΘ a budeme se vesm∞s zab²vat k≤dem, kter² znßte, tak₧e popis bude struΦn². Nakonec si jeÜt∞ ukß₧eme, jak vytvo°enΘ funkce exportovat z knihovny.
Za prvΘ je pot°eba si ud∞lat nßvrh t°φdy - tabulku jako v p°φpad∞ t°φdy CSurface.
Pro CDisplay bude vypadat n∞jak takto:
╚lenskΘ prom∞nnΘ |
|
|
Typ |
JmΘno |
Popis |
LPDIRECTDRAW7 |
m_lpDD |
Ukazatel na rozhranφ objektu DirectDraw. |
LPDIRECTDRAWCLIPPER |
m_lpDDClipper |
Ukazatel na rozhranφ objektu clipper. |
LPDIRECTDRAWPALETTE |
m_lpDDPalette |
Ukazatel na rozhranφ objektu palety. |
CSurface |
m_surBack |
Objekt zadnφho bufferu (back buffer). |
CSurface |
m_surFront |
Objekt p°ednφho bufferu (front buffer). |
Prom∞nnΘ pot°ebnΘ pro vykreslovßnφ pozadφ |
||
CSurface |
m_surBackground |
Objekt povrchu pozadφ. |
CRect |
m_ScrollRect |
ObdΘlnφk pou₧it² p°i posunu pozadφ, viz funkce UpdateBackGround(). |
CRect |
m_BackSource |
Op∞t je to obdΘlnφk vztahujφcφ se k vykreslovßnφ pozadφ. V tomto p°φpad∞ zdrojov² obdΘlnφk pou₧it² p°i vykreslovßnφ statickΘho pozadφ. |
CString |
m_BackBMP |
Cesta k bitmap∞ pozadφ pot°ebnß p°i obnov∞ pozadφ. |
COLORREF |
m_BackColor |
Pokud je pozadφ jednobarevnΘ, tato hodnota urΦuje jeho barvu. |
Informace o rozliÜenφ a formßtu zadnφho a p°ednφho povrchu |
||
UINT |
m_Res_X |
PoΦet pixel∙ v horizontßlnφm sm∞ru - rozliÜenφ. |
UINT |
m_Res_Y |
PoΦet pixel∙ ve vertikßlnφm sm∞ru. |
BYTE |
m_Depth |
Barevnß hloubka povrch∙. |
Nßsledujφ prom∞nnΘ, kterΘ jsou souΦßstφ poΦφtadla FPS (Frame per second) |
||
int |
m_StartTime |
PoΦßteΦnφ Φas p°i poΦφtanφ FPS. |
int |
m_StopTime |
Koncov² Φas FPS. O tom jak funguje FPS counter, se vφce dovφte p°i popisu funkce UpdateFPS(). |
double |
m_Frames |
PoΦet snφmk∙ za urΦit² Φasov² okam₧ik urΦen² konstantou FPS_REFRESH_RATE. |
CString |
m_strFrames |
╪et∞zec, kter² je vykreslovßn na monitor. Je tu jen kv∙li tomu, aby se nemusel po ka₧dΘ obnov∞ pozadφ znovu formßtovat nov² °et∞zec. |
Ostatnφ prom∞nnΘ |
||
BOOL |
m_bIsInit |
TRUE pokud je objekt CDisplay °ßdn∞ zinicializovßn. |
DWORD |
m_dwFlags |
Nastavenφ objektu CDisplay. |
IDirectDrawGammaControl* |
m_GammaControl |
Nakonec je tu podpora °φzenφ gammy (sv∞tlosti). Toto je ukazatel na rozhranφ IDirectDrawGammaControl. ╪φzenφ gammy je novinka, tak₧e to probereme trochu podrobn∞ji u funkcφ, kterΘ se gammou zab²vajφ. |
int |
m_CurGamma |
Aktußlnφ nastavenφ Gamma v rozmezφ 0 - 255. |
Metody |
|
|
Nßvratovß hodnota |
JmΘno |
Popis |
HRESULT |
Zßkladnφ funkce knihovny, kterß musφ b²t zavolßna na prvnφm mφst∞! Prvnφ parametr je handle na okno aplikace. Druh² parametr typu DWORD nastavuje objekt CDisplay, viz dßle. |
|
void | Present() | Funkce Present() provßdφ prohozenφ povrch∙ a obnovu FPS poΦφtadla. |
HRESULT | UpdateFPS() | O tΘto funkci ji₧ byla °eΦ. SpoΦφtß a obnovφ FPS counter. |
HRESULT |
SetPalette() |
Tato funkce nejprve vytvo°φ paletu z p°edem urΦenΘho souboru a potΘ ji nastavφ. |
Prßce s pozadφm | ||
HRESULT |
Nßsledujφcφ dv∞ funkce definujφ pozadφ dv∞ma zp∙soby. Prvnφ verze definuje jednobarevnΘ pozadφ - jedin² parametr urΦuje barvu. |
|
HRESULT |
Druhß verze naproti tomu definuje pozadφ z bitmapy urΦenΘ prvnφm parametrem. DalÜφ vlastnosti pozadφ jsou urΦeny druh²m parametrem typu DWORD. |
|
void |
P°ekreslφ pozadφ definovanΘ p°edchozφmi dv∞ma funkcemi. Tuto funkci je nutno volat na zaΦßtku obnovovacφ smyΦky. |
|
Funkce °φdφcφ Gamma corection |
||
BOOL |
Funkce zjistφ, zda-li je systΘm v∙bec schopen gammu °φdit. |
|
HRESULT | IncrementGamma(int) | Zv²Üφ stupe≥ gammy o hodnotu urΦenou parametrem. V praxi to znamenß zesv∞tlenφ scΘny. |
HRESULT | DecrementGamma(int) | Snφ₧φ stupe≥ gammy o hodnotu urΦenou parametrem. V praxi to znamenß ztmavenφ scΘny. |
Inline metody | ||
BOOL | IsInit() | Vracφ hodnotu prom∞nnΘ m_bIsInit. |
LPDIRECTDRAW7 | GetDirectDraw() | Vracφ ukazatel na rozhranφ objektu DirectDraw. |
CSurface* | GetBackBuffer() | Vracφ ukazatel na objekt zadnφho povrchu. |
CSize | GetResolution() | Vracφ aktußlnφ rozliÜenφ ve struktu°e CSize(cx, cy). |
Ostatnφ funkce | ||
void | Clean() | Funkce provßd∞jφcφ zametacφ prßce, viz minulß lekce. |
- | CDisplay() | Konstruktor t°φdy. |
- | ~CDisplay() | Destruktor t°φdy. |
Vidφte, ₧e t°φda je pom∞rn∞ slo₧itß. V nßsledujφcφch dvou Φßstech si podrobn∞ji probereme jednotlivΘ funkce.
Za prvΘ se podφvejme na deklaraci:
class CDisplay
{
private:
//
// Objects of DirectDraw
LPDIRECTDRAW7 m_lpDD;
LPDIRECTDRAWCLIPPER m_lpDDClipper;
LPDIRECTDRAWPALETTE m_lpDDPalette;
// Front&back
buffer
CSurface m_surFront;
CSurface m_surBack;
//
// Background&scrolling
CSurface m_surBackground;
CRect m_ScrollRect;
CRect m_BackSource;
CString m_BackBMP;
COLORREF m_BackColor;
//
// Common display flags
DWORD m_dwFlags;
//
// Information about display mode
UINT m_Res_X;
UINT m_Res_Y;
BYTE m_Depth;
//
// Initialization of system
BOOL m_bIsInit;
//
// Display FPS counter
int m_StartTime;
int m_StopTime;
double m_Frames;
CString m_strFrames;
//
// Gamma control support
IDirectDrawGammaControl* m_GammaControl;
int m_CurGamma;
public:
BOOL IsInit() {return m_bIsInit;}
//
// Create surfaces etc.
HRESULT CreateFullScreenSystem(HWND hWnd, DWORD dwFlags);
//
// Palette functions
HRESULT SetPalette();
//
// Flipping surfaces
void Present();
//
// Return directdraw objects
LPDIRECTDRAW7 GetDirectDraw() {return m_lpDD;}
CSurface* GetBackSurface() {return &m_surBack;}
// Resolution
CSize GetResolution() {return CSize(m_Res_X, m_Res_Y);}
//
// Background functions
HRESULT DefineBackground(COLORREF crColor);
HRESULT DefineBackground(CString strBMPFile, DWORD dwFlags);
HRESULT UpdateBackground();
//
// Gamma corection support
HRESULT IncrementGamma(int _Amount = 8);
HRESULT DecrementGamma(int _Amount = 8);
private:
HRESULT UpdateFPS();
void Clean();
BOOL HasGammaSupport();
public:
CDisplay();
~CDisplay();
};
Na deklaraci nenφ nic zvlßÜtnφho. Dr₧φme se p°esn∞ tabulky z
·vodu. Jen si vÜimn∞te, ₧e n∞kterΘ metody jsou soukromΘ. Jsou to metody, ke
kter²m nemß b²t p°φstup zvenku. Bylo by to zbyteΦnΘ, proto₧e jsou to ryze
internφ funkce a u₧ivatel o nich nepot°ebuje v∞d∞t. TakΘ si vÜimn∞te n∞kter²ch
implicitnφch parametr∙.
V₧dy se sna₧φm odd∞lit metody a atributy t°φdy. TakΘ nechci
mφchat vÜechny soukromΘ prvky dohromady, proto najdete v deklaraci vφce sekcφ
private a public. Na
tyto drobnosti upozor≥uji p°edevÜφm mΘn∞ zkuÜenΘ cΘΦka°e, kte°φ nemajφ velkΘ
zkuÜenosti s objektov²m programovßnφm.
JeÜt∞ p°ed deklaracφ samotnΘ t°φdy bychom m∞li nadefinovat n∞kterΘ konstanty:
Soubor Core.h:
#define FPS_REFRESH_RATE
1000
#define _C_DEFAULT_SCREENWIDTH 640
#define _C_DEFAULT_SCREENHEIGHT 480
#define _C_DEFAULT_SCREENDEPTH 16
#define _S_LOADING1 _T("\\Graphics\\Backgrounds\\loading1.bmp")
#define _S_ARIAL_DDF _T("\\Graphics\\Fonts\\Arial.ddf")
#define _S_HUMANS_DDF _T("\\Graphics\\Fonts\\Humanst521 BT.ddf")
#define _S_FONT_ARIAL _T("Arial")
#define _S_FONT_HUMANS _T("Humans")
Zde definujeme za prvΘ obnovovacφ interval FPS ukazatele.
╚φslo 1000 znamenß, ₧e FPS counter, se bude obnovovat po 1 vte°in∞. Dßle tam
mßme implicitnφ hodnoty rozliÜenφ, kterΘ se nastavujφ v p°φpad∞, ₧e se nepoda°φ
naΦφst sprßvnΘ hodnoty z konfiguraΦnφho souboru. To samΘ platφ pro barevnou
hloubku. DalÜφ t°i konstanty jsou cesty do datovΘho souboru. Knihovna
Display.dll toti₧ intern∞ pou₧φvß n∞kterΘ bitmapy
(fonty a pozadφ p°i inicializaci). VÜechny bitmapy mßme v adresß°i Graphics.
VÜimn∞te si, jak²m zp∙sobem cesty definujeme. Budeme tak toti₧ definovat cesty i
k vaÜim vlastnφm soubor∙m (nemusφ jφt jen o bitmapy).
Poslednφ dv∞ konstanty definujφ identifikaΦnφ °et∞zec jednotliv²ch font∙.
Podle t∞chto °et∞zc∙ jsou fonty p°epφnßny pomocφ metod ze t°φdy
CDDFontEngine. Tato t°φda se starß o vykreslovßnφ
font∙. Tu zde nebudu rozebφrat, proto₧e jsem ji nepsal jß a nßm staΦφ pouze pßr
jejich funkcφ.
Soubor Common.h (tento soubor je souΦßstφ projektu Display a nemß nic spoleΦnΘho s knihovnou Common.dll):
//
// Flags for CreateFullScreenSystem()
#define DDFLG_CLIPPER 0x00000001
#define DDFLG_WINDOWMODE 0x00000002
#define DDFLG_FULLSCREEN 0x00000004
#define DDFLG_GAMMA 0x00000008
#define DDFLG_PALETTE 0x00000010
// Common flags
#define DDFLG_FPS 0x00000020
// Flags for DefineBackground()
#define DDFLG_SYSTEM_MEMORY
0x10000000
#define DDFLG_VIDEO_MEMORY 0x20000000
#define DDFLG_SCROLLING 0x40000000
#define DDFLG_SOLID 0x80000000
#define DDFLG_COLORKEY 0xF0000000
//
// Keys
// Graphics section
#define _S_KEY_WIDTH _T("ScreenWidth")
#define _S_KEY_HEIGHT _T("ScreenHeight")
#define _S_KEY_DEPTH _T("ScreenDepth")
#define _S_KEY_FPS _T("FPS")
#define _S_KEY_USEGAMMA _T("UseGamma")
#define _S_KEY_SHOWVIDMEM _T("ShowVidMem")
Zde definujeme za prvΘ konstanty pro funkce CreateFullScreenSystem() a pro DefineBackground(). Pomocφ t∞chto konstant m∙₧eme nastavit dalÜφ vlastnosti aplikace a pozadφ. Rozeberme si je podrobn∞ji:
DDFLG_CLIPPER - aktivuje clipper.
Pokud tuto hodnotu nezahrnete p°i volßnφ funkce
CreateFullscreenSystem(), nebude se pou₧φvat clipper.
DDFLG_WINDOWMODE - tento flag myslφm nefunguje, ale
m∞l zabrßnit p°epnutφ do fullscreen m≤du a aplikace tak z∙stala v okn∞.
DDFLG_FULLSCREEN - opak p°edchozφho.
DDFLG_GAMMA - zapnutφ podpory pro °φzenφ gammy.
SystΘm si zjistφ, zda-li je to v∙bec mo₧nΘ.
DDFLG_PALETTE - Tento flag se nastavφ, pokud je
nastavena paleta. Paleta by se m∞la
automaticky zapnout p°i 8-mi bitovΘ hloubce barev.
DDFLG_FPS - tento flag je aktivovßn p°es
konfiguraΦnφ soubor. Pokud je v setup.ini 1, je
tento flag nastaven a FPS counter je zobrazen. V opaΦnΘm p°φpad∞ nikoliv.
DDFLG_SYSTEM_MEMORY - vynuceni ulo₧enφ povrchu
pozadφ do systΘmovΘ pam∞ti. Je pot°eba nastavit na grafick²ch kartßch, kterΘ
majφ mΘn∞ grafickΘ pam∞ti.
DDFLG_VIDEO_MEMORY - prav² opak p°edchozφ
informace. Pozadφ je vytvo°eno ve video pam∞ti a a₧ kdy₧ to nejde, je mφsto
alokovßno v RAM.
DDFLG_SCROLLING - zapφnß scrolling
pozadφ. Zkuste si to a uvidφte jak to funguje. Tato funkce je znaΦn∞ nepru₧nß a
jedno·Φelovß. Zßle₧φ jen na Vßs, jak si to upravφte podle pot°eb.
DDFLG_SOLID - informace o tom, ₧e pozadφ je
jednobarevnΘ.
DDFLG_COLORKEY - tuto hodnotu vyu₧φvß
CSurface p°i uchovßnφ informace o CK.
DalÜφ hodnoty jsou klφΦe v konfiguraΦnφm souboru, ze kterΘho Φteme spoustu
informacφ. Tak m∙₧ete modifikovat chovßnφ aplikace, ani₧ by se musela znovu
p°eklßdat. Co znamenajφ, se dß snadno vyΦφst z jejich nßzvu. JeÜt∞ je celkem
d∙le₧itΘ, ₧e flagy se dajφ kombinovat pomocφ operßtoru OR |.
V dalÜφ Φßsti budeme postupn∞ implementovat a rozebφrat vÜechny metody t°φdy CDisplay. ZaΦneme logicky u inicializace systΘmu:
HRESULT CDisplay::CreateFullScreenSystem(HWND
hWnd, DWORD dwFlags)
{
//
// Temporary front and back buffer
LPDIRECTDRAWSURFACE7 lpDDSBack, lpDDSFront;
DDCAPS Hel; Hel.dwSize = sizeof(DDCAPS);
DDCAPS Driver; Driver.dwSize = sizeof(DDCAPS);
HRESULT dwRet;
//
// Init olny if we not init before
if(m_bIsInit) {
return 1;
}
//
// Check handle to window
ASSERT(hWnd);
//
// 1. krok
// Get resolution from "setup.ini" file
m_Res_X = setGetSetupInt(_S_SECTION_GRAPHICS, _S_KEY_WIDTH);
m_Res_Y = setGetSetupInt(_S_SECTION_GRAPHICS, _S_KEY_HEIGHT);
m_Depth = setGetSetupInt(_S_SECTION_GRAPHICS, _S_KEY_DEPTH);
if(m_Res_X == 0) m_Res_X = _C_DEFAULT_SCREENWIDTH;
if(m_Res_Y == 0) m_Res_Y = _C_DEFAULT_SCREENHEIGHT;
if(m_Depth == 0) m_Depth = _C_DEFAULT_SCREENDEPTH;
if(setGetSetupInt(_S_SECTION_GRAPHICS, _S_KEY_FPS)) {
m_dwFlags |= DDFLG_FPS;
}
//
// Set scroll rect
m_ScrollRect.SetRect(0, 0, m_Res_X, m_Res_Y);
//
DXTRACE("Initializing display...");
//
// 2. krok
// Creating DDraw
object
dwRet = DirectDrawCreateEx(NULL, (void**)&m_lpDD, IID_IDirectDraw7,
NULL);
DXERR ("Creating DirectDraw object", dwRet);
if(dwRet != DD_OK) {
Clean();
return dwRet;
}
//
// 3. krok
// Get capabilities of hardware
dwRet = m_lpDD->GetCaps(&Driver, &Hel);
DXERR ("Getting caps about hardware", dwRet);
if(dwRet != DD_OK) {
Clean();
return dwRet;
}
//
// 4. krok
// Set
cooperative level
dwRet = m_lpDD->SetCooperativeLevel(hWnd,
DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN);
DXERR ("Setting exclusive mode", dwRet);
if(dwRet != DD_OK) {
Clean();
return dwRet;
}
// Set display
mode
dwRet = m_lpDD->SetDisplayMode(m_Res_X,
m_Res_Y, m_Depth, 0, 0);
DXERR("Setting display mode", dwRet);
if(dwRet != DD_OK) {
Clean();
return dwRet;
}
//
// 5. krok
// Create flipping loop
DDSURFACEDESC2
ddsd;
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE;
ddsd.dwBackBufferCount = 1;
//
// Get a pointer to the front buffer
dwRet = m_lpDD->CreateSurface(&ddsd,
&lpDDSFront, NULL);
DXERR ("Getting pointer to front buffer", dwRet);
if(dwRet != DD_OK) {
Clean();
return dwRet;
}
//
// Create front buffer
dwRet = m_surFront.Create(lpDDSFront);
DXERR ("Creating front buffer", dwRet);
if(dwRet != DD_OK) {
Clean();
return dwRet;
}
//
// Get a pointer to the back buffer
DDSCAPS2 ddscaps;
ZeroMemory(&ddscaps, sizeof(ddscaps));
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
dwRet = m_surFront.GetSurface()->GetAttachedSurface(&ddscaps,
&lpDDSBack);
if(dwRet != DD_OK) {
DXERR ("Getting pointer to back
buffer", dwRet);
Clean();
return dwRet;
}
//
// Create back buffer
dwRet = m_surBack.Create(lpDDSBack);
if(dwRet != DD_OK) {
DXERR ("Creating back buffee", dwRet);
Clean();
return dwRet;
}
////////////////////////////////////////////////////////////////////////
m_bIsInit = true;
//
// 6. krok
dwRet = fntCreateFont(_S_ARIAL_DDF, _S_FONT_ARIAL);
if(dwRet != ERROR_SUCCESS) {
DXERR("Cannot create specified font
due", dwRet);
}
dwRet = fntCreateFont(_S_HUMANS_DDF, _S_FONT_HUMANS, TC_DARKGREEN);
if(dwRet != ERROR_SUCCESS) {
DXERR("Cannot create specified font
due", dwRet);
}
//
// 7. krok
// Display loading bitmap
disDefineBackground(_S_LOADING1, DDFLG_VIDEO_MEMORY);
disUpdateBackground();
disPresent();
//
// 8. krok
// Clipper
if(dwFlags & DDFLG_CLIPPER)
{
//
// Create rectangular region
CRgn rect; RGNDATA data; int n;
rect.CreateRectRgnIndirect(CRect(0,
0, m_Res_X, m_Res_Y));
n = rect.GetRegionData(NULL, 0);
if(rect.GetRegionData(&data, n) !=
ERROR) {
//
// Create
clipper
dwRet = m_lpDD->CreateClipper(0, &m_lpDDClipper, NULL);
DXERR ("Creating
clipper object", dwRet);
if(DD_OK !=
dwRet) {
Clean();
return dwRet;
}
//
// Set
clipper
dwRet = m_lpDDClipper->SetClipList(&data, 0);
DXERR ("Setting
clipper list", dwRet);
if(DD_OK !=
dwRet) {
Clean();
return dwRet;
}
dwRet = m_surBack.GetSurface()->SetClipper(m_lpDDClipper);
DXERR ("Setting
clipper", dwRet);
if(DD_OK !=
dwRet) {
Clean();
return dwRet;
}
m_dwFlags |=
DDFLG_CLIPPER;
}
else {
Clean();
return 1;
}
}
//
// 9. krok
// Gamma correction
BOOL bUseGamma = setGetSetupInt(_S_SECTION_GRAPHICS, _S_KEY_USEGAMMA);
if(bUseGamma && (dwFlags & DDFLG_GAMMA) && HasGammaSupport())
{
dwRet = m_surFront.GetSurface()->QueryInterface(IID_IDirectDrawGammaControl,
(LPVOID*) &m_GammaControl);
DXTRACE6("Getting pointer to gamma
correction object due", dwRet);
if(!m_GammaControl) {
Clean();
return dwRet;
}
m_dwFlags |= DDFLG_GAMMA;
}
//
// 10.krok
// Create and set palette
// If we have only 8-bit color depth, we need palette
if(m_Depth == 8) {
dwRet = SetPalette();
DXERR("Setting pallete due", dwRet);
if(dwRet != DD_OK) {
Clean();
return dwRet;
}
m_dwFlags |= DDFLG_PALETTE;
}
return dwRet;
}
Tato funkce je asi nejdelÜφ, ale rozhodn∞ nenφ nikterak
slo₧itß:
V prvnφm kroku naΦteme n∞kterΘ informace z konfiguraΦnφho souboru. KonkrΘtn∞ se
jednß o rozliÜenφ, barevnou hloubku a viditelnost FPS poΦφtadla. Ve druhΘm kroku
vytvß°φme objekt DirectDraw tak, jak jsme zvyklφ.
Ve 3. kroku zφskßme informace o funkcφch grafickΘ karty. Tyto informace m∙₧ete
vyu₧φt pro p°φpadnΘ zjiÜt∞nφ n∞kter²ch vlastnostφ grafickΘ karty.
Dßle (4.krok) nßsleduje dvojice funkcφ SetCooperativeLevel()
a SetDisplayMode(). I tyto dv∞ funkce dob°e znßme z
p°edeÜl²ch lekcφ.
5.krok: Inicializujeme p°ednφ a zadnφ povrch. Ani zde nenφ nic novΘho, snad
krom∞ prvnφho vyu₧itφ objektu z minulΘ lekce CSurface.
Nejprve inicializujeme ukazatele na rozhranφ
LPDIREDRAWSURFACE7 a potΘ z t∞chto ukazatel∙ vytvo°φme objekty
CSurface.
V 6. kroku vytvß°φme internφ fonty pro vykreslenφ FPS apod. Nynφ koneΦn∞ vidφte,
jak budeme pracovat s fonty. Nejd°φve se musφ zavolat funkce
fntCreateFont(), kterß vytvo°φ nov² font z bitmapy. Funkci p°edßte
°et∞zec, pod kter²m tento font p∙jde najφt (m∞l by b²t jedineΦn²), dßle cestu k
bitmap∞ (obojφ jsme definovali) a p°φpadn∞ barvu
fontu.
V 7. kroku pouze definuje pozadφ (Loading...). Jde tedy pouze o informaci
u₧ivateli. Proto₧e flippovacφ smyΦka jeÜt∞ nenφ v provozu, musφte um∞le zavolat
funkce UpdateBackground() a
Present(). Tφm zajistφte, ₧e se pozadφ rovnou zobrazφ na monitoru.
8. krok je clipper. Pokud si to u₧ivatel p°eje, je na zadnφ povrch p°ipojen
clipper. Prßci s nφm jsme ji₧ rovn∞₧ probφrali.
V 9. kroku inicializujeme gamma korekci. Nejprve zjistφme zda-li u₧ivatel chce
°φdit gamma korekci, po tΘ zda-li to chce programßtor a nakonec zda-li je to
v∙bec mo₧nΘ ze strany hardwaru. PotΘ zavolßme funkce
QueryInterface(), abychom zφskali ukazatel na rozhranφ
IDirectDrawGammaControl. Blφ₧e si o °φzenφ gammy
povφme u funkcφ Increment a
DecrementGamma().
10. a poslednφ krok je urΦen palet∞. Pokud u₧ivatel nastavφ 8-mi bitovou hloubku
barev, systΘm naΦte bitmapu z p°ipravenΘho zdroje, kter² je vlo₧en p°φmo do
knihovny.
Dßle si probereme funkci, kterß zjistφ zda-li mß vaÜe grafickß karta schopnost °φdit gamma korekci:
BOOL CDisplay::HasGammaSupport()
{
// Get driver
capabilities to determine gamma support.
DDCAPS ddcaps;
ZeroMemory( &ddcaps, sizeof(ddcaps) );
ddcaps.dwSize = sizeof(ddcaps);
GetDirectDraw()->GetCaps( &ddcaps, NULL );
// Does the
driver support gamma?
// The DirectDraw emulation layer does not support overlays
// so gamma related APIs will fail without hardware support.
if( ddcaps.dwCaps2
& DDCAPS2_PRIMARYGAMMA )
return TRUE;
else
return FALSE;
}
Funkce HasGammaSupport() vracφ TRUE, pokud gamma korekce je mo₧nß, jinak FALSE. Pou₧ijeme k tomu op∞t funkce objektu DirectDraw GetCaps(). Budou nßs zajφmat pouze schopnosti driveru (prvnφ parametr funkce) a nikoliv emulace (druhß parametr), kterß gammu neumφ. Gamma tedy musφ b²t podporovßna hardwarov∞. Nßsledujφcφm p°φkazem zjistφme hodnotu flagu DDCAPS2_PRIMARYGAMMA. Pokud je tato hodnota r∙znß od 0, funkce vracφ TRUE, jinak FALSE.
Funkci Present() ji₧ takΘ znßme z minul²ch lekcφ. Dnes ji obohatφme jen o prßt maliΦkostφ:
void CDisplay::Present()
{
HRESULT dwResult;
//
// Check initialization
if(!m_bIsInit) {
return;
}
//
// Check if we want to draw FPS
if(m_dwFlags & DDFLG_FPS) {
//
// Draw FPS
dwResult = UpdateFPS();
if(dwResult != ERROR_SUCCESS) {
DXERR("Cannot
UpdateFPS due", dwResult);
}
}
//
// Try to flip surfaces
// Neverending loop
while(1)
{
dwResult = m_surFront.GetSurface()->Flip(NULL,
0);
//we must restore main buffers
if(dwResult == DDERR_SURFACELOST) {
DXTRACE("Restoring
surfaces");
m_surFront.Restore();
m_surBack.Restore();
if(m_surBackground.IsValid())
{
m_surBackground.Restore(TRUE);
}
}
if(DD_OK == dwResult) {
break;
}
}
}
Za prvΘ sledujeme, zda-li u₧ivatel mß zßjem o zobrazenφ FPS. V kladnΘm p°φpad∞ FPS obnovφme ve funkci UpdateFPS(). Za zmφnku jeÜt∞ stojφ obnova hlavnφch povrch∙ p°i jejich ztrßt∞ (viz. p°edeÜlΘ lekce). Vyu₧φvßme k tomu ΦlenskΘ metody Restore(). Jinak na tΘto metod∞ nenφ nic zajφmavΘho.
Nßsleduje dvojice metod definujφcφ pozadφ. NßÜ systΘm podporuje dva typy pozadφ. Za prvΘ je to jednobarevnΘ (solid) pozadφ definovanΘ nßsledujφcφ metodou:
HRESULT CDisplay::DefineBackground(COLORREF
crColor)
{
//
// Release old
surface if initialized
m_surBackground.Release();
//
// Check initialization
if(!m_bIsInit) {
return 1;
}
//
// Save color of background
m_BackColor = crColor;
//
// Enable solid background
m_dwFlags |= DDFLG_SOLID;
//
// Disable scrolling
m_dwFlags &= ~DDFLG_SCROLLING;
return ERROR_SUCCESS;
}
Parametr crColor urΦuje barvu pozadφ. K definici tΘto barvy pou₧ijeme makro SURFACECOLOR(r,g,b). V souboru Common.h (projektu Common) je n∞kolik p°eddefinovan²ch barev. Na samotnΘ funkci nic nenφ. Uvolnφme povrch pozadφ, kter² zde nenφ pot°eba a musφme poΦφtat s tφm, ₧e u₧ivatel p°ed tφm mohl tento povrch pot°ebovat. Ulo₧φme si barvu pozadφ, abychom pozadφ mohli obnovit na zaΦßtku ka₧dΘho cyklu. Dßle systΘmu dßme v∞d∞t, ₧e chceme jednobarevnΘ pozadφ a vypneme pro jistotu flag dynamickΘho pozadφ, kter² je zde k niΦemu (viz. dßle). VÜimn∞te si, ₧e v ka₧dΘ funkci testujeme inicializaci objektu CDisplay.
Druhß verze definuje pozadφ na zßklad∞ bitmapy:
HRESULT CDisplay::DefineBackground(CString
strBMPFile, DWORD dwFlags)
{
HRESULT dwRet;
DDSURFACEDESC2 ddsdesc;
// Init size
before use
ddsdesc.dwSize =
sizeof(DDSURFACEDESC2);
//
// Check initialization
if(!m_bIsInit) {
return 1;
}
//
// Release old surface if initialized
m_surBackground.Release();
//
// Try to create new surface for background bitmap
dwRet = m_surBackground.Create(m_Res_X, m_Res_Y, dwFlags);
DXERR("Creating surface for background due", dwRet);
if(dwRet != ERROR_SUCCESS) {
return dwRet;
}
//
// Copy bitmap to surface
dwRet = m_surBackground.CopyBitmap(strBMPFile);
DXERR("Copying bitmap to surface due", dwRet);
if(dwRet != ERROR_SUCCESS) {
return dwRet;
}
//
// Save info about character of background
if(dwFlags & DDFLG_SCROLLING) {
m_dwFlags |= DDFLG_SCROLLING;
}
else {
m_dwFlags &= ~DDFLG_SCROLLING;
}
//
// Save info about background
// Save internal path for restore
m_BackBMP = strBMPFile;
// No solid, we
want bitmap background
m_dwFlags &= ~DDFLG_SOLID;
//
// Init source rectangle for blitting
m_BackSource.left
= 0;
m_BackSource.top = 0;
m_BackSource.right = m_surBackground.Width();
m_BackSource.bottom = m_surBackground.Height();
return dwRet;
}
Zde je to u₧ o trochu slo₧it∞jÜφ. Za prvΘ op∞t uvolnφme p°edchozφ pozadφ (pokud n∞jakΘ je). Po tΘ vytvo°φme nov² povrch o velikosti rozliÜenφ. Do tohoto povrchu nakopφrujeme bitmapu urΦenou parametrem strBMPFile. Dßle zapneme nebo vypneme dynamickΘ pozadφ. Pokud u₧ivatel chce dynamickΘ pozadφ musφ funkce p°edat flag DDFLG_SCROLLING. Na efekt dynamickΘho pozadφ se podφvejte sami v p°φkladu. Ulo₧φme si jmΘno bitmapy, kterΘ pou₧ijeme p°i obnov∞ pozadφ. Vypneme volbu jednobarevnΘho pozadφ a nastavφme zdrojov² obdΘlnφk pro funkci Blt(). To je vÜe.
Te∩ si vysv∞tlφme mo₧nß principieln∞ nejslo₧it∞jÜφ funkci UpdateBackground():
HRESULT CDisplay::UpdateBackground()
{
HRESULT dwReturn;
CRect dest1, src1, dest2, src2;
//
// Detect if background is scrolling or not
if(m_dwFlags & DDFLG_SCROLLING) {
//
// Moving of blitting area
m_ScrollRect.left += 1;
m_ScrollRect.right += 1;
//
// Reset m_rectScroll ,
// End of the screen: m_ScrollRect.left = 0, m_ScrollRect.right = m_Res_X;
if(m_ScrollRect.left == (int)m_Res_X) {
m_ScrollRect.left = 0;
m_ScrollRect.right = m_Res_X;
}
//
// Compute of right and left parts of blitting source anf destination rectangles
//
// Left destination rectangle
dest1.top = 0;
dest1.left = 0;
dest1.right = m_Res_X - m_ScrollRect.left;
dest1.bottom = m_Res_Y;
//
// Left source rectangle
src1.top = 0;
src1.left = m_ScrollRect.right - m_Res_X;
src1.right = m_Res_X;
src1.bottom = m_Res_Y;
//
// Right destination rectangle
dest2.top = 0;
dest2.left = m_Res_X - m_ScrollRect.left;
dest2.right = m_Res_X;
dest2.bottom = m_Res_Y;
//
// Right source rectangle
src2.top = 0;
src2.left = 0;
src2.right = m_ScrollRect.right - m_Res_X;
src2.bottom = m_Res_Y;
//
// Blit both part of background to the BS
//
// Blit first part of bcg
if(src1.left != src1.right) {
dwReturn = m_surBack.Blt(dest1, src1, &m_surBackground);
if(dwReturn != ERROR_SUCCESS) {
DXERR("Cannot blit bitmap scrl part 1 background due", dwReturn);
return dwReturn;
}
}
//
// Blit second part of bcg
if(src2.left != src2.right) {
dwReturn = m_surBack.Blt(dest2, src2, &m_surBackground);
if(dwReturn != ERROR_SUCCESS) {
DXERR("Cannot blit bitmap scrl part 2 background due", dwReturn);
return dwReturn;
}
}
}
else {
if(m_dwFlags & DDFLG_SOLID) {
//
// Blit solid nonscrolling background to the back buffer
dwReturn = m_surBack.Blt(CRect(0, 0, m_Res_X, m_Res_Y), m_BackColor);
if(dwReturn != ERROR_SUCCESS) {
DXERR("Cannot blit solid background due", dwReturn);
return dwReturn;
}
}
else {
//
// Blit bitmap non scrolling background to the BS
dwReturn = m_surBack.Blt(CRect(0, 0, m_Res_X, m_Res_Y), m_BackSource, &m_surBackground);
if(dwReturn != ERROR_SUCCESS) {
DXERR("Cannot blit bitmap background due", dwReturn);
return dwReturn;
}
}
}
return dwReturn;
}
Funkce obnovuje pozadφ, a¥ u₧ jednobarevnΘ Φi bitmapovΘ (statickΘ nebo dynamickΘ). V prvnφ Φßsti obnovujeme prßv∞ dynamickΘ pozadφ. K vysv∞tlenφ si dovolφm obrßzek:
Princip spoΦφvß ve dvou nezßvisl²ch vykreslenφ. Prvnφ vykreslφ Φßst pozadφ do obdΘlnφku dest1 a druh² do obdΘlnφku dest2. Ka₧d² cyklus se pom∞r mezi dest1 a dest2 m∞nφ: dest1 se zv∞tÜuje a dest2 se zmenÜuje a₧ dest1 vyplnφ cel² zadnφ buffer. V dalÜφm cyklu se zaΦne na novo. Zßrove≥ se takΘ musφ sprßvn∞ inicializovat zdrojovΘ obdΘlnφky. Ty jsou urΦeny pr∙nikem obdΘlnφk∙ dest do obdΘlnφku povrchu pozadφ. Pom∞r obou obdΘlnφku je dßn obdΘlnφkem m_ScrollRect. Vidφme, ₧e hodnoty left a right se ka₧d²m cyklem inkrementujφ a po nabytφ maximßlnφ hodnoty (rozliÜenφ v horizontßlnφm sm∞ru) se hodnota left vynuluje a hodnota right inicializuje na rozliÜenφ m_Res_X. Na konci tΘto sekce je samotnΘ vykreslenφ obou Φßstφ.
V dalÜφ Φßsti funkce, se vykresluje statickΘ pozadφ bu∩ jednobarevnΘ nebo bitmapovΘ. JednobarevnΘ vykreslenφ je velice jednoduchΘ. Prost∞ zavolßme verzi funkce Blt(), kterß kreslφ jednobarevnΘ plochy do povrchu. Pokud chceme vykreslovat bitmapovΘ pozadφ, zavolßme druhou verzi tΘto funkce. Parametry jsou zcela logickΘ.
PokraΦujme dßle s funkcφ UpdateFPS(). Jak nßzev napovφdß, funkce mß na starosti v²poΦet a aktualizaci ukazatele FPS, p°φpadn∞ stav grafickΘ pam∞ti:
HRESULT CDisplay::UpdateFPS()
{
DWORD dwRet;
//
// Show video memory
if(setGetSetupInt(_S_SECTION_GRAPHICS,
_S_KEY_SHOWVIDMEM)) {
DDCAPS Driver;
ZeroMemory(&Driver, sizeof(DDCAPS));
Driver.dwSize = sizeof(DDCAPS);
//
// Get capabilities of hardware
dwRet = m_lpDD->GetCaps(&Driver, NULL);
if(dwRet != DD_OK) {
DXERR ("Getting
caps about hardware", dwRet);
Clean();
return dwRet;
}
CString csTMem, csFMem;
csTMem.Format("Total video memory: %d
kB", Driver.dwVidMemTotal / 1024);
csFMem.Format("Free video memory: %d
kB", Driver.dwVidMemFree / 1024);
fntDrawText(0, 20, csTMem, _S_FONT_ARIAL);
fntDrawText(0, 40, csFMem, _S_FONT_ARIAL);
}
//
// Get time of system start
m_StartTime = GetTickCount();
//
// Increment frames counter
m_Frames++;
//
// Compute number of frames per one second
if((m_StartTime - m_StopTime) >= FPS_REFRESH_RATE) {
m_strFrames.Format("%2.1f", m_Frames
* 1000 / (m_StartTime - m_StopTime));
m_Frames = 0;
//
// Save old-new time
m_StopTime = m_StartTime;
}
//
// Draw FPS to the screen
return fntDrawText(0, 0, m_strFrames, _S_FONT_ARIAL);
}
Pokud si u₧ivatel prost°ednictvφm konfiguraΦnφho souboru p°eje zobrazit stav pam∞ti, musφme tento stav vydolovat pomocφ ji₧ znßmΘ funkce GetCaps(). Struktura DDCAPS skr²vß dva atributy dwVidMemTotal pro celkovΘ mno₧stvφ grafickΘ pam∞ti a dwVidMemFree pro volnΘ mno₧stvφ pam∞ti. Hodnoty, kterΘ jsou v bajtech, d∞lφme Φφslem 1024, abychom dosp∞li ke kB. Pomocφ funkce fntDrawText() vykreslφme °et∞zec na obrazovku. Funkce mß 4 parametry. Prvnφ dva urΦujφ sou°adnice textu na monitoru. DalÜφ parametr je °et∞zec, kter² se bude vykreslovat. Poslednφm parametrem je ID fontu, kter² jsme p°edem vytvo°ili funkcφ fntCreateFont(). Zkuste si vytvo°it metodu, kterß bude fungovat podobn∞ jako funkce printf() tj. bude mφt prom∞nn² poΦet parametr∙ a po₧adovan² °et∞zec automaticky zformßtuje a vykreslφ.
O trochu slo₧it∞jÜφ je to s FPS. FPS se aktualizuje jednou za periodu urΦenou konstantou FPS_REFRESH_RATE. V tΘto dob∞ zvyÜujeme poΦet obnoven²ch snφmk∙ o 1. Pokud je Φas obnovit informaci o stavu FPS, spoΦφtßme FPS tak, ₧e poΦet snφmk∙ vyd∞lφme uplynul²m Φasem od poslednφ aktualizace. Konstanta FPS_REFRESH_RATE je v milisekundßch, ale my chceme frame per second, tak₧e je t°eba vÜe p°evΘst na sekundy. Navφc je pot°eba vynulovat poΦφtadlo snφmk∙. Nakonec vykreslφme aktußlnφ stav FPS stejn²m zp∙sobem jako u pam∞ti.
Zkusme se nynφ rozebrat dvojicφ funkce IncrementGamma() a DecrementGamma(). Ob∞ funkce jsou tΘm∞° identickΘ, tak₧e je tu nebudu rozepisovat ob∞. Na mal² rozdφl samoz°ejm∞ upozornφm:
HRESULT CDisplay::IncrementGamma(int
_Amount)
{
DWORD dwRet;
DDGAMMARAMP ramp;
if(m_dwFlags & DDFLG_GAMMA) {
m_CurGamma += _Amount;
if(m_CurGamma > 256) {
m_CurGamma =
256;
return ERROR_SUCCESS;
}
ZeroMemory( &ramp, sizeof(ramp) );
dwRet = m_GammaControl->GetGammaRamp(
0, &ramp);
if(dwRet != DD_OK) {
return dwRet;
}
WORD dwGamma = 0;
m_CurGamma += _Amount;
// ve funkce DecrementGamma() je zde m_CurGamma
-= _Amount;
if(m_CurGamma > 256) m_CurGamma =
256;
for( int
iColor = 0; iColor < 256; iColor++ )
{
ramp.red[iColor] = dwGamma;
ramp.green[iColor] = dwGamma;
ramp.blue[iColor] = dwGamma;
dwGamma += (WORD) m_CurGamma;
}
dwRet = m_GammaControl->SetGammaRamp(
0, &ramp );
if(dwRet != DD_OK) {
return dwRet;
}
}
return 1;//ERROR_NOGAMMA;
}
Princip je jednoduch². Nejd°φve zφskßme aktußlnφ stav gammy,
po tΘ p°iΦteme ke vÜem barevn²m slo₧kßm parametr funkce a tento nov² stav
nastavφme.
Jak jsem slφbil v ·vodu, nynφ si povφme n∞co blφ₧e k °φzenφ gammy. SystΘm dokß₧e
zm∞nit barevnΘ vlastnosti povrch∙, ani₧ by m∞nil jejich obsah. Funkci si m∙₧ete
p°edstavit jako filtr skrz kter² pro₧enete vÜechny pixely danΘho povrchu (ve
skuteΦnosti to lze jen na p°ednφm povrchu) t∞sn∞ p°edtφm
ne₧ se zobrazφ na monitor. Pomocφ rozhranφ
IDirectDrawGammaControl m∙₧ete °φdit tento filtr a dosßhnout tak
zajφmav²ch efekt∙ jako jsou r∙znΘ zßblesky Φi ztmavenφ scΘny. V naÜem systΘmu je
°φzenφ velice jednoduchΘ. ╪φdφme pouze zesv∞tlenφ a ztmavenφ scΘny. To v praxi
znamenß, ₧e m∞nφme vÜechny t°i slo₧ky RGB stejn∞. K modifikaci barvy
jednotliv²ch pixel∙ se pou₧φvajφ tzv. ramp levels pomocφ nich₧ se
definuje zßvislost vstupu a v²stupu filtru. Takovou zßvislost m∙₧ete vid∞t i na
nßsledujφcφm obrßzku:
Tyto modifikovanΘ v²stupnφ hodnoty dßle prochßzejφ p°φmo do D/A p°evodnφku grafickΘ karty (DAC) a pak rovnou v analogovΘ podob∞ na monitor.
Nejprve tedy zφskßme objekt typu DDGAMMARAMP obsahujφcφ ramp levels vÜech t°φ barevn²ch slo₧ek. Tyto hodnoty zφskßme pomocφ funkce GetGammaRamp().
Pokud pou₧φvßme gamma korekci je Barva X nahrazena Barvou Y. Pokud graf prochßzφ osou prvnφho kvadrantu, v²stupnφ barva je stejnß jako vstupnφ (jin²mi slovy, barva se nijak nemodifikuje). Ve funkci je smyΦka for, ve kterΘ se hodnoty v²stupnφ barvy modifikujφ podle prom∞nnΘ m_CurGamma. ╚φm vyÜÜφ jsou tyto hodnoty, tφm je v²stupnφ barva sv∞tlejÜφ, proto₧e toto nastavenφ provßdφme u vÜech t°φ slo₧ek zßrove≥. V poli tedy budou vzestupnΘ hodnoty podobn∞ jako na obrßzku. Funkce m∙₧e modifikovat tak, ₧e zßvislost nebude lineßrnφ a m∙₧ete tak nap°φklad ·pln∞ potlaΦit n∞kterΘ barvy na povrchu.
V poslednφm kroku nastavφm novΘ hodnoty gamma ramp pomocφ funkce SetGammaRamp(). Funkce DecrementGamma() se liÜφ v jedinΘm znamΘnku. Ve zdrojovΘm k≤du je na to upozorn∞no v ÜedΘm komentß°i.
KoneΦn∞ tu mßme poslednφ funkci! Je to celkem slo₧itß funkce SetPalette(). Proto₧e paletu nebudeme pou₧φvat, nebudu zde funkci rozebφrat. Funkce zφskß paletu z p°eddefinovanΘ bitmapy a tuto paletu nastavφ. Abyste paletu mohli pou₧φt, musφte vlo₧it do knihovny zdroj (bitmapu), kterou nazv∞te "PALETA". Tato bitmapa m∙₧e b²t nap°φklad 1x1, ale d∙le₧itß je jejφ paleta, kterou vytvo°φte nap°φklad v CorelDraw p°i exportu.
Nynφ ji₧ mßme knihovnu p°ipravenou k pou₧itφ. Abychom si to trochu ulehΦili, nebudeme v klientskΘ aplikaci vytvß°et objekt CDisplay, ale vyexportujeme n∞kterΘ jejφ funkce.
Do projektu p°idejte soubory novΘ Common.h a Common.cpp. V t∞chto dvou souborech bude deklarace a definice exportovan²ch funkcφ. V Common.cpp navφc musφme vytvo°it objekt CDisplay, pomocφ kterΘho budeme volat v²Üe definovanΘ metody. Intern∞ takΘ pou₧φvßm objekt CDDFontEngine.
Common.h:
#ifndef DISPLAY_COMMON_H
#define DISPLAY_COMMON_H
//
// Include DD headers
#include <ddraw.h>
#include "..\Common\Common.h"
//
// Export/import macros
#ifndef
DISPLAY_API
#define DISPLAY_API __declspec(
dllimport )
#endif //
DISPLAY_API
class CDisplay;
class CSurface;
//
// Flags for CreateFullScreenSystem()
#define DDFLG_CLIPPER
0x00000001
#define DDFLG_WINDOWMODE 0x00000002
#define DDFLG_FULLSCREEN 0x00000004
#define DDFLG_GAMMA 0x00000008
#define DDFLG_PALETTE 0x00000010
// Common flags
#define DDFLG_FPS
0x00000020
// Flags for
DefineBackground()
#define DDFLG_SYSTEM_MEMORY
0x10000000
#define DDFLG_VIDEO_MEMORY 0x20000000
#define DDFLG_SCROLLING 0x40000000
#define DDFLG_SOLID 0x80000000
#define DDFLG_COLORKEY 0xF0000000
//
// Keys
// Graphics section
#define _S_KEY_WIDTH _T("ScreenWidth")
#define _S_KEY_HEIGHT _T("ScreenHeight")
#define _S_KEY_DEPTH _T("ScreenDepth")
#define _S_KEY_FPS _T("FPS")
#define _S_KEY_USEGAMMA _T("UseGamma")
#define _S_KEY_SHOWVIDMEM _T("ShowVidMem")
#include "Surface.h"
#include "DDFontEngine.h"
#include "Core.h"
//exports
DISPLAY_API
HRESULT disInit(HWND hWnd, UINT uFlags);
DISPLAY_API HRESULT disDefineBackground(COLORREF crColor);
DISPLAY_API HRESULT disDefineBackground(CString strBMPFile,
UINT nFlags);
DISPLAY_API HRESULT disBlt(CRect rectDestin, CRect rectSource,
CSurface *surSource);
DISPLAY_API HRESULT disBlt(CRect rectDestin, COLORREF crColor);
DISPLAY_API CSize disGetResolution();
DISPLAY_API HRESULT disUpdateBackground();
DISPLAY_API HRESULT disPresent();
DISPLAY_API HRESULT disDrawText(CString strText, int x = 0,
int y = 0,
COLORREF crColor = TC_YELLOW,
LPTSTR szFontName = NULL, int iHeight = 100);
DISPLAY_API HRESULT disIncreaseGamma(int d = 8);
DISPLAY_API HRESULT disDecreaseGamma(int d = 8);
DISPLAY_API HRESULT disFlash(DWORD dwFlashTime = 320, DWORD
dwUnflashTime = 500);
DISPLAY_API CDisplay* disGetDisplay();
DISPLAY_API HRESULT fntDrawText(int x, int y, CString csText,
CString csFont);
DISPLAY_API HRESULT fntCreateFont(CString csFontFile, CString
csFontName, COLORREF crColor = 0);
#endif // DISPLAY_COMMON_H
V tomto souboru takΘ vidφte n∞kterΘ definice, kterΘ jsem uvedl d°φve.
Common.cpp:
#include "stdafx.h"
#define DISPLAY_API __declspec(dllexport)
#include "Common.h"
CDisplay theDisplay;
CDDFontEngine theFontEngine;
//
// Exports function
DISPLAY_API HRESULT disInit(HWND hWnd, UINT uFlags)
{
return theDisplay.CreateFullScreenSystem(hWnd, uFlags);
}
DISPLAY_API HRESULT disDefineBackground(COLORREF crColor)
{
return theDisplay.DefineBackground(crColor);
}
DISPLAY_API HRESULT disDefineBackground(CString strBMPFile, UINT nFlags)
{
return theDisplay.DefineBackground(strBMPFile, nFlags);
}
DISPLAY_API HRESULT disBlt(CRect rectDestin, CRect rectSource, CSurface*
surSource)
{
return theDisplay.GetBackSurface()->Blt(rectDestin,
rectSource, surSource);
}
DISPLAY_API HRESULT disBlt(CRect rectDestin, COLORREF crColor)
{
return theDisplay.GetBackSurface()->Blt(rectDestin, crColor);
}
DISPLAY_API CSize disGetResolution()
{
return theDisplay.GetResolution();
}
DISPLAY_API HRESULT disUpdateBackground()
{
return theDisplay.UpdateBackground();
}
DISPLAY_API HRESULT disPresent()
{
theDisplay.Present();
return ERROR_SUCCESS;
}
DISPLAY_API HRESULT disIncreaseGamma(int d)
{
return theDisplay.IncrementGamma(d);
}
DISPLAY_API HRESULT disDecreaseGamma(int d)
{
return theDisplay.DecrementGamma(d);
}
DISPLAY_API CDisplay* disGetDisplay()
{
return &theDisplay;
}
DISPLAY_API HRESULT fntDrawText(int x, int y, CString csText, CString csFont)
{
return theFontEngine.DrawText(x, y, csText, csFont);
}
DISPLAY_API HRESULT fntCreateFont(CString csFontFile, CString csFontName,
COLORREF crColor)
{
return theFontEngine.CreateFont(csFontFile, csFontName,
crColor);
}
Nynφ ji₧ staΦφ vlo₧it hlaviΦkov² soubor Common.h z projektu Display do hlavnφho projektu Game a m∙₧ete pou₧φt vÜechny v²Üe definovanΘ funkce. Pokud by Vßm n∞co neÜlo nebo nefungovalo, podφvejte se do p°φkladu, kter² najdete v sekci Downloads.
V²Üe uveden² postup exportu funkcφ jsme probφrali v minul²ch lekcφch, tak₧e se zde nebudu dßle rozepisovat.
A je tu op∞t konec. DneÜnφ lekce byla celkem rozsßhlß, ₧e? P°esto se nedov∞d∞li tΘm∞° nic novΘho. Jen aplikujeme to, co u₧ znßme.
V p°φÜtφ lekci zapojφme do naÜeho projektu knihovnu Input.dll, kterou ji₧ mßme tΘm∞° p°ipravenou. StaΦφ ji jen malinko modifikovat, abychom vykreslovali kurzor pomocφ DirectDraw a m∙₧eme to celΘ spustit. PotΘ zaΦneme op∞t n∞co novΘho.
T∞Üφm se p°φÜt∞ nashledanou.