home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / directx2 / sdk / samples / misc / d3dmain.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-28  |  45.6 KB  |  1,234 lines

  1. /*
  2.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  3.  *
  4.  *  File: d3dmain.cpp
  5.  *
  6.  *  Each of the Direct3D samples must be linked with this file.  It contains
  7.  *  the code which allows them to run in the Windows environment.
  8.  *
  9.  *  A window is created using d3dmain.res which allows the user to select the
  10.  *  Direct3D driver to use and change the render options.  The D3DApp
  11.  *  collection of functions is used to initialize DirectDraw, Direct3D and
  12.  *  keep surfaces and D3D devices available for rendering.
  13.  *
  14.  *  Frame rate and a screen mode information buffer is Blt'ed to the screen
  15.  *  by functions in stats.cpp.
  16.  *
  17.  *  Each sample is executed through the functions: InitScene, InitView,
  18.  *  RenderScene, ReleaseView, ReleaseScene and OverrideDefaults, as described
  19.  *  in d3ddemo.h.  Samples can also read mouse and keyboard input via
  20.  *  SetMouseCallback and SetKeyboardCallback.
  21.  */
  22.  
  23. #include "d3dmain.h"
  24.  
  25. /*
  26.  * GLOBAL VARIABLES
  27.  */
  28. D3DAppInfo* d3dapp;         /* Pointer to read only collection of DD and D3D
  29.                                objects maintained by D3DApp */
  30. d3dmainglobals myglobs;     /* collection of global variables */
  31.  
  32. BOOL(*MouseHandler)(UINT, WPARAM, LPARAM);    /* sample's function which traps
  33.                                                  mouse input */
  34. BOOL(*KeyboardHandler)(UINT, WPARAM, LPARAM); /* sample's functions which traps
  35.                                                  keyboard input */
  36.  
  37. /*
  38.  *  INTERNAL FUNCTION PROTOTYPES
  39.  */
  40. static BOOL AppInit(HINSTANCE hInstance, LPSTR lpCmdLine);
  41. static BOOL CreateD3DApp(LPSTR lpCmdLine);
  42. static BOOL BeforeDeviceDestroyed(LPVOID lpContext);
  43. static BOOL AfterDeviceCreated(int w, int h, LPDIRECT3DVIEWPORT* lpViewport,
  44.                                LPVOID lpContext);
  45. void CleanUpAndPostQuit(void);
  46. static void InitGlobals(void);
  47. static BOOL AppPause(BOOL f);
  48. void ReportD3DAppError(void);
  49. static BOOL RenderLoop(void);
  50. static BOOL RestoreSurfaces();
  51. long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam,
  52.                            LPARAM lParam );
  53.  
  54. /****************************************************************************/
  55. /*                            WinMain                                       */
  56. /****************************************************************************/
  57. /*
  58.  * Initializes the application then enters a message loop which calls sample's
  59.  * RenderScene until a quit message is received.
  60.  */
  61. int PASCAL
  62. WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
  63.         int nCmdShow)
  64. {
  65.     int failcount = 0; /* number of times RenderLoop has failed */
  66.     MSG msg;
  67.     HACCEL hAccelApp;
  68.  
  69.     hPrevInstance;
  70.     /*
  71.      * Create the window and initialize all objects needed to begin rendering
  72.      */
  73.     if(!AppInit(hInstance, lpCmdLine))
  74.         return FALSE;
  75.     hAccelApp = LoadAccelerators(hInstance, "AppAccel");    
  76.  
  77.     while (!myglobs.bQuit) {
  78.         /* 
  79.          * Monitor the message queue until there are no pressing
  80.          * messages
  81.          */
  82.         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  83.             if (msg.message == WM_QUIT) {
  84.                 CleanUpAndPostQuit();
  85.                 break;
  86.             }
  87.             if (!myglobs.hWndMain || !TranslateAccelerator(myglobs.hWndMain,
  88.                                                            hAccelApp, &msg)) {
  89.                 TranslateMessage(&msg); 
  90.                 DispatchMessage(&msg);
  91.             }
  92.         }
  93.         /* 
  94.          * If the app is not minimized, not about to quit, not paused and D3D
  95.          * has been initialized, we can render
  96.          */
  97.         if (d3dapp->bRenderingIsOK && !d3dapp->bMinimized && !d3dapp->bPaused
  98.             && !myglobs.bQuit) {
  99.             /*
  100.              * If were are not in single step mode or if we are and the
  101.              * bDrawAFrame flag is set, render one frame
  102.              */
  103.             if (!(myglobs.bSingleStepMode && !myglobs.bDrawAFrame)) {
  104.                 /* 
  105.                  * Attempt to render a frame, if it fails, take a note.  If
  106.                  * rendering fails more than twice, abort execution.
  107.                  */
  108.                 if (!RenderLoop()) {
  109.                     ++failcount;
  110.                     if (failcount == 3) {
  111.                         Msg("Rendering has failed too many times.  Aborting execution.\n");
  112.                         CleanUpAndPostQuit();
  113.                         break;
  114.                     }
  115.                 }
  116.             }
  117.             /*
  118.              * Reset the bDrawAFrame flag if we are in single step mode
  119.              */
  120.             if (myglobs.bSingleStepMode)
  121.                 myglobs.bDrawAFrame = FALSE;
  122.         }
  123.     }
  124.     return msg.wParam;
  125. }
  126.  
  127. /****************************************************************************/
  128. /*             D3DApp Initialization and callback functions                 */
  129. /****************************************************************************/
  130. /*
  131.  * AppInit
  132.  * Creates the window and initializes all objects necessary to begin rendering
  133.  */
  134. static BOOL
  135. AppInit(HINSTANCE hInstance, LPSTR lpCmdLine)
  136. {
  137.     WNDCLASS wc;
  138.  
  139.     /*
  140.      * Initialize the global variables
  141.      */
  142.     InitGlobals();
  143.     myglobs.hInstApp = hInstance;
  144.     /*
  145.      * Register the window class
  146.      */
  147.     wc.style = CS_HREDRAW | CS_VREDRAW;
  148.     wc.lpfnWndProc = WindowProc;
  149.     wc.cbClsExtra = 0;
  150.     wc.cbWndExtra = 0;
  151.     wc.hInstance = hInstance;
  152.     wc.hIcon = LoadIcon( hInstance, "AppIcon");
  153.     wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  154.     wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  155.     wc.lpszMenuName = "AppMenu";
  156.     wc.lpszClassName = "Example";
  157.     if (!RegisterClass(&wc))
  158.         return FALSE;
  159.     /*
  160.      * Create a window with some default settings that may change
  161.      */
  162.     myglobs.hWndMain = CreateWindowEx(
  163.          WS_EX_APPWINDOW,
  164.          "Example",
  165.          "D3D Example",
  166.          WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
  167.          WS_THICKFRAME | WS_MINIMIZEBOX,
  168.          CW_USEDEFAULT, CW_USEDEFAULT,
  169.          START_WIN_SIZE, START_WIN_SIZE,
  170.          NULL,                              /* parent window */
  171.          NULL,                              /* menu handle */
  172.          hInstance,                         /* program handle */
  173.          NULL);                             /* create parms */  
  174.     if (!myglobs.hWndMain){
  175.         Msg("CreateWindowEx failed");
  176.         return FALSE;
  177.     }
  178.     /*
  179.      * Display the window
  180.      */
  181.     ShowWindow(myglobs.hWndMain, SW_SHOWNORMAL);
  182.     UpdateWindow(myglobs.hWndMain);
  183.     /* 
  184.      * Have the example initialize it components which remain constant
  185.      * throughout execution
  186.      */
  187.     if (!InitScene())
  188.         return FALSE;
  189.     /*
  190.      * Call D3DApp to initialize all DD and D3D objects necessary to render.
  191.      * D3DApp will call the device creation callback which will initialize the
  192.      * viewport and the sample's execute buffers.
  193.      */
  194.     if (!CreateD3DApp(lpCmdLine))
  195.         return FALSE;
  196.  
  197.     return TRUE;
  198. }
  199.  
  200. /*
  201.  * CreateD3DApp
  202.  * Create all DirectDraw and Direct3D objects necessary to begin rendering.
  203.  * Add the list of D3D drivers to the file menu.
  204.  */
  205. static BOOL
  206. CreateD3DApp(LPSTR lpCmdLine)
  207. {
  208.     HMENU hmenu;
  209.     int i;
  210.     LPSTR option;
  211.     BOOL bOnlySystemMemory, bOnlyEmulation;
  212.     DWORD flags;
  213.     Defaults defaults;
  214.  
  215.     /*
  216.      * Give D3DApp a list of textures to keep track of.
  217.      */
  218.     D3DAppAddTexture("checker.ppm");
  219.     D3DAppAddTexture("tex2.ppm");
  220.     D3DAppAddTexture("tex7.ppm");
  221.     D3DAppAddTexture("win95.ppm");
  222.     /*
  223.      * Parse the command line in seach of one of the following options:
  224.      *     systemmemory  All surfaces should be created in system memory.
  225.      *                   Hardware DD and D3D devices are disabled, but
  226.      *                   debugging during the Win16 lock becomes possible.
  227.      *     emulation     Do not use hardware DD or D3D devices.
  228.      */
  229.     bOnlySystemMemory = FALSE;
  230.     bOnlyEmulation = FALSE;
  231.     option = strtok(lpCmdLine, " -");
  232.     while(option != NULL )   {
  233.         if (!lstrcmp(option, "systemmemory")) {
  234.             bOnlySystemMemory = TRUE;
  235.         } else if (!lstrcmp(option, "emulation")) {
  236.             bOnlyEmulation = TRUE;
  237.         } else {
  238.             Msg("Invalid command line options given.\nLegal options: -systemmemory, -emulation\n");
  239.             return FALSE;
  240.         }
  241.         option = strtok(NULL, " -");
  242.     }
  243.     /*
  244.      * Set the flags to pass to the D3DApp creation based on command line
  245.      */
  246.     flags = ((bOnlySystemMemory) ? D3DAPP_ONLYSYSTEMMEMORY : 0) | 
  247.             ((bOnlyEmulation) ? (D3DAPP_ONLYD3DEMULATION |
  248.                                  D3DAPP_ONLYDDEMULATION) : 0);
  249.     /*
  250.      * Create all the DirectDraw and D3D objects neccesary to render.  The
  251.      * AfterDeviceCreated callback function is called by D3DApp to create the
  252.      * viewport and the example's execute buffers.
  253.      */
  254.     if (!D3DAppCreateFromHWND(flags, myglobs.hWndMain, AfterDeviceCreated,
  255.                               NULL, BeforeDeviceDestroyed, NULL, &d3dapp)) {
  256.         ReportD3DAppError();
  257.         return FALSE;
  258.     }
  259.     /*
  260.      * Add the the list of display modes D3DApp found to the mode menu
  261.      */
  262.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 4);
  263.     for (i = 0; i < d3dapp->NumModes; i++) {
  264.         char ach[80];
  265.         wsprintf(ach,"%dx%dx%d", d3dapp->Mode[i].w, d3dapp->Mode[i].h,
  266.                  d3dapp->Mode[i].bpp);
  267.         AppendMenu(hmenu, MF_STRING, MENU_FIRST_MODE+i, ach);
  268.     }
  269.     /*
  270.      * Add the list of D3D drivers D3DApp foudn to the file menu
  271.      */
  272.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 0);
  273.     for (i = 0; i < d3dapp->NumDrivers; i++) {
  274.         InsertMenu(hmenu, 6 + i, MF_BYPOSITION | MF_STRING,
  275.                    MENU_FIRST_DRIVER + i, d3dapp->Driver[i].Name);
  276.     }
  277.     /*
  278.      * Allow the sample to override the default render state and other
  279.      * settings
  280.      */
  281.     if (!D3DAppGetRenderState(&defaults.rs)) {
  282.         ReportD3DAppError();
  283.         return FALSE;
  284.     }
  285.     lstrcpy(defaults.Name, "D3D Example");
  286.     defaults.bTexturesDisabled = FALSE;
  287.     defaults.bResizingDisabled = myglobs.bResizingDisabled;
  288.     defaults.bClearsOn = myglobs.bClearsOn;
  289.     OverrideDefaults(&defaults);
  290.     myglobs.bClearsOn = defaults.bClearsOn;
  291.     myglobs.bResizingDisabled = defaults.bResizingDisabled;
  292.     /*
  293.      * Apply any changes to the render state
  294.      */
  295.     memcpy(&myglobs.rstate, &defaults.rs, sizeof(D3DAppRenderState));
  296.     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  297.         ReportD3DAppError();
  298.         return FALSE;
  299.     }
  300.     /*
  301.      * If I should begin with textures off, disable them and re-create
  302.      * the view.
  303.      */
  304.     if (defaults.bTexturesDisabled) {
  305.         if (!D3DAppDisableTextures(defaults.bTexturesDisabled)) {
  306.             ReportD3DAppError();
  307.             return FALSE;
  308.         }
  309.         /*
  310.          * Release all objects (ie execute buffers) created by InitView
  311.          */
  312.         ReleaseView(d3dapp->lpD3DViewport);
  313.         /*
  314.          * Create the sample's execute buffers via InitView
  315.          */
  316.         if (!InitView(d3dapp->lpDD, d3dapp->lpD3D, d3dapp->lpD3DDevice,
  317.                       d3dapp->lpD3DViewport, d3dapp->NumTextures,
  318.                       d3dapp->TextureHandle)) {
  319.             Msg("InitView failed.\n");
  320.             CleanUpAndPostQuit();
  321.             return FALSE;
  322.         }
  323.     }
  324.  
  325.     SetWindowText(myglobs.hWndMain, defaults.Name);
  326.  
  327.     return TRUE;
  328. }
  329.  
  330. /*
  331.  * AfterDeviceCreated
  332.  * D3DApp will call this function immediately after the D3D device has been
  333.  * created (or re-created).  D3DApp expects the D3D viewport to be created and
  334.  * returned.  The sample's execute buffers are also created (or re-created)
  335.  * here.
  336.  */
  337. static BOOL
  338. AfterDeviceCreated(int w, int h, LPDIRECT3DVIEWPORT* lplpViewport, LPVOID lpContext)
  339. {
  340.     HMENU hmenu;
  341.     int i;
  342.     char ach[20];
  343.     LPDIRECT3DVIEWPORT lpD3DViewport;
  344.     HRESULT rval;
  345.  
  346.     /*
  347.      * Create the D3D viewport object
  348.      */
  349.     rval = d3dapp->lpD3D->CreateViewport(&lpD3DViewport, NULL);
  350.     if (rval != D3D_OK) {
  351.         Msg("Create D3D viewport failed.\n%s", D3DAppErrorToString(rval));
  352.         CleanUpAndPostQuit();
  353.         return FALSE;
  354.     }
  355.     /*
  356.      * Add the viewport to the D3D device
  357.      */
  358.     rval = d3dapp->lpD3DDevice->AddViewport(lpD3DViewport);
  359.     if (rval != D3D_OK) {
  360.         Msg("Add D3D viewport failed.\n%s", D3DAppErrorToString(rval));
  361.         CleanUpAndPostQuit();
  362.         return FALSE;
  363.     }
  364.     /*
  365.      * Setup the viewport for a reasonable viewing area
  366.      */
  367.     D3DVIEWPORT viewData;
  368.     memset(&viewData, 0, sizeof(D3DVIEWPORT));
  369.     viewData.dwSize = sizeof(D3DVIEWPORT);
  370.     viewData.dwX = viewData.dwY = 0;
  371.     viewData.dwWidth = w;
  372.     viewData.dwHeight = h;
  373.     viewData.dvScaleX = viewData.dwWidth / (float)2.0;
  374.     viewData.dvScaleY = viewData.dwHeight / (float)2.0;
  375.     viewData.dvMaxX = (float)D3DDivide(D3DVAL(viewData.dwWidth),
  376.                                        D3DVAL(2 * viewData.dvScaleX));
  377.     viewData.dvMaxY = (float)D3DDivide(D3DVAL(viewData.dwHeight),
  378.                                        D3DVAL(2 * viewData.dvScaleY));
  379.     rval = lpD3DViewport->SetViewport(&viewData);
  380.     if (rval != D3D_OK) {
  381.         Msg("SetViewport failed.\n%s", D3DAppErrorToString(rval));
  382.         CleanUpAndPostQuit();
  383.         return FALSE;
  384.     }
  385.     /*
  386.      * Return the viewport to D3DApp so it can use it
  387.      */
  388.     *lplpViewport = lpD3DViewport;
  389.     /*
  390.      * Create the sample's execute buffers via InitView
  391.      */
  392.     if (!InitView(d3dapp->lpDD, d3dapp->lpD3D, d3dapp->lpD3DDevice,
  393.                   lpD3DViewport, d3dapp->NumTextures,
  394.                   d3dapp->TextureHandle)) {
  395.         Msg("InitView failed.\n");
  396.         CleanUpAndPostQuit();
  397.         return FALSE;
  398.     }
  399.     /*
  400.      * Add the list of texture formats found by D3DApp to the texture menu
  401.      */
  402.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 3);
  403.     for (i = 0; i < d3dapp->NumTextureFormats; i++) {
  404.         if (d3dapp->TextureFormat[i].bPalettized) {
  405.             wsprintf(ach, "%d-bit Palettized",
  406.                      d3dapp->TextureFormat[i].IndexBPP);
  407.         } else {
  408.             wsprintf(ach, "%d%d%d RGB", d3dapp->TextureFormat[i].RedBPP,
  409.                      d3dapp->TextureFormat[i].GreenBPP,
  410.                      d3dapp->TextureFormat[i].BlueBPP);
  411.         }
  412.         AppendMenu(hmenu, MF_STRING, MENU_FIRST_FORMAT + i, ach);
  413.     }
  414.     /*
  415.      * Create and initialize the surfaces containing the frame rate and
  416.      * window information
  417.      */
  418.     InitFontAndTextBuffers();
  419.  
  420.     return TRUE;
  421. }
  422.  
  423. /*
  424.  * BeforeDeviceDestroyed
  425.  * D3DApp will call this function before the current D3D device is destroyed
  426.  * to give the app the opportunity to destroy objects it has created with the
  427.  * DD or D3D objects.
  428.  */
  429. static BOOL
  430. BeforeDeviceDestroyed(LPVOID lpContext)
  431. {
  432.     HMENU hmenu;
  433.     int i;
  434.     /*
  435.      * Release all objects (ie execute buffers) created by InitView
  436.      */
  437.     ReleaseView(d3dapp->lpD3DViewport);
  438.     /*
  439.      * Since we created the viewport it is our responsibility to release
  440.      * it.  Use D3DApp's pointer to it since we didn't save one.
  441.      */
  442.     d3dapp->lpD3DViewport->Release();
  443.     /*
  444.      * Delete the list of texture formats from the texture menu because
  445.      * they are likely to change
  446.      */
  447.     hmenu = GetSubMenu(GetMenu(myglobs.hWndMain), 3);
  448.     for (i = 0; i < d3dapp->NumTextureFormats; i++) {
  449.         DeleteMenu(hmenu, MENU_FIRST_FORMAT + i, MF_BYCOMMAND);
  450.     }
  451.     return TRUE;
  452. }
  453.  
  454. /****************************************************************************/
  455. /*                            Rendering loop                                */
  456. /****************************************************************************/
  457. /*
  458.  * RenderLoop
  459.  * Render the next frame and update the window
  460.  */
  461. static BOOL
  462. RenderLoop()
  463. {
  464.     D3DRECT extents[D3DAPP_MAXCLEARRECTS];
  465.     int count;
  466.     /*
  467.      * If all the DD and D3D objects have been initialized we can render
  468.      */
  469.     if (d3dapp->bRenderingIsOK) {
  470.         /*
  471.          * Restore any lost surfaces
  472.          */
  473.         if (!RestoreSurfaces()) {
  474.             /*
  475.              * Restoring surfaces sometimes fails because the surfaces cannot
  476.              * yet be restored.  If this is the case, the error will show up
  477.              * somewhere else and we should return success here to prevent
  478.              * unnecessary error's being reported.
  479.              */
  480.             return TRUE;
  481.         }
  482.         /*
  483.          * Calculate the frame rate
  484.          */
  485.         if (!CalculateFrameRate())
  486.             return FALSE;
  487.  
  488.         /*
  489.          * Clear the back buffer and Z buffer if enabled.  If bResized is set,
  490.          * clear the entire window.
  491.          */
  492.         if (myglobs.bClearsOn) {
  493.             if (!D3DAppClearBackBuffer(myglobs.bResized ?
  494.                                        D3DAPP_CLEARALL : NULL)) {
  495.                 ReportD3DAppError();
  496.                 return FALSE;
  497.             }
  498.         }
  499.         /*
  500.          * Call the sample's RenderScene to render this frame
  501.          */
  502.         {
  503.             if (!RenderScene(d3dapp->lpD3DDevice, d3dapp->lpD3DViewport,
  504.                              &extents[0])) {
  505.                 Msg("RenderScene failed.\n");
  506.                 return FALSE;
  507.             }
  508.             count = 1;
  509.         }
  510.         /*
  511.          * Blt the frame rate and window stat text to the back buffer
  512.          */
  513.         if (!DisplayFrameRate(&count, &extents[1]))
  514.             return FALSE;
  515.         /*
  516.          * Give D3DApp the extents so it can keep track of dirty sections of
  517.          * the back and front buffers
  518.          */
  519.         if (!D3DAppRenderExtents(count, extents, myglobs.bResized ?
  520.                                  D3DAPP_CLEARALL : NULL)) {
  521.             ReportD3DAppError();
  522.             return FALSE;
  523.         }
  524.         /*
  525.          * Blt or flip the back buffer to the front buffer.  Don't report an
  526.          * error if this fails.
  527.          */
  528.         D3DAppShowBackBuffer(myglobs.bResized ? D3DAPP_SHOWALL : NULL);
  529.  
  530.         /*
  531.          * Reset the resize flag
  532.          */
  533.         myglobs.bResized = FALSE;
  534.     }
  535.     return TRUE;
  536. }
  537.  
  538. /*
  539.  * AppPause
  540.  * Pause and unpause the application
  541.  */
  542. static BOOL
  543. AppPause(BOOL f)
  544. {
  545.     /*
  546.      * Flip to the GDI surface and halt rendering
  547.      */
  548.     if (!D3DAppPause(f))
  549.         return FALSE;
  550.     /*
  551.      * When returning from a pause, reset the frame rate count
  552.      */
  553.     if (!f) {
  554.         ResetFrameRate();
  555.     }
  556.     return TRUE;
  557. }
  558.  
  559. /*
  560.  * RestoreSurfaces
  561.  * Restores any lost surfaces.  Returns TRUE if all surfaces are not lost and
  562.  * FALSE if one or more surfaces is lost and can not be restored at the
  563.  * moment.
  564.  */
  565. static BOOL
  566. RestoreSurfaces()
  567. {
  568.     HRESULT d3drval;
  569.  
  570.     /*
  571.      * Have D3DApp check all the surfaces it's in charge of
  572.      */
  573.     if (!D3DAppCheckForLostSurfaces()) {
  574.             return FALSE;
  575.     }
  576.     /*
  577.      * Check frame rate and info surfaces and re-write them if they
  578.      * were lost.
  579.      */
  580.     if (myglobs.lpFrameRateBuffer->IsLost() == DDERR_SURFACELOST) {
  581.         d3drval = myglobs.lpFrameRateBuffer->Restore();
  582.         if (d3drval != DD_OK) {
  583.             return FALSE;
  584.         }
  585.         if (!WriteFrameRateBuffer(0.0f, 0))
  586.             return FALSE;
  587.     }
  588.     if (myglobs.lpInfoBuffer->IsLost() == DDERR_SURFACELOST) {
  589.         d3drval = myglobs.lpInfoBuffer->Restore();
  590.         if (d3drval != DD_OK) {
  591.             return FALSE;
  592.         }
  593.         if (!WriteInfoBuffer())
  594.             return FALSE;
  595.     }
  596.     return TRUE;
  597. }
  598.  
  599.  
  600. /*************************************************************************
  601.   Windows message handlers
  602.  *************************************************************************/
  603. /*
  604.  * AppAbout
  605.  * About box message handler
  606.  */
  607. BOOL
  608. FAR PASCAL AppAbout(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  609. {
  610.   switch (msg)
  611.   {
  612.     case WM_COMMAND:
  613.       if (LOWORD(wParam) == IDOK)
  614.         EndDialog(hwnd, TRUE);
  615.       break;
  616.  
  617.     case WM_INITDIALOG:
  618.       return TRUE;
  619.   }
  620.   return FALSE;
  621. }
  622.  
  623. /*
  624.  * WindowProc
  625.  * Main window message handler.
  626.  */
  627. long
  628. FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam,
  629.                            LPARAM lParam )
  630. {
  631.     int i;
  632.     BOOL bStop;
  633.     LRESULT lresult;
  634.  
  635.     /*
  636.      * Give D3DApp an opportunity to process any messages it MUST see in order
  637.      * to perform it's function.
  638.      */
  639.     if (!D3DAppWindowProc(&bStop, &lresult, hWnd, message, wParam, lParam)) {
  640.         ReportD3DAppError();
  641.         CleanUpAndPostQuit();
  642.         return 0;
  643.     }
  644.  
  645.     /*
  646.      * Prevent resizing through this message
  647.      */
  648.     if (message == WM_GETMINMAXINFO && myglobs.bResizingDisabled && !d3dapp->bFullscreen && !d3dapp->bMinimized) {
  649.         RECT rc;
  650.         GetWindowRect(hWnd, &rc);
  651.         ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = START_WIN_SIZE;
  652.         ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = START_WIN_SIZE;
  653.         ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = START_WIN_SIZE;
  654.         ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = START_WIN_SIZE;
  655.         return 0;
  656.     }
  657.  
  658.     /* 
  659.      * If bStop is set by D3DApp, the app should not process the message but
  660.      * return lresult.
  661.      */
  662.     if (bStop)
  663.         return lresult;
  664.  
  665.     switch( message ) {
  666.         case WM_MOUSEMOVE:
  667.         case WM_LBUTTONDOWN:
  668.         case WM_LBUTTONUP:
  669.         case WM_RBUTTONDOWN:
  670.         case WM_RBUTTONUP:
  671.         case WM_MBUTTONDOWN:
  672.         case WM_MBUTTONUP:
  673.             /*
  674.              * Call the sample's MouseHandler if available
  675.              */
  676.             if (!MouseHandler)
  677.                 break;
  678.             if ((MouseHandler)(message, wParam, lParam))
  679.                 return 1;
  680.             break;
  681.         case WM_KEYDOWN:
  682.             /*
  683.              * Call the sample's keyboard handler if available
  684.              */
  685.             if (!KeyboardHandler)
  686.                 break;
  687.             if ((KeyboardHandler)(message, wParam, lParam))
  688.                 return 1;
  689.             break;
  690.         /*
  691.          * Pause and unpause the app when entering/leaving the menu
  692.          */
  693.         case WM_ENTERMENULOOP:
  694.             AppPause(TRUE);
  695.             break;
  696.         case WM_EXITMENULOOP:
  697.             AppPause(FALSE);
  698.             break;
  699.         case WM_DESTROY:
  700.             myglobs.hWndMain = NULL;
  701.             CleanUpAndPostQuit();
  702.             break;
  703.         case WM_INITMENUPOPUP:
  704.             /*
  705.              * Check and enable the appropriate menu items
  706.              */
  707.             if (d3dapp->ThisDriver.bDoesZBuffer) {
  708.                 EnableMenuItem((HMENU)wParam, MENU_ZBUFFER, MF_ENABLED);
  709.                 CheckMenuItem((HMENU)wParam, MENU_ZBUFFER, myglobs.rstate.bZBufferOn ? MF_CHECKED : MF_UNCHECKED);
  710.             } else {
  711.                 EnableMenuItem((HMENU)wParam, MENU_ZBUFFER, MF_GRAYED);
  712.                 CheckMenuItem((HMENU)wParam, MENU_ZBUFFER, MF_UNCHECKED);
  713.             }
  714.             CheckMenuItem((HMENU)wParam, MENU_STEP, (myglobs.bSingleStepMode) ? MF_CHECKED : MF_UNCHECKED);
  715.             EnableMenuItem((HMENU)wParam, MENU_GO, (myglobs.bSingleStepMode) ? MF_ENABLED : MF_GRAYED);
  716.             CheckMenuItem((HMENU)wParam, MENU_FLAT, (myglobs.rstate.ShadeMode == D3DSHADE_FLAT) ? MF_CHECKED : MF_UNCHECKED);
  717.             CheckMenuItem((HMENU)wParam, MENU_GOURAUD, (myglobs.rstate.ShadeMode == D3DSHADE_GOURAUD) ? MF_CHECKED : MF_UNCHECKED);
  718.             CheckMenuItem((HMENU)wParam, MENU_PHONG, (myglobs.rstate.ShadeMode == D3DSHADE_PHONG) ? MF_CHECKED : MF_UNCHECKED);
  719.             EnableMenuItem((HMENU)wParam, MENU_PHONG, MF_GRAYED);
  720.             CheckMenuItem((HMENU)wParam, MENU_CLEARS, myglobs.bClearsOn ? MF_CHECKED : MF_UNCHECKED);
  721.             CheckMenuItem((HMENU)wParam, MENU_POINT, (myglobs.rstate.FillMode == D3DFILL_POINT) ? MF_CHECKED : MF_UNCHECKED);
  722.             CheckMenuItem((HMENU)wParam, MENU_WIREFRAME, (myglobs.rstate.FillMode == D3DFILL_WIREFRAME) ? MF_CHECKED : MF_UNCHECKED);
  723.             CheckMenuItem((HMENU)wParam, MENU_SOLID, (myglobs.rstate.FillMode == D3DFILL_SOLID) ? MF_CHECKED : MF_UNCHECKED);
  724.             CheckMenuItem((HMENU)wParam, MENU_DITHERING, myglobs.rstate.bDithering ? MF_CHECKED : MF_UNCHECKED);
  725.             CheckMenuItem((HMENU)wParam, MENU_SPECULAR, myglobs.rstate.bSpecular ? MF_CHECKED : MF_UNCHECKED);
  726.             EnableMenuItem((HMENU)wParam, MENU_SPECULAR, MF_ENABLED);
  727.             CheckMenuItem((HMENU)wParam, MENU_FOG, myglobs.rstate.bFogEnabled ? MF_CHECKED : MF_UNCHECKED);
  728.             CheckMenuItem((HMENU)wParam, MENU_ANTIALIAS, myglobs.rstate.bAntialiasing ? MF_CHECKED : MF_UNCHECKED);
  729.             if (d3dapp->ThisDriver.bDoesTextures) {
  730.                 CheckMenuItem((HMENU)wParam, MENU_TEXTURE_TOGGLE, (!d3dapp->bTexturesDisabled) ? MF_CHECKED : MF_UNCHECKED);
  731.                 EnableMenuItem((HMENU)wParam, MENU_TEXTURE_TOGGLE, MF_ENABLED);
  732.                 EnableMenuItem((HMENU)wParam, MENU_TEXTURE_SWAP, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  733.                 CheckMenuItem((HMENU)wParam, MENU_PERSPCORRECT, myglobs.rstate.bPerspCorrect ? MF_CHECKED : MF_UNCHECKED);
  734.                 EnableMenuItem((HMENU)wParam, MENU_PERSPCORRECT, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  735.                 CheckMenuItem((HMENU)wParam, MENU_POINT_FILTER, (myglobs.rstate.TextureFilter == D3DFILTER_NEAREST) ? MF_CHECKED : MF_UNCHECKED);
  736.                 EnableMenuItem((HMENU)wParam, MENU_POINT_FILTER, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  737.                 CheckMenuItem((HMENU)wParam, MENU_LINEAR_FILTER, (myglobs.rstate.TextureFilter == D3DFILTER_LINEAR) ? MF_CHECKED : MF_UNCHECKED);
  738.                 EnableMenuItem((HMENU)wParam, MENU_LINEAR_FILTER, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  739.                 for (i = 0; i < d3dapp->NumTextureFormats; i++) {
  740.                     CheckMenuItem((HMENU)wParam, MENU_FIRST_FORMAT + i, (i == d3dapp->CurrTextureFormat) ? MF_CHECKED : MF_UNCHECKED);
  741.                     EnableMenuItem((HMENU)wParam, MENU_FIRST_FORMAT + i, (d3dapp->bTexturesDisabled) ? MF_GRAYED : MF_ENABLED);
  742.                 }
  743.             } else {
  744.                 EnableMenuItem((HMENU)wParam, MENU_TEXTURE_SWAP, MF_GRAYED);
  745.                 EnableMenuItem((HMENU)wParam, MENU_TEXTURE_TOGGLE, MF_GRAYED);
  746.                 EnableMenuItem((HMENU)wParam, MENU_POINT_FILTER, MF_GRAYED);
  747.                 EnableMenuItem((HMENU)wParam, MENU_LINEAR_FILTER, MF_GRAYED);
  748.                 EnableMenuItem((HMENU)wParam, MENU_PERSPCORRECT, MF_GRAYED);
  749.             }
  750.             if (d3dapp->bIsPrimary) {
  751.                 CheckMenuItem((HMENU)wParam, MENU_FULLSCREEN, d3dapp->bFullscreen ? MF_CHECKED : MF_UNCHECKED);
  752.                 EnableMenuItem((HMENU)wParam, MENU_FULLSCREEN, d3dapp->bFullscreen && !d3dapp->ThisDriver.bCanDoWindow ? MF_GRAYED : MF_ENABLED);
  753.                 EnableMenuItem((HMENU)wParam, MENU_NEXT_MODE, (!d3dapp->bFullscreen) ? MF_GRAYED : MF_ENABLED);
  754.                 EnableMenuItem((HMENU)wParam, MENU_PREVIOUS_MODE, (!d3dapp->bFullscreen) ? MF_GRAYED : MF_ENABLED);
  755.             } else {
  756.                 EnableMenuItem((HMENU)wParam, MENU_FULLSCREEN, MF_GRAYED);
  757.                 EnableMenuItem((HMENU)wParam, MENU_NEXT_MODE, MF_GRAYED);
  758.                 EnableMenuItem((HMENU)wParam, MENU_PREVIOUS_MODE, MF_GRAYED);
  759.             }
  760.             for (i = 0; i < d3dapp->NumModes; i++) {
  761.                 CheckMenuItem((HMENU)wParam, MENU_FIRST_MODE + i, (i == d3dapp->CurrMode) ? MF_CHECKED : MF_UNCHECKED);
  762.                 EnableMenuItem((HMENU)wParam, MENU_FIRST_MODE + i, (d3dapp->Mode[i].bThisDriverCanDo) ? MF_ENABLED : MF_GRAYED);
  763.             }
  764.             for (i = 0; i < d3dapp->NumDrivers; i++) {
  765.                 CheckMenuItem((HMENU)wParam, MENU_FIRST_DRIVER + i, (i == d3dapp->CurrDriver) ? MF_CHECKED : MF_UNCHECKED);
  766.             }
  767.             break;
  768.         case WM_GETMINMAXINFO:
  769.             /*
  770.              * Some samples don't like being resized, such as those which use
  771.              * screen coordinates (TLVERTEXs).
  772.              */
  773.             if (myglobs.bResizingDisabled) {
  774.                 ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = START_WIN_SIZE;
  775.                 ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = START_WIN_SIZE;
  776.                 ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = START_WIN_SIZE;
  777.                 ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = START_WIN_SIZE;
  778.                 return 0;
  779.             }
  780.             break;
  781.         case WM_COMMAND:
  782.             switch(LOWORD(wParam)) {
  783.                 case MENU_ABOUT:
  784.                     AppPause(TRUE);
  785.                     DialogBox(myglobs.hInstApp, "AppAbout", myglobs.hWndMain, (DLGPROC)AppAbout);
  786.                     AppPause(FALSE);
  787.                     break;
  788.                 case MENU_EXIT:
  789.                     CleanUpAndPostQuit();
  790.                     break;
  791.                 case MENU_STEP:
  792.                     /*
  793.                      * Begin single step more or draw a frame if in single
  794.                      * step mode
  795.                      */
  796.                     if (!myglobs.bSingleStepMode) {
  797.                         myglobs.bSingleStepMode = TRUE;
  798.                         myglobs.bDrawAFrame = TRUE;
  799.                     } else if (!myglobs.bDrawAFrame) {
  800.                         myglobs.bDrawAFrame = TRUE;
  801.                     }
  802.                     break;
  803.                 case MENU_GO:
  804.                     /*
  805.                      * Exit single step mode
  806.                      */
  807.                     if (myglobs.bSingleStepMode) {
  808.                         myglobs.bSingleStepMode = FALSE;
  809.                         ResetFrameRate();
  810.                     }
  811.                     break;
  812.                 case MENU_STATS:
  813.                     /*
  814.                      * Toggle output of frame rate and window info
  815.                      */
  816.                     if ((myglobs.bShowFrameRate) && (myglobs.bShowInfo)) {
  817.                         myglobs.bShowFrameRate = FALSE;
  818.                         myglobs.bShowInfo = FALSE;
  819.                         break;
  820.                     }
  821.                     if ((!myglobs.bShowFrameRate) && (!myglobs.bShowInfo)) {
  822.                         myglobs.bShowFrameRate = TRUE;
  823.                         break;
  824.                     }
  825.                     myglobs.bShowInfo = TRUE;
  826.                     break;
  827.                 case MENU_FULLSCREEN:
  828.                     if (d3dapp->bFullscreen) {
  829.                         /*
  830.                          * Return to a windowed mode.  Let D3DApp decide which
  831.                          * D3D driver to use in case this one cannot render to
  832.                          * the Windows display depth
  833.                          */
  834.                         if (!D3DAppWindow(D3DAPP_YOUDECIDE, D3DAPP_YOUDECIDE)) {
  835.                             ReportD3DAppError();
  836.                             CleanUpAndPostQuit();
  837.                             break;
  838.                         }
  839.                     } else {
  840.                         /*
  841.                          * Enter the current fullscreen mode.  D3DApp may
  842.                          * resort to another mode if this driver cannot do
  843.                          * the currently selected mode.
  844.                          */
  845.                         if (!D3DAppFullscreen(d3dapp->CurrMode)) {
  846.                             ReportD3DAppError();
  847.                             CleanUpAndPostQuit();
  848.                             break;
  849.                         }
  850.                     }
  851.                     break;
  852.                 /*
  853.                  * Texture filter method selection
  854.                  */
  855.                 case MENU_POINT_FILTER:
  856.                     if (myglobs.rstate.TextureFilter == D3DFILTER_NEAREST)
  857.                         break;
  858.                     myglobs.rstate.TextureFilter = D3DFILTER_NEAREST;
  859.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  860.                         ReportD3DAppError();
  861.                         break;
  862.                     }
  863.                     break;
  864.                 case MENU_LINEAR_FILTER:
  865.                     if (myglobs.rstate.TextureFilter == D3DFILTER_LINEAR)
  866.                         break;
  867.                     myglobs.rstate.TextureFilter = D3DFILTER_LINEAR;
  868.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  869.                         ReportD3DAppError();
  870.                         break;
  871.                     }
  872.                     break;
  873.                 /* 
  874.                  * Shading selection
  875.                  */
  876.                 case MENU_FLAT:
  877.                     if (myglobs.rstate.ShadeMode == D3DSHADE_FLAT)
  878.                         break;
  879.                     myglobs.rstate.ShadeMode = D3DSHADE_FLAT;
  880.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  881.                         ReportD3DAppError();
  882.                         break;
  883.                     }
  884.                     break;
  885.                 case MENU_GOURAUD:
  886.                     if (myglobs.rstate.ShadeMode == D3DSHADE_GOURAUD)
  887.                         break;
  888.                     myglobs.rstate.ShadeMode = D3DSHADE_GOURAUD;
  889.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  890.                         ReportD3DAppError();
  891.                         break;
  892.                     }
  893.                     break;
  894.                 case MENU_PHONG:
  895.                     if (myglobs.rstate.ShadeMode == D3DSHADE_PHONG)
  896.                         break;
  897.                     myglobs.rstate.ShadeMode = D3DSHADE_PHONG;
  898.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  899.                         ReportD3DAppError();
  900.                         break;
  901.                     }
  902.                     break;
  903.                 /*
  904.                  * Fill mode selection
  905.                  */
  906.                 case MENU_POINT:
  907.                     if (myglobs.rstate.FillMode == D3DFILL_POINT)
  908.                         break;
  909.                     myglobs.rstate.FillMode = D3DFILL_POINT;
  910.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  911.                         ReportD3DAppError();
  912.                         break;
  913.                     }
  914.                     break;
  915.                 case MENU_WIREFRAME:
  916.                     if (myglobs.rstate.FillMode == D3DFILL_WIREFRAME)
  917.                         break;
  918.                     myglobs.rstate.FillMode = D3DFILL_WIREFRAME;
  919.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  920.                         ReportD3DAppError();
  921.                         break;
  922.                     }
  923.                     break;
  924.                 case MENU_SOLID:
  925.                     if (myglobs.rstate.FillMode == D3DFILL_SOLID)
  926.                         break;
  927.                     myglobs.rstate.FillMode = D3DFILL_SOLID;
  928.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  929.                         ReportD3DAppError();
  930.                         break;
  931.                     }
  932.                     break;
  933.                 case MENU_PERSPCORRECT:
  934.                     /*
  935.                      * Toggle perspective correction
  936.                      */
  937.                     myglobs.rstate.bPerspCorrect =
  938.                         !myglobs.rstate.bPerspCorrect;
  939.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  940.                         ReportD3DAppError();
  941.                         break;
  942.                     }
  943.                     break;
  944.                 case MENU_CLEARS:
  945.                     /*
  946.                      * Toggle the clearing the the back buffer and Z-buffer
  947.                      * and set the resized flag to clear the entire window
  948.                      */
  949.                     myglobs.bClearsOn = !myglobs.bClearsOn;
  950.                     if (myglobs.bClearsOn)
  951.                         myglobs.bResized = TRUE;
  952.                     break;
  953.                 case MENU_ZBUFFER:
  954.                     /*
  955.                      * Toggle the use of a Z-buffer
  956.                      */
  957.                     myglobs.rstate.bZBufferOn = !myglobs.rstate.bZBufferOn;
  958.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  959.                         ReportD3DAppError();
  960.                         break;
  961.                     }
  962.                     break;
  963.                 case MENU_DITHERING:
  964.                     /*
  965.                      * Toggle dithering
  966.                      */
  967.                     myglobs.rstate.bDithering = !myglobs.rstate.bDithering;
  968.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  969.                         ReportD3DAppError();
  970.                         break;
  971.                     }
  972.                     break;
  973.                 case MENU_SPECULAR:
  974.                     /*
  975.                      * Toggle specular highlights
  976.                      */
  977.                     myglobs.rstate.bSpecular = !myglobs.rstate.bSpecular;
  978.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  979.                         ReportD3DAppError();
  980.                         break;
  981.                     }
  982.                     break;
  983.                 case MENU_FOG:
  984.                     /*
  985.                      * Toggle fog
  986.                      */
  987.                     myglobs.rstate.bFogEnabled = !myglobs.rstate.bFogEnabled;
  988.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  989.                         ReportD3DAppError();
  990.                         break;
  991.                     }
  992.                     break;
  993.                 case MENU_ANTIALIAS:
  994.                     /*
  995.                      * Toggle anti-aliasing
  996.                      */
  997.                     myglobs.rstate.bAntialiasing =
  998.                         !myglobs.rstate.bAntialiasing;
  999.                     if (!D3DAppSetRenderState(&myglobs.rstate)) {
  1000.                         ReportD3DAppError();
  1001.                         break;
  1002.                     }
  1003.                     break;
  1004.                 case MENU_TEXTURE_TOGGLE:
  1005.                     /*
  1006.                      * Release the sample's execute buffers, toggle the
  1007.                      * texture disabled state and recreate them.
  1008.                      */
  1009.                     ReleaseView(d3dapp->lpD3DViewport);
  1010.                     D3DAppDisableTextures(!d3dapp->bTexturesDisabled);
  1011.                     {
  1012.                         if (!InitView(d3dapp->lpDD, d3dapp->lpD3D,
  1013.                                       d3dapp->lpD3DDevice,
  1014.                                       d3dapp->lpD3DViewport,
  1015.                                       d3dapp->NumTextures,
  1016.                                       d3dapp->TextureHandle)) {
  1017.                             Msg("InitView failed.\n");
  1018.                             CleanUpAndPostQuit();
  1019.                             break;
  1020.                         }
  1021.                     }
  1022.                     myglobs.bResized = TRUE;
  1023.                     break;
  1024.                 case MENU_TEXTURE_SWAP:
  1025.                     /*
  1026.                      * Swap textures using the load command
  1027.                      */
  1028.                     if (!D3DAppSwapTextures()) {
  1029.                         ReportD3DAppError();
  1030.                         break;
  1031.                     }
  1032.                     /*
  1033.                      * Just in case we have a texture background
  1034.                      */
  1035.                     myglobs.bResized = TRUE;
  1036.                     break;
  1037.                 case MENU_NEXT_MODE:
  1038.                     /*
  1039.                      * Enter the next usable fullscreen mode
  1040.                      */
  1041.                     i = d3dapp->CurrMode;
  1042.                     do {
  1043.                         ++i;
  1044.                         if (i >= d3dapp->NumModes)
  1045.                             i = 0;
  1046.                         if (!d3dapp->Mode[i].bThisDriverCanDo)
  1047.                             continue;
  1048.                         else {
  1049.                             if (!D3DAppFullscreen(i)) {
  1050.                                 ReportD3DAppError();
  1051.                                 CleanUpAndPostQuit();
  1052.                             }
  1053.                             break;
  1054.                         }
  1055.                     } while(i != d3dapp->CurrMode);
  1056.                     break;
  1057.                 case MENU_PREVIOUS_MODE:
  1058.                     /*
  1059.                      * Enter the previous usable fullscreen mode
  1060.                      */
  1061.                     i = d3dapp->CurrMode;
  1062.                     do {
  1063.                         --i;
  1064.                         if (i < 0)
  1065.                             i = d3dapp->NumModes - 1;
  1066.                         if (!d3dapp->Mode[i].bThisDriverCanDo)
  1067.                             continue;
  1068.                         else {
  1069.                             if (!D3DAppFullscreen(i)) {
  1070.                                 ReportD3DAppError();
  1071.                                 CleanUpAndPostQuit();
  1072.                             }
  1073.                             break;
  1074.                         }
  1075.                     } while(i != d3dapp->CurrMode);
  1076.                     break;
  1077.             }
  1078.             if (   LOWORD(wParam) >= MENU_FIRST_FORMAT
  1079.                 && LOWORD(wParam) < MENU_FIRST_FORMAT +
  1080.                     D3DAPP_MAXTEXTUREFORMATS
  1081.                 && d3dapp->CurrTextureFormat !=
  1082.                     LOWORD(wParam) - MENU_FIRST_FORMAT) {
  1083.                 /*
  1084.                  * Release the sample's execute buffers, change the texture
  1085.                  * format and recreate the view.
  1086.                  */
  1087.                 ReleaseView(d3dapp->lpD3DViewport);
  1088.                 if (!D3DAppChangeTextureFormat(LOWORD(wParam) -
  1089.                                                MENU_FIRST_FORMAT)) {
  1090.                     ReportD3DAppError();
  1091.                     CleanUpAndPostQuit();
  1092.                 }
  1093.                 {
  1094.                     if (!InitView(d3dapp->lpDD, d3dapp->lpD3D,
  1095.                                   d3dapp->lpD3DDevice, d3dapp->lpD3DViewport,
  1096.                                   d3dapp->NumTextures,
  1097.                                   d3dapp->TextureHandle)) {
  1098.                         Msg("InitView failed.\n");
  1099.                         CleanUpAndPostQuit();
  1100.                         break;
  1101.                     }
  1102.                 }
  1103.                 ResetFrameRate();
  1104.             }
  1105.             if (   LOWORD(wParam) >= MENU_FIRST_DRIVER
  1106.                 && LOWORD(wParam) < MENU_FIRST_DRIVER + D3DAPP_MAXD3DDRIVERS
  1107.                 && d3dapp->CurrDriver != LOWORD(wParam) - MENU_FIRST_DRIVER) {
  1108.                 /*
  1109.                  * Change the D3D driver
  1110.                  */
  1111.                 if (!D3DAppChangeDriver(LOWORD(wParam) - MENU_FIRST_DRIVER,
  1112.                                         NULL)) {
  1113.                     ReportD3DAppError();
  1114.                     CleanUpAndPostQuit();
  1115.                 }
  1116.             }
  1117.             if (   LOWORD(wParam) >= MENU_FIRST_MODE
  1118.                 && LOWORD(wParam) < MENU_FIRST_MODE+100) {
  1119.                 /*
  1120.                  * Switch to the selected fullscreen mode
  1121.                  */
  1122.                 if (!D3DAppFullscreen(LOWORD(wParam) - MENU_FIRST_MODE)) {
  1123.                     ReportD3DAppError();
  1124.                     CleanUpAndPostQuit();
  1125.                 }
  1126.             }
  1127.             /*
  1128.              * Whenever we receive a command in single step mode, draw a frame
  1129.              */
  1130.             if (myglobs.bSingleStepMode)
  1131.                 myglobs.bDrawAFrame = TRUE;
  1132.             return 0L;
  1133.     }
  1134.     return DefWindowProc(hWnd, message, wParam, lParam);
  1135. }
  1136.  
  1137.  
  1138. /****************************************************************************/
  1139. /*                 Setting up callbacks for examples                        */
  1140. /****************************************************************************/
  1141.  /*
  1142.   * SetMouseCallback
  1143.   * Called in an example to set a callback function for all WM messages
  1144.   * dealing with the mouse.  The handler should return whether or not
  1145.   * it handled the message.
  1146.   */
  1147. BOOL
  1148. SetMouseCallback(BOOL(*Handler)(UINT, WPARAM, LPARAM))
  1149. {
  1150.     MouseHandler = Handler;
  1151.     return TRUE;
  1152. }
  1153.  
  1154. /*
  1155.  * SetKeyboardCallback
  1156.  * Called in an example to set a callback function for all WM messages
  1157.  * dealing with the keyboard. The handler should return whether or not it
  1158.  * handled the message.
  1159.  */
  1160. BOOL
  1161. SetKeyboardCallback(BOOL(*Handler)(UINT, WPARAM, LPARAM)) {
  1162.     
  1163.     KeyboardHandler = Handler;
  1164.     return TRUE;
  1165. }
  1166.  
  1167. /****************************************************************************/
  1168. /*          Initialization, error reporting and release functions.          */
  1169. /****************************************************************************/
  1170. /*
  1171.  * InitGlobals
  1172.  * Called once at program initialization to initialize global variables.
  1173.  */
  1174. static void
  1175. InitGlobals(void)
  1176. {
  1177.     d3dapp = NULL;
  1178.     memset(&myglobs.rstate, 0, sizeof(myglobs.rstate));
  1179.     memset(&myglobs, 0, sizeof(myglobs));
  1180.     myglobs.bClearsOn = TRUE;
  1181.     myglobs.bShowFrameRate = TRUE;
  1182.     myglobs.bShowInfo = TRUE;
  1183.     MouseHandler = NULL;
  1184.     KeyboardHandler = NULL;
  1185. }
  1186.  
  1187. /*
  1188.  * CleanUpAndPostQuit
  1189.  * Release all D3D objects, post a quit message and set the bQuit flag
  1190.  */
  1191. void
  1192. CleanUpAndPostQuit(void)
  1193. {
  1194.     if (myglobs.bQuit)
  1195.         return;
  1196.     if (!D3DAppDestroy())
  1197.         ReportD3DAppError();
  1198.     ReleaseScene();
  1199.     myglobs.bQuit = TRUE;
  1200.     PostQuitMessage( 0 );
  1201. }
  1202.  
  1203. /*
  1204.  * ReportD3DAppError
  1205.  * Reports an error during a d3d app call.
  1206.  */
  1207. void
  1208. ReportD3DAppError(void)
  1209. {
  1210.     Msg("%s", D3DAppLastErrorString());
  1211. }
  1212.  
  1213. /* Msg
  1214.  * Message output for error notification.
  1215.  */
  1216. void __cdecl
  1217. Msg( LPSTR fmt, ... )
  1218. {
  1219.     char buff[256];
  1220.  
  1221.     wvsprintf(buff, fmt, (char *)(&fmt+1));
  1222.     lstrcat(buff, "\r\n");
  1223.     AppPause(TRUE);
  1224.     if (d3dapp && d3dapp->bFullscreen)
  1225.         SetWindowPos(myglobs.hWndMain, HWND_NOTOPMOST, 0, 0, 0, 0,
  1226.                      SWP_NOSIZE | SWP_NOMOVE);
  1227.     MessageBox( NULL, buff, "D3D Example Message", MB_OK );
  1228.     if (d3dapp && d3dapp->bFullscreen)
  1229.         SetWindowPos(myglobs.hWndMain, HWND_TOPMOST, 0, 0, 0, 0,
  1230.                      SWP_NOSIZE | SWP_NOMOVE);
  1231.     AppPause(FALSE);
  1232. }
  1233.  
  1234.