windows-nt/Source/XPSP1/NT/multimedia/directx/dinput/diconfig/winmain.cpp
2020-09-26 16:20:57 +08:00

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;
}