32. DirectDraw I
  1. DalÜφ program, kter²m se budeme zab²vat je aplikace DirectDraw. Tento program vy₧aduje nainstalovan²  b∞hov² DirectDraw na poΦφtaΦi. To je souΦßstφ operaΦnφch systΘm∙ Windows 98 a Windows 2000 (NT verze 5.0). Pokud pou₧φvßme Windows NT 4, musφme mφt nainstalovan² alespo≥ Service Pack 3, kter² obsahuje DirectDraw 3.0. Zda DirectDraw je na naÜem systΘmu zjistφme jednoduÜe tak, ₧e se podφvßme do adresß°e Windows\System nebo do adresß°e Winnt\System32 zda zde existujφ soubory DDRAW.DLL a DSOUND.DLL.

  2. DirectDraw umo₧≥uje v prost°edφ Windows provßd∞t velmi rychlΘ grafickΘ operace (umo₧≥uje p°φm² p°φstup do videopam∞ti na grafickΘ kart∞). Pro dobrΘ v²sledky je vhodnΘ mφt na grafickΘ kart∞ alespo≥ 2 Mslabik pam∞ti. DirectDraw umo₧≥uje vytvo°it vyrovnßvacφ pam∞¥, kreslit do nφ a pak ji p°esunout do viditelnΘ oblasti v naÜφ videopam∞ti. Pokud jsme v exklusivnφm re₧imu a mßme dostatek videopam∞ti k ulo₧enφ jak primßrnφ a zadnφ vrstvy ve video RAM, pak operace p°epnutφ nenφ kopφrovacφ procedura, ale jednoduchß zm∞na adresy bloku pam∞ti urΦujφcφ viditelnou oblast pam∞ti grafickΘ karty. Operace je velmi rychlß a prob∞hne v synchronizaci s obnovovacφ operacφ naÜeho monitoru. DirectDraw m∙₧eme pou₧φt k provßd∞nφ dokonal²ch animacφ.
    K≤d naÜφ aplikace je nejjednoduÜÜφ mo₧n² program DirectDraw. Je to p°φklad DDX1 z SDK Microsoft DirectDraw, kter² je p°epsßn do prost°edφ zalo₧enΘm na formulß°i (k≤d pou₧φvß objekt TTimer namφsto volßnφ SetTimer a reaguje na udßlosti typu OnKeyDown namφsto p°φmΘho zpracovßnφ zprßv WM_KEYDOWN; zvyÜuje to Φitelnost programu).
    K≤d naÜeho programu mß nßsledujφcφ metody: Podφvejme se na nßÜ program. ZaΦneme v²voj novΘ aplikace. Na formulß° vlo₧φme komponentu Timer. Do deklarace t°φdy formulß°e p°idßme nßsledujφcφ soukromΘ slo₧ky (je zde i jedna metoda):
    LPDIRECTDRAW            lpDD;           // objekt DirectDraw
    LPDIRECTDRAWSURFACE     lpDDSPrimary;   // primßrnφ vrstva DirectDraw
    LPDIRECTDRAWSURFACE     lpDDSBack;      // zadnφ vrstva DirectDraw
    BOOL                    bActive;        // je aplikace aktivnφ?
    BYTE phase;
    AnsiString FrontMsg;
    AnsiString BackMsg;
    void __fastcall Start();
    Nßsleduje v²pis celΘho zdrojovΘho souboru formulß°e. Podφvejte se jak jsou jednotlivΘ metody naprogramovanΘ a aplikaci vyzkouÜejte.
    #include <vcl.h>
    #include <ddraw.h>
    #pragma hdrstop
    #include "Main.h"
    #pragma resource "*.dfm"
    #define TIMER_ID        1
    #define TIMER_RATE      500
    TForm1 *Form1;
    ///////////////////////////////////////
    // Konstruktor
    ///////////////////////////////////////
    __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)";
    }
    ///////////////////////////////////////
    // Obsluha OnDestroy formulß°e
    ///////////////////////////////////////
    void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
      if(lpDD != NULL)
      {
        if(lpDDSPrimary != NULL)
        {
          lpDDSPrimary->Release();
          lpDDSPrimary = NULL;
        }
        lpDD->Release();
        lpDD = NULL;
      }
    }
    ///////////////////////////////////////
    // Metoda Start
    ///////////////////////////////////////
    void __fastcall TForm1::Start()
    {
      HRESULT ddrval;
      DDSURFACEDESC ddsd;
      DDSCAPS ddscaps;
      HDC DC;
      char buf[256];
      ddrval = DirectDrawCreate(NULL, &lpDD, NULL);
      if(ddrval == DD_OK)
      {
        // zφskßnφ exklusivnφho re₧imu
        ddrval = lpDD->SetCooperativeLevel(Handle,
          DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
        if(ddrval == DD_OK)
        {
          ddrval = lpDD->SetDisplayMode(640, 480, 8);
          if(ddrval == DD_OK)
          {
            // vytvo°enφ primßrnφ a zadnφ vrstvy
            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)
            {
              // zφskßnφ ukazatele na zadnφ vrstvu
              ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
              ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps,
                                                    &lpDDSBack);
              if(ddrval == DD_OK)
              {
                // zobrazenφ textu
                if (lpDDSPrimary->GetDC(&DC) == DD_OK)
                {
                    SetBkColor(DC, RGB(0, 0, 255));
                    SetTextColor(DC, RGB(255, 255, 0));
                    TextOut(DC, 0, 0, FrontMsg.c_str(), FrontMsg.Length());
                    lpDDSPrimary->ReleaseDC(DC);
                }
                if (lpDDSBack->GetDC(&DC) == DD_OK)
                {
                    SetBkColor(DC, RGB(0, 0, 255));
                    SetTextColor(DC, RGB(255, 255, 0));
                    TextOut(DC, 0, 0, BackMsg.c_str(), BackMsg.Length());
                    lpDDSBack->ReleaseDC(DC);
                }
                // Povolenφ ΦasovaΦe
                Timer1->Enabled = True;
                bActive = True;
                return;
              }
            }
          }
        }
      }
      wsprintf(buf, "Direct Draw Init Failed (%08lx)\n", ddrval);
      MessageBox(Handle, buf, "ERROR", MB_OK);
      Close();
    }
    ///////////////////////////////////////
    // Obsluha stisku klßvesy
    ///////////////////////////////////////
    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;
       }
    }
    ///////////////////////////////////////
    // Obsluha OnPaint formulß°e
    ///////////////////////////////////////
    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);
      }
    }
    ///////////////////////////////////////
    // Obsluha OnTimer
    ///////////////////////////////////////
    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;
        }
        if(ddrval != DDERR_WASSTILLDRAWING) break;
      }
    }
    V aplikaci jsou p°epφnßny jednotlivΘ vrstvy (obsahujφ pouze text).
  3. DalÜφ aplikace se podobß p°edchßzejφcφ. Po obrazovce se v nφ pohybuje zelen² kruh. ZaΦneme v²voj novΘ aplikace. Formulß° nynφ nechßme prßzdn². Jako soukromΘ slo₧ky formulß°e nynφ vlo₧φme:

  4. LPDIRECTDRAW            lpDD;
    LPDIRECTDRAWSURFACE     lpDDSPrimary;
    LPDIRECTDRAWSURFACE     lpDDSBack;
    BOOL FActive;
    BYTE FPhase;
    RECT FShapeRect;
    int FValueAdd;
    AnsiString FrontMsg;
    AnsiString BackMsg;
    void __fastcall Start();
    MESSAGE void Run(TMessage &Message);
    void DrawShape(HDC &DC);
    Je zde takΘ provedeno mapovßnφ zprßvy:
    BEGIN_MESSAGE_MAP
      MESSAGE_HANDLER(WM_RUNAPP, TMessage, Run);
    END_MESSAGE_MAP(TForm);
    Nßsleduje v²pis zdrojovΘho souboru formulß°e (obsluhy OnDestroy, OnKeyDown a OnPaint jsou stejnΘ jako v p°edchozφ aplikaci a nejsou zde uvedeny):
    __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
    {
      lpDD = NULL;
      FPhase = 0;
      FActive = False;
      FrontMsg = "Front buffer (F12 or Esc to quit)";
      BackMsg = "Back buffer (F12 or Esc to quit)";
      FShapeRect = Rect(25, 25, 50, 50);
      FValueAdd = 2;
    }
    ///////////////////////////////////////
    // SpuÜt∞nφ programu
    ///////////////////////////////////////
    void TForm1::Run(TMessage &Message)
    {
      do {
        Timer1Timer(NULL);
        Application->ProcessMessages();
      } while (FActive);
    }
    ///////////////////////////////////////
    // Zprßvy WM_TIMER
    ///////////////////////////////////////
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
      HDC DC;
      if (lpDDSBack->GetDC(&DC) == DD_OK)
      {
        DrawShape(DC);
        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;
        }
        if(ddrval != DDERR_WASSTILLDRAWING)
        {
          FActive = False;
          Close();
        }
      }
    }
    /* Nezapome≥te, ₧e mßme dv∞ vrstvy. Kdy₧ ruÜφme star² obrßzek, musφme
       provΘst dv∞ iterace zp∞t a ne jednu. */
    void TForm1::DrawShape(HDC &DC)
    {
      HBRUSH Brush, OldBrush;
      Brush = CreateSolidBrush(RGB(0, 0, 0));
      OldBrush = SelectObject(DC, Brush);
      Ellipse(DC, FShapeRect.left - FValueAdd, FShapeRect.top,
        FShapeRect.right - FValueAdd, FShapeRect.bottom);
      SelectObject(DC, OldBrush);
      DeleteObject(Brush);
      FShapeRect.left += FValueAdd;
      FShapeRect.right += FValueAdd;
      if (FShapeRect.right > 637)
      {
        FValueAdd = -2;
      }
      if (FShapeRect.left < 3)
      {
        FValueAdd = 2;
      }
      Brush = CreateSolidBrush(RGB(0, 255, 0));
      OldBrush = SelectObject(DC, Brush);
      Ellipse(DC, FShapeRect.left, FShapeRect.top, FShapeRect.right, FShapeRect.bottom);
      SelectObject(DC, OldBrush);
      DeleteObject(Brush);
    }
    Metoda Start se liÜφ pouze v n∞kolika mßlo °ßdcφch. Namφsto (na konci obsluhy):
                // Povolenφ ΦasovaΦe
                Timer1->Enabled = True;
                bActive = True;
                return;
    je zde nynφ:
                // Povolenφ ΦasovaΦe
                PostMessage(Handle, WM_RUNAPP, 0, 0);
                return;
    Program vyzkouÜejte.
  5. DalÜφ program ukazuje animaci vφce objekt∙ pomocφ DirectDraw. Po p°epnutφ do exklusivnφho re₧imu je nakresleno n∞kolik barevn²ch objekt∙ (kruh∙ a Φtverc∙). Ka₧d² tvar se pohybuje po svΘ vlastnφ drßze. Nynφ jsou v programu dv∞ hlavnφ t°φdy: TDrawShape (reprezentuje jeden tvar zobrazen² na obrazovce; ka₧dß instance mß mφsto, tvar, sm∞r a barvu - volßnφ metody Draw p°esune objekt na dalÜφ mφsto na jeho drßze) a TForm1 (tento objekt °φdφ b∞h programu; obsahuje objekt TList ve kterΘm jsou ulo₧eny jednotlivΘ tvary). HlaviΦkov² soubor mß nßsledujφcφ obsah:

  6. #ifndef MainH
    #define MainH
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <Menus.hpp>
    #include <ExtCtrls.hpp>
    #define WM_RUNAPP WM_USER
    #define CIRCLETYPE 0
    #define RECTTYPE 1
    class TDrawShape : public TObject
    {
    private:
      int FX;
      int FY;
      int FX1;
      int FY1;
      int FMoveValX;
      int FMoveValY;
      int FShapeType;
      RECT FPrevRect, FPrevRect2;
      TColor FColor;
      RECT __fastcall GetRect(){return Rect(FX,FY,FX1,FY1);}
      void __fastcall SetRect(RECT R)
      {
        FX = R.left; FY = R.top; FX1 = R.right; FY1 = R.bottom;
      }
    public:
      __fastcall TDrawShape(int ValX, int ValY)
        { FMoveValX = ValX; FMoveValY = ValY; }
      __fastcall TDrawShape(int ValX, int ValY, int X, int Y, int AType,
                            TColor AColor);
      void Move();
      void Draw(HDC &DC);
      __property RECT ShapeRect={read=GetRect, write=SetRect};
      __property int ShapeType={read=FShapeType, write=FShapeType};
      __property TColor Color={read=FColor, write=FColor};
    };
    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;
      BOOL FActive;
      BYTE FPhase;
      RECT FShapeRect;
      TList *FShapeList;
      int FValueAdd;
      void BuildList();
      void DrawShape(HDC &DC);
      void PerformAction();
      MESSAGE void Run(TMessage &Message);
      void __fastcall Start();
    public:
      __fastcall TForm1(TComponent* Owner);
    BEGIN_MESSAGE_MAP
      MESSAGE_HANDLER(WM_RUNAPP, TMessage, Run);
    END_MESSAGE_MAP(TForm);
    };
    extern TForm1 *Form1;
    #endif
    Zdrojov² soubor formulß°e obsahuje:
    #include <vcl.h>
    #include <ddraw.h>
    #pragma hdrstop
    #include "Main.h"
    #pragma resource "*.dfm"
    TForm1 *Form1;
    __fastcall TDrawShape::TDrawShape(int ValX, int ValY, int X, int Y,
      int AType, TColor AColor)
    {
      FMoveValX = ValX;
      FMoveValY = ValY;
      ShapeRect = Rect(X, Y, X+25, Y+25);
      ShapeType = AType;
      Color = AColor;
    }
    void TDrawShape::Move()
    {
      FPrevRect2 = Rect(FPrevRect.left, FPrevRect.top, FPrevRect.right, FPrevRect.bottom);
      FPrevRect = Rect(FX, FY, FX1, FY1);
      FX += FMoveValX;
      FY += FMoveValY;
      FX1 += FMoveValX;
      FY1 += FMoveValY;
      if (FX1 > 637) FMoveValX = -2;
      if (FX < 3) FMoveValX = 2;
      if (FY1 > 477) FMoveValY = - 2;
      if (FY < 3) FMoveValY = 2;
    }
    void TDrawShape::Draw(HDC &DC)
    {
      HBRUSH Brush, OldBrush;
      Brush = CreateSolidBrush(RGB(0, 0, 0));
      OldBrush = SelectObject(DC, Brush);
      if (FShapeType==CIRCLETYPE)
        Ellipse(DC, FPrevRect2.left-1, FPrevRect2.top-1, FPrevRect2.right+1,
                FPrevRect2.bottom+1);
      else if (FShapeType == RECTTYPE)
        Rectangle(DC, FPrevRect2.left-1, FPrevRect2.top-1,
                  FPrevRect2.right+1, FPrevRect2.bottom+1);
      SelectObject(DC, OldBrush);
      DeleteObject(Brush);
      Move();
      Brush = CreateSolidBrush(FColor);
      OldBrush = SelectObject(DC, Brush);
      if (FShapeType==CIRCLETYPE) Ellipse(DC, FX, FY, FX1, FY1);
      else if (FShapeType == RECTTYPE) Rectangle(DC, FX, FY, FX1, FY1);
      SelectObject(DC, OldBrush);
      DeleteObject(Brush);
    }
    __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
    {
      lpDD = NULL;
      FPhase = 0;
      FActive = False;
      FShapeRect = Rect(25, 25, 50, 50);
      FValueAdd = 2;
      BuildList();
    }
    void TForm1::BuildList()
    {
      FShapeList = new TList();
      FShapeList->Add(new TDrawShape(-2, 2, 175, 175, CIRCLETYPE, clLime));
      FShapeList->Add(new TDrawShape(2, 2, 125, 125, RECTTYPE, clBlue));
      FShapeList->Add(new TDrawShape(2, -2, 200, 200, RECTTYPE, clYellow));
      FShapeList->Add(new TDrawShape(2, -2, 75, 75, CIRCLETYPE, clRed));
      FShapeList->Add(new TDrawShape(-2, 2, 325, 350, RECTTYPE, clPurple));
      FShapeList->Add(new TDrawShape(-2, -2, 275, 250, CIRCLETYPE, clFuchsia));
      FShapeList->Add(new TDrawShape(-2, 2, 125, 325, CIRCLETYPE, clTeal));
      FShapeList->Add(new TDrawShape(2, 2, 350, 175, RECTTYPE, clNavy));
      FShapeList->Add(new TDrawShape(2, -2, 150, 250, CIRCLETYPE, clOlive));
      FShapeList->Add(new TDrawShape(-2, 2, 225, 25, CIRCLETYPE, clSilver));
    }
    void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
      TDrawShape *Shape;
      int i;
      for (i = 0; i < FShapeList->Count; i++)
      {
        Shape = (TDrawShape*)FShapeList->Items[i];
        delete Shape;
      }
      delete FShapeList;
      if(lpDD != NULL)
      {
        if(lpDDSPrimary != NULL)
        {
          lpDDSPrimary->Release();
          lpDDSPrimary = 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)
              {
                PostMessage(Handle, WM_RUNAPP, 0, 0);
                return;
              }
            }
          }
        }
      }
      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:
           FActive = True;
           Start();
           break;
         case VK_ESCAPE:
         case VK_F12:
           FActive = False;
           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 (!FActive)
      {
        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 TForm1::Run(TMessage &Message)
    {
      do {
        PerformAction();
        Application->ProcessMessages();
      } while (FActive);
    }
    void TForm1::PerformAction()
    {
      HDC DC;
      if (lpDDSBack->GetDC(&DC) == DD_OK)
      {
        DrawShape(DC);
        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;
        }
        if(ddrval != DDERR_WASSTILLDRAWING)
        {
          FActive = False;
          Close();
        }
      }
    }
    void TForm1::DrawShape(HDC &DC)
    {
      TDrawShape *Shape;
      int i;
      for (i = 0; i < FShapeList->Count; i++)
      {
        Shape = (TDrawShape*)FShapeList->Items[i];
        Shape->Draw(DC);
      }
    }
    Pokuste se pochopit, jak program pracuje a vyzkouÜejte jej.
32. DirectDraw I