음 어떻게 생각하실진 모르지만 일단 저 같이 창모드 랑 풀스크린의 개념을
잡을려는 사람들을 위해서 올려 봅니다.
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
DirectDraw가 어느 정도 빠른지 알 수 있을까요?
(FullScreen 모드에서 실행하지 않고, Window 모드에서 실행했을 때 어느 정도인지
알고싶습니다.)