C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[456] directx ddraw 응용 창모드 와 풀스크린 예제 입니다.
이진수 [linuz] 13024 읽음    2005-01-28 17:12
음 어떻게 생각하실진 모르지만 일단 저 같이 창모드 랑 풀스크린의 개념을
잡을려는 사람들을 위해서 올려 봅니다.
dx의 개념을 잡기 위해서는 여기 검색에서는 찾기 힘들더군요
데스피아 등 다른 사이트를 전전하며 그리고 빌더 예제 ddraw1a 를 전전하며
시작했는데......
ddraw에서는 풀모드만 만들어 주더군여...
그래서 공부하다 현재는 풀모드 창모드 선택해서 띄우게 예제를 만들어 봤습니다.
빌더 dx 하시는분들 참고 하세여...
일단 빌더6.0에서 만들었구요
빌더에서 컴파일하셔서 쓰심 될거 같구 디폴트는 풀모드입니다.
빌더 에서 Fullscreen=true or false 해서 컴파일 하시면 창모드와
풀스크린을 보실수 있구요....
담에 더 발전 함 올려 드릴께여...
저도 여기까지...파악...ㅠㅠ
그럼 이만...
------------------- 참고 소스 ---main.cpp-------------------------
/*
  This is a DirectDraw example program. DirectDraw programs require that you
  have the DirectDraw runtime on your system. The runtime files are available
  from Microsoft's web site, though many machines will have them on them
  already, as they ship with a wide variety of products, including games, the
  future operating systems Windows 98 and Windows NT 5.0. If you are using NT 4,
  you should upgrade to at least Service Pack 3, so that you can have access
  to DirectDraw 3.0, which is part of that Service Pack. Don't
  try to install the DirectDraw runtime on a Windows NT system, instead, get
  the latest Service Pack. The runtime install is meant only for Windows 95 or
  98. One way to tell if you have DirectDraw on your system is to look in the
  Windows/System directory or Winnt/System32 directory for the files DDRAW.DLL
  and DSOUND.DLL.

  The purpose of DirectDraw is to allow you to perform very fast graphics
  operations inside the Windows environment. In particular, DirectDraw can
  give you direct access to the video buffers on a video card. For best
  results, you should have at least 2 MB of memory on your video card.
  DirectDraw allows you to create a backbuffer, draw to it, and then
  flip it to the visible area in your video memory. Assuming that you are
  in exclusive mode, and have enough video memory to keep both your primary
  surface and back surface in video RAM, then the flip operation is
  not a copy procedure, but simply changes the address of the block of
  memory referenced by the visible area of your video card's memory. In short
  the operation is very fast, and is guarenteed to happen in sync with
  the refresh operations on your monitor. As a result, you can use DirectDraw
  to perform very smooth animations. For a complete explanation, go to the
  DirectDraw area on Microsoft's web site, or visit my web site at
  http://users.aol.com/charliecal.

  The code shown here is the simplest possible DirectDraw program. It is
  modeled closely after the DDX1 example that ships with the Microsoft's
  DirectDraw SDK. I've simply taken their program, and rewritten it to
  compile under a form based environment. In particular, the code uses a
  TTimer object rather than calling SetTimer, and it responds to events
  such as OnKeyDown rather than directly handling WM_KEYDOWN messages.
  The conversion to a form based paradigm makes the code easier to read,
  but doesn't change its underlying structure.

  If you do not want to use forms, the DDX1 program will compile unchanged
  under CBuilder. Simply start a standard CBuilder project, remove the main
  form, then replace the code in the Project Source with the code from
  DDX1.cpp, which file ships with Microsoft's SDK. Press compile, and the
  program will run fine.

  The code in this project has five methods:

  CONSTRUCTOR:
    Perform trivial initialization of variables.

  FORMDESTROY:
    Destroy the direct draw surfaces created in the Start method.

  START:
    Call DirectDrawCreate, which initializes DirectDraw, and returns a pointer
      to a DirectDraw object.
    Call SetCooperativeLevel to switch into exclusive mode.
    Call SetDisplayMode to switch to 640X480 8 bit resolution.
    Call CreateSurface to create a primary surface
    Call GetAttachedSurface to get a pointer to the back surface
    Paint the front and back surface to black, and paint text to each
      so you can recognize them when they are flipped to the screen.
    Enable the timer.

  FORMKEYDOWN:
    Respond to key presses designating the user's desire to switch into
      exclusive mode and begin the demo.
    Respond to the F12 or Esc keys by shutting down the application.

  FORMPAINT:
    Paint some simple instructions for the user in the middle of the screen.
    This method is not called while the program is in Exclusive mode.

  TIMER1TIMER:
    Flip between the primary and back surfaces. This is the key method in this
    demo as it shows how to swap two different surfaces, which is what you
    want to do in an animated graphics program. This method is somewhat
    misleading, though, because most of the time you will want to swap at
    the fastest rate possible, rather than waiting for the timer to call
    your program and ask you to swap. For instance, a smooth animation
    should have a frame rate of at least 25 frames per second, a rate which
    is not practical to achieve using a timer.

*/

