DIEX2.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:16k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /**************************************************************************
  2.     DIEX2.CPP - DirectInput simple sample 2
  3.     Demonstrates an application which receives relative mouse data
  4.     in exclusive mode via a game loop.
  5.  **************************************************************************/
  6. /**************************************************************************
  7.     (C) Copyright 1997 Microsoft Corp.  All rights reserved.
  8.     You have a royalty-free right to use, modify, reproduce and
  9.     distribute the Sample Files (and/or any modified version) in
  10.     any way you find useful, provided that you agree that
  11.     Microsoft has no warranty obligations or liability for any
  12.     Sample Application Files which are modified.
  13.  **************************************************************************/
  14. #include <windows.h>
  15. #include <dinput.h>
  16. #include "diex2.h"
  17. /****************************************************************************
  18.  *
  19.  *      Global variables
  20.  *
  21.  ****************************************************************************/
  22. char c_szClassName[] = "DIEX2";
  23. HINSTANCE       g_hinst;                /* My instance handle */
  24. BOOL            g_fPaused = TRUE;       /* Should I be paused? */
  25. /****************************************************************************
  26.  *
  27.  *      DirectInput globals
  28.  *
  29.  ****************************************************************************/
  30. LPDIRECTINPUT           g_pdi;
  31. LPDIRECTINPUTDEVICE     g_pMouse;
  32. char                    g_szText[1024]; /* What we display in client area */
  33. /****************************************************************************
  34.  *
  35.  *      Complain
  36.  *
  37.  *      Whine and moan.
  38.  *
  39.  ****************************************************************************/
  40. void
  41. Complain(
  42.     HWND hwndOwner,
  43.     HRESULT hr,
  44.     LPCSTR pszMessage
  45. )
  46. {
  47.     MessageBox(hwndOwner, pszMessage, "DirectInput Sample", MB_OK);
  48. }
  49. /****************************************************************************
  50.  *
  51.  *      DIInit
  52.  *
  53.  *      Initialize the DirectInput variables.
  54.  *
  55.  *      This entails the following four functions:
  56.  *
  57.  *          DirectInputCreate
  58.  *          IDirectInput::CreateDevice
  59.  *          IDirectInputDevice::SetDataFormat
  60.  *          IDirectInputDevice::SetCooperativeLevel
  61.  *
  62.  ****************************************************************************/
  63. BOOL
  64. DIInit(
  65.     HWND hwnd
  66. )
  67. {
  68.     HRESULT hr;
  69.     /*
  70.      *  Register with the DirectInput subsystem and get a pointer
  71.      *  to a IDirectInput interface we can use.
  72.      *
  73.      *  Parameters:
  74.      *
  75.      *      g_hinst
  76.      *
  77.      *          Instance handle to our application or DLL.
  78.      *
  79.      *      DIRECTINPUT_VERSION
  80.      *
  81.      *          The version of DirectInput we were designed for.
  82.      *          We take the value from the <dinput.h> header file.
  83.      *
  84.      *      &g_pdi
  85.      *
  86.      *          Receives pointer to the IDirectInput interface
  87.      *          that was created.
  88.      *
  89.      *      NULL
  90.      *
  91.      *          We do not use OLE aggregation, so this parameter
  92.      *          must be NULL.
  93.      *
  94.      */
  95.     hr = DirectInputCreate(g_hinst, DIRECTINPUT_VERSION, &g_pdi, NULL);
  96.     if (FAILED(hr)) {
  97.         Complain(hwnd, hr, "DirectInputCreate");
  98.         return FALSE;
  99.     }
  100.     /*
  101.      *  Obtain an interface to the system mouse device.
  102.      *
  103.      *  Parameters:
  104.      *
  105.      *      GUID_SysMouse
  106.      *
  107.      *          The instance GUID for the device we wish to access.
  108.      *          GUID_SysMouse is a predefined instance GUID that
  109.      *          always refers to the system mouse device.
  110.      *
  111.      *      &g_pMouse
  112.      *
  113.      *          Receives pointer to the IDirectInputDevice interface
  114.      *          that was created.
  115.      *
  116.      *      NULL
  117.      *
  118.      *          We do not use OLE aggregation, so this parameter
  119.      *          must be NULL.
  120.      *
  121.      */
  122.     hr = g_pdi->CreateDevice(GUID_SysMouse, &g_pMouse, NULL);
  123.     if (FAILED(hr)) {
  124.         Complain(hwnd, hr, "CreateDevice");
  125.         return FALSE;
  126.     }
  127.     /*
  128.      *  Set the data format to "mouse format".
  129.      *
  130.      *  A data format specifies which controls on a device we
  131.      *  are interested in, and how they should be reported.
  132.      *
  133.      *  This tells DirectInput that we will be passing a
  134.      *  DIMOUSESTATE structure to IDirectInputDevice::GetDeviceState.
  135.      *
  136.      *  Parameters:
  137.      *
  138.      *      c_dfDIMouse
  139.      *
  140.      *          Predefined data format which describes
  141.      *          a DIMOUSESTATE structure.
  142.      */
  143.     hr = g_pMouse->SetDataFormat(&c_dfDIMouse);
  144.     if (FAILED(hr)) {
  145.         Complain(hwnd, hr, "SetDataFormat");
  146.         return FALSE;
  147.     }
  148.     /*
  149.      *  Set the cooperativity level to let DirectInput know how
  150.      *  this device should interact with the system and with other
  151.      *  DirectInput applications.
  152.      *
  153.      *  Parameters:
  154.      *
  155.      *      DISCL_EXCLUSIVE
  156.      *
  157.      *          When the mouse is acquired, no other application
  158.      *          will be able to acquire the mouse exclusively.
  159.      *          Furthermore, the Windows mouse cursor will not move.
  160.      *
  161.      *      DISCL_FOREGROUND
  162.      *
  163.      *          If the user switches away from our application,
  164.      *          automatically release the mouse back to the system.
  165.      *
  166.      */
  167.     hr = g_pMouse->SetCooperativeLevel(hwnd,
  168.                                        DISCL_EXCLUSIVE | DISCL_FOREGROUND);
  169.     if (FAILED(hr)) {
  170.         Complain(hwnd, hr, "SetCooperativeLevel");
  171.         return FALSE;
  172.     }
  173.     return TRUE;
  174. }
  175. /****************************************************************************
  176.  *
  177.  *      DITerm
  178.  *
  179.  *      Terminate our usage of DirectInput.
  180.  *
  181.  ****************************************************************************/
  182. void
  183. DITerm(void)
  184. {
  185.     /*
  186.      *  Destroy any lingering IDirectInputDevice object.
  187.      */
  188.     if (g_pMouse) {
  189.         /*
  190.          *  Cleanliness is next to godliness.  Unacquire the device
  191.          *  one last time just in case we got really confused and tried
  192.          *  to exit while the device is still acquired.
  193.          */
  194.         g_pMouse->Unacquire();
  195.         g_pMouse->Release();
  196.         g_pMouse = NULL;
  197.     }
  198.     /*
  199.      *  Destroy any lingering IDirectInput object.
  200.      */
  201.     if (g_pdi) {
  202.         g_pdi->Release();
  203.         g_pdi = NULL;
  204.     }
  205. }
  206. /****************************************************************************
  207.  *
  208.  *      Ex_OnPaint
  209.  *
  210.  *      Display the current mouse position and button state.
  211.  *
  212.  ****************************************************************************/
  213. LRESULT
  214. Ex_OnPaint(
  215.     HWND hwnd
  216. )
  217. {
  218.     PAINTSTRUCT ps;
  219.     HDC hdc = BeginPaint(hwnd, &ps);
  220.     if (hdc) {
  221.         ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &ps.rcPaint, g_szText,
  222.                    lstrlen(g_szText), NULL);
  223.         EndPaint(hwnd, &ps);
  224.     }
  225.     return 0;
  226. }
  227. /****************************************************************************
  228.  *
  229.  *      Ex_OneFrame
  230.  *
  231.  *      The game plays here.
  232.  *
  233.  *      Our "game" consists entirely of reading mouse data
  234.  *      and displaying it.
  235.  *
  236.  ****************************************************************************/
  237. void
  238. Ex_OneFrame(HWND hwnd)
  239. {
  240.     if (g_pMouse) {
  241.         DIMOUSESTATE dims;          /* DirectInput mouse state structure */
  242.         HRESULT hr;
  243.     again:;
  244.         hr = g_pMouse->GetDeviceState(sizeof(DIMOUSESTATE), &dims);
  245.         if (hr == DIERR_INPUTLOST) {
  246.             /*
  247.              *  DirectInput is telling us that the input stream has
  248.              *  been interrupted.  We aren't tracking any state
  249.              *  between polls, so we don't have any special reset
  250.              *  that needs to be done.  We just re-acquire and
  251.              *  try again.
  252.              */
  253.             hr = g_pMouse->Acquire();
  254.             if (SUCCEEDED(hr)) {
  255.                 goto again;
  256.             }
  257.         }
  258.         if (SUCCEEDED(hr)) {
  259.             char szBuf[1024];
  260.             /*
  261.              *  Build the new status string.
  262.              *
  263.              *  Display mouse coordinates (x, y, z) and buttons.
  264.              */
  265.             wsprintf(szBuf, "(%d, %d, %d) %c %c %c %c",
  266.                      dims.lX, dims.lY, dims.lZ,
  267.                      (dims.rgbButtons[0] & 0x80) ? '0' : ' ',
  268.                      (dims.rgbButtons[1] & 0x80) ? '1' : ' ',
  269.                      (dims.rgbButtons[2] & 0x80) ? '2' : ' ',
  270.                      (dims.rgbButtons[3] & 0x80) ? '3' : ' ');
  271.             /*
  272.              *  Trigger a repaint only if the status string changed.
  273.              *  This avoids flicker.
  274.              */
  275.             if (lstrcmp(g_szText, szBuf)) {
  276.                 lstrcpy(g_szText, szBuf);
  277.                 InvalidateRect(hwnd, NULL, TRUE);
  278.             }
  279.         }
  280.     }
  281.     /*
  282.      *  Sleep for a few milliseconds to simulate a 30fps frame rate.
  283.      */
  284.     Sleep(1000 / 30);
  285. }
  286. /****************************************************************************
  287.  *
  288.  *      Ex_SyncAcquire
  289.  *
  290.  *      Acquire or unacquire the mouse, depending on the the g_fPaused
  291.  *      flag.  This synchronizes the device with our internal view of
  292.  *      the world.
  293.  *
  294.  ****************************************************************************/
  295. void
  296. Ex_SyncAcquire(HWND hwnd)
  297. {
  298.     if (g_fPaused) {
  299.         if (g_pMouse) g_pMouse->Unacquire();
  300.     } else {
  301.         if (g_pMouse) g_pMouse->Acquire();
  302.     }
  303. }
  304. /****************************************************************************
  305.  *
  306.  *      Private messages
  307.  *
  308.  *      WM_SYNCACQUIRE forces us to re-synchronize our acquisition
  309.  *      with the world.  There are some subtleties with the way
  310.  *      Windows manages mouse ownership, so we post this message
  311.  *      to ourselves to say "Okay, things have settled down; now go
  312.  *      synchronize DirectInput with our internal view of the world."
  313.  *
  314.  ****************************************************************************/
  315. #define WM_SYNCACQUIRE      (WM_USER + 0)
  316. /****************************************************************************
  317.  *
  318.  *      Ex_WndProc
  319.  *
  320.  *      Window procedure for simple sample.
  321.  *
  322.  ****************************************************************************/
  323. LRESULT CALLBACK
  324. Ex_WndProc(
  325.     HWND hwnd,
  326.     UINT msg,
  327.     WPARAM wParam,
  328.     LPARAM lParam
  329. )
  330. {
  331.     LRESULT lRc;
  332.     switch (msg) {
  333.     case WM_PAINT:      return Ex_OnPaint(hwnd);
  334.     /*
  335.      *  WM_ACTIVATE
  336.      *
  337.      *      Windows sends this message when the window becomes
  338.      *      the active window or stops being the active window.
  339.      *
  340.      *      wParam = WA_INACTIVE if window is no longer active
  341.      *
  342.      *      wParam = WA_ACTIVE or WA_CLICKACTIVE if window is now active
  343.      *
  344.      *      If we are losing activation, then pause.
  345.      *
  346.      *      If we are gaining activation, then unpause.
  347.      *
  348.      *      After deciding whether we are paused or unpaused,
  349.      *      tell DirectInput that we don't (paused) or do (unpaused)
  350.      *      want exclusive access to the mouse.
  351.      *
  352.      */
  353.     case WM_ACTIVATE:
  354.         g_fPaused = wParam == WA_INACTIVE;
  355.         Ex_SyncAcquire(hwnd);
  356.         break;
  357.     /*
  358.      *  Unacquire the mouse if a menu appears, so that the user can
  359.      *  interact with the menu in the normal manner.
  360.      *
  361.      *  From Windows' point of view, we are still the active window
  362.      *  when a menu appears, but we want to act like the menu deactivated
  363.      *  us.
  364.      */
  365.     case WM_ENTERMENULOOP:
  366.     case WM_ENTERSIZEMOVE:
  367.         g_fPaused = TRUE;
  368.         Ex_SyncAcquire(hwnd);
  369.         break;
  370.     /*
  371.      *  Reacquire the devices when the menu goes away.
  372.      *
  373.      *  SUBTLETY 1:  Windows actually sends the WM_EXITMENULOOP message
  374.      *  before all the menu-related stuff is finished, so post ourselves
  375.      *  a private message to reacquire after the menu has been torn
  376.      *  down for real.
  377.      *
  378.      *  SUBTLETY 2:  Don't assume that just because the menu is going
  379.      *  away that you are still the active window.  You might not be.
  380.      *
  381.      *  SUBTLETY 3:  Don't assume that just because you're the active
  382.      *  window that you are restored and ready for action.  You might
  383.      *  just be a taskbar button.
  384.      */
  385.     case WM_EXITMENULOOP:
  386.     case WM_EXITSIZEMOVE:
  387.         g_fPaused = GetActiveWindow() != hwnd || IsIconic(hwnd);
  388.         PostMessage(hwnd, WM_SYNCACQUIRE, 0, 0L);
  389.         break;
  390.     case WM_SYNCACQUIRE:
  391.         Ex_SyncAcquire(hwnd);
  392.         break;
  393.     case WM_SYSCOMMAND:
  394.         lRc = DefWindowProc(hwnd, msg, wParam, lParam);
  395.         /*
  396.          * The WM_SYSCOMMAND might've been a WM_CLOSE, in which case
  397.          * our window no longer exists.  So be careful.
  398.          */
  399.         if (IsWindow(hwnd)) {
  400.             Ex_SyncAcquire(hwnd);
  401.         }
  402.         return lRc;
  403.     case WM_DESTROY:
  404.         PostQuitMessage(0);
  405.         break;
  406.     }
  407.     return DefWindowProc(hwnd, msg, wParam, lParam);
  408. }
  409. /****************************************************************************
  410.  *
  411.  *      AppInit
  412.  *
  413.  *      Set up everything the application needs to get started.
  414.  *
  415.  ****************************************************************************/
  416. HWND
  417. AppInit(
  418.     HINSTANCE hinst,
  419.     int nCmdShow
  420. )
  421. {
  422.     /*
  423.      *  Save instance handle for future reference.
  424.      */
  425.     g_hinst = hinst;
  426.     /*
  427.      *  Set up the window class.
  428.      */
  429.     WNDCLASS wc;
  430.     wc.hCursor        = LoadCursor(0, IDC_ARROW);
  431.     wc.hIcon          = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
  432.     wc.lpszMenuName   = NULL;
  433.     wc.lpszClassName  = c_szClassName;
  434.     wc.hbrBackground  = 0;
  435.     wc.hInstance      = hinst;
  436.     wc.style          = 0;
  437.     wc.lpfnWndProc    = Ex_WndProc;
  438.     wc.cbClsExtra     = 0;
  439.     wc.cbWndExtra     = 0;
  440.     if (!RegisterClass(&wc)) {
  441.         return NULL;
  442.     }
  443.     HWND hwnd = CreateWindow(
  444.                     c_szClassName,                  // Class name
  445.                     "DIEX2 - Alt+F4 to exit",       // Caption
  446.                     WS_OVERLAPPEDWINDOW,            // Style
  447.                     CW_USEDEFAULT, CW_USEDEFAULT,   // Position
  448.                     CW_USEDEFAULT, CW_USEDEFAULT,   // Size
  449.                     NULL,                           // No parent
  450.                     NULL,                           // No menu
  451.                     g_hinst,                        // inst handle
  452.                     0                               // no params
  453.                     );
  454.     if (!DIInit(hwnd)) {
  455.         DestroyWindow(hwnd);
  456.         return NULL;
  457.     }
  458.     ShowWindow(hwnd, nCmdShow);
  459.     return hwnd;
  460. }
  461. /****************************************************************************
  462.  *
  463.  *      WinMain
  464.  *
  465.  *      Application entry point.
  466.  *
  467.  ****************************************************************************/
  468. int PASCAL
  469. WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR szCmdLine, int nCmdShow)
  470. {
  471.     MSG msg;
  472.     msg.wParam = 0;         /* In case something goes horribly wrong */
  473.     HWND hwnd = AppInit(hinst, nCmdShow);
  474.     if (hwnd) {
  475.         /*
  476.          *  Standard game loop.
  477.          */
  478.         for (;;) {
  479.             if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  480.                 /* If it's a quit message, we're outta here */
  481.                 if (msg.message == WM_QUIT) {
  482.                     break;
  483.                 } else {
  484.                     TranslateMessage(&msg);
  485.                     DispatchMessage(&msg);
  486.                 }
  487.             } else if (g_fPaused) {
  488.                 WaitMessage();
  489.             } else {
  490.                 Ex_OneFrame(hwnd);
  491.             }
  492.         }
  493.     }
  494.     DITerm();
  495.     return msg.wParam;
  496. }