home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / boids / winproc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-15  |  46.0 KB  |  1,846 lines

  1. /*
  2. **-----------------------------------------------------------------------------
  3. **  File:       WinProc.cpp
  4. **  Purpose:    A sample windows proc for supporting D3D.
  5. **  Notes:
  6. **
  7. **  Copyright (c) 1995 - 1997 by Microsoft, all rights reserved.
  8. **-----------------------------------------------------------------------------
  9. */
  10.  
  11. /*
  12. **-----------------------------------------------------------------------------
  13. **    Include Files
  14. **-----------------------------------------------------------------------------
  15. */
  16.  
  17. #include "WinProc.h"
  18. #include "WinMain.h"
  19. #include "Debug.h"
  20.  
  21. /*
  22. **-----------------------------------------------------------------------------
  23. **    Local Typedefs
  24. **-----------------------------------------------------------------------------
  25. */
  26.  
  27. typedef struct tagChangeDDInfo {
  28.     DDDrvInfo  * lpDrvOrig;            // Original Driver
  29.     DDDrvInfo  * lpDrvNew;            // New Driver (user choice)
  30.     
  31.     D3DDevInfo * lpDevOrig;            // Original D3D device
  32.     D3DDevInfo * lpDevNew;            // New D3D device (user choice)
  33.  
  34.     DDModeInfo * lpModeOrig;        // Orignal Mode
  35.     DDModeInfo * lpModeNew;            // New Mode (user choice)
  36. } ChangeDDInfo;
  37. typedef ChangeDDInfo * LPChangeDDInfo;
  38.  
  39.  
  40. /*
  41. **-----------------------------------------------------------------------------
  42. **    Local Variables
  43. **-----------------------------------------------------------------------------
  44. */
  45.  
  46. BOOL g_fMinimized = FALSE;
  47. BOOL g_fMaximized = FALSE;
  48.  
  49.  
  50.  
  51. /*
  52. **-----------------------------------------------------------------------------
  53. **    Local function prototypes
  54. **-----------------------------------------------------------------------------
  55. */
  56.  
  57. // About Message proc
  58. BOOL FAR PASCAL AboutBoxProc (HWND hWnd, UINT uiMsg,
  59.                               WPARAM wParam, LPARAM lParam);
  60.  
  61. // Change Dialog
  62. BOOL DlgDriversInit (HWND hDlg);
  63. BOOL DlgDevicesInit (HWND hDlg);
  64. BOOL DlgModesInit (HWND hDlg);
  65.  
  66. int _cdecl CompareModes (const void* element1, const void* element2);
  67.  
  68. LPDDDrvInfo  DlgGetDriver (HWND hDlg);
  69. LPD3DDevInfo DlgGetDevice (HWND hDlg);
  70. LPDDModeInfo DlgGetMode (HWND hDlg);
  71.  
  72. BOOL FAR PASCAL ChangeDriverProc (HWND hWnd, UINT uiMsg,
  73.                                   WPARAM wParam, LPARAM lParam);
  74. void OnChangeDriver (HWND hWindow, int idDialog);
  75.  
  76.  
  77.  
  78. /*
  79. **-----------------------------------------------------------------------------
  80. **    Functions
  81. **-----------------------------------------------------------------------------
  82. */
  83.  
  84. /*
  85. **-----------------------------------------------------------------------------
  86. **  Name:       D3DWindowProc
  87. **  Purpose:    handles windows messages for D3DWindow's
  88. **-----------------------------------------------------------------------------
  89. */
  90.  
  91. LRESULT CALLBACK D3DWindowProc (
  92.     HWND    hWindow,
  93.     UINT    uiMsg,
  94.     WPARAM  wParam,
  95.     LPARAM  lParam)
  96. {
  97.     LONG lResult;
  98.  
  99.     //
  100.     // Windows messages
  101.     //
  102.     switch (uiMsg)
  103.     {
  104.     case WM_ACTIVATE:
  105.         return OnActivate (hWindow, wParam, lParam);
  106.  
  107.     case WM_ACTIVATEAPP:
  108.         return OnActivateApp (hWindow, wParam, lParam);
  109.  
  110.     case WM_CLOSE:
  111.         return OnClose (hWindow);
  112.  
  113.     case WM_COMMAND:
  114.         return OnCommand (hWindow, wParam, lParam);
  115.  
  116.     case WM_CREATE:
  117.         return OnCreate (hWindow);
  118.             
  119.     case WM_DESTROY:
  120.         return OnDestroy (hWindow);
  121.  
  122.     case WM_DISPLAYCHANGE:
  123.         return OnDisplayChange (hWindow);
  124.  
  125.     case WM_ERASEBKGND:
  126.         return OnEraseBackground (hWindow, wParam, lParam);
  127.  
  128.     case WM_ENTERMENULOOP:
  129.         return OnEnterMenuLoop (hWindow, wParam, lParam);
  130.  
  131.     case WM_EXITMENULOOP:
  132.         return OnExitMenuLoop (hWindow, wParam, lParam);
  133.  
  134.     case WM_GETMINMAXINFO:
  135.         return OnGetMinMaxInfo (hWindow, wParam, lParam);
  136.  
  137.     case WM_MOVE:
  138.         return OnMove (hWindow, wParam, lParam);
  139.  
  140.     case WM_NCPAINT:
  141.         return OnNCPaint (hWindow, wParam, lParam);
  142.  
  143.     case WM_PAINT:
  144.     {
  145.         HDC         hdc;
  146.         PAINTSTRUCT ps;
  147.  
  148.         hdc = BeginPaint (hWindow, &ps);            
  149.         lResult = OnPaint (hWindow, hdc, &ps);
  150.         EndPaint (hWindow, &ps);
  151.     }
  152.         return lResult;
  153.  
  154.     case WM_PALETTECHANGED:
  155.         // Note:  We need to support this
  156.         break;
  157.  
  158.     case WM_QUERYNEWPALETTE:
  159.         // Note:  We need to support this
  160.         break;
  161.  
  162.     case WM_SETCURSOR:
  163.         return OnSetCursor (hWindow, wParam, lParam);
  164.  
  165.     case WM_SIZE:
  166.         return OnSize (hWindow, wParam, lParam);
  167.  
  168.     case WM_SYSCOMMAND:
  169.         return OnSysCommand (hWindow, wParam, lParam);
  170.      
  171.     case WM_WINDOWPOSCHANGING:
  172.         return OnWindowPosChanging (hWindow, wParam, lParam);
  173.         
  174.      //
  175.      // D3D Window Query/Notification messages
  176.      //  
  177.     case D3DWIN_GET_VALID:       // Get valid size
  178.         {
  179.         LPD3DWindow lpd3dWindow;
  180.     
  181.         //    Get D3DWindow pointer
  182.         lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  183.         if (! lpd3dWindow)
  184.             return FALSE;
  185.         return lpd3dWindow->isValid();
  186.         }
  187.  
  188.     case D3DWIN_GET_POINTER:
  189.         //    Get D3DWindow pointer
  190.         return (LRESULT)GetWindowLong (hWindow, GWL_USERDATA);
  191.  
  192.     case D3DWIN_GET_SURFACE:
  193.         {
  194.         LPD3DWindow lpd3dWindow;
  195.     
  196.         //    Get D3DWindow pointer
  197.         lpd3dWindow =  (LPD3DWindow)(void *)GetWindowLong (hWindow, GWL_USERDATA);
  198.         if (! lpd3dWindow)
  199.             return NULL;
  200.         return (LPARAM)(lpd3dWindow->GetRender ());
  201.         }
  202.  
  203.     case D3DWIN_INIT:
  204.         return OnD3DInit (hWindow, (LPD3DWindow) lParam);
  205.  
  206.     case D3DWIN_FINI:
  207.         return OnD3DFini (hWindow, (LPD3DWindow) lParam);
  208.  
  209.     case D3DWIN_CHANGED_DRIVER:
  210.         return OnD3DChangeDriver (hWindow);
  211.  
  212.     case D3DWIN_CHANGED_MODE:
  213.         return OnD3DChangeMode (hWindow);
  214.  
  215.     case D3DWIN_CHANGED_DEVICE:
  216.         return OnD3DChangeDevice (hWindow);
  217.  
  218.     } // End Switch
  219.  
  220.    // Do Default window behavior
  221.    return DefWindowProc (hWindow, uiMsg, wParam, lParam);
  222. } // End D3DWindowProc
  223.  
  224.  
  225.  
  226. /*
  227. **-----------------------------------------------------------------------------
  228. **  Name:       AboutBoxProc
  229. **  Purpose:    handles messages for About Dialog box
  230. **-----------------------------------------------------------------------------
  231. */
  232. BOOL
  233. FAR PASCAL AboutBoxProc (HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  234. {
  235.     switch (uiMsg)
  236.     {
  237.     case WM_COMMAND:
  238.         if (LOWORD(wParam) == IDOK)
  239.             EndDialog (hWnd, TRUE);
  240.         break;
  241.  
  242.     case WM_INITDIALOG:
  243.         return TRUE;
  244.     }
  245.     return FALSE;
  246. } // End AboutBoxProc 
  247.  
  248.  
  249.   
  250. /*
  251. **-----------------------------------------------------------------------------
  252. **  Name:       OnAbout
  253. **  Purpose:    Display About Dialog
  254. **-----------------------------------------------------------------------------
  255. */
  256.  
  257. LRESULT OnAbout (HWND hWindow)
  258. {
  259.     HINSTANCE hInstance;
  260.  
  261.     if ((! hWindow) || (! IsWindow (hWindow)))
  262.         return 0L;
  263.  
  264.     hInstance = (HINSTANCE) GetWindowLong (hWindow, GWL_HINSTANCE);
  265.     if (! hInstance)
  266.         return 0L;
  267.  
  268.     // Pause App
  269.     OnPause (hWindow, TRUE);
  270.  
  271.     // Do About Dialog here
  272.     DialogBox (hInstance, MAKEINTRESOURCE (IDD_ABOUT), hWindow, (DLGPROC)AboutBoxProc);
  273.  
  274.     // UnPause app
  275.     OnPause (hWindow, FALSE);
  276.  
  277.     return 0L;
  278. } // End OnAbout
  279.  
  280.  
  281.  
  282. /*
  283. **-----------------------------------------------------------------------------
  284. **  Name:       OnActivate
  285. **  Purpose:    handles WM_ACTIVATE message
  286. **-----------------------------------------------------------------------------
  287. */
  288.  
  289. LRESULT OnActivate (HWND hWindow, WPARAM wParam, LPARAM lParam)
  290. {
  291.     BOOL fActive        = (BOOL) LOWORD(wParam); // activation flag 
  292.     BOOL fMinimized        = (BOOL) HIWORD(wParam); // minimized flag 
  293.     HWND hwndPrevious    = (HWND) lParam;         // window handl
  294.  
  295.     // Do Default Behavior
  296.     return DefWindowProc (hWindow, WM_ACTIVATE, wParam, lParam);
  297. } // End OnActivate
  298.     
  299.  
  300.   
  301. /*
  302. **-----------------------------------------------------------------------------
  303. **  Name:       OnActivateApp
  304. **  Purpose:    handles WM_ACTIVATEAPP message
  305. **-----------------------------------------------------------------------------
  306. */
  307.  
  308. LRESULT OnActivateApp (HWND hWindow, WPARAM wParam, LPARAM lParam)
  309. {
  310.     BOOL    fActive        = (BOOL) wParam;    // Activate or deactivate
  311.     DWORD    dwThreadID    = (DWORD) lParam;    // thread identifier 
  312.  
  313.     // Get D3D Window pointer
  314.     LPD3DWindow lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  315.  
  316.     if (fActive)
  317.     {
  318.         // Reactivating - Realize current palette
  319.         if (lpd3dWindow)
  320.         {
  321.             lpd3dWindow->turnActiveOn ();
  322.             lpd3dWindow->Restore ();
  323.             lpd3dWindow->RealizePalette ();
  324.         }
  325.     }
  326.     else
  327.     {
  328.         //
  329.         //  If we have been deactivated invalidate
  330.         //  to show the paused display.
  331.         //
  332.         if (lpd3dWindow)
  333.         {
  334.             lpd3dWindow->turnActiveOff ();
  335.             InvalidateRect (hWindow, NULL, FALSE);
  336.         }
  337.  
  338.     }
  339.  
  340.     // Do default behavior
  341.     return DefWindowProc (hWindow, WM_ACTIVATEAPP, wParam, lParam);
  342. } // End OnActivateApp
  343.  
  344.  
  345.   
  346. /*
  347. **-----------------------------------------------------------------------------
  348. **  Name:       OnClose
  349. **  Purpose:    handles WM_CLOSE message
  350. **-----------------------------------------------------------------------------
  351. */
  352.  
  353. LRESULT OnClose (HWND hWindow)
  354. {
  355.     // Close down window
  356.     DestroyWindow (hWindow);
  357.     return 0L;
  358. } // End OnClose
  359.  
  360.   
  361.  
  362. /*
  363. **-----------------------------------------------------------------------------
  364. **  Name:       OnCommand
  365. **  Purpose:    handles WM_COMMAND messages
  366. **-----------------------------------------------------------------------------
  367. */
  368.  
  369. LRESULT OnCommand (HWND hWindow, WPARAM wParam, LPARAM lParam)
  370. {   
  371.     HWND  hControl    = (HWND)lParam;
  372.     DWORD dwNotify    = (DWORD)HIWORD(wParam);
  373.     DWORD dwID      = (DWORD)LOWORD(wParam);
  374.  
  375.     if (hControl)
  376.     {
  377.         //
  378.         // Handle messages from controls here
  379.         //
  380.     }
  381.     else 
  382.     {
  383.         // 
  384.         // Handle Menu messages here
  385.         //
  386.         switch (dwID)
  387.         {
  388.         case IDM_EXIT:
  389.             // Close down app
  390.             SendMessage (hWindow, WM_CLOSE, 0, 0);
  391.             return 0;
  392.  
  393.         case IDM_ABOUT:
  394.             // Bring up the "About" dialog
  395.             OnAbout (hWindow);
  396.             break;
  397.  
  398.         case IDM_CHANGE_DRIVERS:
  399.             // Bring up the "Change Driver" dialog
  400.             OnChangeDriver (hWindow, IDD_CHANGE_DRIVER);
  401.             break;
  402.  
  403.         case IDM_CHANGE_DEVICES:
  404.             // Bring up the "Change Device" dialog
  405.             OnChangeDriver (hWindow, IDD_CHANGE_DEVICE);
  406.             break;
  407.  
  408.         case IDM_CHANGE_MODES:
  409.             // Bring up the "Change Mode" dialog
  410.             OnChangeDriver (hWindow, IDD_CHANGE_MODE);
  411.             break;
  412.  
  413.         default:
  414.             // Unknown Menu Command
  415.             break;
  416.         }
  417.     }
  418.  
  419.     // Let Default Window Proc handle it for us.
  420.     return DefWindowProc (hWindow, WM_COMMAND, wParam, lParam);
  421. } // End OnCommand
  422.  
  423.  
  424.  
  425. /*
  426. **-----------------------------------------------------------------------------
  427. **  Name:       OnCreate
  428. **  Purpose:    Handles WM_CREATE message
  429. **-----------------------------------------------------------------------------
  430. */
  431.  
  432. LRESULT OnCreate (HWND hWindow)
  433. {
  434.     // Success
  435.     return 0L;
  436. } // End OnCreate
  437.  
  438.  
  439.   
  440. /*
  441. **-----------------------------------------------------------------------------
  442. **  Name:       OnDestroy
  443. **  Purpose:    Handles WM_DESTROY message
  444. **-----------------------------------------------------------------------------
  445. */
  446.  
  447. LRESULT OnDestroy (HWND hWindow)
  448. {
  449.     LPD3DWindow lpd3dWindow;
  450.     
  451.     //    Delete associated D3DWindow from this window
  452.     lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, 0L);
  453.     if (lpd3dWindow)
  454.         lpd3dWindow->Fini ();
  455.     SetWindowLong (hWindow, GWL_USERDATA, 0L);
  456.  
  457.     // Tell windows to QUIT!
  458.     PostQuitMessage (0);
  459.     return 0L;
  460. } // End OnDestroy
  461.  
  462.  
  463.   
  464. /*
  465. **-----------------------------------------------------------------------------
  466. **  Name:       OnDisplayChange
  467. **  Purpose:    Handles WM_DISPLAYCHANGE message
  468. **  Notes:        This means the desktop mode has changed underneath us
  469. **-----------------------------------------------------------------------------
  470. */
  471.  
  472. LRESULT OnDisplayChange (HWND hWindow)
  473. {
  474.     HRESULT        hResult;
  475.     LPD3DWindow lpd3dWindow;
  476.  
  477.     // Get D3D window pointer
  478.     lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  479.     if (! lpd3dWindow)
  480.         return 0L;
  481.     
  482.     // Change Primary surface to new desktop
  483.     hResult = lpd3dWindow->ChangeDesktop ();
  484.     if (FAILED (hResult))
  485.         return 0L;
  486.  
  487.     // Success
  488.     return 0L;
  489. } // End OnDestroy
  490.  
  491.   
  492.   
  493. /*
  494. **-----------------------------------------------------------------------------
  495. **  Name:       OnEraseBackground
  496. **  Purpose:    Handles WM_ERASEBKGND message
  497. **-----------------------------------------------------------------------------
  498. */
  499.  
  500. LRESULT OnEraseBackground (HWND hWindow, WPARAM wParam, LPARAM lParam)
  501. {
  502.     LPD3DWindow lpd3dWindow;
  503.  
  504.     // Get D3D window pointer
  505.     lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  506.     if ((lpd3dWindow) &&
  507.         (lpd3dWindow->isValid ()) &&
  508.         (lpd3dWindow->isActive ()) &&
  509.         (! lpd3dWindow->isPaused ()))
  510.     {
  511.         // Tell system we erased background, even though we didn't
  512.         // It will soon get covered up by a frame from RenderScene
  513.         return 1L;
  514.     }
  515.  
  516.     // Do the Default behavior (erase the background)
  517.     return DefWindowProc (hWindow, WM_ERASEBKGND, wParam, lParam);
  518. } // End OnEraseBackground
  519.   
  520.  
  521.  
  522. /*
  523. **-----------------------------------------------------------------------------
  524. **  Name:       OnEnterMenuLoop
  525. **  Purpose:    Handles WM_ENTERMENULOOP messages
  526. **-----------------------------------------------------------------------------
  527. */
  528.  
  529. LRESULT OnEnterMenuLoop (HWND hWindow, WPARAM wParam, LPARAM lParam)
  530. {
  531.     LPD3DWindow lpd3dWindow;
  532.  
  533.     // Get D3D window pointer
  534.     lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  535.     if ((lpd3dWindow) && (lpd3dWindow->isValid ()))
  536.     {
  537.         // pause app (go into GDI drawing mode)
  538.         lpd3dWindow->Pause (TRUE);
  539.  
  540.         // Restore cursor 
  541.         SetCursor (g_hMainCursor);
  542.     }
  543.  
  544.     // Do the Default behavior 
  545.     return DefWindowProc (hWindow, WM_ENTERMENULOOP, wParam, lParam);
  546. } // End OnEnterMenuLoop
  547.   
  548.  
  549.   
  550. /*
  551. **-----------------------------------------------------------------------------
  552. **  Name:       OnExitMenuLoop
  553. **  Purpose:    Handles WM_EXITMENULOOP messages
  554. **-----------------------------------------------------------------------------
  555. */
  556.  
  557. LRESULT OnExitMenuLoop (HWND hWindow, WPARAM wParam, LPARAM lParam)
  558. {
  559.     LPD3DWindow lpd3dWindow;
  560.  
  561.     // Get D3D window pointer
  562.     lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  563.     if ((lpd3dWindow) && (lpd3dWindow->isValid ()))
  564.     {
  565.         // Get Rid of cursor again
  566.         SetCursor (NULL);        
  567.  
  568.         // Unpause app (return from GDI drawing)
  569.         lpd3dWindow->Pause (FALSE);
  570.     }
  571.  
  572.     // Do the Default behavior 
  573.     return DefWindowProc (hWindow, WM_EXITMENULOOP, wParam, lParam);
  574. } // End OnExitMenuLoop
  575.  
  576.  
  577.  
  578. /*
  579. **-----------------------------------------------------------------------------
  580. **  Name:       OnGetMinMaxInfo
  581. **  Purpose:    Handles WM_GETMINMAXINFO message
  582. **-----------------------------------------------------------------------------
  583. */
  584.  
  585. LRESULT OnGetMinMaxInfo (HWND hWindow, WPARAM wParam, LPARAM lParam)
  586. {
  587.     LPMINMAXINFO    lpmmi;
  588.     LPD3DWindow        lpd3dWindow;
  589.     RECT            rSurf;
  590.     DWORD            dwWidth;
  591.     DWORD            dwHeight;
  592.  
  593.     lpmmi = (LPMINMAXINFO)lParam;
  594.  
  595.     // Get D3D window pointer
  596.     lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  597.     if ((lpd3dWindow) && 
  598.         (lpd3dWindow->isFullscreen ()) &&
  599.         (! g_fMinimized))
  600.     {
  601.         // Get Width and height of current surface
  602.         lpd3dWindow->GetSurfaceRect (rSurf);
  603.  
  604.         dwWidth  = abs (rSurf.right - rSurf.left);
  605.         dwHeight = abs (rSurf.bottom - rSurf.top);
  606.  
  607.         // Prevent changes in size
  608.         lpmmi->ptMaxTrackSize.x = dwWidth;
  609.         lpmmi->ptMaxTrackSize.y = dwHeight;
  610.         lpmmi->ptMinTrackSize.x = dwWidth;
  611.         lpmmi->ptMinTrackSize.y = dwHeight;
  612.  
  613.         return 0L;
  614.     }
  615.  
  616.     return DefWindowProc (hWindow, WM_GETMINMAXINFO, wParam, lParam);
  617. } // End OnGetMinMaxInfo
  618.  
  619.  
  620.  
  621. /*
  622. **-----------------------------------------------------------------------------
  623. **  Name:       OnIdle
  624. **  Purpose:    Animate while system is idle
  625. **-----------------------------------------------------------------------------
  626. */
  627.  
  628. void OnIdle (HWND hWindow)
  629. {
  630.     HRESULT hResult;
  631.     LPD3DWindow  lpd3dWindow;
  632.  
  633.     // Get D3D window pointer
  634.     lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  635.     if (! lpd3dWindow)
  636.         return;
  637.  
  638.     //
  639.     // Only animate if we are the foreground app, we aren't suspended
  640.     // and we have completed initialization and we aren't minimized
  641.     //
  642.     if ((! lpd3dWindow->isActive ()) || 
  643.         (lpd3dWindow->isPaused ()) ||
  644.         (! lpd3dWindow->isValid ()) ||
  645.         (g_fMinimized))
  646.         return;
  647.  
  648.     hResult = lpd3dWindow->DrawFrame ();
  649.     if (FAILED (hResult))
  650.         return;
  651. } // End OnIdle
  652.  
  653.  
  654.  
  655. /*
  656. **-----------------------------------------------------------------------------
  657. **  Name:       OnMove
  658. **  Purpose:    handles WM_MOVE message
  659. **-----------------------------------------------------------------------------
  660. */
  661.  
  662. LRESULT OnMove (HWND hWindow, WPARAM wParam, LPARAM lParam)
  663. {
  664.     // We don't support moving Full-screen windows
  665.  
  666.     // Do default behavior
  667.     return DefWindowProc (hWindow, WM_MOVE, wParam, lParam);
  668. } // End OnMove
  669.  
  670.  
  671.  
  672. /*
  673. **-----------------------------------------------------------------------------
  674. **  Name:       OnNCPaint
  675. **  Purpose:    Handles WM_NCPaint message
  676. **-----------------------------------------------------------------------------
  677. */
  678.  
  679. LRESULT OnNCPaint (HWND hWindow, WPARAM wParam, LPARAM lParam)
  680. {
  681.     LPD3DWindow lpd3dWindow;
  682.  
  683.     // Get D3D window pointer
  684.     lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  685.     if ((lpd3dWindow) &&
  686.         (lpd3dWindow->isValid ()) &&
  687.         (lpd3dWindow->isActive ()) &&
  688.         (! lpd3dWindow->isPaused ()) &&
  689.         (! g_fMinimized))
  690.     {
  691.         // Prevent the system from drawing the NC frame
  692.         return 0L;
  693.     }
  694.  
  695.     // Do the Default behavior (Draw the NC Frame)
  696.     return DefWindowProc (hWindow, WM_NCPAINT, wParam, lParam);
  697. } // End OnNCPaint
  698.   
  699.  
  700.   
  701. /*
  702. **-----------------------------------------------------------------------------
  703. **  Name:       OnPaint
  704. **  Purpose:    Handles WM_PAINT messages
  705. **-----------------------------------------------------------------------------
  706. */
  707.  
  708. LRESULT OnPaint (HWND hWindow, HDC hdc, LPPAINTSTRUCT lpps)
  709. {
  710.     HRESULT        hResult;
  711.     LPD3DWindow lpd3dWindow;
  712.  
  713.     // Get D3D Window pointer
  714.     lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  715.  
  716.     if (lpd3dWindow && 
  717.         lpd3dWindow->isActive () && 
  718.         !lpd3dWindow->isPaused () && 
  719.         lpd3dWindow->isValid() &&
  720.         ! g_fMinimized)
  721.     {
  722.         //
  723.         // NOTE: DrawFrame() re-renders the scene as well as blitting the
  724.         // result to the primary. As all we really want to do here is
  725.         // repaint the client area we don't really need to re-render -
  726.         // just re-blit. For this simple sample this inefficiency
  727.         // doesn't matter but for real applications not re-rendering
  728.         // may be a useful optimization.
  729.         //
  730.         hResult = lpd3dWindow->DrawFrame ();
  731.         if (FAILED (hResult))
  732.             return 0L;
  733.     }
  734.     else
  735.     {
  736.         //
  737.         // Show the suspended image if the D3Dwinow is not yet created,
  738.         // created, the window is inactive, or paused.
  739.         //
  740.         PaintPaused (hWindow, hdc);
  741.     }
  742.  
  743.     return 0L;
  744. } // End OnPaint
  745.  
  746.  
  747.   
  748. /*
  749. **-----------------------------------------------------------------------------
  750. **  Name:        OnPause
  751. **  Purpose:    Pause/Unpause app
  752. **-----------------------------------------------------------------------------
  753. */
  754.  
  755. void OnPause (HWND hWindow, BOOL fPause)
  756. {
  757.     LPD3DWindow lpd3dWindow;
  758.  
  759.     // Get D3D Window pointer
  760.     lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  761.     if (! lpd3dWindow)
  762.         return;
  763.  
  764.     lpd3dWindow->Pause (fPause);
  765. } // End OnPause
  766.  
  767.  
  768.   
  769. /*
  770. **-----------------------------------------------------------------------------
  771. **  Name:       OnSetCursor
  772. **  Purpose:    Handles WM_SETCURSOR messages
  773. **-----------------------------------------------------------------------------
  774. */
  775.  
  776. LRESULT OnSetCursor (HWND hWindow, WPARAM wParam, LPARAM lParam)
  777. {
  778.     LPD3DWindow  lpd3dWindow;
  779.  
  780.     // Get D3D window pointer
  781.     lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  782.     
  783.     // Don't show cursor while in fullscreen
  784.     if ((lpd3dWindow) && (lpd3dWindow->isFullscreen ()))
  785.     {
  786.         if ((lpd3dWindow->isPaused ()) ||
  787.             (! lpd3dWindow->isActive ()))
  788.         {
  789.             // Restore cursor
  790.             SetCursor (g_hMainCursor);
  791.         }
  792.         else
  793.         {
  794.             // Get rid of cursor
  795.             SetCursor (NULL);
  796.         }
  797.         return TRUE;
  798.     }
  799.  
  800.     // Do Default behavior
  801.     return DefWindowProc (hWindow, WM_SETCURSOR, wParam, lParam);
  802. } // End OnSetCursor
  803.  
  804.  
  805.  
  806. /*
  807. **-----------------------------------------------------------------------------
  808. **  Name:       OnSize
  809. **  Purpose:    Handles WM_SIZE messages
  810. **-----------------------------------------------------------------------------
  811. */
  812.  
  813. LRESULT OnSize (HWND hWindow, WPARAM wParam, LPARAM lParam)
  814. {
  815.     DWORD        fwSizeType    = (DWORD)wParam;
  816.     LPD3DWindow    lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  817.  
  818.     switch (fwSizeType)
  819.     {
  820.     case SIZE_MAXHIDE:
  821.         // Message is sent to all pop-up windows when some other window is maximized. 
  822.         break;
  823.  
  824.     case SIZE_MAXIMIZED:
  825.         // Window has been maximized. 
  826.         g_fMaximized = TRUE;
  827.         g_fMinimized = FALSE;
  828.         break;
  829.  
  830.     case SIZE_MAXSHOW:
  831.         // Message is sent to all pop-up windows when some other window has been restored to its former size. 
  832.         break;
  833.  
  834.     case SIZE_MINIMIZED:
  835.         // Window has been minimized. 
  836.         g_fMinimized = TRUE;
  837.         g_fMaximized = FALSE;
  838.         break;
  839.  
  840.     case SIZE_RESTORED:  
  841.         // Window has been resized but neither minimized nor maximized 
  842.         if (g_fMinimized)
  843.         {
  844.             // Restore surfaces
  845.             if (lpd3dWindow)
  846.                 lpd3dWindow->Restore ();
  847.  
  848.             g_fMaximized = FALSE;
  849.             g_fMinimized = FALSE;
  850.         }
  851.         return 0L;
  852.     }
  853.  
  854.     // Do Default Behavior
  855.     return DefWindowProc (hWindow, WM_SIZE, wParam, lParam);
  856. } // End OnSize
  857.  
  858.  
  859.  
  860.  
  861. /*
  862. **-----------------------------------------------------------------------------
  863. **  Name:       OnSysCommand
  864. **  Purpose:    Handles WM_SYSCOMMAND messages
  865. **-----------------------------------------------------------------------------
  866. */
  867.  
  868. LRESULT OnSysCommand (HWND hWindow, WPARAM wParam, LPARAM lParam)
  869. {
  870.     // Get D3D window pointer
  871.     LPD3DWindow    lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  872.     DWORD    uCmdType = wParam;        // Type of system command requested 
  873.     int        xPos = LOWORD(lParam);    // horizontal postion, in screen coordinates 
  874.     int        yPos = HIWORD(lParam);    // vertical postion, in screen coordinates 
  875.  
  876.     switch (uCmdType)
  877.     {
  878.     case SC_MAXIMIZE:
  879.         // Maximizes the window. 
  880.         g_fMaximized = TRUE;
  881.         g_fMinimized = FALSE;
  882.  
  883.         // Not supported
  884.         return 0L;
  885.  
  886.     case SC_MINIMIZE:
  887.         // Minimizes the window.
  888.         g_fMinimized = TRUE;
  889.         g_fMaximized = FALSE;
  890.         break;
  891.  
  892.     case SC_MOVE:
  893.         // Moves the window
  894.         
  895.         // Not supported
  896.         return 0L;
  897.   
  898.     case SC_RESTORE:
  899.         //Restores the window to its normal position and size. 
  900.         if (g_fMinimized)
  901.         {
  902.             // Restore app
  903.             if (lpd3dWindow)
  904.                 lpd3dWindow->Restore ();
  905.         }
  906.  
  907.         g_fMinimized = FALSE;
  908.         g_fMaximized = FALSE;
  909.         break;
  910.  
  911.     case SC_SCREENSAVE:
  912.         // Executes the screen saver application specified in the [boot] section of the SYSTEM.INI file. 
  913.         break;
  914.  
  915.     case SC_SIZE:
  916.         // Sizes the window. 
  917.         
  918.         // Not supported
  919.         return 0L; 
  920.     }
  921.  
  922.     // Do Default Behavior
  923.     return DefWindowProc (hWindow, WM_SYSCOMMAND, wParam, lParam);
  924. } // End OnSysCommand
  925.  
  926.  
  927.  
  928. /*
  929. **-----------------------------------------------------------------------------
  930. **  Name:       OnWindowPosChanging
  931. **  Purpose:    handles WM_WINDOWPOSCHANGING message
  932. **  Notes:        
  933. **
  934. **    1. This is where we protect ourselves against unwanted moving
  935. **       and resizing of the window.  (We are fullscreen after all)
  936. **
  937. **  2. First gotcha:  Changing the Display mode causes the window
  938. **       to change size and we want to let that happen.  So we will
  939. **       compare the current window size to the current surface size.
  940. **       If they don't match we will resize the window to match the surface.
  941. **  
  942. **  3. Second gotcha.  DirectDraw hooks the window procedure and on
  943. **       a deactivate app call trys to minimize the window on our behalf.
  944. **       We should allow this to happen!!!
  945. **       It can do this by either calling ShowWindow or SetWindowPos
  946. **
  947. **-----------------------------------------------------------------------------
  948. */
  949.  
  950. LRESULT OnWindowPosChanging (HWND hWindow, WPARAM wParam, LPARAM lParam)
  951. {
  952.     // We don't support moving Full-screen windows
  953.     // Get D3D Window pointer
  954.     LPD3DWindow lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  955.     if (lpd3dWindow && 
  956.         (lpd3dWindow->isFullscreen ()) &&
  957.         (! g_fMinimized))
  958.     {
  959.         LPWINDOWPOS lpwp = (LPWINDOWPOS) lParam;
  960.         
  961.         if (lpwp)
  962.         {
  963.             // Let minimize commands fall through
  964.             // Check for minimize by seeing if window is iconic
  965.             // this state should already be set by the time
  966.             // we get this window message
  967.             if (IsIconic (hWindow))
  968.             {
  969.                 // Looks like we are getting minimized
  970.                 g_fMinimized = TRUE;
  971.             }
  972.             else
  973.             {
  974.                 RECT    rWin, rSurf;
  975.                 DWORD    dwWinW, dwWinH;
  976.                 DWORD    dwSurfW, dwSurfH;
  977.  
  978.                 GetWindowRect (hWindow, &rWin);
  979.                 dwWinW = abs (rWin.right - rWin.left);
  980.                 dwWinH = abs (rWin.bottom - rWin.top);
  981.  
  982.                 lpd3dWindow->GetSurfaceRect (rSurf);
  983.                 dwSurfW = abs (rSurf.right - rSurf.left);
  984.                 dwSurfH = abs (rSurf.bottom - rSurf.top);
  985.  
  986.                 // Make sure the surface is some reasonable size
  987.                 if (dwSurfW < 320)
  988.                     dwSurfW = 320;
  989.                 if (dwSurfH < 200)
  990.                     dwSurfH = 200;
  991.  
  992.                 // Is our window the same size as our surface ?!?
  993.                 if ((dwSurfW != dwWinW) || (dwSurfH != dwWinH))
  994.                 {
  995.                     // No, then resize it
  996.                     lpwp->x = rSurf.left;
  997.                     lpwp->y = rSurf.top;
  998.                     lpwp->cx = dwSurfW;
  999.                     lpwp->cy = dwSurfH;
  1000.  
  1001.                     // Force resize
  1002.                     lpwp->flags &= ~(SWP_NOMOVE | SWP_NOSIZE);
  1003.                 }
  1004.                 else
  1005.                 {
  1006.                     // Prevent resizing and moving
  1007.                     lpwp->flags |= (SWP_NOMOVE | SWP_NOSIZE);
  1008.                 }
  1009.  
  1010.                 // Fall through to default window proc
  1011.             }
  1012.         }
  1013.     }
  1014.  
  1015.     // Do Default Behavior
  1016.     return DefWindowProc (hWindow, WM_WINDOWPOSCHANGING, wParam, lParam);
  1017. } // End OnWindowPosChanging
  1018.  
  1019.   
  1020.  
  1021. /*
  1022. **-----------------------------------------------------------------------------
  1023. **  Name:       OnD3DInit
  1024. **  Purpose:    Notification that associated D3D Window object
  1025. **                has successfully initialized
  1026. **-----------------------------------------------------------------------------
  1027. */
  1028.  
  1029. LRESULT OnD3DInit (HWND hWindow, LPD3DWindow lpd3dWindow)
  1030. {
  1031.     if ((! lpd3dWindow) || (! lpd3dWindow->isValid ()))
  1032.     {
  1033.         // Error, something went wrong
  1034.         return 0L;
  1035.     }
  1036.  
  1037.     // Save the pointer to the D3D Window object
  1038.     SetWindowLong (hWindow, GWL_USERDATA, (long)(void *)lpd3dWindow);
  1039.  
  1040.     // Make sure we are properly marked as active/inactive
  1041.     HWND hActive = GetActiveWindow ();
  1042.     if (hActive == hWindow)
  1043.         lpd3dWindow->turnActiveOn ();
  1044.     else
  1045.         lpd3dWindow->turnActiveOff ();
  1046.  
  1047.     // Success
  1048.     return 0L;
  1049. } // End OnD3DInit
  1050.  
  1051.  
  1052.   
  1053. /*
  1054. **-----------------------------------------------------------------------------
  1055. **  Name:       OnD3DFini
  1056. **  Purpose:    Notification that the D3D window object
  1057. **                is cleaning up.
  1058. **-----------------------------------------------------------------------------
  1059. */
  1060.  
  1061. LRESULT OnD3DFini (HWND hWindow, LPD3DWindow lpd3dWindow)
  1062. {
  1063.     // Set our window pointer to NULL
  1064.     // so we don't attempt to misuse it later.
  1065.     SetWindowLong (hWindow, GWL_USERDATA, 0L);
  1066.     
  1067.     // Success
  1068.     return 0L;
  1069. } // End OnD3DFini
  1070.  
  1071.  
  1072.  
  1073. /*
  1074. **-----------------------------------------------------------------------------
  1075. **  Name:       OnD3DChangeDriver
  1076. **  Purpose:    Notification that our associated D3D Window object
  1077. **                has changed it's DD Driver.
  1078. **  Notes:        This is a good time to update our Menus
  1079. **-----------------------------------------------------------------------------
  1080. */
  1081.  
  1082. LRESULT OnD3DChangeDriver (HWND hWindow)
  1083. {
  1084.     // Success
  1085.     return 0L;
  1086. } // End OnD3DChangeDriver
  1087.  
  1088.   
  1089.  
  1090.   
  1091. /*
  1092. **-----------------------------------------------------------------------------
  1093. **  Name:       OnD3DChangeMode
  1094. **  Purpose:    Notification that our associated D3D Window object
  1095. **                has changed it's mode.
  1096. **  Notes:        This is a good time to update our Menus
  1097. **-----------------------------------------------------------------------------
  1098. */
  1099.  
  1100. LRESULT OnD3DChangeMode (HWND hWindow)
  1101. {
  1102.     // Success
  1103.     return 0L;
  1104. } // End OnD3DChangeMode
  1105.  
  1106.  
  1107.   
  1108. /*
  1109. **-----------------------------------------------------------------------------
  1110. **  Name:       OnD3DChangeDevice
  1111. **  Purpose:    Notification that our associated D3D Window object
  1112. **                has changed it's D3D device.
  1113. **  Notes:        This is a good time to update our Menus
  1114. **-----------------------------------------------------------------------------
  1115. */
  1116.  
  1117. LRESULT OnD3DChangeDevice (HWND hWindow)
  1118. {
  1119.     // Success
  1120.     return 0L;
  1121. } // End OnD3DChangeDevice
  1122.  
  1123.  
  1124.   
  1125. /*
  1126. **-----------------------------------------------------------------------------
  1127. **  Name:       PaintPaused
  1128. **  Purpose:    Paint the window as Paused
  1129. **  Notes:      
  1130. **
  1131. **  1.  We show the paused state by drawing a text string
  1132. **      in the client area of the window.
  1133. **
  1134. **-----------------------------------------------------------------------------
  1135. */
  1136.  
  1137. void PaintPaused (HWND hWindow, HDC hdc)
  1138. {
  1139.     HPEN     hOldPen;
  1140.     HBRUSH   hOldBrush;
  1141.     COLORREF crOldTextColor;
  1142.     INT      oldMode;
  1143.     INT      x;
  1144.     INT      y;
  1145.     SIZE     size;
  1146.     RECT     rect;
  1147.     INT      nStrLen;
  1148.  
  1149.     //
  1150.     // Black background.
  1151.     //
  1152.     hOldPen   = (HPEN)SelectObject (hdc, GetStockObject (NULL_PEN));
  1153.     hOldBrush = (HBRUSH)SelectObject (hdc, GetStockObject (BLACK_BRUSH));
  1154.  
  1155.     //
  1156.     // White text.
  1157.     //
  1158.     oldMode = SetBkMode (hdc, TRANSPARENT);
  1159.     crOldTextColor = SetTextColor (hdc, RGB(255, 255, 255));
  1160.  
  1161.     // 
  1162.     GetClientRect (hWindow, &rect);
  1163.  
  1164.     //
  1165.     // Clear the client area.
  1166.     //
  1167.     Rectangle (hdc, rect.left, rect.top, rect.right + 1, rect.bottom + 1);
  1168.  
  1169.     //
  1170.     // Draw the string centered in the client area.
  1171.     //
  1172.     nStrLen = strlen (g_szPaused);
  1173.     GetTextExtentPoint32 (hdc, g_szPaused, nStrLen, &size);
  1174.     x = (rect.right  - size.cx) / 2;
  1175.     y = (rect.bottom - size.cy) / 2;
  1176.     TextOut (hdc, x, y, g_szPaused, nStrLen);
  1177.  
  1178.     // Cleanup
  1179.     SetTextColor (hdc, crOldTextColor);
  1180.     SetBkMode (hdc, oldMode);
  1181.  
  1182.     SelectObject (hdc, hOldBrush);
  1183.     SelectObject (hdc, hOldPen);
  1184. } // End PaintPaused
  1185.  
  1186.  
  1187.  
  1188.   
  1189. /*
  1190. **-----------------------------------------------------------------------------
  1191. **    Dialog Functions
  1192. **-----------------------------------------------------------------------------
  1193. */
  1194.  
  1195. /*
  1196. **-----------------------------------------------------------------------------
  1197. **  Name:       DlgDriversInit
  1198. **  Purpose:    Set up Drivers for dialog 
  1199. **  Notes:        Shows list of current Drivers
  1200. **-----------------------------------------------------------------------------
  1201. */
  1202.  
  1203. BOOL DlgDriversInit (HWND hDlg)
  1204. {
  1205.     LPChangeDDInfo    lpChange;
  1206.     LPDDDrvInfo        lpDriver;
  1207.     LPDDDrvInfo        lpCurr, lpNext;
  1208.     DWORD            dwIndex;
  1209.     LPGUID            lpGuidDD;
  1210.  
  1211.     // Check Parameters
  1212.     lpChange = (LPChangeDDInfo)(void *)GetWindowLong (hDlg, DWL_USER);
  1213.     if (! lpChange)
  1214.         return FALSE;
  1215.  
  1216.     lpDriver = lpChange->lpDrvNew;
  1217.  
  1218.     // Validate Driver
  1219.     if (! lpDriver)
  1220.         lpGuidDD = NULL;
  1221.     else
  1222.         lpGuidDD = lpDriver->GetGuid ();
  1223.     lpDriver = ValidateDriver (lpGuidDD);
  1224.     if (! lpDriver)
  1225.         return FALSE;
  1226.     
  1227.     // Dump Driver list to Combo Box
  1228.     dwIndex = 0;
  1229.     lpCurr = DDDrvMgr::g_lpDriverRoot;
  1230.     while (lpCurr)
  1231.     {
  1232.         TCHAR szBuff[80];
  1233.         DWORD dwNew;
  1234.  
  1235.         lpNext = lpCurr->lpNext;
  1236.  
  1237.         if (lpCurr->isPrimary ())
  1238.             wsprintf (szBuff, TEXT("%s (Primary)"), lpCurr->szName);
  1239.         else
  1240.             wsprintf (szBuff, TEXT("%s"), lpCurr->szName);
  1241.  
  1242.         // Add String to Combo Box
  1243.         dwNew = SendDlgItemMessage (hDlg, IDC_DRIVERS, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)szBuff);
  1244.  
  1245.         // Set up pointer to driver for this item
  1246.         SendDlgItemMessage (hDlg, IDC_DRIVERS, CB_SETITEMDATA, (WPARAM)dwNew, (LPARAM)(void *)lpCurr);
  1247.  
  1248.         // Is it the current Driver
  1249.         if (lpDriver == lpCurr)
  1250.         {
  1251.             // Set as our current selection
  1252.             SendDlgItemMessage (hDlg, IDC_DRIVERS, CB_SETCURSEL, (WPARAM)dwNew, 0L);
  1253.         }
  1254.  
  1255.         lpCurr = lpNext;
  1256.     }
  1257.  
  1258.     // Success
  1259.     return TRUE;
  1260. } // End DlgDriversInit
  1261.     
  1262.  
  1263.  
  1264. /*
  1265. **-----------------------------------------------------------------------------
  1266. **  Name:       DlgDevicesInit
  1267. **  Purpose:    Set up Devices for dialog 
  1268. **  Notes:        Shows list of current Devices
  1269. **-----------------------------------------------------------------------------
  1270. */
  1271.  
  1272. BOOL DlgDevicesInit (HWND hDlg)
  1273. {
  1274.     LPChangeDDInfo    lpChange;
  1275.     LPDDDrvInfo        lpDriver;
  1276.     LPD3DDevInfo    lpDevice;
  1277.     LPD3DDevInfo    lpCurr, lpNext;
  1278.     DWORD            dwIndex;
  1279.     LPGUID            lpGuidD3D;
  1280.  
  1281.     // Check Parameters
  1282.     lpChange = (LPChangeDDInfo)(void *)GetWindowLong (hDlg, DWL_USER);
  1283.     if (! lpChange)
  1284.         return FALSE;
  1285.  
  1286.     lpDriver = lpChange->lpDrvNew;
  1287.     if (! lpDriver)
  1288.         return FALSE;
  1289.  
  1290.     lpDevice = lpChange->lpDevNew;
  1291.  
  1292.     // Validate Device
  1293.     if (! lpDevice)
  1294.         lpGuidD3D = NULL;
  1295.     else
  1296.         lpGuidD3D = &(lpDevice->guid);
  1297.     lpDevice = ValidateDevice (lpDriver, lpGuidD3D, NULL);
  1298.     if (! lpDevice)
  1299.         return FALSE;
  1300.     
  1301.     // Dump Device list to Combo Box
  1302.     dwIndex = 0;
  1303.     lpCurr = lpDriver->lpDeviceRoot;
  1304.     while (lpCurr)
  1305.     {
  1306.         TCHAR szBuff[80];
  1307.         DWORD dwNew;
  1308.  
  1309.         lpNext = lpCurr->lpNext;
  1310.  
  1311.         // Get Device String
  1312.         wsprintf (szBuff, TEXT("%s"), lpCurr->szName);
  1313.  
  1314.         // Add String to Combo Box
  1315.         dwNew = SendDlgItemMessage (hDlg, IDC_DEVICES, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)szBuff);
  1316.  
  1317.         // Set up pointer to device for this item
  1318.         SendDlgItemMessage (hDlg, IDC_DEVICES, CB_SETITEMDATA, (WPARAM)dwNew, (LPARAM)(void *)lpCurr);
  1319.  
  1320.         // Is it the current device
  1321.         if (lpDevice == lpCurr)
  1322.         {
  1323.             // Set as our current selection
  1324.             SendDlgItemMessage (hDlg, IDC_DEVICES, CB_SETCURSEL, (WPARAM)dwNew, 0L);
  1325.         }
  1326.  
  1327.         lpCurr = lpNext;
  1328.     }
  1329.  
  1330.     // Success
  1331.     return TRUE;
  1332. } // End DlgDevicesInit
  1333.  
  1334.  
  1335.  
  1336. /*
  1337. **-----------------------------------------------------------------------------
  1338. **  Name:       CompareModes
  1339. **  Purpose:    Comparision function used with Quick sort 
  1340. **                to get sorted list of modes
  1341. **-----------------------------------------------------------------------------
  1342. */
  1343.  
  1344. int _cdecl CompareModes (const void * element1, const void * element2) 
  1345. {
  1346.     LPDDModeInfo lpMode1;
  1347.     LPDDModeInfo lpMode2;
  1348.     DWORD w1, h1, bpp1, refresh1;
  1349.     DWORD w2, h2, bpp2, refresh2;
  1350.     int   iCompare = 0;
  1351.  
  1352.     lpMode1 = *((LPDDModeInfo *)element1);
  1353.     lpMode2 = *((LPDDModeInfo *)element2);
  1354.  
  1355.     // Handle Null pointers
  1356.     if ((! lpMode1) && (! lpMode2))
  1357.         return 0;
  1358.     if ((lpMode1) && (! lpMode2))
  1359.         return -1;
  1360.     if ((! lpMode2) && (lpMode2))
  1361.         return 1;
  1362.  
  1363.     // Get Mode Data
  1364.     lpMode1->GetMode (w1, h1, bpp1, refresh1);
  1365.     lpMode2->GetMode (w2, h2, bpp2, refresh2);
  1366.  
  1367.     // Sort first on BPP then width then height
  1368.     if (bpp1 < bpp2)
  1369.         iCompare = -1;
  1370.     else if (bpp1 > bpp2)
  1371.         iCompare = 1;
  1372.     else if (w1 < w2)
  1373.         iCompare = -1;
  1374.     else if (w1 > w2)
  1375.         iCompare = 1;
  1376.     else if (h1 < h2)
  1377.         iCompare = -1;
  1378.     else if (h1 > h2)
  1379.         iCompare = 1;
  1380.  
  1381.     // Equality
  1382.     return iCompare;
  1383. } // End CompareModes
  1384.  
  1385.  
  1386.   
  1387. /*
  1388. **-----------------------------------------------------------------------------
  1389. **  Name:       DlgModesInit
  1390. **  Purpose:    Set up Modes for dialog 
  1391. **  Notes:        Shows list of current modes, compatible with the current 
  1392. **                device.  This list is displayed in sorted order (bpp, w, h)
  1393. **-----------------------------------------------------------------------------
  1394. */
  1395.  
  1396. BOOL DlgModesInit (HWND hDlg)
  1397. {
  1398.     LPChangeDDInfo    lpChange;
  1399.     LPDDDrvInfo        lpDriver;
  1400.     LPD3DDevInfo    lpDevice;
  1401.     LPDDModeInfo    lpModeCurr, lpModeRoot, lpCurr, lpNext;
  1402.     DWORD            cModes;
  1403.     DWORD            cbSize;
  1404.     DWORD            dwIndex;
  1405.     LPDDModeInfo *    lpModes;
  1406.  
  1407.     // Check Parameters
  1408.     lpChange = (LPChangeDDInfo)(void *)GetWindowLong (hDlg, DWL_USER);
  1409.     if (! lpChange)
  1410.         return FALSE;
  1411.  
  1412.     lpDriver   = lpChange->lpDrvNew;
  1413.     lpDevice   = lpChange->lpDevNew;
  1414.     lpModeCurr = lpChange->lpModeNew;
  1415.  
  1416.     if (! lpDriver)
  1417.         return FALSE;
  1418.  
  1419.     if (! lpDevice)
  1420.     {
  1421.         lpDevice = ValidateDevice (lpDriver, NULL, NULL);
  1422.         if (! lpDevice)
  1423.             return FALSE;
  1424.     }
  1425.  
  1426.     lpModeRoot = lpDriver->lpModeRoot;
  1427.     if (! lpModeRoot)
  1428.         return FALSE;
  1429.  
  1430.     cModes = lpDriver->countModes ();
  1431.     if (! cModes)
  1432.         return FALSE;
  1433.     
  1434.     if (! lpModeCurr)
  1435.     {
  1436.         lpModeCurr = ValidateMode (lpDriver, 640, 480, 16, 0, lpDevice);
  1437.     }
  1438.  
  1439.     // Get memory for Mode list
  1440.     cbSize = cModes * sizeof (LPDDModeInfo);
  1441.     lpModes = (LPDDModeInfo *) malloc (cbSize);
  1442.     if (! lpModes)
  1443.         return FALSE;
  1444.  
  1445.     // Create Mode List
  1446.     dwIndex = 0;
  1447.     lpCurr = lpModeRoot;
  1448.     while (lpCurr)
  1449.     {
  1450.         lpNext = lpCurr->lpNext;
  1451.  
  1452.         lpModes[dwIndex] = lpCurr;
  1453.  
  1454.         dwIndex++;
  1455.  
  1456.         lpCurr = lpNext;
  1457.     }
  1458.  
  1459.     // Sort Mode list
  1460.     qsort ((void *)lpModes, (size_t)cModes, sizeof(LPDDModeInfo), CompareModes);
  1461.  
  1462.     // Dump Mode list to Combo Box
  1463.     for (dwIndex = 0; dwIndex < cModes; dwIndex++)
  1464.     {
  1465.         // Make sure mode is supported by D3D device
  1466.         if ((lpModes[dwIndex]) && 
  1467.             (lpModes[dwIndex]->ModeSupported (lpDevice)))
  1468.         {
  1469.             TCHAR szBuff[80];
  1470.             DWORD w, h, bpp, refresh;
  1471.             DWORD dwNew;
  1472.  
  1473.             lpModes[dwIndex]->GetMode (w, h, bpp, refresh);
  1474.             
  1475.             // Set up Mode String
  1476.             if (refresh)
  1477.                 wsprintf (szBuff, TEXT("%4d x %4d x %4d (%4d Hz)"), 
  1478.                           w, h, bpp, refresh);
  1479.             else
  1480.                 wsprintf (szBuff, TEXT("%4d x %4d x %4d"), 
  1481.                           w, h, bpp);
  1482.  
  1483.             // Add String to Combo Box
  1484.             dwNew = SendDlgItemMessage (hDlg, IDC_MODES, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)szBuff);
  1485.  
  1486.             // Set up pointer to Mode Info for this item
  1487.             SendDlgItemMessage (hDlg, IDC_MODES, CB_SETITEMDATA, (WPARAM)dwNew, (LPARAM)(void *)lpModes[dwIndex]);
  1488.  
  1489.             // Is it the current Mode 
  1490.             if (lpModeCurr == lpModes[dwIndex])
  1491.             {
  1492.                 // Set as our current selection
  1493.                 SendDlgItemMessage (hDlg, IDC_MODES, CB_SETCURSEL, (WPARAM)dwNew, 0L);
  1494.             }
  1495.         }
  1496.     }    
  1497.  
  1498.     // Cleanup Memory
  1499.     free (lpModes);
  1500.     lpModes = NULL;
  1501.  
  1502.     // Success
  1503.     return TRUE;
  1504. } // End DlgModesInit
  1505.  
  1506.  
  1507.  
  1508.   
  1509. /*
  1510. **-----------------------------------------------------------------------------
  1511. **  Name:       DlgGetDriver
  1512. **  Purpose:    Get current driver selection
  1513. **-----------------------------------------------------------------------------
  1514. */
  1515.  
  1516. LPDDDrvInfo DlgGetDriver (HWND hDlg)
  1517. {
  1518.     DWORD dwIndex = SendDlgItemMessage (hDlg, IDC_DRIVERS, CB_GETCURSEL, 0, 0);
  1519.     if (dwIndex != CB_ERR)
  1520.     {
  1521.         // Get pointer to driver
  1522.         LPDDDrvInfo lpDriver = (LPDDDrvInfo) SendDlgItemMessage (hDlg, 
  1523.                                                                    IDC_DRIVERS, 
  1524.                                                                  CB_GETITEMDATA, 
  1525.                                                                  (WPARAM)dwIndex, 
  1526.                                                                  (LPARAM)0);
  1527.         return lpDriver;
  1528.     }            
  1529.  
  1530.     // Failure
  1531.     return NULL;
  1532. } // End DlgGetDriver
  1533.  
  1534.  
  1535.   
  1536. /*
  1537. **-----------------------------------------------------------------------------
  1538. **  Name:       DlgGetDevice
  1539. **  Purpose:    Get current device selection
  1540. **-----------------------------------------------------------------------------
  1541. */
  1542.  
  1543. LPD3DDevInfo DlgGetDevice (HWND hDlg)
  1544. {
  1545.     DWORD dwIndex = SendDlgItemMessage (hDlg, IDC_DEVICES, CB_GETCURSEL, 0, 0);
  1546.     if (dwIndex != CB_ERR)
  1547.     {
  1548.         // Get pointer to device
  1549.         LPD3DDevInfo lpDevice = (LPD3DDevInfo) SendDlgItemMessage (hDlg, 
  1550.                                                                      IDC_DEVICES, 
  1551.                                                                    CB_GETITEMDATA, 
  1552.                                                                    (WPARAM)dwIndex, 
  1553.                                                                    (LPARAM)0);
  1554.         return lpDevice;
  1555.     }            
  1556.  
  1557.     // Failure
  1558.     return NULL;
  1559. } // End DlgGetDevice
  1560.  
  1561.  
  1562.   
  1563. /*
  1564. **-----------------------------------------------------------------------------
  1565. **  Name:       DlgGetMode
  1566. **  Purpose:    Get current mode selection
  1567. **-----------------------------------------------------------------------------
  1568. */
  1569.  
  1570. LPDDModeInfo DlgGetMode (HWND hDlg)
  1571. {
  1572.     DWORD dwIndex = SendDlgItemMessage (hDlg, IDC_MODES, CB_GETCURSEL, 0, 0);
  1573.     if (dwIndex != CB_ERR)
  1574.     {
  1575.         // Get pointer to device
  1576.         LPDDModeInfo lpMode = (LPDDModeInfo) SendDlgItemMessage (hDlg, 
  1577.                                                                  IDC_MODES, 
  1578.                                                                  CB_GETITEMDATA, 
  1579.                                                                  (WPARAM)dwIndex, 
  1580.                                                                  (LPARAM)0);
  1581.         return lpMode;
  1582.     }            
  1583.  
  1584.     // Failure
  1585.     return NULL;
  1586. } // End DlgGetMode
  1587.  
  1588.   
  1589.  
  1590.  
  1591.   
  1592. /*
  1593. **-----------------------------------------------------------------------------
  1594. **  Name:       OnChangeDriver
  1595. **  Purpose:    Allows user to choose a new Driver from dialog
  1596. **    Notes:        User can also choose a new device and mode
  1597. **-----------------------------------------------------------------------------
  1598. */
  1599.  
  1600. void OnChangeDriver (HWND hWindow, int idDialog)
  1601. {
  1602.     HINSTANCE        hInstance;
  1603.     int                fResult;
  1604.     ChangeDDInfo    changeInfo;
  1605.     LPD3DWindow        lpd3dWindow;
  1606.  
  1607.     // Get application instance
  1608.     hInstance = (HINSTANCE) GetWindowLong (hWindow, GWL_HINSTANCE);
  1609.     if (! hInstance)
  1610.         return;
  1611.  
  1612.     // Get D3D Window pointer
  1613.     lpd3dWindow =  (LPD3DWindow)GetWindowLong (hWindow, GWL_USERDATA);
  1614.     if (! lpd3dWindow)
  1615.         return;
  1616.  
  1617.     // Setup Change info
  1618.     changeInfo.lpDrvOrig    = lpd3dWindow->GetDriverInfo ();
  1619.     changeInfo.lpDrvNew        = changeInfo.lpDrvOrig;
  1620.  
  1621.     changeInfo.lpDevOrig    = lpd3dWindow->GetDeviceInfo ();
  1622.     changeInfo.lpDevNew        = changeInfo.lpDevOrig;
  1623.  
  1624.     changeInfo.lpModeOrig    = lpd3dWindow->GetModeInfo ();
  1625.     changeInfo.lpModeNew    = changeInfo.lpModeOrig;
  1626.  
  1627.  
  1628.     // Pause App
  1629.     OnPause (hWindow, TRUE);
  1630.  
  1631.     // Do Change Mode Dialog here
  1632.     fResult = DialogBoxParam (hInstance, MAKEINTRESOURCE (idDialog), 
  1633.                               hWindow, (DLGPROC)ChangeDriverProc,
  1634.                               (LPARAM)(void *)&changeInfo);
  1635.  
  1636.     // UnPause app
  1637.     OnPause (hWindow, FALSE);
  1638.  
  1639.     // Did user request a change ?!?
  1640.     if (fResult == TRUE)
  1641.     {
  1642.         LPGUID lpGuidDD, lpGuidD3D;
  1643.         DWORD w, h, bpp, refresh;
  1644.  
  1645.         if (changeInfo.lpDrvOrig != changeInfo.lpDrvNew)
  1646.         {
  1647.             if (changeInfo.lpDrvNew)
  1648.                 lpGuidDD = changeInfo.lpDrvNew->GetGuid ();
  1649.             else
  1650.                 lpGuidDD = NULL;
  1651.  
  1652.             lpd3dWindow->ChangeDriver (lpGuidDD,
  1653.                                        changeInfo.lpDevNew,
  1654.                                        changeInfo.lpModeNew);
  1655.         }
  1656.         else if (changeInfo.lpDevOrig != changeInfo.lpDevNew)
  1657.         {
  1658.             if (changeInfo.lpDevNew)
  1659.                 lpGuidD3D = &(changeInfo.lpDevNew->guid);
  1660.             else
  1661.                 lpGuidD3D = NULL;
  1662.  
  1663.             lpd3dWindow->ChangeDevice (lpGuidD3D, changeInfo.lpModeNew);
  1664.         }
  1665.         else if (changeInfo.lpModeOrig != changeInfo.lpModeNew)
  1666.         {
  1667.             changeInfo.lpModeNew->GetMode (w, h, bpp, refresh);
  1668.             lpd3dWindow->ChangeMode (w, h, bpp, refresh);
  1669.         }
  1670.     }
  1671. } // End OnChangeDriver
  1672.   
  1673.  
  1674.  
  1675. /*
  1676. **-----------------------------------------------------------------------------
  1677. **  Name:       ChangeDriverProc
  1678. **  Purpose:    handles messages for Change Driver,
  1679. **                D3D device, and mode dialog boxes
  1680. **-----------------------------------------------------------------------------
  1681. */
  1682.  
  1683. BOOL CALLBACK ChangeDriverProc(
  1684.     HWND hDlg,        // handle to dialog box
  1685.     UINT uiMsg,        // message
  1686.     WPARAM wParam,    // first message parameter
  1687.     LPARAM lParam)     // second message parameter
  1688. {
  1689.     BOOL            fChanged;
  1690.     LPChangeDDInfo  lpChange;
  1691.     LPDDDrvInfo        lpDriver;
  1692.     LPDDModeInfo    lpMode;
  1693.     LPD3DDevInfo    lpDevice;
  1694.  
  1695.     switch (uiMsg)
  1696.     {
  1697.     case WM_COMMAND:
  1698.         switch (LOWORD(wParam))
  1699.         {
  1700.         case IDOK:
  1701.             // Get Change Info
  1702.             lpChange = (LPChangeDDInfo) GetWindowLong (hDlg, DWL_USER);
  1703.             if (! lpChange)
  1704.                 EndDialog (hDlg, FALSE);
  1705.  
  1706.             fChanged = FALSE;
  1707.  
  1708.             // Get New Driver
  1709.             lpDriver = DlgGetDriver (hDlg);
  1710.             if ((lpDriver) && (lpDriver != lpChange->lpDrvOrig))
  1711.             {
  1712.                 fChanged = TRUE;
  1713.                 lpChange->lpDrvNew = lpDriver;
  1714.             }
  1715.             else
  1716.                 lpChange->lpDrvNew = lpChange->lpDrvOrig;
  1717.  
  1718.             // Get New Device
  1719.             lpDevice = DlgGetDevice (hDlg);
  1720.             if ((lpDevice) && (lpDevice != lpChange->lpDevOrig))
  1721.             {
  1722.                 fChanged = TRUE;
  1723.                 lpChange->lpDevNew = lpDevice;
  1724.             }
  1725.             else
  1726.                 lpChange->lpDevNew = lpChange->lpDevOrig;
  1727.             
  1728.             // Get New Mode
  1729.             lpMode = DlgGetMode (hDlg);
  1730.             if ((lpMode) && (lpMode != lpChange->lpModeOrig))
  1731.             {
  1732.                 fChanged = TRUE;
  1733.                 lpChange->lpModeNew = lpMode;
  1734.             }
  1735.             else
  1736.                 lpChange->lpModeNew = lpChange->lpModeOrig;
  1737.  
  1738.             // Return success/failure
  1739.             EndDialog (hDlg, fChanged);
  1740.             break;
  1741.  
  1742.         case IDCANCEL:
  1743.             EndDialog (hDlg, FALSE);
  1744.             break;
  1745.  
  1746.         case IDC_DRIVERS:
  1747.             switch (HIWORD (wParam))
  1748.             {
  1749.             case CBN_SELENDOK:
  1750.                 // User has changed the current driver
  1751.                 lpChange = (LPChangeDDInfo) GetWindowLong (hDlg, DWL_USER);
  1752.             
  1753.                 // Check if user has changed the Driver
  1754.                 lpDriver = DlgGetDriver (hDlg);
  1755.                 if ((lpDriver) && (lpDriver != lpChange->lpDrvNew))
  1756.                 {
  1757.                     lpChange->lpDrvNew = lpDriver;
  1758.                     lpChange->lpDevNew = NULL;    // Pick a new device
  1759.                     lpChange->lpModeNew = NULL;    // Pick a new mode
  1760.                     
  1761.                     // Update the Device list
  1762.                     SendDlgItemMessage (hDlg, IDC_DEVICES, CB_RESETCONTENT, 0, 0);
  1763.                     DlgDevicesInit (hDlg);
  1764.  
  1765.                     // Update the Mode list
  1766.                     SendDlgItemMessage (hDlg, IDC_MODES, CB_RESETCONTENT, 0, 0);
  1767.                     DlgModesInit (hDlg);
  1768.                 }
  1769.                 break;
  1770.             }
  1771.             break;
  1772.  
  1773.         case IDC_DEVICES:
  1774.             switch (HIWORD (wParam))
  1775.             {
  1776.             case CBN_SELENDOK:
  1777.                 // User has changed the current device
  1778.                 lpChange = (LPChangeDDInfo) GetWindowLong (hDlg, DWL_USER);
  1779.                 
  1780.                 // Check if user has changed the device
  1781.                 lpDevice = DlgGetDevice (hDlg);
  1782.                 if ((lpDevice) && (lpDevice != lpChange->lpDevNew))
  1783.                 {
  1784.                     lpChange->lpDevNew = lpDevice;
  1785.                     
  1786.                     // Update the Mode list
  1787.                     SendDlgItemMessage (hDlg, IDC_MODES, CB_RESETCONTENT, 0, 0);
  1788.                     DlgModesInit (hDlg);
  1789.                 }
  1790.                 break;
  1791.             }
  1792.             break;
  1793.  
  1794.         case IDC_MODES:
  1795.             switch (HIWORD (wParam))
  1796.             {
  1797.             case CBN_SELENDOK:
  1798.                 // User has changed the current mode
  1799.                 lpChange = (LPChangeDDInfo) GetWindowLong (hDlg, DWL_USER);
  1800.                 
  1801.                 // Check if user has changed the Mode
  1802.                 lpMode = DlgGetMode (hDlg);
  1803.                 if ((lpMode) && (lpMode != lpChange->lpModeNew))
  1804.                 {
  1805.                     lpChange->lpModeNew = lpMode;
  1806.                 }
  1807.                 break;
  1808.             }
  1809.             break;
  1810.         }
  1811.         break;
  1812.  
  1813.     case WM_INITDIALOG:
  1814.         // Save pointer to ChangeInfo
  1815.         SetWindowLong (hDlg, DWL_USER, (long)lParam);
  1816.  
  1817.         // Set up the current driver, device, and mode lists
  1818.         if (GetDlgItem (hDlg, IDC_DRIVERS))
  1819.             if (! DlgDriversInit (hDlg))    
  1820.                 return FALSE;
  1821.  
  1822.         if (GetDlgItem (hDlg, IDC_DEVICES))
  1823.             if (! DlgDevicesInit (hDlg))
  1824.                 return FALSE;
  1825.  
  1826.         if (GetDlgItem (hDlg, IDC_MODES))
  1827.             if (! DlgModesInit (hDlg))
  1828.                 return FALSE;
  1829.  
  1830.         // Successful init
  1831.         return TRUE;
  1832.     }
  1833.     return FALSE;
  1834. } // End ChangeDriverProc 
  1835.  
  1836.  
  1837.  
  1838.   
  1839. /*
  1840. **-----------------------------------------------------------------------------
  1841. **  End of File
  1842. **-----------------------------------------------------------------------------
  1843. */
  1844.  
  1845.  
  1846.