// Includes
#include <vcl.h>
#include <windows.h>
#include <ddraw.h>
#pragma hdrstop
#include "Main.h"
#pragma resource "*.dfm"

//Const
#define TIMER_ID        1
#define TIMER_RATE      500
bool Fullscreen;
// Global Variables
TFormMain *FormMain;
void ClearSurface(LPDIRECTDRAWSURFACE lpSurface)
{
    DDSURFACEDESC ddsd;
    LPBYTE SurfaceBuf;
    UINT SurfaceWidth, SurfaceHeight;

    memset(&ddsd, 0, sizeof(DDSURFACEDESC));
    ddsd.dwSize = sizeof(DDSURFACEDESC);

    lpSurface->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
NULL);
    SurfaceWidth = ddsd.lPitch;
    SurfaceHeight = ddsd.dwHeight;
    SurfaceBuf = (LPBYTE) ddsd.lpSurface;
    memset(SurfaceBuf, 0, SurfaceWidth * SurfaceHeight);
    lpSurface->Unlock(ddsd.lpSurface);
}


///////////////////////////////////////
// Constructor
///////////////////////////////////////
__fastcall TFormMain::TFormMain(TComponent* Owner)
        : TForm(Owner)
{
  lpDD = NULL;
  phase = 0;
  bActive = False;
  Fullscreen=true;
  MaxX=1024;
  MaxY=768;
  FrontMsg = "나는 이진수 입니다.[P] www.nedakai.pe.kr";
  BackMsg = "나는 이진수 입니다.[B] www.nedakai.pe.kr";
}

///////////////////////////////////////
// WM_DESTROY messages
///////////////////////////////////////
void __fastcall TFormMain::FormDestroy(TObject *Sender)
{
  if(lpDD != NULL)
  {
    if(lpDDSPrimary != NULL)
    {
      lpDDSPrimary->Release();
      lpDDSPrimary = NULL;
    }
    lpDD->Release();
    lpDD = NULL;
  }
}


