C++ Builder Visual Components wrapping DirectX

Welcome to BCB-Tools.com Latest News

Development Tools Demo Applications Step-By-Step Tutorials Component Reference

Register our Tools Available Downloads

Frequently Asked Questions Discussion Forums Receive emails from BCB-Tools.com Send us some Feedback

Links to other sites Information about the BCB-Tools.com website










    TECHNOLOGY COMPARISON
    Go to the Welcome Page
        TECH COMPARISON...

    Technology Comment...

    Let's compare Microsoft Visual C++ with Borland C++ Builder...
    They are both "best of breed" technologies... but which one is better?

    Using the TDx_Library, you can now do in 5-10 lines of Borland C++ Builder code
    what you previously would do writing 50-100 lines of Visual C++ code...

    ...


  • Let's start with Borland C++ Builder...


  • Let's write two applications to animate a bitmap full-screen, and play a sound effect out the speakers...

    Here's the complete pseudo-code :-
    
    	#pragma link "TDx_Draw_Library_Install"
    	#pragma link "TDx_Sound_Library_Install"
    	void __fastcall TMainForm::Button1Click( TObject* Sender )
    	{
    	DirectDraw->Create(NULL);
    	DirectSound->Create(NULL);
    	DirectDraw->CreatePrimarySurface();
    	DirectSound->CreatePrimarySoundBuffer();
    	DirectDraw->Blt();
    	DirectSound->Play();
    	while (DirectSound->Playing) 
    		{
    		DirectDraw->Flip();
    		Sleep(1);
    		}
    	}
    	


    And here is the actual code required to animate a bitmap full-screen, with lots of other stuff thrown in...
    
    //---------------------------------------------------------------------------
    // File: TMainForm.cpp, TDx_Draw_Library, Example9 - Fast Page Flipping
    //
    // Date: 7th January, 2004
    // Author: Darren John Dwyer
    // Copyright: (c) 2002-2004 Darren John Dwyer, All Rights Reserved.
    //
    // Description:
    //
    // This example shows how to partially optimize page flipping.
    // It uses Application->OnIdle() instead of Timer1->OnTimer()
    // It uses global TCanvas's, rather than creating and destroying
    // each time a TCanvas is required.
    //
    // See later examples for increased frame rates.
    //
    //---------------------------------------------------------------------------
    #include 
    #pragma hdrstop
    //---------------------------------------------------------------------------
    #include "TMainForm.h"
    //---------------------------------------------------------------------------
    #if (__BORLANDC__ >= 0x0530) // BCB Version 3 +
        #pragma package(smart_init)
    #endif
    //---------------------------------------------------------------------------
    #pragma link "tddscaps"
    #pragma link "tddsurfacedesc"
    #pragma link "tdx_draw"
    #pragma link "tdx_drawsurface"
    #pragma resource "*.dfm"
    //---------------------------------------------------------------------------
    #pragma link "TDx_Draw"
    #pragma link "TDx_DrawSurface"
    #pragma link "TDDCaps"
    #pragma link "TDDPixelFormat"
    #pragma link "TDDSCaps"
    #pragma link "TDDSurfaceDesc"
    #pragma link "TDx_Draw_Library_Install"
    //---------------------------------------------------------------------------
    TMainForm *MainForm;
    //---------------------------------------------------------------------------
    AnsiString IntToHexStr( unsigned int hexvalue )
    {
    char* hexchars[16] = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
    AnsiString string = "0x";
    int value = 0x10000000;
    for (int i=0;i<8;i++)
        {
        string += hexchars[hexvalue/value];
        hexvalue -= value * (hexvalue/value);
        value = value >> 4;
        }
    return string;
    }
    //---------------------------------------------------------------------------
    #define Msg(A)  {\
                    if (StatusMemo->Text.Length()>30000) StatusMemo->Text = "";\
                    StatusMemo->Lines->Add(A);\
                    }
    //---------------------------------------------------------------------------
    __fastcall TMainForm::TMainForm(TComponent* Owner)
        : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    __fastcall TMainForm::~TMainForm()
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::FormCreate(TObject *Sender)
    {
    Top=0;
    Left=0;
    Width=800;
    Height=600;
    canvas = new TCanvas();
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::FormDestroy(TObject *Sender)
    {
    Application->OnIdle = NULL;
    if (Dx_Draw1->Created) Dx_Draw1->Destroy();
    if (canvas) delete canvas;
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::ExitButtonClick(TObject *Sender)
    {
    Close();
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::ClearButtonClick(TObject *Sender)
    {
    StatusMemo->Lines->Clear();
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::Dx_Draw1Create(TObject *Sender)
    {
    NumModes=0;
    ModesListBox->Items->Clear();
    Dx_Draw1->EnumDisplayModes(0,NULL,NULL);
    Dx_Draw1->SetCooperativeLevel( Application->Handle, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE );
    // create a complex primary surface
    PrimarySurfaceDesc->Flags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
    PrimarySurfaceDesc->BackBufferCount = 1;
    PrimaryCaps->Caps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
    PrimarySurfaceDesc->SCaps = PrimaryCaps;
    PrimarySurface->Create( PrimarySurfaceDesc, Dx_Draw1 );
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::Dx_Draw1Destroy(TObject *Sender)
    {
    PrimarySurface->Destroy();
    Dx_Draw1->SetCooperativeLevel( Application->Handle, DDSCL_NORMAL );
    if (Dx_Draw1->RestoreDisplayMode())
        {
        Top=0;
        Left=0;
        Width=800;
        Height=600;
        Invalidate();
        }
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::Dx_Draw1Error(TObject *Sender, AnsiString Function,
        AnsiString Error, AnsiString ErrorMessage)
    {
    Msg("ERROR ["+Error+"]: "+Function+", "+ErrorMessage);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::Dx_Draw1EnumDisplayModes(TObject *Sender,
          TDDSurfaceDesc *SurfaceDesc, void *Context, bool &Finished;)
    {
    int width = SurfaceDesc->Width;
    int height = SurfaceDesc->Height;
    int refresh_rate = SurfaceDesc->RefreshRate;
    int bit_depth;
    if (SurfaceDesc->PixelFormat->Flags[0] & DDPF_PALETTEINDEXED1) bit_depth = 1;
    else if (SurfaceDesc->PixelFormat->Flags[0] & DDPF_PALETTEINDEXED2) bit_depth = 2;
    else if (SurfaceDesc->PixelFormat->Flags[0] & DDPF_PALETTEINDEXED4) bit_depth = 4;
    else if (SurfaceDesc->PixelFormat->Flags[0] & DDPF_PALETTEINDEXED8) bit_depth = 8;
    else if (SurfaceDesc->PixelFormat->Flags[0] & DDPF_PALETTEINDEXEDTO8) bit_depth = 8;
    else if (SurfaceDesc->PixelFormat->Flags[0] & DDPF_ALPHA) bit_depth = SurfaceDesc->PixelFormat->AlphaBitDepth[0];
    else if (SurfaceDesc->PixelFormat->Flags[0] & DDPF_ALPHAPIXELS) bit_depth = SurfaceDesc->PixelFormat->AlphaBitDepth[0];
    else if (SurfaceDesc->PixelFormat->Flags[0] & DDPF_ALPHAPREMULT) bit_depth = SurfaceDesc->PixelFormat->AlphaBitDepth[0];
    else if (SurfaceDesc->PixelFormat->Flags[0] & DDPF_BUMPDUDV) bit_depth = SurfaceDesc->PixelFormat->BumpBitCount[0];
    else if (SurfaceDesc->PixelFormat->Flags[0] & DDPF_BUMPLUMINANCE) bit_depth = SurfaceDesc->PixelFormat->BumpBitCount[0];
    else if (SurfaceDesc->PixelFormat->Flags[0] & DDPF_RGB) bit_depth = SurfaceDesc->PixelFormat->RGBBitCount[0];
    else if (SurfaceDesc->PixelFormat->Flags[0] & DDPF_YUV) bit_depth = SurfaceDesc->PixelFormat->YUVBitCount[0];
    if (NumModesItems->Add( IntToStr(width)+"x"+IntToStr(height)+"x"+IntToStr(bit_depth)+" @ "+IntToStr(refresh_rate)+"Hz" );
        }
    else
        Finished = true;
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::NextModeButtonClick(TObject *Sender)
    {
    if (ModesListBox->Items->Count>0)
        {
        Msg("Selecting Next Available Mode");
        if (ModesListBox->ItemIndex==ModesListBox->Items->Count-1) ModesListBox->ItemIndex=0;
        else ModesListBox->ItemIndex = ModesListBox->ItemIndex + 1;
        ModesListBox->OnClick(this);
        }
    else
        ModesListBox->ItemIndex = -1;
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::ModesListBoxClick(TObject *Sender)
    {
    if (ModesListBox->ItemIndex!=-1)
        {
        int index = ModesListBox->ItemIndex;
        AnsiString name = ModesListBox->Items->Strings[index];
        Msg("Mode Selected: '"+name+"'");
        CurrentModeLabel->Caption = name;
        }
    else
        CurrentModeLabel->Caption = "-- default --";
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::PrimarySurfaceCreate(TObject *Sender)
    {
    Msg(">>> Primary Surface Created");
    // get it's attached backbuffer
    if (PrimarySurface->GetAttachedSurface( BackBufferCaps, BackBuffer ))
        // call the backbuffer::OnCreate() event manually.
        BackBuffer->OnCreate(this);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::PrimarySurfaceDestroy(TObject *Sender)
    {
    Msg(">>> Primary Surface Destroy");
    if (BackBuffer->Created) BackBuffer->Destroy();
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::PrimarySurfaceSurfaceLost(TObject *Sender)
    {
    PrimarySurface->Restore();
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::ModesListBoxDblClick(TObject *Sender)
    {
    SelectModeButton->OnClick(this);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::SelectModeButtonClick(TObject *Sender)
    {
    if (ModesListBox->Items->Count>0)
        {
        ShowMessage("Please Note:\n\
    You may experience difficulty restoring your display mode.\n\
    To return to the original display mode at any time, press ALT-R (Restore) or ALT-X (eXit)" );
        int index = ModesListBox->ItemIndex;
        PrimarySurface->Destroy();
        if (Dx_Draw1->SetDisplayMode( Widths[index], Heights[index], BitDepths[index], RefreshRates[index], 0 ))
            {
            Msg("SelectModeButton> Display mode has been set" );
            }
        PrimarySurface->Create( PrimarySurfaceDesc, Dx_Draw1 );
        RepaintButton->OnClick(this);
        }
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::RepaintButtonClick(TObject *Sender)
    {
    Application->OnIdle = NULL;
    if (Dx_Draw1->Created) Dx_Draw1->FlipToGDISurface();
        int old_top = Top;
        Top=Screen->Height+1;
        Invalidate();
        Top=old_top;
        Invalidate();
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::BackBufferCreate(TObject *Sender)
    {
    Msg(">>> BackBuffer Created");
    Image2->AutoSize = false;
    Image2->Stretch = true;
    Image2->Width = Screen->Width;
    Image2->Height = Screen->Height;
    Image2->Canvas->StretchDraw( Image2->Canvas->ClipRect, Image1->Picture->Graphic );
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::BackBufferDestroy(TObject *Sender)
    {
    Msg(">>> BackBuffer Destroyed");
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::CreateButtonClick(TObject *Sender)
    {
    Dx_Draw1->Create(NULL);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::FlipButtonClick(TObject *Sender)
    {
    ShowMessage("Please Note:\n\
    After the primary surface has been painted the contents of the current form\n\
    will no longer be visible though it is still active. To repaint the form\n\
    Press ALT-R (Restore) or to exit the application, press ALT-X (eXit)" );
    CurrentPageNumber = 0;
    Application->OnIdle = OnIdle;
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::OnIdle(TObject *Sender, bool& Done)
    {
    if (!BackBuffer->Created) return;
    if (!PrimarySurface->Created) return;
    // error-proof vcl code
    HDC hdc;
    if (BackBuffer->GetDC(&hdc;))
        {
        try
            {
            // make sure to reassign the canvas so it paints in the right spot
            canvas->Handle = hdc;
            // paint the background star image
            canvas->CopyRect( canvas->ClipRect, Image2->Canvas, Image2->Canvas->ClipRect );
            // paint some text
            canvas->Brush->Style = bsClear;
            canvas->Pen->Style = psClear;
            canvas->Font->Name = "Arial";
            canvas->Font->Style = TFontStyles();
            canvas->Font->Size = 20;
            canvas->Font->Color = (TColor) RGB(0,0,0);
            canvas->TextOut( 2, 2, "Paint onto the BackBuffer, then flip to the Primary Surface" );
            canvas->Font->Color = (TColor) RGB(128,255,128);
            canvas->TextOut( 0, 0, "Paint onto the BackBuffer, then flip to the Primary Surface" );
            // and more text
            canvas->Brush->Style = bsClear;
            canvas->Font->Name = "Comic Sans MS";
            canvas->Font->Style = TFontStyles() << fsBold << fsItalic << fsUnderline << fsStrikeOut;
            canvas->Font->Size = 24;
            canvas->Font->Color = (TColor) RGB(0,0,0);
            canvas->TextOut( 102 + CurrentPageNumber, 42, "Frame# "+IntToStr(CurrentPageNumber) );
            canvas->Font->Color = (TColor) RGB(128+CurrentPageNumber%128,255,128+CurrentPageNumber%128);
            canvas->TextOut( 100 + CurrentPageNumber, 40, "Frame# "+IntToStr(CurrentPageNumber) );
            // and remove our temporary canvas handle
            canvas->Handle = NULL;
            }
        catch (Exception &e;)
            {
            Application->OnIdle = NULL;
            }
        BackBuffer->ReleaseDC(hdc);
        }
    PrimarySurface->Flip( BackBuffer, DDFLIP_DONOTWAIT );
    CurrentPageNumber++;
    // continue immediately
    Done = false;
    }
    //---------------------------------------------------------------------------
    	


    And here is the code to play a sound effect, with lots of other stuff thrown in...
    
    //---------------------------------------------------------------------------
    // File: TMainForm.cpp
    //
    //  TDx_Sound_Library
    //  Example2 - Playing with Sounds
    //
    // Date: 9th January, 2004
    // Author: Darren John Dwyer
    // Copyright: (c) 2002-2004 Darren John Dwyer, All Rights Reserved.
    //
    // Description:
    //
    // This example shows how to manipulate sounds while they are playing,
    // including adjusting the volume, pan and frequency.
    //
    //---------------------------------------------------------------------------
    #include 
    #pragma hdrstop
    #include "TMainForm.h"
    //---------------------------------------------------------------------------
    #pragma link "TDx_Sound"
    #pragma link "TDx_SoundBuffer"
    #pragma link "TDSCaps"
    #pragma link "TDSBufferDesc"
    #pragma link "TDx_Sound_Library_Install"
    #pragma resource "*.dfm"
    //---------------------------------------------------------------------------
    TMainForm *MainForm;
    //---------------------------------------------------------------------------
    __fastcall TMainForm::TMainForm(TComponent* Owner)
        : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::FormCreate(TObject *Sender)
    {
    KnownDevices = new TStringList();
    KnownModules = new TStringList();
    KnownGuids = new TList();
    DevicesListBox->Items->Clear();
    if (Dx_Sound1->DSEnumerate( NULL ))
        {
        if (KnownDevices->Count>0)
            {
            DevicesListBox->ItemIndex = 0;
            Dx_Sound1->Create( (GUID*) KnownGuids->Items[DevicesListBox->ItemIndex] );
            }
        }
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::FormDestroy(TObject *Sender)
    {
    if (Dx_Sound1->Created) Dx_Sound1->Destroy();
    if (KnownGuids) delete KnownGuids;
    if (KnownModules) delete KnownModules;
    if (KnownDevices) delete KnownDevices;
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::DevicesListBoxClick(TObject *Sender)
    {
    if (Dx_Sound1->Created) Dx_Sound1->Destroy();
    NotCreatedLabel->Visible = !Dx_Sound1->Create( (GUID*) KnownGuids->Items[DevicesListBox->ItemIndex] );
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::Dx_Sound1Destroy(TObject *Sender)
    {
    if (Dx_SoundBuffer1->Created) Dx_SoundBuffer1->Destroy();
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::Dx_SoundBuffer1BufferLost(TObject *Sender)
    {
    Dx_SoundBuffer1->CreateFromFile( Edit1->Text, DSBufferDesc1, Dx_Sound1 );
    Dx_SoundBuffer1->Play(0,0);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::PlayButtonClick(TObject *Sender)
    {
    if (Paused)
        {
        Paused = false;
        if (LoopingCheckBox->Checked) Dx_SoundBuffer1->Play(0,DSBPLAY_LOOPING);
        else Dx_SoundBuffer1->Play(0,0);
        return;
        }
    if (Dx_SoundBuffer1->Created) Dx_SoundBuffer1->Destroy();
    if (Edit1->Text.Pos("*.WAV"))
        {
    //    StatusMemo->Lines->Add( "Cannot select *.WAV" );
        return;
        }
    if (Dx_SoundBuffer1->CreateFromFile( Edit1->Text, DSBufferDesc1, Dx_Sound1 ))
        {
        BufferSizeLabel->Caption = "Buffer Size: "+IntToStr(DSBufferDesc1->BufferBytes)+" bytes";
        if (LoopingCheckBox->Checked) Dx_SoundBuffer1->Play(0,DSBPLAY_LOOPING);
        else Dx_SoundBuffer1->Play(0,0);
        }
    else
        ShowMessage("Couldn't Create From File");
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::Timer1Timer(TObject *Sender)
    {
    if (!Dx_SoundBuffer1->Created) return;
    if (Dx_SoundBuffer1->Playing)
        PlayingLabel->Caption = "Buffer is Playing...";
    else
        PlayingLabel->Caption = "Buffer is Stopped.";
    Dx_SoundBuffer1->GetCurrentPosition( &CurrentPlayPos;, &CurrentWritePos; );
    BufferPosLabel->Caption = "Buffer Position: "+IntToStr(CurrentPlayPos);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::Dx_SoundBuffer1Create(TObject *Sender)
    {
    if (Dx_SoundBuffer1->Created)
        {
        Dx_SoundBuffer1->GetPan( &Pan; );
        Dx_SoundBuffer1->GetVolume( &Volume; );
        Dx_SoundBuffer1->GetFrequency( &Frequency; );
        PanScrollBar->Position = Pan;
        VolumeScrollBar->Position = Volume;
        FrequencyScrollBar->Position = Frequency/10;    // see bugfix below
        PanLabel->Caption = "Pan: "+IntToStr((int) Pan);
        VolumeLabel->Caption = "Volume: "+IntToStr((int) Volume);
        FrequencyLabel->Caption = "Frequency: "+IntToStr((int) Frequency);
        }
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::PanScrollBarChange(TObject *Sender)
    {
    Pan = PanScrollBar->Position;
    if (Dx_SoundBuffer1->SetPan( Pan )) PanLabel->Caption = "Pan: "+IntToStr((int) Pan);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::VolumeScrollBarChange(TObject *Sender)
    {
    Volume = VolumeScrollBar->Position;
    if (Dx_SoundBuffer1->SetVolume( Volume )) VolumeLabel->Caption = "Volume: "+IntToStr((int) Volume);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::FrequencyScrollBarChange(TObject *Sender)
    {
    // There seems to be a bug in the TScrollBar, in which the TScrollBar does
    // not seem to handle ranges 0..100,000 correctly and truncates values.
    // So, we've fiddled with the FrequencyScrollBar's Position, Min, Max,
    // SmallChange & LargeChange properties so they fit a smaller scale 0..10,000,
    // which works appropriately.
    Frequency = FrequencyScrollBar->Position * 10;
    if (Dx_SoundBuffer1->SetFrequency( Frequency ))    FrequencyLabel->Caption = "Frequency: "+IntToStr(Frequency);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::Dx_SoundBuffer1Destroy(TObject *Sender)
    {
    Dx_SoundBuffer1->Stop();
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::FileListBox1DblClick(TObject *Sender)
    {
    PlayButtonClick(this);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::StopButtonClick(TObject *Sender)
    {
    Dx_SoundBuffer1->Stop();
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::RewindButtonClick(TObject *Sender)
    {
    Dx_SoundBuffer1->SetCurrentPosition(CurrentPlayPos-DSBufferDesc1->BufferBytes/10);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::ForwardButtonClick(TObject *Sender)
    {
    Dx_SoundBuffer1->SetCurrentPosition(CurrentPlayPos+DSBufferDesc1->BufferBytes/10);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::PauseButtonClick(TObject *Sender)
    {
    if (Dx_SoundBuffer1->Playing)
        {
        Paused = Dx_SoundBuffer1->Stop();
        PlayingLabel->Caption = "Buffer is Paused..";
        }
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::ExitButtonClick(TObject *Sender)
    {
    Close();
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::Dx_Sound1Create(TObject *Sender)
    {
    Dx_Sound1->SetCooperativeLevel(Application->Handle, DSSCL_PRIORITY);
    }
    //---------------------------------------------------------------------------
    void __fastcall TMainForm::Dx_Sound1DSEnumerate(TObject *Sender, GUID *Guid,
        AnsiString DriverDescription, AnsiString DriverModule, void *Context,
        bool &Finished;)
    {
    if (KnownDevices && KnownModules && KnownGuids)
        {
        KnownDevices->Add( DriverDescription );
        KnownModules->Add( DriverModule );
        KnownGuids->Add( (void*) Guid );
        DevicesListBox->Items->Add( DriverDescription + ", ("+DriverModule+")" );
        }
    else
        Finished = true;
    }
    //---------------------------------------------------------------------------
    	





  • Let's do the same thing, with much less fancy stuff thrown in, using Microsoft Visual C++...


  • Let's write two applications to animate a bitmap full-screen, and play a sound effect our the speakers...

    Here's the complete code to animate a bitmap full-screen :-
    
    //-----------------------------------------------------------------------------
    // File: DDEx3.CPP
    //
    // Desc: Direct Draw example program 3.  Adds functionality to 
    //       example program 2.  Creates two offscreen surfaces in 
    //       addition to the primary surface and back buffer.  Loads
    //       a bitmap file into each offscreen surface.  Uses BltFast
    //       to copy the contents of an offscreen surface to the back
    //       buffer and then flips the buffers and copies the next 
    //       offscreen surface to the back buffer.  Press F12 to exit
    //       the program.  This program requires at least 1.2 Megs of 
    //       video ram.
    //
    // Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
    //-----------------------------------------------------------------------------
    #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
    #endif
    //-----------------------------------------------------------------------------
    // Include files
    //-----------------------------------------------------------------------------
    #include 
    #include 
    #include 
    #include 
    #include "resource.h"
    #include "ddutil.h"
    //-----------------------------------------------------------------------------
    // Local definitions
    //-----------------------------------------------------------------------------
    #define NAME                "DDExample3"
    #define TITLE               "Direct Draw Example 3"
    //-----------------------------------------------------------------------------
    // Default settings
    //-----------------------------------------------------------------------------
    #define TIMER_ID            1
    #define TIMER_RATE          500
    //-----------------------------------------------------------------------------
    // Global data
    //-----------------------------------------------------------------------------
    LPDIRECTDRAW7               g_pDD = NULL;        // DirectDraw object
    LPDIRECTDRAWSURFACE7        g_pDDSPrimary = NULL;// DirectDraw primary surface
    LPDIRECTDRAWSURFACE7        g_pDDSBack = NULL;   // DirectDraw back surface
    LPDIRECTDRAWSURFACE7        g_pDDSOne = NULL;    // Offscreen surface 1
    LPDIRECTDRAWSURFACE7        g_pDDSTwo = NULL;    // Offscreen surface 2
    LPDIRECTDRAWPALETTE         g_pDDPal = NULL;     // The primary surface palette
    BOOL                        g_bActive = FALSE;   // Is application active?
    //-----------------------------------------------------------------------------
    // Local data
    //-----------------------------------------------------------------------------
    // Name of our bitmap resource.
    static char                 szBitmap[] = "DDEX3";
    //-----------------------------------------------------------------------------
    // Name: ReleaseAllObjects()
    // Desc: Finished with all objects we use; release them
    //-----------------------------------------------------------------------------
    static void
    ReleaseAllObjects(void)
    {
        if (g_pDD != NULL)
        {
            if (g_pDDSPrimary != NULL)
            {
                g_pDDSPrimary->Release();
                g_pDDSPrimary = NULL;
            }
            if (g_pDDSOne != NULL)
            {
                g_pDDSOne->Release();
                g_pDDSOne = NULL;
            }
            if (g_pDDSTwo != NULL)
            {
                g_pDDSTwo->Release();
                g_pDDSTwo = NULL;
            }
            if (g_pDDPal != NULL)
            {
                g_pDDPal->Release();
                g_pDDPal = NULL;
            }
            g_pDD->Release();
            g_pDD = NULL;
        }
    }
    //-----------------------------------------------------------------------------
    // Name: InitFail()
    // Desc: This function is called if an initialization function fails
    //-----------------------------------------------------------------------------
    HRESULT
    InitFail(HWND hWnd, HRESULT hRet, LPCTSTR szError,...)
    {
        char                        szBuff[128];
        va_list                     vl;
        va_start(vl, szError);
        vsprintf(szBuff, szError, vl);
        ReleaseAllObjects();
        MessageBox(hWnd, szBuff, TITLE, MB_OK);
        DestroyWindow(hWnd);
        va_end(vl);
        return hRet;
    }
    //-----------------------------------------------------------------------------
    // Name: InitSurfaces()
    // Desc: This function reads the bitmap file FRNTBACK.BMP and stores half of it
    //       in offscreen surface 1 and the other half in offscreen surface 2.
    //-----------------------------------------------------------------------------
    BOOL 
    InitSurfaces(void)
    {
        HBITMAP                     hbm;
        // Load our bitmap resource.
        hbm = (HBITMAP) LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, 0,
                                  0, LR_CREATEDIBSECTION);
        if (hbm == NULL)
            return FALSE;
        DDCopyBitmap(g_pDDSOne, hbm, 0, 0, 640, 480);
        DDCopyBitmap(g_pDDSTwo, hbm, 0, 480, 640, 480);
        DeleteObject(hbm);
        return TRUE;
    }
    //-----------------------------------------------------------------------------
    // Name: RestoreAll()
    // Desc: Restore all lost objects
    //-----------------------------------------------------------------------------
    HRESULT 
    RestoreAll(void)
    {
        HRESULT                     hRet;
        hRet = g_pDDSPrimary->Restore();
        if (hRet == DD_OK)
        {
            hRet = g_pDDSOne->Restore();
            if (hRet == DD_OK)
            {
                hRet = g_pDDSTwo->Restore();
                if (hRet == DD_OK)
                {
                    InitSurfaces();
                }
            }
        }
        return hRet;
    }
    //-----------------------------------------------------------------------------
    // Name: UpdateFrame()
    // Desc: Displays the proper image for the page
    //-----------------------------------------------------------------------------
    static void
    UpdateFrame(HWND hWnd)
    {
        static BYTE                 phase = 0;
        HRESULT                     hRet;
        LPDIRECTDRAWSURFACE7        pdds;
        RECT                        rcRect;
        rcRect.left = 0;
        rcRect.top = 0;
        rcRect.right = 640;
        rcRect.bottom = 480;
        if (phase)
        {
            pdds = g_pDDSTwo;
            phase = 0;
        }
        else
        {
            pdds = g_pDDSOne;
            phase = 1;
        }
        while (TRUE)
        {
            hRet = g_pDDSBack->BltFast(0, 0, pdds, &rcRect;, FALSE);
            if (hRet == DD_OK)
                break;
            if (hRet == DDERR_SURFACELOST)
            {
                hRet = RestoreAll();
                if (hRet != DD_OK)
                    break;
            }
            if (hRet != DDERR_WASSTILLDRAWING)
                break;
        }
    }
    //-----------------------------------------------------------------------------
    // Name: WindowProc()
    // Desc: The Main Window Procedure
    //-----------------------------------------------------------------------------
    long FAR PASCAL
    WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        HRESULT                     hRet;
        switch (message)
        {
            case WM_ACTIVATE:
                // Pause if minimized
                g_bActive = !((BOOL)HIWORD(wParam));
                return 0L;
            case WM_DESTROY:
                // Clean up and close the app
                ReleaseAllObjects();
                PostQuitMessage(0);
                return 0L;
            case WM_KEYDOWN:
                // Handle any non-accelerated key commands
                switch (wParam)
                {
                    case VK_ESCAPE:
                    case VK_F12:
                        PostMessage(hWnd, WM_CLOSE, 0, 0);
                        return 0L;
                }
                break;
            case WM_SETCURSOR:
                // Turn off the cursor since this is a full-screen app
                SetCursor(NULL);
                return TRUE;
            case WM_TIMER:
                // Update and flip surfaces
                if (g_bActive && TIMER_ID == wParam)
                {
                    UpdateFrame(hWnd);
                    while (TRUE)
                    {
                        hRet = g_pDDSPrimary->Flip(NULL, 0);
                        if (hRet == DD_OK)
                            break;
                        if (hRet == DDERR_SURFACELOST)
                        {
                            hRet = RestoreAll();
                            if (hRet != DD_OK)
                                break;
                        }
                        if (hRet != DDERR_WASSTILLDRAWING)
                            break;
                    }
                }
                break;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    //-----------------------------------------------------------------------------
    // Name: InitApp()
    // Desc: Do work required for every instance of the application:
    //          Create the window, initialize data
    //-----------------------------------------------------------------------------
    static HRESULT
    InitApp(HINSTANCE hInstance, int nCmdShow)
    {
        HWND                        hWnd;
        WNDCLASS                    wc;
        DDSURFACEDESC2              ddsd;
        DDSCAPS2                    ddscaps;
        HRESULT                     hRet;
        // Set up and register window class
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WindowProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = hInstance;
        wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN_ICON));
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH )GetStockObject(BLACK_BRUSH);
        wc.lpszMenuName = NAME;
        wc.lpszClassName = NAME;
        RegisterClass(&wc;);
        // Create a window
        hWnd = CreateWindowEx(WS_EX_TOPMOST,
                              NAME,
                              TITLE,
                              WS_POPUP,
                              0,
                              0,
                              GetSystemMetrics(SM_CXSCREEN),
                              GetSystemMetrics(SM_CYSCREEN),
                              NULL,
                              NULL,
                              hInstance,
                              NULL);
        if (!hWnd)
            return FALSE;
        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);
        SetFocus(hWnd);
        ///////////////////////////////////////////////////////////////////////////
        // Create the main DirectDraw object
        ///////////////////////////////////////////////////////////////////////////
        hRet = DirectDrawCreateEx(NULL, (VOID**)&g;_pDD, IID_IDirectDraw7, NULL);
        if (hRet != DD_OK)
            return InitFail(hWnd, hRet, "DirectDrawCreateEx FAILED");
        // Get exclusive mode
        hRet = g_pDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
        if (hRet != DD_OK)
            return InitFail(hWnd, hRet, "SetCooperativeLevel FAILED");
        // Set the video mode to 640x480x8
        hRet = g_pDD->SetDisplayMode(640, 480, 8, 0, 0);
        if (hRet != DD_OK)
            return InitFail(hWnd, hRet, "SetDisplayMode FAILED");
        // Create the primary surface with 1 back buffer
        ZeroMemory(&ddsd;, sizeof(ddsd));
        ddsd.dwSize = sizeof(ddsd);
        ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
                              DDSCAPS_FLIP |
                              DDSCAPS_COMPLEX;
        ddsd.dwBackBufferCount = 1;
        hRet = g_pDD->CreateSurface(&ddsd;, &g;_pDDSPrimary, NULL);
        if (hRet != DD_OK)
            return InitFail(hWnd, hRet, "CreateSurface FAILED");
        // Get a pointer to the back buffer
        ZeroMemory(&ddscaps;, sizeof(ddscaps));
        ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
        hRet = g_pDDSPrimary->GetAttachedSurface(&ddscaps;, &g;_pDDSBack);
        if (hRet != DD_OK)
            return InitFail(hWnd, hRet, "GetAttachedSurface FAILED");
        // Create a offscreen bitmap.
        ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
        ddsd.dwHeight = 480;
        ddsd.dwWidth = 640;
        hRet = g_pDD->CreateSurface(&ddsd;, &g;_pDDSOne, NULL);
        if (hRet != DD_OK)
            return InitFail(hWnd, hRet, "CreateSurface FAILED");
        // Create another offscreen bitmap.
        hRet = g_pDD->CreateSurface(&ddsd;, &g;_pDDSTwo, NULL);
        if (hRet != DD_OK)
            return InitFail(hWnd, hRet, "CreateSurface FAILED");
        // Create a Direct Draw Palette and associate it with the front buffer
        g_pDDPal = DDLoadPalette(g_pDD, szBitmap);
        if (g_pDDPal)
            g_pDDSPrimary->SetPalette(g_pDDPal);
        if (!InitSurfaces())
            return InitFail(hWnd, hRet, "InitSurfaces FAILED");
        // Create a timer to flip the pages
        if (TIMER_ID != SetTimer(hWnd, TIMER_ID, TIMER_RATE, NULL))
            return InitFail(hWnd, hRet, "SetTimer FAILED");
        return DD_OK;
    }
    //-----------------------------------------------------------------------------
    // Name: WinMain()
    // Desc: Initialization, message loop
    //-----------------------------------------------------------------------------
    int PASCAL
    WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpCmdLine,
            int nCmdShow)
    {
        MSG                         msg;
        if (InitApp(hInstance, nCmdShow) != DD_OK)
            return FALSE;
        while (GetMessage(&msg;, NULL, 0, 0))
        {
            TranslateMessage(&msg;);
            DispatchMessage(&msg;);
        }
        return msg.wParam;
    }
    	


    Plus you need this code as well, to actually load the bitmap
    
    //-----------------------------------------------------------------------------
    // File: ddutil.cpp
    //
    // Desc: Routines for loading bitmap and palettes from resources
    //
    //
    // Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
    //-----------------------------------------------------------------------------
    #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
    #endif
    //-----------------------------------------------------------------------------
    // Include files
    //-----------------------------------------------------------------------------
    #include 
    #include 
    #include 
    #include "ddutil.h"
    //-----------------------------------------------------------------------------
    // Name: DDLoadBitmap()
    // Desc: Create a DirectDrawSurface from a bitmap resource.
    //-----------------------------------------------------------------------------
    extern "C" IDirectDrawSurface7*
    DDLoadBitmap(IDirectDraw7 * pdd, LPCSTR szBitmap, int dx, int dy)
    {
        HBITMAP                 hbm;
        BITMAP                  bm;
        DDSURFACEDESC2          ddsd;
        IDirectDrawSurface7    *pdds;
        //
        //  Try to load the bitmap as a resource, if that fails, try it as a file
        //
        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;
        //
        // Get size of the bitmap
        //
        GetObject(hbm, sizeof(bm), &bm;);
        //
        // Create a DirectDrawSurface for this bitmap
        //
        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;
    }
    //-----------------------------------------------------------------------------
    // Name: DDReLoadBitmap()
    // Desc: Load a bitmap from a file or resource into a directdraw surface.
    //       normaly used to re-load a surface after a restore.
    //-----------------------------------------------------------------------------
    HRESULT
    DDReLoadBitmap(IDirectDrawSurface7 * pdds, LPCSTR szBitmap)
    {
        HBITMAP                 hbm;
        HRESULT                 hr;
        //
        //  Try to load the bitmap as a resource, if that fails, try it as a file
        //
        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;
    }
    //-----------------------------------------------------------------------------
    // Name: DDCopyBitmap()
    // Desc: Draw a bitmap into a DirectDrawSurface
    //-----------------------------------------------------------------------------
    extern "C" HRESULT
    DDCopyBitmap(IDirectDrawSurface7 * pdds, HBITMAP hbm, int x, int y,
                 int dx, int dy)
    {
        HDC                     hdcImage;
        HDC                     hdc;
        BITMAP                  bm;
        DDSURFACEDESC2          ddsd;
        HRESULT                 hr;
        if (hbm == NULL || pdds == NULL)
            return E_FAIL;
        //
        // Make sure this surface is restored.
        //
        pdds->Restore();
        //
        // Select bitmap into a memoryDC so we can use it.
        //
        hdcImage = CreateCompatibleDC(NULL);
        if (!hdcImage)
            OutputDebugString("createcompatible dc failed\n");
        SelectObject(hdcImage, hbm);
        //
        // Get size of the bitmap
        //
        GetObject(hbm, sizeof(bm), &bm;);
        dx = dx == 0 ? bm.bmWidth : dx;     // Use the passed size, unless zero
        dy = dy == 0 ? bm.bmHeight : dy;
        //
        // Get size of surface.
        //
        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;
    }
    //-----------------------------------------------------------------------------
    // Name: DDLoadPalette()
    // Desc: Create a DirectDraw palette object from a bitmap resource
    //       if the resource does not exist or NULL is passed create a
    //       default 332 palette.
    //-----------------------------------------------------------------------------
    extern "C" IDirectDrawPalette *
    DDLoadPalette(IDirectDraw7 * pdd, LPCSTR szBitmap)
    {
        IDirectDrawPalette     *ddpal;
        int                     i;
        int                     n;
        int                     fh;
        HRSRC                   h;
        LPBITMAPINFOHEADER      lpbi;
        PALETTEENTRY            ape[256];
        RGBQUAD                *prgb;
        //
        // Build a 332 palette as the default.
        //
        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;
        }
        //
        // Get a pointer to the bitmap resource.
        //
        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;
            //
            //  A DIB color table has its colors stored BGR not RGB
            //  so flip them around.
            //
            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;
            //
            //  A DIB color table has its colors stored BGR not RGB
            //  so flip them around.
            //
            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;
    }
    //-----------------------------------------------------------------------------
    // Name: DDColorMatch()
    // Desc: Convert a RGB color to a pysical color.
    //       We do this by leting GDI SetPixel() do the color matching
    //       then we lock the memory and see what it got mapped to.
    //-----------------------------------------------------------------------------
    extern "C" DWORD
    DDColorMatch(IDirectDrawSurface7 * pdds, COLORREF rgb)
    {
        COLORREF                rgbT;
        HDC                     hdc;
        DWORD                   dw = CLR_INVALID;
        DDSURFACEDESC2          ddsd;
        HRESULT                 hres;
        //
        //  Use GDI SetPixel to color match for us
        //
        if (rgb != CLR_INVALID && pdds->GetDC(&hdc;) == DD_OK)
        {
            rgbT = GetPixel(hdc, 0, 0);     // Save current pixel value
            SetPixel(hdc, 0, 0, rgb);       // Set our value
            pdds->ReleaseDC(hdc);
        }
        //
        // Now lock the surface so we can read back the converted color
        //
        ddsd.dwSize = sizeof(ddsd);
        while ((hres = pdds->Lock(NULL, &ddsd;, 0, NULL)) == DDERR_WASSTILLDRAWING)
            ;
        if (hres == DD_OK)
        {
            dw = *(DWORD *) ddsd.lpSurface;                 // Get DWORD
            if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
                dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1;  // Mask it to bpp
            pdds->Unlock(NULL);
        }
        //
        //  Now put the color that was there back.
        //
        if (rgb != CLR_INVALID && pdds->GetDC(&hdc;) == DD_OK)
        {
            SetPixel(hdc, 0, 0, rgbT);
            pdds->ReleaseDC(hdc);
        }
        return dw;
    }
    //-----------------------------------------------------------------------------
    // Name: DDSetColorKey()
    // Desc: Set a color key for a surface, given a RGB.
    //       If you pass CLR_INVALID as the color key, the pixel
    //       in the upper-left corner will be used.
    //-----------------------------------------------------------------------------
    extern "C" HRESULT
    DDSetColorKey(IDirectDrawSurface7 * pdds, COLORREF rgb)
    {
        DDCOLORKEY              ddck;
        ddck.dwColorSpaceLowValue = DDColorMatch(pdds, rgb);
        ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
        return pdds->SetColorKey(DDCKEY_SRCBLT, &ddck;);
    }
    	


    ...

    And here's the code to play a sound effect...
    
    //-----------------------------------------------------------------------------
    // File: PlaySound.cpp
    //
    // Desc: DirectSound support for how to load a wave file and play it using a 
    //       static DirectSound buffer.
    //
    // Copyright (c) 1999 Microsoft Corp. All rights reserved.
    //-----------------------------------------------------------------------------
    #define STRICT
    #include 
    #include 
    #include 
    #include 
    #include 
    #include "resource.h"
    #include "WavRead.h"
    //-----------------------------------------------------------------------------
    // Function-prototypes
    //-----------------------------------------------------------------------------
    extern VOID OnEnablePlayUI( HWND hDlg, BOOL bEnable );
    extern VOID SetFileUI( HWND hDlg, TCHAR* strFileName );
    VOID LoadWaveFile( TCHAR* strFileName );
    HRESULT CreateStaticBuffer( HWND hDlg, TCHAR* strFileName );
    HRESULT FillBuffer();
    HRESULT RestoreBuffers();
    //-----------------------------------------------------------------------------
    // Defines, constants, and global variables
    //-----------------------------------------------------------------------------
    #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
    #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
    LPDIRECTSOUND       g_pDS            = NULL;
    LPDIRECTSOUNDBUFFER g_pDSBuffer      = NULL;
    LPDIRECTSOUNDNOTIFY g_pDSNotify      = NULL;
    CWaveSoundRead*     g_pWaveSoundRead = NULL;
    DWORD               g_dwBufferBytes;
    //-----------------------------------------------------------------------------
    // Name: InitDirectSound()
    // Desc: Initilizes DirectSound
    //-----------------------------------------------------------------------------
    HRESULT InitDirectSound( HWND hDlg )
    {
        HRESULT             hr;
        LPDIRECTSOUNDBUFFER pDSBPrimary = NULL;
        // Initialize COM
        if( hr = CoInitialize( NULL ) )
            return hr;
        // Create IDirectSound using the primary sound device
        if( FAILED( hr = DirectSoundCreate( NULL, &g;_pDS, NULL ) ) )
            return hr;
        // Set coop level to DSSCL_PRIORITY
        if( FAILED( hr = g_pDS->SetCooperativeLevel( hDlg, DSSCL_PRIORITY ) ) )
            return hr;
        // Get the primary buffer 
        DSBUFFERDESC dsbd;
        ZeroMemory( &dsbd;, sizeof(DSBUFFERDESC) );
        dsbd.dwSize        = sizeof(DSBUFFERDESC);
        dsbd.dwFlags       = DSBCAPS_PRIMARYBUFFER;
        dsbd.dwBufferBytes = 0;
        dsbd.lpwfxFormat   = NULL;
        if( FAILED( hr = g_pDS->CreateSoundBuffer( &dsbd;, &pDSBPrimary;, NULL ) ) )
            return hr;
        // Set primary buffer format to 22kHz and 16-bit output.
        WAVEFORMATEX wfx;
        ZeroMemory( &wfx;, sizeof(WAVEFORMATEX) ); 
        wfx.wFormatTag      = WAVE_FORMAT_PCM; 
        wfx.nChannels       = 2; 
        wfx.nSamplesPerSec  = 22050; 
        wfx.wBitsPerSample  = 16; 
        wfx.nBlockAlign     = wfx.wBitsPerSample / 8 * wfx.nChannels;
        wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
        if( FAILED( hr = pDSBPrimary->SetFormat(&wfx;) ) )
            return hr;
        SAFE_RELEASE( pDSBPrimary );
        return S_OK;
    }
    //-----------------------------------------------------------------------------
    // Name: FreeDirectSound()
    // Desc: Releases DirectSound 
    //-----------------------------------------------------------------------------
    HRESULT FreeDirectSound()
    {
        SAFE_DELETE( g_pWaveSoundRead );
        // Release DirectSound interfaces
        SAFE_RELEASE( g_pDSBuffer );
        SAFE_RELEASE( g_pDS ); 
        // Release COM
        CoUninitialize();
        return S_OK;
    }
    //-----------------------------------------------------------------------------
    // Name: LoadWaveFile()
    // Desc: Loads the wave file into a secondary static DirectSound buffer
    //-----------------------------------------------------------------------------
    VOID LoadWaveFile( HWND hDlg, TCHAR* strFileName )
    {
        // Create the sound buffer object from the wave file data
        if( FAILED( CreateStaticBuffer( hDlg, strFileName ) ) )
        {        
            SetFileUI( hDlg, TEXT("Couldn't create sound buffer.") ); 
        }
        else // The sound buffer was successfully created
        {
            // Fill the buffer with wav data
            FillBuffer();
            // Update the UI controls to show the sound as the file is loaded
            SetFileUI( hDlg, strFileName );
            OnEnablePlayUI( hDlg, TRUE );
        }
    }
    //-----------------------------------------------------------------------------
    // Name: CreateStaticBuffer()
    // Desc: Creates a wave file, sound buffer and notification events 
    //-----------------------------------------------------------------------------
    HRESULT CreateStaticBuffer( HWND hDlg, TCHAR* strFileName )
    {
        HRESULT hr; 
        // Free any previous globals 
        SAFE_DELETE( g_pWaveSoundRead );
        SAFE_RELEASE( g_pDSBuffer );
        // Create a new wave file class
        g_pWaveSoundRead = new CWaveSoundRead();
        // Load the wave file
        if( FAILED( g_pWaveSoundRead->Open( strFileName ) ) )
        {
            SetFileUI( hDlg, TEXT("Bad wave file.") );
        }
        // Set up the direct sound buffer, and only request the flags needed
        // since each requires some overhead and limits if the buffer can 
        // be hardware accelerated
        DSBUFFERDESC dsbd;
        ZeroMemory( &dsbd;, sizeof(DSBUFFERDESC) );
        dsbd.dwSize        = sizeof(DSBUFFERDESC);
        dsbd.dwFlags       = DSBCAPS_STATIC;
        dsbd.dwBufferBytes = g_pWaveSoundRead->m_ckIn.cksize;
        dsbd.lpwfxFormat   = g_pWaveSoundRead->m_pwfx;
        // Create the static DirectSound buffer 
        if( FAILED( hr = g_pDS->CreateSoundBuffer( &dsbd;, &g;_pDSBuffer, NULL ) ) )
            return hr;
        // Remember how big the buffer is
        g_dwBufferBytes = dsbd.dwBufferBytes;
        return S_OK;
    }
    //-----------------------------------------------------------------------------
    // Name: FillBuffer()
    // Desc: Fill the DirectSound buffer with data from the wav file
    //-----------------------------------------------------------------------------
    HRESULT FillBuffer()
    {
        HRESULT hr; 
        BYTE*   pbWavData; // Pointer to actual wav data 
        UINT    cbWavSize; // Size of data
        VOID*   pbData  = NULL;
        VOID*   pbData2 = NULL;
        DWORD   dwLength;
        DWORD   dwLength2;
        // The size of wave data is in pWaveFileSound->m_ckIn
        INT nWaveFileSize = g_pWaveSoundRead->m_ckIn.cksize;
        // Allocate that buffer.
        pbWavData = new BYTE[ nWaveFileSize ];
        if( NULL == pbWavData )
            return E_OUTOFMEMORY;
        if( FAILED( hr = g_pWaveSoundRead->Read( nWaveFileSize, 
                                               pbWavData, 
                                               &cbWavSize; ) ) )           
            return hr;
        // Reset the file to the beginning 
        g_pWaveSoundRead->Reset();
        // Lock the buffer down
        if( FAILED( hr = g_pDSBuffer->Lock( 0, g_dwBufferBytes, &pbData;, &dwLength;, 
                                       &pbData2;, &dwLength2;, 0L ) ) )
            return hr;
        // Copy the memory to it.
        memcpy( pbData, pbWavData, g_dwBufferBytes );
        // Unlock the buffer, we don't need it anymore.
        g_pDSBuffer->Unlock( pbData, g_dwBufferBytes, NULL, 0 );
        pbData = NULL;
        // We dont need the wav file data buffer anymore, so delete it 
        SAFE_DELETE( pbWavData );
        return S_OK;
    }
    //-----------------------------------------------------------------------------
    // Name: PlayBuffer()
    // Desc: User hit the "Play" button, so play the DirectSound buffer
    //-----------------------------------------------------------------------------
    BOOL IsBufferPlaying() 
    {
        DWORD dwStatus = 0;
        if( NULL == g_pDSBuffer )
            return E_FAIL;
        g_pDSBuffer->GetStatus( &dwStatus; );
        if( dwStatus & DSBSTATUS_PLAYING )
            return TRUE;
        else 
            return FALSE;
    }
    //-----------------------------------------------------------------------------
    // Name: PlayBuffer()
    // Desc: User hit the "Play" button, so play the DirectSound buffer
    //-----------------------------------------------------------------------------
    HRESULT PlayBuffer( BOOL bLooped )
    {
        HRESULT hr;
        if( NULL == g_pDSBuffer )
            return E_FAIL;
        // Restore the buffers if they are lost
        if( FAILED( hr = RestoreBuffers() ) )
            return hr;
        // Play buffer 
        DWORD dwLooped = bLooped ? DSBPLAY_LOOPING : 0L;
        if( FAILED( hr = g_pDSBuffer->Play( 0, 0, dwLooped ) ) )
            return hr;
        return S_OK;
    }
    //-----------------------------------------------------------------------------
    // Name: StopBuffer()
    // Desc: Stop the DirectSound buffer from playing 
    //-----------------------------------------------------------------------------
    VOID StopBuffer( BOOL bResetPosition ) 
    {
        if( NULL == g_pDSBuffer )
            return;
        g_pDSBuffer->Stop();
        if( bResetPosition )
            g_pDSBuffer->SetCurrentPosition( 0L );    
    }
    //-----------------------------------------------------------------------------
    // Name: IsSoundPlaying()
    // Desc: Checks to see if a sound is playing and returns TRUE if it is.
    //-----------------------------------------------------------------------------
    BOOL IsSoundPlaying()
    {
        if( g_pDSBuffer )
        {  
            DWORD dwStatus = 0;
            g_pDSBuffer->GetStatus( &dwStatus; );
            return( ( dwStatus & DSBSTATUS_PLAYING ) != 0 );
        }
        else
        {
            return FALSE;
        }
    }
    //-----------------------------------------------------------------------------
    // Name: RestoreBuffers()
    // Desc: Restore lost buffers and fill them up with sound if possible
    //-----------------------------------------------------------------------------
    HRESULT RestoreBuffers()
    {
        HRESULT hr;
        if( NULL == g_pDSBuffer )
            return S_OK;
        DWORD dwStatus;
        if( FAILED( hr = g_pDSBuffer->GetStatus( &dwStatus; ) ) )
            return hr;
        if( dwStatus & DSBSTATUS_BUFFERLOST )
        {
            // Since the app could have just been activated, then
            // DirectSound may not be giving us control yet, so 
            // the restoring the buffer may fail.  
            // If it does, sleep until DirectSound gives us control.
            do 
            {
                hr = g_pDSBuffer->Restore();
                if( hr == DSERR_BUFFERLOST )
                    Sleep( 10 );
            }
            while( hr = g_pDSBuffer->Restore() );
            if( FAILED( hr = FillBuffer() ) )
                return hr;
        }
        return S_OK;
    }
    	


    Plus you need this code as well, to load the sound data from a .wav file
    
    //-----------------------------------------------------------------------------
    // File: WavRead.cpp
    //
    // Desc: Wave file support for loading and playing Wave files using DirectSound 
    //       buffers.
    //
    // Copyright (c) 1999 Microsoft Corp. All rights reserved.
    //-----------------------------------------------------------------------------
    #include 
    #include "WavRead.h"
    //-----------------------------------------------------------------------------
    // Defines, constants, and global variables
    //-----------------------------------------------------------------------------
    #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
    #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
    //-----------------------------------------------------------------------------
    // Name: ReadMMIO()
    // Desc: Support function for reading from a multimedia I/O stream
    //-----------------------------------------------------------------------------
    HRESULT ReadMMIO( HMMIO hmmioIn, MMCKINFO* pckInRIFF, WAVEFORMATEX** ppwfxInfo )
    {
        MMCKINFO        ckIn;           // chunk info. for general use.
        PCMWAVEFORMAT   pcmWaveFormat;  // Temp PCM structure to load in.       
        *ppwfxInfo = NULL;
        if( ( 0 != mmioDescend( hmmioIn, pckInRIFF, NULL, 0 ) ) )
            return E_FAIL;
        if( (pckInRIFF->ckid != FOURCC_RIFF) ||
            (pckInRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E') ) )
            return E_FAIL;
        // Search the input file for for the 'fmt ' chunk.
        ckIn.ckid = mmioFOURCC('f', 'm', 't', ' ');
        if( 0 != mmioDescend(hmmioIn, &ckIn;, pckInRIFF, MMIO_FINDCHUNK) )
            return E_FAIL;
        // Expect the 'fmt' chunk to be at least as large as ;
        // if there are extra parameters at the end, we'll ignore them
           if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) )
               return E_FAIL;
        // Read the 'fmt ' chunk into .
        if( mmioRead( hmmioIn, (HPSTR) &pcmWaveFormat;, 
                      sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) )
            return E_FAIL;
        // Allocate the waveformatex, but if its not pcm format, read the next
        // word, and thats how many extra bytes to allocate.
        if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM )
        {
            if( NULL == ( *ppwfxInfo = new WAVEFORMATEX ) )
                return E_FAIL;
            // Copy the bytes from the pcm structure to the waveformatex structure
            memcpy( *ppwfxInfo, &pcmWaveFormat;, sizeof(pcmWaveFormat) );
            (*ppwfxInfo)->cbSize = 0;
        }
        else
        {
            // Read in length of extra bytes.
            WORD cbExtraBytes = 0L;
            if( mmioRead( hmmioIn, (CHAR*)&cbExtraBytes;, sizeof(WORD)) != sizeof(WORD) )
                return E_FAIL;
            *ppwfxInfo = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ];
            if( NULL == *ppwfxInfo )
                return E_FAIL;
            // Copy the bytes from the pcm structure to the waveformatex structure
            memcpy( *ppwfxInfo, &pcmWaveFormat;, sizeof(pcmWaveFormat) );
            (*ppwfxInfo)->cbSize = cbExtraBytes;
            // Now, read those extra bytes into the structure, if cbExtraAlloc != 0.
            if( mmioRead( hmmioIn, (CHAR*)(((BYTE*)&((*ppwfxInfo)->cbSize))+sizeof(WORD)),
                          cbExtraBytes ) != cbExtraBytes )
            {
                delete *ppwfxInfo;
                *ppwfxInfo = NULL;
                return E_FAIL;
            }
        }
        // Ascend the input file out of the 'fmt ' chunk.
        if( 0 != mmioAscend( hmmioIn, &ckIn;, 0 ) )
        {
            delete *ppwfxInfo;
            *ppwfxInfo = NULL;
            return E_FAIL;
        }
        return S_OK;
    }
    //-----------------------------------------------------------------------------
    // Name: WaveOpenFile()
    // Desc: This function will open a wave input file and prepare it for reading,
    //       so the data can be easily read with WaveReadFile. Returns 0 if
    //       successful, the error code if not.
    //-----------------------------------------------------------------------------
    HRESULT WaveOpenFile( CHAR* strFileName, HMMIO* phmmioIn, WAVEFORMATEX** ppwfxInfo,
                      MMCKINFO* pckInRIFF )
    {
        HRESULT hr;
        HMMIO   hmmioIn = NULL;
        if( NULL == ( hmmioIn = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF|MMIO_READ ) ) )
            return E_FAIL;
        if( FAILED( hr = ReadMMIO( hmmioIn, pckInRIFF, ppwfxInfo ) ) )
        {
            mmioClose( hmmioIn, 0 );
            return hr;
        }
        *phmmioIn = hmmioIn;
        return S_OK;
    }
    //-----------------------------------------------------------------------------
    // Name: WaveStartDataRead()
    // Desc: Routine has to be called before WaveReadFile as it searches for the
    //       chunk to descend into for reading, that is, the 'data' chunk.  For
    //       simplicity, this used to be in the open routine, but was taken out and
    //       moved to a separate routine so there was more control on the chunks
    //       that are before the data chunk, such as 'fact', etc...
    //-----------------------------------------------------------------------------
    HRESULT WaveStartDataRead( HMMIO* phmmioIn, MMCKINFO* pckIn,
                               MMCKINFO* pckInRIFF )
    {
        // Seek to the data
        if( -1 == mmioSeek( *phmmioIn, pckInRIFF->dwDataOffset + sizeof(FOURCC),
                            SEEK_SET ) )
            return E_FAIL;
        // Search the input file for for the 'data' chunk.
        pckIn->ckid = mmioFOURCC('d', 'a', 't', 'a');
        if( 0 != mmioDescend( *phmmioIn, pckIn, pckInRIFF, MMIO_FINDCHUNK ) )
            return E_FAIL;
        return S_OK;
    }
    //-----------------------------------------------------------------------------
    // Name: WaveReadFile()
    // Desc: Reads wave data from the wave file. Make sure we're descended into
    //       the data chunk before calling this function.
    //          hmmioIn      - Handle to mmio.
    //          cbRead       - # of bytes to read.   
    //          pbDest       - Destination buffer to put bytes.
    //          cbActualRead - # of bytes actually read.
    //-----------------------------------------------------------------------------
    HRESULT WaveReadFile( HMMIO hmmioIn, UINT cbRead, BYTE* pbDest,
                          MMCKINFO* pckIn, UINT* cbActualRead )
    {
        MMIOINFO mmioinfoIn;         // current status of 
        *cbActualRead = 0;
        if( 0 != mmioGetInfo( hmmioIn, &mmioinfoIn;, 0 ) )
            return E_FAIL;
        UINT cbDataIn = cbRead;
        if( cbDataIn > pckIn->cksize ) 
            cbDataIn = pckIn->cksize;       
        pckIn->cksize -= cbDataIn;
        for( DWORD cT = 0; cT < cbDataIn; cT++ )
        {
            // Copy the bytes from the io to the buffer.
            if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
            {
                if( 0 != mmioAdvance( hmmioIn, &mmioinfoIn;, MMIO_READ ) )
                    return E_FAIL;
                if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
                    return E_FAIL;
            }
            // Actual copy.
            *((BYTE*)pbDest+cT) = *((BYTE*)mmioinfoIn.pchNext);
            mmioinfoIn.pchNext++;
        }
        if( 0 != mmioSetInfo( hmmioIn, &mmioinfoIn;, 0 ) )
            return E_FAIL;
        *cbActualRead = cbDataIn;
        return S_OK;
    }
    //-----------------------------------------------------------------------------
    // Name: CWaveSoundRead()
    // Desc: Constructs the class
    //-----------------------------------------------------------------------------
    CWaveSoundRead::CWaveSoundRead()
    {
        m_pwfx   = NULL;
    }
    //-----------------------------------------------------------------------------
    // Name: ~CWaveSoundRead()
    // Desc: Destructs the class
    //-----------------------------------------------------------------------------
    CWaveSoundRead::~CWaveSoundRead()
    {
        Close();
        SAFE_DELETE( m_pwfx );
    }
    //-----------------------------------------------------------------------------
    // Name: Open()
    // Desc: Opens a wave file for reading
    //-----------------------------------------------------------------------------
    HRESULT CWaveSoundRead::Open( CHAR* strFilename )
    {
        SAFE_DELETE( m_pwfx );
        HRESULT  hr;
        if( FAILED( hr = WaveOpenFile( strFilename, &m;_hmmioIn, &m;_pwfx, &m;_ckInRiff ) ) )
            return hr;
        if( FAILED( hr = Reset() ) )
            return hr;
        return hr;
    }
    //-----------------------------------------------------------------------------
    // Name: Reset()
    // Desc: Resets the internal m_ckIn pointer so reading starts from the 
    //       beginning of the file again 
    //-----------------------------------------------------------------------------
    HRESULT CWaveSoundRead::Reset()
    {
        return WaveStartDataRead( &m;_hmmioIn, &m;_ckIn, &m;_ckInRiff );
    }
    //-----------------------------------------------------------------------------
    // Name: Read()
    // Desc: Reads a wave file into a pointer and returns how much read
    //       using m_ckIn to determine where to start reading from
    //-----------------------------------------------------------------------------
    HRESULT CWaveSoundRead::Read( UINT nSizeToRead, BYTE* pbData, UINT* pnSizeRead )
    {
        return WaveReadFile( m_hmmioIn, nSizeToRead, pbData, &m;_ckIn, pnSizeRead );
    }
    //-----------------------------------------------------------------------------
    // Name: Close()
    // Desc: Closes an open wave file 
    //-----------------------------------------------------------------------------
    HRESULT CWaveSoundRead::Close()
    {
        mmioClose( m_hmmioIn, 0 );
        return S_OK;
    }
    	






  • Want More Information? Click Below...


  • Technology Comment...




















Top

Welcome |  Latest News |  Tools |  Demos |  Tutorials |  Reference |  Register |  Downloads
FAQ |  Forums |  Feedback |  Mailing List |  Links |  Site Information

This page is Copyright © 2000-2007 BCB-Tools.com Pty. Ltd., Sydney, Australia. All Rights Reserved.
Borland C++ Builder, CBuilder, etc are Trademarks of Borland Corporation.
DirectX, DirectDraw, Windows, etc are Trademarks of Microsoft Corporation.