526 lines
16 KiB
C++
526 lines
16 KiB
C++
//-----------------------------------------------------------------------------
|
|
// File: WinMain.CPP
|
|
//
|
|
// Desc: This sample demonstrates how to bring up a dialog, or any type of
|
|
// window, in a DirectDraw full-screen exclusive mode, even on non GDI
|
|
// devices.
|
|
//
|
|
//
|
|
// Copyright (c) 1998-1999 Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#define NAME "FSWindow"
|
|
#define TITLE "DDraw Full-Screen Dialog Example"
|
|
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Include files
|
|
//-----------------------------------------------------------------------------
|
|
#include "dconfigp.h"
|
|
|
|
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
BOOL Init();
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Global Variables
|
|
//-----------------------------------------------------------------------------
|
|
extern HINSTANCE g_hInst;
|
|
IDirectDraw7 *g_pDD = NULL; // DirectDraw object
|
|
IDirectDrawSurface7 *g_pDDSPrimary = NULL; // DirectDraw primary surface
|
|
IDirectDrawSurface7 *g_pDDSBack = NULL; // DirectDraw back surface
|
|
BOOL g_fActive = FALSE; // App is running/active
|
|
BOOL g_fReady = FALSE; // App is ready for updates
|
|
BOOL g_fPaused = FALSE; // App is paused
|
|
HWND g_hWndHelp = NULL;
|
|
HWND g_hWndDlg = NULL; // Sample dialog box handle
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DebugMsg()
|
|
// Desc: This function essentially is a printf for debug output.
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
DebugMsg(LPCTSTR szError,...)
|
|
{
|
|
char szBuff[128];
|
|
va_list vl;
|
|
|
|
va_start(vl, szError);
|
|
#ifdef WIN95
|
|
{
|
|
char *psz = NULL;
|
|
char szDfs[1024]={0};
|
|
strcpy(szDfs,szError); // make a local copy of format string
|
|
while (psz = strstr(szDfs,"%p")) // find each %p
|
|
*(psz+1) = 'x'; // replace each %p with %x
|
|
vsprintf(szBuff, szDfs, vl); // use the local format string
|
|
}
|
|
#else
|
|
{
|
|
vsprintf(szBuff, szError, vl);
|
|
}
|
|
#endif
|
|
OutputDebugString(szBuff);
|
|
va_end(vl);
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ReleaseAllObjects()
|
|
// Desc: Release all DDraw objects we use.
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
ReleaseAllObjects(HWND hWnd)
|
|
{
|
|
if (g_pDD != NULL)
|
|
{
|
|
g_pDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);
|
|
if (g_pDDSBack != NULL)
|
|
{
|
|
g_pDDSBack->Release();
|
|
g_pDDSBack = NULL;
|
|
}
|
|
if (g_pDDSPrimary != NULL)
|
|
{
|
|
g_pDDSPrimary->Release();
|
|
g_pDDSPrimary = NULL;
|
|
}
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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);
|
|
#ifdef WIN95
|
|
{
|
|
char *psz = NULL;
|
|
char szDfs[1024]={0};
|
|
strcpy(szDfs,szError); // make a local copy of format string
|
|
while (psz = strstr(szDfs,"%p")) // find each %p
|
|
*(psz+1) = 'x'; // replace each %p with %x
|
|
vsprintf(szBuff, szDfs, vl); // use the local format string
|
|
}
|
|
#else
|
|
{
|
|
vsprintf(szBuff, szError, vl);
|
|
}
|
|
#endif
|
|
ReleaseAllObjects(hWnd);
|
|
MessageBox(hWnd, szBuff, TITLE, MB_OK);
|
|
DestroyWindow(hWnd);
|
|
va_end(vl);
|
|
return hRet;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: AppPause()
|
|
// Desc: Toggles the pause mode of the app.
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
AppPause(HWND hWnd, BOOL fPause)
|
|
{
|
|
if (fPause)
|
|
{
|
|
g_fPaused = TRUE;
|
|
g_pDD->FlipToGDISurface();
|
|
RedrawWindow(hWnd, NULL, NULL, RDW_FRAME);
|
|
}
|
|
else
|
|
{
|
|
RedrawWindow(hWnd, NULL, NULL, RDW_FRAME);
|
|
g_fPaused = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: InitSurfaces()
|
|
// Desc: Create all the needed DDraw surfaces and set the coop level.
|
|
//-----------------------------------------------------------------------------
|
|
static HRESULT
|
|
InitSurfaces(HWND hWnd)
|
|
{
|
|
HRESULT hRet;
|
|
DDSURFACEDESC2 ddsd;
|
|
DDSCAPS2 ddscaps;
|
|
|
|
// 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 640x480x16
|
|
hRet = g_pDD->SetDisplayMode(1024, 768, 16, 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 (3) FAILED");
|
|
|
|
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");
|
|
|
|
// Do help initialization
|
|
FSWindow_Init(hWnd, g_pDD, g_pDDSPrimary, g_pDDSBack);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ChangeCoopLevel()
|
|
// Desc: Called when the user wants to toggle between Full-Screen & Windowed.
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
ChangeCoopLevel(HWND hWnd)
|
|
{
|
|
HRESULT hRet;
|
|
|
|
// Release all objects that need to be re-created for the new device
|
|
if (FAILED(hRet = ReleaseAllObjects(hWnd)))
|
|
return InitFail(hWnd, hRet, "ReleaseAllObjects FAILED");
|
|
|
|
// Re-create the surfaces
|
|
hRet = InitSurfaces(hWnd);
|
|
return hRet;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: RenderFrame()
|
|
// Desc: Blts and moves a bouncing ball, as well as displays helpful text.
|
|
//-----------------------------------------------------------------------------
|
|
BOOL
|
|
RenderFrame()
|
|
{
|
|
DDBLTFX ddbltfx;
|
|
HDC hDC;
|
|
static int x1 = 0,
|
|
y1 = 0,
|
|
x2 = 40,
|
|
y2 = 40;
|
|
HBRUSH hOldBrush;
|
|
HPEN hOldPen;
|
|
static int xDir = +8,
|
|
yDir = +8;
|
|
|
|
// Use the blter to do a color fill to clear the back buffer
|
|
ZeroMemory(&ddbltfx, sizeof(ddbltfx));
|
|
ddbltfx.dwSize = sizeof(ddbltfx);
|
|
ddbltfx.dwFillColor = 0;
|
|
g_pDDSBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
|
|
|
|
if (g_pDDSBack->GetDC(&hDC) == DD_OK)
|
|
{
|
|
// Paint the bouncing ball
|
|
SetBkColor(hDC, RGB(0, 0, 255));
|
|
SetTextColor(hDC, RGB(255, 255, 0));
|
|
hOldBrush = (HBRUSH) SelectObject(hDC, GetStockObject(LTGRAY_BRUSH));
|
|
hOldPen = (HPEN) SelectObject(hDC, GetStockObject(WHITE_PEN));
|
|
Ellipse(hDC, x1, y1, x2, y2);
|
|
SelectObject(hDC, hOldPen);
|
|
SelectObject(hDC, hOldBrush);
|
|
|
|
// Move the bouncing ball and make it bounce
|
|
x1 += xDir;
|
|
x2 += xDir;
|
|
if (x1 < 0)
|
|
{
|
|
x1 = 0;
|
|
x2 = 40;
|
|
xDir = -xDir;
|
|
}
|
|
if (x2 >= 640)
|
|
{
|
|
x1 = 640 - 1 - 40;
|
|
x2 = 640 - 1;
|
|
xDir = -xDir;
|
|
}
|
|
y1 += yDir;
|
|
y2 += yDir;
|
|
if (y1 < 0)
|
|
{
|
|
y1 = 0;
|
|
y2 = 40;
|
|
yDir = -yDir;
|
|
}
|
|
if (y2 >= 480)
|
|
{
|
|
y1 = 480 - 1 - 40;
|
|
y2 = 480 - 1;
|
|
yDir = -yDir;
|
|
}
|
|
|
|
// Display the proper text
|
|
TextOut(hDC, 0, 0, "Press Escape to quit", 20);
|
|
TextOut(hDC, 0, 20, "Press F1 to bring up the dialog", 31);
|
|
|
|
g_pDDSBack->ReleaseDC(hDC);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: UpdateFrame()
|
|
// Desc: Call RenderFrame() and the BLT and/or flip the new frame.
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
UpdateFrame()
|
|
{
|
|
HRESULT hRet;
|
|
|
|
// Update the background and flip
|
|
//RenderFrame();
|
|
while (TRUE)
|
|
{
|
|
if (FSWindow_IsActive())
|
|
{
|
|
FSWindow_Update();
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// Else we are in fullscreen mode, so perform a flip.
|
|
hRet = g_pDDSPrimary->Flip(NULL, 0L);
|
|
}
|
|
if (hRet == DD_OK)
|
|
break;
|
|
if (hRet == DDERR_SURFACELOST)
|
|
{
|
|
hRet = g_pDDSPrimary->Restore();
|
|
if (hRet != DD_OK)
|
|
break;
|
|
}
|
|
if (hRet != DDERR_WASSTILLDRAWING)
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: MainWndProc()
|
|
// Desc: The Main Window Procedure.
|
|
//-----------------------------------------------------------------------------
|
|
LRESULT CALLBACK
|
|
MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (msg)
|
|
{
|
|
case WM_ACTIVATEAPP:
|
|
// Pause if minimized
|
|
g_fActive = !((BOOL)HIWORD(wParam));
|
|
return 0L;
|
|
|
|
case WM_CLOSE:
|
|
FSWindow_End();
|
|
DestroyWindow(hWnd);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
// Clean up and close the app
|
|
ReleaseAllObjects(hWnd);
|
|
PostQuitMessage(0);
|
|
return 0L;
|
|
|
|
case WM_KEYDOWN:
|
|
// Handle any non-accelerated key commands
|
|
switch (wParam)
|
|
{
|
|
case VK_PAUSE:
|
|
// Allow the app to be paused
|
|
AppPause(hWnd, !g_fPaused);
|
|
break;
|
|
case VK_ESCAPE:
|
|
case VK_F12:
|
|
PostMessage(hWnd, WM_CLOSE, 0, 0);
|
|
return 0L;
|
|
case VK_F1:
|
|
|
|
g_hWndHelp = FSWindow_Begin(g_hWndDlg, FALSE);
|
|
g_hWndDlg = CreateDialog(g_hInst,
|
|
MAKEINTRESOURCE(IDD_DCONFIG_DIALOG),
|
|
hWnd, (DLGPROC) DialogProc);
|
|
|
|
ShowWindow(g_hWndDlg, SW_SHOWNORMAL);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_SETCURSOR:
|
|
// Display the cursor if conditions are right
|
|
if (g_fActive && g_fReady && !g_fPaused && !FSWindow_IsActive())
|
|
{
|
|
SetCursor(NULL);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: WinMain()
|
|
// Desc: Entry point to the program. Initializes everything and calls
|
|
// AppIdle() when idle from the message pump.
|
|
//-----------------------------------------------------------------------------
|
|
int PASCAL
|
|
WinMain(HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpszCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
WNDCLASS wc;
|
|
MSG msg;
|
|
HWND hWnd;
|
|
HRESULT hRet;
|
|
HINSTANCE hDDrawDLL;
|
|
LPDIRECTDRAWENUMERATEEX pDirectDrawEnumerateEx;
|
|
DWORD dwLastTime;
|
|
DWORD dwThisTime;
|
|
|
|
if (!hPrevInstance)
|
|
{
|
|
// Register the Window Class
|
|
wc.lpszClassName = NAME;
|
|
wc.lpfnWndProc = MainWndProc;
|
|
wc.style = CS_VREDRAW | CS_HREDRAW;
|
|
wc.hInstance = hInstance;
|
|
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DCONFIG_ICON));
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
if (!RegisterClass(&wc))
|
|
return FALSE;
|
|
}
|
|
|
|
g_hInst = g_hInst = hInstance;
|
|
|
|
// Init();
|
|
// Create and Show the Main Window
|
|
hWnd = CreateWindowEx(0,
|
|
NAME,
|
|
TITLE,
|
|
WS_CLIPCHILDREN | WS_POPUP,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
1024,
|
|
768,
|
|
NULL,
|
|
NULL,
|
|
hInstance,
|
|
NULL);
|
|
if (hWnd == NULL)
|
|
return FALSE;
|
|
|
|
// You need to do a GetModuleHandle and GetProcAddress in order to get the
|
|
// DirectDrawEnumerateEx function pointer
|
|
hDDrawDLL = GetModuleHandle("DDRAW");
|
|
if (!hDDrawDLL)
|
|
return InitFail(hWnd, DD_OK, "GetModuleHandle FAILED");
|
|
|
|
//Create the main DirectDraw object
|
|
hRet = DirectDrawCreateEx(NULL, (VOID**)&g_pDD, IID_IDirectDraw7, NULL);
|
|
if (hRet != DD_OK)
|
|
return InitFail(hWnd, hRet, "DirectDrawCreateEx FAILED");
|
|
|
|
//Initialize all the surfaces we need
|
|
hRet = InitSurfaces(hWnd);
|
|
if (FAILED(hRet))
|
|
return FALSE;
|
|
|
|
g_fReady = TRUE;
|
|
|
|
g_hWndDlg = CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_DCONFIG_DIALOG),
|
|
hWnd, (DLGPROC) DialogProc);
|
|
|
|
ShowWindow(g_hWndDlg, SW_SHOWNORMAL);
|
|
Sleep(1000);
|
|
|
|
g_hWndHelp = FSWindow_Begin(g_hWndDlg, FALSE);
|
|
// Put up the sample dialog right away, to show the sample user what this
|
|
// sample is trying to demonstrate.
|
|
|
|
//-------------------------------------------------------------------------
|
|
// The Message Pump
|
|
//-------------------------------------------------------------------------
|
|
dwLastTime = 0;
|
|
dwThisTime = timeGetTime();
|
|
while (TRUE)
|
|
{
|
|
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
|
|
{
|
|
if (!GetMessage(&msg, NULL, 0, 0))
|
|
break;
|
|
// If the dialog is showing, translate messages for it since it's
|
|
// a modeless dialog.
|
|
if (g_hWndDlg == (HWND )NULL || !IsDialogMessage(g_hWndDlg, &msg))
|
|
{
|
|
// Translate and dispatch the message
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
else
|
|
if (g_fActive && g_fReady && !g_fPaused)
|
|
{
|
|
dwThisTime = timeGetTime();
|
|
// 1000/FPS = number of milliseconds to wait
|
|
if ((dwThisTime - dwLastTime) >= (1000/30))
|
|
{
|
|
UpdateFrame();
|
|
dwLastTime = timeGetTime();
|
|
}
|
|
}
|
|
else
|
|
// Make sure we go to sleep if we have nothing else to do
|
|
WaitMessage();
|
|
}
|
|
// Release the main DDraw interface
|
|
if (g_pDD)
|
|
g_pDD->Release();
|
|
|
|
return msg.wParam;
|
|
}
|
|
|
|
|
|
|