///////////////////////////////////////
// Initialize DirectDraw
///////////////////////////////////////
void __fastcall TFormMain::Start()
{
  HRESULT ddrval;
  DDSURFACEDESC ddsd;
  DDSCAPS ddscaps;
  HDC DC;
  RECT rc, rcWork;
  DWORD dwStyle;
  char buf[256];

  ddrval = DirectDrawCreate(NULL, &lpDD, NULL);
//  if (ddrval != DD_OK) return DirectDrawError("드로우 객체 생성 실패");
if (Fullscreen){
  if(ddrval == DD_OK)
  {


    // Get exclusive mode
    ddrval = lpDD->SetCooperativeLevel(Handle,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
   // ddrval = lpDD->SetCooperativeLevel(Handle,DDSCL_NORMAL);
    if(ddrval == DD_OK)
    {
      ddrval = lpDD->SetDisplayMode(MaxX,MaxY, 8);
      if(ddrval == DD_OK)
      {
        // Create the primary surface with 1 back buffer
        ddsd.dwSize = sizeof(ddsd);
        ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
//        ddsd.dwFlags = DDSD_CAPS;
        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |DDSCAPS_COMPLEX;
//        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
        ddsd.dwBackBufferCount = 1;
        ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
        if(ddrval == DD_OK)
        {




           ZeroMemory(&ddsd,sizeof(ddsd));
           ddsd.dwSize=sizeof(ddsd.dwSize);
           ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
           ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
           ddsd.dwWidth=100;
           ddsd.dwHeight=100;
           ddrval=lpDD->CreateSurface(&ddsd,&lpDDSBack,NULL);

           //lpDD->CreateClipper(0,&g_pDDC,NULL);


          //ShowMessage("ok1");
          // Get a pointer to the back buffer
          ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
          ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps,
                                                &lpDDSBack);
          if(ddrval == DD_OK)
          {
            // draw some text.
            if (lpDDSPrimary->GetDC(&DC) == DD_OK)
            {
                SetBkColor(DC, RGB(0, 0, 0));
                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, 0));
                SetTextColor(DC, RGB(255, 255, 0));
                TextOut(DC, 0, 0, BackMsg.c_str(), BackMsg.Length());
                lpDDSBack->ReleaseDC(DC);
            }
             ClearSurface(lpDDSPrimary);
               ClearSurface(lpDDSBack);
            // Create a timer to flip the pages
            Timer1->Enabled = True;
            bActive = True;
            return;
          }

        }
      }
    }
  }
  }
  else {
  if(ddrval == DD_OK)
  {

      ShowCursor(TRUE);
         // 윈도 형식 변경
         DC = GetDC(NULL);
         BitP = GetDeviceCaps(DC, BITSPIXEL);
         ReleaseDC(NULL, DC);

         dwStyle = GetWindowLong(Handle, GWL_STYLE);
         dwStyle &= ~WS_POPUP;
         dwStyle |= WS_OVERLAPPED | WS_MINIMIZEBOX |WS_CAPTION  
         |WS_THICKFRAME | WS_SYSMENU;
         SetWindowLong(Handle, GWL_STYLE, dwStyle);

         SetRect(&rc, 0, 0, MaxX, MaxY);

         AdjustWindowRectEx(&rc, GetWindowLong(Handle, GWL_STYLE),
         GetMenu(Handle) != NULL,
         GetWindowLong(Handle, GWL_EXSTYLE));
         SetWindowPos( Handle, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
                                    SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
         SetWindowPos( Handle, HWND_NOTOPMOST, 0, 0, 0, 0,
                                     SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);

         SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0);
         GetWindowRect(Handle, &rc);
         if(rc.left < rcWork.left) rc.left = rcWork.left;
         if(rc.top < rcWork.top ) rc.top = rcWork.top;
         SetWindowPos(Handle, NULL, rc.left, rc.top, 0, 0,
                                    SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);

    // Get exclusive mode
    //ddrval = lpDD->SetCooperativeLevel(Handle,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
    ddrval = lpDD->SetCooperativeLevel(Handle, DDSCL_NORMAL);
   // ddrval = lpDD->SetCooperativeLevel(Handle,DDSCL_NORMAL);
    if(ddrval == DD_OK)
    {
      //ddrval = lpDD->SetDisplayMode(1024,768, 8);

      // Create the primary surface with 1 back buffer
      memset(&ddsd, 0, sizeof(ddsd));
      ddsd.dwSize =sizeof(ddsd);
      ddsd.dwFlags = DDSD_CAPS;
      ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
      ddrval = lpDD->CreateSurface (&ddsd, &lpDDSPrimary, NULL);
      if(ddrval == DD_OK)
      {


         ZeroMemory(&ddsd,sizeof(ddsd));
         ddsd.dwSize=sizeof(ddsd.dwSize);
         ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
         ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;
         ddsd.dwWidth=800;
         ddsd.dwHeight=600;
         ddrval=lpDD->CreateSurface(&ddsd,&lpDDSBack,NULL);

         //lpDD->CreateClipper(0,&g_pDDC,NULL);

// 클리핑 화면 생성 및 세팅
         ddrval = lpDD -> CreateClipper (0, &lpClipper, NULL);
         //if(ddrval!= DD_OK)return DirectDrawError("클리핑 생성 실패");
         ddrval = lpClipper -> SetHWnd(0, Handle);
         //if(ddrval!= DD_OK)return DirectDrawError("클리핑 생성 실패");
         ddrval = lpDDSPrimary -> SetClipper(lpClipper);
         //if(ddrval!= DD_OK)return DirectDrawError("클리핑 생성 실패");

          // Create a timer to flip the pages
          Timer1->Enabled = True;
          bActive = True;
          return;
       // }

      }
   
  }
}

  }
    wsprintf(buf, "eerror (%08lx)\n", ddrval);
  MessageBox(Handle, buf, "ERROR", MB_OK);
  Close();

}

