33. DirectDraw II
  1. DalÜφ p°φklad ukazuje, jak inicializovat DirectDraw, vytvo°it u₧ivatelskou paletu a zobrazit ji na DirectDrawSurface. ZaΦneme v²voj novΘ aplikace. Formulß° nechßme prßzdn², je u n∞j pouze dopln∞n konstruktor a vytvo°ena obsluha udßlosti OnPaint. Do deklarace t°φdy formulß°e bylo dopln∞no n∞kolik ve°ejn²ch slo₧ek (t°i metody a p∞t datov²ch slo₧ek):

  2. void __fastcall InitializeDirectDraw();
    void __fastcall SetupPrimarySurface();
    void __fastcall ShowPalette();
    int ddColors, ddWidth, ddHeight;
    IDirectDraw *DirectDraw;
    IDirectDrawSurface *PrimarySurface;
    Nßsleduje v²pis zdrojovΘho souboru formulß°e:
    #include <vcl.h>
    #pragma hdrstop
    #include "DDCP.h"
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
    {
      BorderStyle = bsNone;
      InitializeDirectDraw();
    }
    void __fastcall TForm1::InitializeDirectDraw()
    {
      DirectDrawCreate(NULL, &DirectDraw, NULL);
      DirectDraw->SetCooperativeLevel(Handle, DDSCL_ALLOWREBOOT |
        DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
      DirectDraw->SetDisplayMode(640, 480, 8);
      SetupPrimarySurface();
    }
    void __fastcall TForm1::SetupPrimarySurface()
    {
      DDSURFACEDESC ddsd;
      ZeroMemory(&ddsd, sizeof(ddsd));
      ddsd.dwSize = sizeof(ddsd);
      ddsd.dwFlags = DDSD_CAPS;
      ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
      DirectDraw->CreateSurface(&ddsd, &PrimarySurface, NULL);
    }
    void __fastcall TForm1::ShowPalette()
    {
      RECT rect;
      rect.top = 60;
      DDBLTFX ddbltfx;
      ZeroMemory(&ddbltfx, sizeof(ddbltfx));
      ddbltfx.dwSize = sizeof(ddbltfx);
      IDirectDrawPalette *palette332;
      PALETTEENTRY pe[256];
      // algoritmus pro paletu 332
      for(int i = 0; i < 256; i++)
      {
        pe[i].peRed = (BYTE) (((i >> 5)& 7)* 255/ 7);
        pe[i].peGreen = (BYTE) (((i >> 2)& 7)* 255/ 7);
        pe[i].peBlue = (BYTE) (((i >> 0)& 3)* 255/ 3);
        pe[i].peFlags = (BYTE)0;
      }
      DirectDraw->CreatePalette(DDPCAPS_8BIT, pe, &palette332, NULL);
      PrimarySurface->SetPalette(palette332);
      for (int i = 0; i < 255; i++)
      {
        ddbltfx.dwFillColor = i;
        if(i % 16 == 0)
        {
          rect.top += 20;
          rect.left = 160;
          rect.right = rect.left + 10;
          rect.bottom = rect.top + 10;
        }
        else
        {
          rect.left += 20;
          rect.right = rect.left + 10;
        }
        PrimarySurface->Blt(&rect, NULL, NULL, DDBLT_COLORFILL, &ddbltfx);
      }
    }
    void __fastcall TForm1::FormPaint(TObject *Sender)
    {
      DDBLTFX ddbltfx;
      ZeroMemory(&ddbltfx, sizeof(ddbltfx));
      ddbltfx.dwSize = sizeof(ddbltfx);
      ddbltfx.dwFillColor = RGB(0x00, 0x00, 0x00);
      PrimarySurface->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx);
      ShowPalette();
    }
    Program si prostudujte. Po jeho spuÜt∞nφ je inicializovßn DirectDraw, vytvo°ena primßrnφ vrstva, vytvo°ena a zobrazena paleta. Program nenφ mo₧no b∞₧n²m zp∙sobem ukonΦit.
  3. DalÜφ program ukazuje koncepci zavßd∞nφ bitovΘ mapy do DirectDraw. Program ukazuje p°epφnßnφ mezi dv∞mi vrstvami (jedna obsahuje bitovou mapu a druhß je Φernß). Obrßzek tedy blikß. Tento program pou₧φvß pomocnou knihovnu funkcφ pro zavßd∞nφ bitov²ch map a palet ze zdroj∙. Nßsleduje v²pis hlaviΦkovΘho souboru tΘto zdrojovΘ jednotky (soubor ddutil.h):

  4. /*  Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
     *  File:       ddutil.cpp
     *  Content:    Routines for loading bitmap and palettes from resources
     *********************************************************************/
    #ifdef __cplusplus
    extern "C" {            /* Assume C declarations for C++ */
    #endif /* __cplusplus */
    extern IDirectDrawPalette * DDLoadPalette(IDirectDraw *pdd,
           LPCSTR szBitmap);
    extern IDirectDrawSurface * DDLoadBitmap(IDirectDraw *pdd,
           LPCSTR szBitmap, int dx, int dy);
    extern HRESULT DDReLoadBitmap(IDirectDrawSurface *pdds,LPCSTR szBitmap);
    extern HRESULT DDCopyBitmap(IDirectDrawSurface *pdds, HBITMAP hbm,
           int x, int y, int dx, int dy);
    extern DWORD DDColorMatch(IDirectDrawSurface *pdds, COLORREF rgb);
    extern HRESULT DDSetColorKey(IDirectDrawSurface *pdds, COLORREF rgb);
    #ifdef __cplusplus
    }
    #endif /* __cplusplus */
    Zdrojov² soubor ddutil.cpp mß nßsledujφcφ obsah:
    #undef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    #include <windowsx.h>
    #include <ddraw.h>
    #include "ddutil.h"
    /*
     *  DDLoadBitmap - zavßd∞nφ vrstvy DirectDraw ze zdroje bitovΘ mapy.
     */
    extern "C" IDirectDrawSurface * DDLoadBitmap(IDirectDraw *pdd,
               LPCSTR szBitmap, int dx, int dy)
    {
      HBITMAP             hbm;
      BITMAP              bm;
      DDSURFACEDESC       ddsd;
      IDirectDrawSurface *pdds;
      // pokus o zavedenφ bitovΘ mapy jako zdroje, p°i ne·sp∞chu ji zavedeme
      // ze souboru
      hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), szBitmap,
             IMAGE_BITMAP, dx, dy, LR_CREATEDIBSECTION);
      if (hbm == NULL)
        hbm = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP, dx, dy,
               LR_LOADFROMFILE|LR_CREATEDIBSECTION);
      if (hbm == NULL) return NULL;
      // zφskßnφ velikosti bitovΘ mapy
      GetObject(hbm, sizeof(bm), &bm);
      // vytvo°enφ vrstvy pro tuto bitovou mapu
      ZeroMemory(&ddsd, sizeof(ddsd));
      ddsd.dwSize = sizeof(ddsd);
      ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
      ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
      ddsd.dwWidth = bm.bmWidth;
      ddsd.dwHeight = bm.bmHeight;
      if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK) return NULL;
      DDCopyBitmap(pdds, hbm, 0, 0, 0, 0);
      DeleteObject(hbm);
      return pdds;
    }
    /*
     * DDReLoadBitmap - zavedenφ bitovΘ mapy ze souboru nebo zdroje
     * na vrstvu (pou₧φvßno k op∞tovnΘmu zavedenφ vrstvy po obnoveni).
     */
    HRESULT DDReLoadBitmap(IDirectDrawSurface *pdds, LPCSTR szBitmap)
    {
      HBITMAP             hbm;
      HRESULT             hr;
      hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), szBitmap,
             IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
      if (hbm == NULL)
      hbm = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP, 0, 0,
            LR_LOADFROMFILE|LR_CREATEDIBSECTION);
      if (hbm == NULL)
      {
        OutputDebugString("handle is null\n");
        return E_FAIL;
      }
      hr = DDCopyBitmap(pdds, hbm, 0, 0, 0, 0);
      if (hr != DD_OK) OutputDebugString("ddcopybitmap failed\n");
      DeleteObject(hbm);
      return hr;
    }

    /*
     *  DDCopyBitmap - kreslenφ bitovΘ mapy na vrstv∞
     */
    extern "C" HRESULT DDCopyBitmap(IDirectDrawSurface *pdds, HBITMAP hbm,
            int x, int y, int dx, int dy)
    {
      HDC                 hdcImage;
      HDC                 hdc;
      BITMAP              bm;
      DDSURFACEDESC       ddsd;
      HRESULT             hr;
      if (hbm == NULL || pdds == NULL) return E_FAIL;
      // obnovenφ vrstvy
      pdds->Restore();
      // v²b∞r bitovΘ mapy v memoryDC, kterou chceme pou₧φt
      hdcImage = CreateCompatibleDC(NULL);
      if (!hdcImage) OutputDebugString("createcompatible dc failed\n");
      SelectObject(hdcImage, hbm);
      // zφskßnφ velikosti bitovΘ mapy
      GetObject(hbm, sizeof(bm), &bm);
      dx = dx == 0 ? bm.bmWidth  : dx;
      dy = dy == 0 ? bm.bmHeight : dy;
      // zφskßnφ velikosti vrstvy
      ddsd.dwSize = sizeof(ddsd);
      ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
      pdds->GetSurfaceDesc(&ddsd);
      if ((hr = pdds->GetDC(&hdc)) == DD_OK)
      {
        StretchBlt(hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, x, y,
                   dx, dy, SRCCOPY);
        pdds->ReleaseDC(hdc);
      }
      DeleteDC(hdcImage);
      return hr;
    }
    //
    // DDLoadPalette - vytvo°enφ objektu palety DirectDraw ze zdroje bitovΘ
    // mapy (pokud zdroj neexistuje vytvo°φme implicitnφ paletu 332).
    //
    #pragma warn -pia-
    extern "C" IDirectDrawPalette * DDLoadPalette(IDirectDraw *pdd,
            LPCSTR szBitmap)
    {
      IDirectDrawPalette* ddpal;
      int                 i;
      int                 n;
      int                 fh;
      HRSRC               h;
      LPBITMAPINFOHEADER  lpbi;
      PALETTEENTRY        ape[256];
      RGBQUAD *           prgb;
      // vytvo°enφ palety 332 jako implicitnφ
      for (i=0; i<256; i++)
      {
        ape[i].peRed   = (BYTE)(((i >> 5) & 0x07) * 255 / 7);
        ape[i].peGreen = (BYTE)(((i >> 2) & 0x07) * 255 / 7);
        ape[i].peBlue  = (BYTE)(((i >> 0) & 0x03) * 255 / 3);
        ape[i].peFlags = (BYTE)0;
      }
      // zφskßnφ ukazatele na zdroj bitovΘ mapy
      if (szBitmap && (h = FindResource(NULL, szBitmap, RT_BITMAP)))
      {
        lpbi = (LPBITMAPINFOHEADER)LockResource(LoadResource(NULL, h));
        if (!lpbi) OutputDebugString("lock resource failed\n");
        prgb = (RGBQUAD*)((BYTE*)lpbi + lpbi->biSize);
        if (lpbi == NULL || lpbi->biSize < sizeof(BITMAPINFOHEADER)) n = 0;
        else if (lpbi->biBitCount > 8) n = 0;
        else if (lpbi->biClrUsed == 0) n = 1 << lpbi->biBitCount;
        else n = lpbi->biClrUsed;
        // tabulka barev DIB mß svΘ bavy uloeny jako BGR a ne RGB
        for(i=0; i<n; i++ )
        {
          ape[i].peRed   = prgb[i].rgbRed;
          ape[i].peGreen = prgb[i].rgbGreen;
          ape[i].peBlue  = prgb[i].rgbBlue;
          ape[i].peFlags = 0;
        }
      }
      else if (szBitmap && (fh = _lopen(szBitmap, OF_READ)) != -1)
      {
        BITMAPFILEHEADER bf;
        BITMAPINFOHEADER bi;
        _lread(fh, &bf, sizeof(bf));
        _lread(fh, &bi, sizeof(bi));
        _lread(fh, ape, sizeof(ape));
        _lclose(fh);
        if (bi.biSize != sizeof(BITMAPINFOHEADER)) n = 0;
        else if (bi.biBitCount > 8) n = 0;
        else if (bi.biClrUsed == 0) n = 1 << bi.biBitCount;
        else n = bi.biClrUsed;
        // tabulka barev DIB mß svΘ bavy uloeny jako BGR a ne RGB
        for(i=0; i<n; i++ )
        {
          BYTE r = ape[i].peRed;
          ape[i].peRed  = ape[i].peBlue;
          ape[i].peBlue = r;
        }
      }
      pdd->CreatePalette(DDPCAPS_8BIT, ape, &ddpal, NULL);
      return ddpal;
    }
    #pragma warn -pia
    /*
     * DDColorMatch - p°evod RGB barvy na fyzickΘ barvy
     */
    extern "C" DWORD DDColorMatch(IDirectDrawSurface *pdds, COLORREF rgb)
    {
      COLORREF rgbT;
      HDC hdc;
      DWORD dw = CLR_INVALID;
      DDSURFACEDESC ddsd;
      HRESULT hres;
      if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
      {
        rgbT = GetPixel(hdc, 0, 0); // ulo₧enφ souΦasnΘ barvy
        SetPixel(hdc, 0, 0, rgb);   // nastavenφ vlastnφ barvy
        pdds->ReleaseDC(hdc);
      }
      ddsd.dwSize = sizeof(ddsd);
      while((hres=pdds->Lock(NULL,&ddsd,0,NULL))==DDERR_WASSTILLDRAWING);
      if (hres == DD_OK)
      {
        dw  = *(DWORD *)ddsd.lpSurface;
        if(ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
          dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1;
        pdds->Unlock(NULL);
      }
      if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
      {
        SetPixel(hdc, 0, 0, rgbT);
        pdds->ReleaseDC(hdc);
      }
      return dw;
    }
    /*
     * DDSetColorKey - nastavenφ barevnΘho klφΦe pro vrstvu
     */
    extern "C" HRESULT DDSetColorKey(IDirectDrawSurface *pdds, COLORREF rgb)
    {
      DDCOLORKEY          ddck;
      ddck.dwColorSpaceLowValue  = DDColorMatch(pdds, rgb);
      ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
      return pdds->SetColorKey(DDCKEY_SRCBLT, &ddck);
    }
    ZaΦneme v²vojem novΘ aplikace. Do projektu p°idßme v²Üe uveden² zdrojov² soubor. NaÜe aplikace pot°ebuje soubor zdroj∙ bitovΘ mapy. Bitovou mapu si stßhneme a ulo₧φme do stejnΘho adresß°e jako ostatnφ soubory projektu. K vytvo°enφ souboru zdroj∙ z tΘto bitovΘ mapy vytvo°φme soubor ddex2.rc, kter² takΘ p°idßme k projektu (ve stejnΘm adresß°i jako je projekt) s nßsledujφcφm obsahem:
    BACK BITMAP BACK.BMP
    Na formulß° vlo₧φme komponentu Timer a vytvo°φme n∞kolik obsluh udßlostφ. HlaviΦkov² soubor formulß°e vypadß takto:
    #ifndef MainH
    #define MainH
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <Menus.hpp>
    #include <ExtCtrls.hpp>
    class TForm1 : public TForm
    {
    __published:
            TTimer *Timer1;
            void __fastcall FormDestroy(TObject *Sender);
            void __fastcall FormKeyDown(TObject *Sender, WORD &Key,
                                        TShiftState Shift);
            void __fastcall FormPaint(TObject *Sender);
            void __fastcall Timer1Timer(TObject *Sender);
    private:
      LPDIRECTDRAW         lpDD;           // objekt DirectDraw
      LPDIRECTDRAWSURFACE  lpDDSPrimary;   // primßrnφ vrstva DirectDraw
      LPDIRECTDRAWSURFACE  lpDDSBack;      // zadnφ vrstva DirectDraw
      LPDIRECTDRAWPALETTE  lpDDPal;        // paleta DirectDraw
      BOOL                 bActive;
      BYTE phase;
      AnsiString FrontMsg;
      AnsiString BackMsg;
      void __fastcall Start();
    public:
            __fastcall TForm1(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif
    Zdrojov² soubor formulß°e tvo°φ:
    #include <vcl.h>
    #include <ddraw.h>
    #pragma hdrstop
    #include "Main.h"
    #include "ddutil.h"
    #pragma resource "*.dfm"
    #define TIMER_ID        1
    #define TIMER_RATE      500
    TForm1 *Form1;
    char szBackground[] = "BACK";
    __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
    {
      lpDD = NULL;
      phase = 0;
      bActive = False;
      FrontMsg = "Front buffer (F12 or Esc to quit)";
      BackMsg = "Back buffer (F12 or Esc to quit)";
    }
    void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
      if(lpDD != NULL)
      {
        if(lpDDSPrimary != NULL)
        {
          lpDDSPrimary->Release();
          lpDDSPrimary = NULL;
        }
        if(lpDDPal != NULL )
        {
          lpDDPal->Release();
          lpDDPal = NULL;
        }
        lpDD->Release();
        lpDD = NULL;
      }
    }
    void __fastcall TForm1::Start()
    {
      HRESULT ddrval;
      DDSURFACEDESC ddsd;
      DDSCAPS ddscaps;
      char buf[256];
      ddrval = DirectDrawCreate(NULL, &lpDD, NULL);
      if(ddrval == DD_OK)
      {
        ddrval = lpDD->SetCooperativeLevel(Handle,
          DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
        if(ddrval == DD_OK)
        {
          ddrval = lpDD->SetDisplayMode(640, 480, 8);
          if(ddrval == DD_OK)
          {
            ddsd.dwSize = sizeof(ddsd);
            ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
            ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
                                  DDSCAPS_FLIP | DDSCAPS_COMPLEX;
            ddsd.dwBackBufferCount = 1;
            ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
            if(ddrval == DD_OK)
            {
              ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
              ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps,
                                                    &lpDDSBack);
              if(ddrval == DD_OK)
              {
                lpDDPal = DDLoadPalette(lpDD, szBackground);
                if (lpDDPal == NULL) goto error;
                ddrval = lpDDSPrimary->SetPalette(lpDDPal);
                if( ddrval != DD_OK ) goto error;
                ddrval = DDReLoadBitmap(lpDDSBack, szBackground);
                if( ddrval != DD_OK ) goto error;
                Timer1->Enabled = True;
                bActive = True;
                return;
              }
            }
          }
        }
      }
    error:
      wsprintf(buf, "Direct Draw Init Failed (%08lx)\n", ddrval);
      MessageBox(Handle, buf, "ERROR", MB_OK);
      Close();
    }
    void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,
            TShiftState Shift)
    {
       switch (Key)
       {
         case VK_F3:
           Start();
           break;
         case VK_ESCAPE:
         case VK_F12:
           Close();
           break;
       }
    }
    void __fastcall TForm1::FormPaint(TObject *Sender)
    {
      RECT rc;
      SIZE size;
      char szMsg[]="Page Flipping Test: Press F3 to start, F12 or Esc to exit";
      if (!bActive)
      {
        HDC DC = GetDC(Handle);
        rc = GetClientRect();
        GetTextExtentPoint(DC, szMsg, lstrlen(szMsg), &size);
        SetBkColor(DC, RGB(0, 0, 0));
        SetTextColor(DC, RGB(255, 255, 0));
        TextOut(DC, (rc.right - size.cx)/2, (rc.bottom - size.cy)/2,
          szMsg, sizeof(szMsg)-1);
        ReleaseDC(Handle, DC);
      }
    }
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
      HDC DC;
      if (lpDDSBack->GetDC(&DC) == DD_OK)
      {
        if(phase)
        {
          SetBkColor(DC, RGB(0, 0, 255));
          SetTextColor(DC, RGB(255, 255, 0));
          TextOut(DC, 0, 0, FrontMsg.c_str(), FrontMsg.Length());
          phase = 0;
        }
        else
        {
          SetBkColor(DC, RGB(0, 0, 255));
          SetTextColor(DC, RGB(0, 255, 255));
          TextOut(DC, 0, 0, BackMsg.c_str(), BackMsg.Length());
          phase = 1;
        }
        lpDDSBack->ReleaseDC(DC);
      }
      while(1)
      {
        HRESULT ddrval;
        ddrval = lpDDSPrimary->Flip( NULL, 0 );
        if( ddrval == DD_OK )
          break;
        if( ddrval == DDERR_SURFACELOST )
        {
          ddrval = lpDDSPrimary->Restore();
          if( ddrval != DD_OK ) break;
          ddrval = DDReLoadBitmap(lpDDSBack, szBackground);
          if( ddrval != DD_OK ) break;
        }
        if( ddrval != DDERR_WASSTILLDRAWING ) break;
      }
    }
    Zde jsou pou₧ity nßm ji₧ znßmΘ metody. Aplikaci vyzkouÜejte.

  5. Jako poslednφ aplikaci pou₧φvajφcφ DirectDraw si ukß₧eme aplikaci provßd∞jφcφ ji₧ skuteΦnou animaci. ZaΦneme v²voj novΘ aplikace. Tato aplikace op∞t vyu₧φvß funkce z jednotky ddutil.cpp (jako p°edchozφ aplikace). P°idßme tedy tuto jednotku k naÜemu projektu (hlaviΦkov² soubor ddutil.h musφ b²t ve stejnΘm adresß°i). Aplikace op∞t bude pot°ebovat soubor zdroj∙ s bitovou mapou. Stßhneme si bitovou mapu a umφstφme ji do adresß°e projektu. Z tΘto bitovΘ mapy vytvo°φme soubor zdroj∙ pomocφ nßsledujφcφho soubor∙ (je zapot°ebφ aby byl v adresß°i projektu, nazveme jej ddex4.rc a p°idßme jej k projektu):

  6. #include "resource.h"
    ALL BITMAP ALL.BMP
    IDR_MENU MENU DISCARDABLE
    BEGIN
        POPUP "&File"
        BEGIN
            MENUITEM "E&xit",  IDM_EXIT
        END
    END
    Vidφme ₧e tento soubor vklßdß hlaviΦkov² soubor resource.h. Tento hlaviΦkov² soubor obsahuje (umφstφme jej do stejnΘho adresß°e; jsou zde definice identifikßtor∙ prvk∙ souboru zdroj∙):
    #define IDR_MENU                        102
    #define IDM_EXIT                        40001
    HlaviΦkov² soubor formulß°e mß nßsledujφcφ obsah:
    #ifndef MainH
    #define MainH
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #define WM_INFOSTART WM_USER
    class TForm1 : public TForm
    {
    __published:
      void __fastcall FormDestroy(TObject *Sender);
      void __fastcall FormKeyDown(TObject *Sender, WORD &Key,
        TShiftState Shift);
      void __fastcall FormPaint(TObject *Sender);
    private:
      LPDIRECTDRAW  lpDD;
      LPDIRECTDRAWSURFACE  lpDDSPrimary;
      LPDIRECTDRAWSURFACE  lpDDSBack;
      LPDIRECTDRAWSURFACE  lpDDSOne;
      LPDIRECTDRAWPALETTE  lpDDPal;
      BOOL FActive;
      BOOL FRunApp;
      void UpdateFrame(void);
      void Start();
      void InitFail();
      HRESULT RestoreAll(void);
      MESSAGE void MyMove(TMessage &Message);
    public:
      __fastcall TForm1(TComponent* Owner);
    BEGIN_MESSAGE_MAP
      MESSAGE_HANDLER(WM_INFOSTART, TMessage, MyMove);
    END_MESSAGE_MAP(TForm);
    };
    extern TForm1 *Form1;
    #endif
    a zdrojov² soubor formulß°e obsahuje:
    #include <vcl.h>
    #include <ddraw.h>
    #pragma hdrstop
    #include "ddutil.h"
    #include "Main.h"
    #pragma resource "*.dfm"
    #define NAME "DDExample4"
    #define TITLE "Direct Draw Example 4"
    char szBitmap[] = "ALL";
    TForm1 *Form1;
    __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
    {
      FRunApp = True;
      FActive = False;
    }
    MESSAGE void TForm1::MyMove(TMessage &Message)
    {
      do {
        UpdateFrame();
        Application->ProcessMessages();
      } while(FRunApp == True);
    }
    void TForm1::InitFail()
    {
        MessageBox(Handle, "DirectDraw Init FAILED", TITLE, MB_OK );
        Close();
    }
    void TForm1::Start()
    {
      HRESULT ddrval;
      DDSURFACEDESC ddsd;
      DDSCAPS ddscaps;
      ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
      if( ddrval != DD_OK )
      {
         InitFail();
         return;
      }
      ddrval = lpDD->SetCooperativeLevel(Handle, DDSCL_EXCLUSIVE |
               DDSCL_FULLSCREEN );
      if( ddrval != DD_OK )
      {
        InitFail();
        return;
      }
      ddrval = lpDD->SetDisplayMode( 640, 480, 8);
      if( ddrval != DD_OK )
      {
        InitFail();
        return;
      }
      ddsd.dwSize = sizeof( ddsd );
      ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
      ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
                            DDSCAPS_FLIP | DDSCAPS_COMPLEX;
      ddsd.dwBackBufferCount = 1;
      ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
      if( ddrval != DD_OK )
      {
        InitFail();
        return;
      }
      ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
      ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack);
      if( ddrval != DD_OK )
      {
        InitFail();
        return;
      }
      lpDDPal = DDLoadPalette(lpDD, szBitmap);
      if (lpDDPal)
          lpDDSPrimary->SetPalette(lpDDPal);
      lpDDSOne = DDLoadBitmap(lpDD, szBitmap, 0, 0);
      if( lpDDSOne == NULL )
      {
        InitFail();
        return;
      }
      DDSetColorKey(lpDDSOne, RGB(0,0,0));
    }
    void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
      if( lpDD != NULL )
      {
        if( lpDDSPrimary != NULL )
        {
          lpDDSPrimary->Release();
          lpDDSPrimary = NULL;
        }
        if( lpDDSOne != NULL )
        {
          lpDDSOne->Release();
          lpDDSOne = NULL;
        }
        if( lpDDPal != NULL )
        {
          lpDDPal->Release();
          lpDDPal = NULL;
        }
        lpDD->Release();
        lpDD = NULL;
      }
    }
    void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,
            TShiftState Shift)
    {
      switch (Key)
      {
        case VK_F3:
          FActive = True;
          Start();
          PostMessage(Handle, WM_INFOSTART, 0, 0);
          break;
        case VK_ESCAPE:
        case VK_F12:
          FRunApp = False;
          FActive = False;
          Close();
          break;
      }
    }
    HRESULT TForm1::RestoreAll( void )
    {
      HRESULT ddrval;
      ddrval = lpDDSPrimary->Restore();
      if( ddrval == DD_OK )
      {
       ddrval = lpDDSOne->Restore();
       if( ddrval == DD_OK ) DDReLoadBitmap(lpDDSOne, szBitmap);
      }
      return ddrval;
    }
    void TForm1::UpdateFrame( void )
    {
      static DWORD lastTickCount[3] = {0,0,0};
      static int  currentFrame[3] = {0,0,0};
      DWORD  thisTickCount;
      RECT  rcRect;
      DWORD  delay[3] = {50, 78, 13};
      int   i;
      int   xpos[3] = {288, 190, 416};
      int   ypos[3] = {128, 300, 256};
      HRESULT  ddrval;
      thisTickCount = GetTickCount();
      for(i=0; i<3; i++)
      {
        if((thisTickCount - lastTickCount[i]) > delay[i])
        {
          lastTickCount[i] = thisTickCount;
          currentFrame[i]++;
          if(currentFrame[i] > 59) currentFrame[i] = 0;
        }
      }
      rcRect.left = 0;
      rcRect.top = 0;
      rcRect.right = 640;
      rcRect.bottom = 480;
      while(1)
      {
        ddrval = lpDDSBack->BltFast( 0, 0, lpDDSOne,
        &rcRect, DDBLTFAST_NOCOLORKEY );
        if( ddrval == DD_OK ) break;
        if( ddrval == DDERR_SURFACELOST )
        {
          ddrval = RestoreAll();
          if( ddrval != DD_OK ) return;
        }
        if( ddrval != DDERR_WASSTILLDRAWING ) return;
      }
      if(ddrval != DD_OK) return;
      for(i=0; i<3; i++)
      {
        rcRect.left   = currentFrame[i]%10*64;
        rcRect.top    = currentFrame[i]/10*64 + 480;
        rcRect.right  = currentFrame[i]%10*64 + 64;
        rcRect.bottom = currentFrame[i]/10*64 + 64 + 480;
        while( 1 )
        {
          ddrval = lpDDSBack->BltFast( xpos[i], ypos[i], lpDDSOne,
            &rcRect, DDBLTFAST_SRCCOLORKEY );
          if( ddrval == DD_OK ) break;
          if( ddrval == DDERR_SURFACELOST )
          {
            ddrval = RestoreAll();
            if( ddrval != DD_OK ) return;
          }
          if( ddrval != DDERR_WASSTILLDRAWING ) return;
        }
      }
      while( 1 )
      {
        ddrval = lpDDSPrimary->Flip( NULL, 0 );
        if( ddrval == DD_OK ) break;
        if( ddrval == DDERR_SURFACELOST )
        {
          ddrval = RestoreAll();
          if( ddrval != DD_OK ) break;
        }
        if( ddrval != DDERR_WASSTILLDRAWING ) break;
      }
    }
    void __fastcall TForm1::FormPaint(TObject *Sender)
    {
      AnsiString S = "F3 to Start, Esc to Exit";
      HDC DC = GetDC(Handle);
      if (!FActive)
      {
        SetBkMode(DC, TRANSPARENT);
        TextOut(DC, 25, 100, S.c_str(), S.Length());
      }
      ReleaseDC(Handle, DC);
    }
    Aplikace je hotova, m∙₧eme ji vyzkouÜej. Pokuste se zjistit, jak je animace provßd∞na.
  7. Pokuste se vytvo°it n∞jakou jinou aplikaci, ve kterΘ se bude provßd∞t animace.
33. DirectDraw II