Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

525 lines
16 KiB

  1. //-----------------------------------------------------------------------------
  2. // File: WinMain.CPP
  3. //
  4. // Desc: This sample demonstrates how to bring up a dialog, or any type of
  5. // window, in a DirectDraw full-screen exclusive mode, even on non GDI
  6. // devices.
  7. //
  8. //
  9. // Copyright (c) 1998-1999 Microsoft Corporation. All rights reserved.
  10. //-----------------------------------------------------------------------------
  11. #define NAME "FSWindow"
  12. #define TITLE "DDraw Full-Screen Dialog Example"
  13. #ifndef WIN32_LEAN_AND_MEAN
  14. #define WIN32_LEAN_AND_MEAN
  15. #endif
  16. //-----------------------------------------------------------------------------
  17. // Include files
  18. //-----------------------------------------------------------------------------
  19. #include "dconfigp.h"
  20. BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  21. BOOL Init();
  22. //-----------------------------------------------------------------------------
  23. // Global Variables
  24. //-----------------------------------------------------------------------------
  25. extern HINSTANCE g_hInst;
  26. IDirectDraw7 *g_pDD = NULL; // DirectDraw object
  27. IDirectDrawSurface7 *g_pDDSPrimary = NULL; // DirectDraw primary surface
  28. IDirectDrawSurface7 *g_pDDSBack = NULL; // DirectDraw back surface
  29. BOOL g_fActive = FALSE; // App is running/active
  30. BOOL g_fReady = FALSE; // App is ready for updates
  31. BOOL g_fPaused = FALSE; // App is paused
  32. HWND g_hWndHelp = NULL;
  33. HWND g_hWndDlg = NULL; // Sample dialog box handle
  34. //-----------------------------------------------------------------------------
  35. // Name: DebugMsg()
  36. // Desc: This function essentially is a printf for debug output.
  37. //-----------------------------------------------------------------------------
  38. void
  39. DebugMsg(LPCTSTR szError,...)
  40. {
  41. char szBuff[128];
  42. va_list vl;
  43. va_start(vl, szError);
  44. #ifdef WIN95
  45. {
  46. char *psz = NULL;
  47. char szDfs[1024]={0};
  48. strcpy(szDfs,szError); // make a local copy of format string
  49. while (psz = strstr(szDfs,"%p")) // find each %p
  50. *(psz+1) = 'x'; // replace each %p with %x
  51. vsprintf(szBuff, szDfs, vl); // use the local format string
  52. }
  53. #else
  54. {
  55. vsprintf(szBuff, szError, vl);
  56. }
  57. #endif
  58. OutputDebugString(szBuff);
  59. va_end(vl);
  60. }
  61. //-----------------------------------------------------------------------------
  62. // Name: ReleaseAllObjects()
  63. // Desc: Release all DDraw objects we use.
  64. //-----------------------------------------------------------------------------
  65. HRESULT
  66. ReleaseAllObjects(HWND hWnd)
  67. {
  68. if (g_pDD != NULL)
  69. {
  70. g_pDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);
  71. if (g_pDDSBack != NULL)
  72. {
  73. g_pDDSBack->Release();
  74. g_pDDSBack = NULL;
  75. }
  76. if (g_pDDSPrimary != NULL)
  77. {
  78. g_pDDSPrimary->Release();
  79. g_pDDSPrimary = NULL;
  80. }
  81. }
  82. return DD_OK;
  83. }
  84. //-----------------------------------------------------------------------------
  85. // Name: InitFail()
  86. // Desc: This function is called if an initialization function fails.
  87. //-----------------------------------------------------------------------------
  88. HRESULT
  89. InitFail(HWND hWnd, HRESULT hRet, LPCTSTR szError,...)
  90. {
  91. char szBuff[128];
  92. va_list vl;
  93. va_start(vl, szError);
  94. #ifdef WIN95
  95. {
  96. char *psz = NULL;
  97. char szDfs[1024]={0};
  98. strcpy(szDfs,szError); // make a local copy of format string
  99. while (psz = strstr(szDfs,"%p")) // find each %p
  100. *(psz+1) = 'x'; // replace each %p with %x
  101. vsprintf(szBuff, szDfs, vl); // use the local format string
  102. }
  103. #else
  104. {
  105. vsprintf(szBuff, szError, vl);
  106. }
  107. #endif
  108. ReleaseAllObjects(hWnd);
  109. MessageBox(hWnd, szBuff, TITLE, MB_OK);
  110. DestroyWindow(hWnd);
  111. va_end(vl);
  112. return hRet;
  113. }
  114. //-----------------------------------------------------------------------------
  115. // Name: AppPause()
  116. // Desc: Toggles the pause mode of the app.
  117. //-----------------------------------------------------------------------------
  118. void
  119. AppPause(HWND hWnd, BOOL fPause)
  120. {
  121. if (fPause)
  122. {
  123. g_fPaused = TRUE;
  124. g_pDD->FlipToGDISurface();
  125. RedrawWindow(hWnd, NULL, NULL, RDW_FRAME);
  126. }
  127. else
  128. {
  129. RedrawWindow(hWnd, NULL, NULL, RDW_FRAME);
  130. g_fPaused = FALSE;
  131. }
  132. }
  133. //-----------------------------------------------------------------------------
  134. // Name: InitSurfaces()
  135. // Desc: Create all the needed DDraw surfaces and set the coop level.
  136. //-----------------------------------------------------------------------------
  137. static HRESULT
  138. InitSurfaces(HWND hWnd)
  139. {
  140. HRESULT hRet;
  141. DDSURFACEDESC2 ddsd;
  142. DDSCAPS2 ddscaps;
  143. // Get exclusive mode
  144. hRet = g_pDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
  145. if (hRet != DD_OK)
  146. return InitFail(hWnd, hRet, "SetCooperativeLevel FAILED");
  147. // Set the video mode to 640x480x16
  148. hRet = g_pDD->SetDisplayMode(1024, 768, 16, 0, 0);
  149. if (hRet != DD_OK)
  150. return InitFail(hWnd, hRet, "SetDisplayMode FAILED");
  151. // Create the primary surface with 1 back buffer
  152. ZeroMemory(&ddsd, sizeof(ddsd));
  153. ddsd.dwSize = sizeof(ddsd);
  154. ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  155. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
  156. ddsd.dwBackBufferCount = 1;
  157. hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL);
  158. if (hRet != DD_OK)
  159. return InitFail(hWnd, hRet, "CreateSurface (3) FAILED");
  160. ZeroMemory(&ddscaps, sizeof(ddscaps));
  161. ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  162. hRet = g_pDDSPrimary->GetAttachedSurface(&ddscaps, &g_pDDSBack);
  163. if (hRet != DD_OK)
  164. return InitFail(hWnd, hRet, "GetAttachedSurface FAILED");
  165. // Do help initialization
  166. FSWindow_Init(hWnd, g_pDD, g_pDDSPrimary, g_pDDSBack);
  167. return DD_OK;
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Name: ChangeCoopLevel()
  171. // Desc: Called when the user wants to toggle between Full-Screen & Windowed.
  172. //-----------------------------------------------------------------------------
  173. HRESULT
  174. ChangeCoopLevel(HWND hWnd)
  175. {
  176. HRESULT hRet;
  177. // Release all objects that need to be re-created for the new device
  178. if (FAILED(hRet = ReleaseAllObjects(hWnd)))
  179. return InitFail(hWnd, hRet, "ReleaseAllObjects FAILED");
  180. // Re-create the surfaces
  181. hRet = InitSurfaces(hWnd);
  182. return hRet;
  183. }
  184. //-----------------------------------------------------------------------------
  185. // Name: RenderFrame()
  186. // Desc: Blts and moves a bouncing ball, as well as displays helpful text.
  187. //-----------------------------------------------------------------------------
  188. BOOL
  189. RenderFrame()
  190. {
  191. DDBLTFX ddbltfx;
  192. HDC hDC;
  193. static int x1 = 0,
  194. y1 = 0,
  195. x2 = 40,
  196. y2 = 40;
  197. HBRUSH hOldBrush;
  198. HPEN hOldPen;
  199. static int xDir = +8,
  200. yDir = +8;
  201. // Use the blter to do a color fill to clear the back buffer
  202. ZeroMemory(&ddbltfx, sizeof(ddbltfx));
  203. ddbltfx.dwSize = sizeof(ddbltfx);
  204. ddbltfx.dwFillColor = 0;
  205. g_pDDSBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
  206. if (g_pDDSBack->GetDC(&hDC) == DD_OK)
  207. {
  208. // Paint the bouncing ball
  209. SetBkColor(hDC, RGB(0, 0, 255));
  210. SetTextColor(hDC, RGB(255, 255, 0));
  211. hOldBrush = (HBRUSH) SelectObject(hDC, GetStockObject(LTGRAY_BRUSH));
  212. hOldPen = (HPEN) SelectObject(hDC, GetStockObject(WHITE_PEN));
  213. Ellipse(hDC, x1, y1, x2, y2);
  214. SelectObject(hDC, hOldPen);
  215. SelectObject(hDC, hOldBrush);
  216. // Move the bouncing ball and make it bounce
  217. x1 += xDir;
  218. x2 += xDir;
  219. if (x1 < 0)
  220. {
  221. x1 = 0;
  222. x2 = 40;
  223. xDir = -xDir;
  224. }
  225. if (x2 >= 640)
  226. {
  227. x1 = 640 - 1 - 40;
  228. x2 = 640 - 1;
  229. xDir = -xDir;
  230. }
  231. y1 += yDir;
  232. y2 += yDir;
  233. if (y1 < 0)
  234. {
  235. y1 = 0;
  236. y2 = 40;
  237. yDir = -yDir;
  238. }
  239. if (y2 >= 480)
  240. {
  241. y1 = 480 - 1 - 40;
  242. y2 = 480 - 1;
  243. yDir = -yDir;
  244. }
  245. // Display the proper text
  246. TextOut(hDC, 0, 0, "Press Escape to quit", 20);
  247. TextOut(hDC, 0, 20, "Press F1 to bring up the dialog", 31);
  248. g_pDDSBack->ReleaseDC(hDC);
  249. }
  250. return TRUE;
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Name: UpdateFrame()
  254. // Desc: Call RenderFrame() and the BLT and/or flip the new frame.
  255. //-----------------------------------------------------------------------------
  256. void
  257. UpdateFrame()
  258. {
  259. HRESULT hRet;
  260. // Update the background and flip
  261. //RenderFrame();
  262. while (TRUE)
  263. {
  264. if (FSWindow_IsActive())
  265. {
  266. FSWindow_Update();
  267. break;
  268. }
  269. else
  270. {
  271. // Else we are in fullscreen mode, so perform a flip.
  272. hRet = g_pDDSPrimary->Flip(NULL, 0L);
  273. }
  274. if (hRet == DD_OK)
  275. break;
  276. if (hRet == DDERR_SURFACELOST)
  277. {
  278. hRet = g_pDDSPrimary->Restore();
  279. if (hRet != DD_OK)
  280. break;
  281. }
  282. if (hRet != DDERR_WASSTILLDRAWING)
  283. break;
  284. }
  285. }
  286. //-----------------------------------------------------------------------------
  287. // Name: MainWndProc()
  288. // Desc: The Main Window Procedure.
  289. //-----------------------------------------------------------------------------
  290. LRESULT CALLBACK
  291. MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  292. {
  293. switch (msg)
  294. {
  295. case WM_ACTIVATEAPP:
  296. // Pause if minimized
  297. g_fActive = !((BOOL)HIWORD(wParam));
  298. return 0L;
  299. case WM_CLOSE:
  300. FSWindow_End();
  301. DestroyWindow(hWnd);
  302. break;
  303. case WM_DESTROY:
  304. // Clean up and close the app
  305. ReleaseAllObjects(hWnd);
  306. PostQuitMessage(0);
  307. return 0L;
  308. case WM_KEYDOWN:
  309. // Handle any non-accelerated key commands
  310. switch (wParam)
  311. {
  312. case VK_PAUSE:
  313. // Allow the app to be paused
  314. AppPause(hWnd, !g_fPaused);
  315. break;
  316. case VK_ESCAPE:
  317. case VK_F12:
  318. PostMessage(hWnd, WM_CLOSE, 0, 0);
  319. return 0L;
  320. case VK_F1:
  321. g_hWndHelp = FSWindow_Begin(g_hWndDlg, FALSE);
  322. g_hWndDlg = CreateDialog(g_hInst,
  323. MAKEINTRESOURCE(IDD_DCONFIG_DIALOG),
  324. hWnd, (DLGPROC) DialogProc);
  325. ShowWindow(g_hWndDlg, SW_SHOWNORMAL);
  326. break;
  327. }
  328. break;
  329. case WM_SETCURSOR:
  330. // Display the cursor if conditions are right
  331. if (g_fActive && g_fReady && !g_fPaused && !FSWindow_IsActive())
  332. {
  333. SetCursor(NULL);
  334. return TRUE;
  335. }
  336. break;
  337. }
  338. return DefWindowProc(hWnd, msg, wParam, lParam);
  339. }
  340. //-----------------------------------------------------------------------------
  341. // Name: WinMain()
  342. // Desc: Entry point to the program. Initializes everything and calls
  343. // AppIdle() when idle from the message pump.
  344. //-----------------------------------------------------------------------------
  345. int PASCAL
  346. WinMain(HINSTANCE hInstance,
  347. HINSTANCE hPrevInstance,
  348. LPSTR lpszCmdLine,
  349. int nCmdShow)
  350. {
  351. WNDCLASS wc;
  352. MSG msg;
  353. HWND hWnd;
  354. HRESULT hRet;
  355. HINSTANCE hDDrawDLL;
  356. LPDIRECTDRAWENUMERATEEX pDirectDrawEnumerateEx;
  357. DWORD dwLastTime;
  358. DWORD dwThisTime;
  359. if (!hPrevInstance)
  360. {
  361. // Register the Window Class
  362. wc.lpszClassName = NAME;
  363. wc.lpfnWndProc = MainWndProc;
  364. wc.style = CS_VREDRAW | CS_HREDRAW;
  365. wc.hInstance = hInstance;
  366. wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DCONFIG_ICON));
  367. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  368. wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  369. wc.lpszMenuName = NULL;
  370. wc.cbClsExtra = 0;
  371. wc.cbWndExtra = 0;
  372. if (!RegisterClass(&wc))
  373. return FALSE;
  374. }
  375. g_hInst = g_hInst = hInstance;
  376. // Init();
  377. // Create and Show the Main Window
  378. hWnd = CreateWindowEx(0,
  379. NAME,
  380. TITLE,
  381. WS_CLIPCHILDREN | WS_POPUP,
  382. CW_USEDEFAULT,
  383. CW_USEDEFAULT,
  384. 1024,
  385. 768,
  386. NULL,
  387. NULL,
  388. hInstance,
  389. NULL);
  390. if (hWnd == NULL)
  391. return FALSE;
  392. // You need to do a GetModuleHandle and GetProcAddress in order to get the
  393. // DirectDrawEnumerateEx function pointer
  394. hDDrawDLL = GetModuleHandle("DDRAW");
  395. if (!hDDrawDLL)
  396. return InitFail(hWnd, DD_OK, "GetModuleHandle FAILED");
  397. //Create the main DirectDraw object
  398. hRet = DirectDrawCreateEx(NULL, (VOID**)&g_pDD, IID_IDirectDraw7, NULL);
  399. if (hRet != DD_OK)
  400. return InitFail(hWnd, hRet, "DirectDrawCreateEx FAILED");
  401. //Initialize all the surfaces we need
  402. hRet = InitSurfaces(hWnd);
  403. if (FAILED(hRet))
  404. return FALSE;
  405. g_fReady = TRUE;
  406. g_hWndDlg = CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_DCONFIG_DIALOG),
  407. hWnd, (DLGPROC) DialogProc);
  408. ShowWindow(g_hWndDlg, SW_SHOWNORMAL);
  409. Sleep(1000);
  410. g_hWndHelp = FSWindow_Begin(g_hWndDlg, FALSE);
  411. // Put up the sample dialog right away, to show the sample user what this
  412. // sample is trying to demonstrate.
  413. //-------------------------------------------------------------------------
  414. // The Message Pump
  415. //-------------------------------------------------------------------------
  416. dwLastTime = 0;
  417. dwThisTime = timeGetTime();
  418. while (TRUE)
  419. {
  420. if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
  421. {
  422. if (!GetMessage(&msg, NULL, 0, 0))
  423. break;
  424. // If the dialog is showing, translate messages for it since it's
  425. // a modeless dialog.
  426. if (g_hWndDlg == (HWND )NULL || !IsDialogMessage(g_hWndDlg, &msg))
  427. {
  428. // Translate and dispatch the message
  429. TranslateMessage(&msg);
  430. DispatchMessage(&msg);
  431. }
  432. }
  433. else
  434. if (g_fActive && g_fReady && !g_fPaused)
  435. {
  436. dwThisTime = timeGetTime();
  437. // 1000/FPS = number of milliseconds to wait
  438. if ((dwThisTime - dwLastTime) >= (1000/30))
  439. {
  440. UpdateFrame();
  441. dwLastTime = timeGetTime();
  442. }
  443. }
  444. else
  445. // Make sure we go to sleep if we have nothing else to do
  446. WaitMessage();
  447. }
  448. // Release the main DDraw interface
  449. if (g_pDD)
  450. g_pDD->Release();
  451. return msg.wParam;
  452. }