///////////////////////////////////////
// WM_KEYDOWN messages
///////////////////////////////////////
void __fastcall TFormMain::FormKeyDown(TObject *Sender, WORD &Key,
        TShiftState Shift)
{

   switch (Key)
   {
     case VK_F3:

       Start();
       break;


     case VK_F12:
     case VK_ESCAPE:
        Close();
       break;
   }
}

///////////////////////////////////////
// WM_PAINT messages
///////////////////////////////////////
void __fastcall TFormMain::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);
  }
}

///////////////////////////////////////
// WM_TIMER messages
///////////////////////////////////////
void __fastcall TFormMain::Timer1Timer(TObject *Sender)
{
HDC DC;
RECT DestRC;
    RECT SrcRC;
    POINT pt;
if (Fullscreen){
if (lpDDSBack->GetDC(&DC) == DD_OK)
  {
    if(phase)
    {
      SetBkColor(DC, RGB(0, 0, 0));
      SetTextColor(DC, RGB(255, 255, 0));


      TextOut(DC, 0, 0, FrontMsg.c_str(), FrontMsg.Length());
      phase = 0;
    }
    else
    {
      SetBkColor(DC, RGB(0, 0, 0));
      SetTextColor(DC, RGB(255, 255, 0));
      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;
  }
  }
  else{
      //ClientToScreen(this->Handle, &pt);
        ClientToScreen(pt);
        //GetClientRect( hWnd, &DestRC);
        SetRect( &SrcRC, 0, 0, MaxX, MaxY);
        SetRect( &DestRC, 0, 0, MaxX, MaxY);
        OffsetRect(&DestRC, pt.x, pt.y);
        ShowCursor(FALSE);
        lpDDSPrimary->Blt(&DestRC, lpDDSBack, &SrcRC, 0 , NULL);
        ShowCursor(TRUE);
  }

}

------------------------- main.h------------------------------------

//---------------------------------------------------------------------------
#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Menus.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TFormMain : 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;           // DirectDraw object
// LPDIRECTCLIPPER
  LPDIRECTDRAWCLIPPER     lpClipper;
  LPDIRECTDRAWSURFACE     lpDDSPrimary;   // DirectDraw primary surface
  LPDIRECTDRAWSURFACE     lpDDSBack;      // DirectDraw back surface
  BOOL                    bActive;        // is application active?
 
  BYTE phase;
  int MaxX;
int MaxY;
int BitP;
  AnsiString FrontMsg;
  AnsiString BackMsg;
  void __fastcall Start();
  void __fastcall InitDirectDraw();
public:
        __fastcall TFormMain(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern TFormMain *FormMain;
//---------------------------------------------------------------------------
#endif
최익수 [tick]   2005-02-07 11:25 X
1024 X 1024 X 8bit 이미지를 GDI를 이용해서 화면에 뿌리는 거랑 비교해서
DirectDraw가 어느 정도 빠른지 알 수 있을까요?
(FullScreen 모드에서 실행하지 않고, Window 모드에서 실행했을 때 어느 정도인지
알고싶습니다.)

+ -

관련 글 리스트
456 directx ddraw 응용 창모드 와 풀스크린 예제 입니다. 이진수 13024 2005/01/28
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.