So… before we go any further with CMouse, let’s look at the code to initialize DirectInput. Note that this code doesn’t belong in our CMouse::Init() routine; the DirectInput pointer is used by the entire game, not just the mouse, so the code that inits DirectInput should go in your main init function - the same time you init DirectDraw, DirectSound, etc. A DirectInput interface pointer is different than a DirectInput device pointer; you use DirectInput pointers to get DirectInputDevice pointers.

Here’s the code to initialize the master DirectInput interface pointer:

LPDIRECTINPUT di = NULL;

hr = DirectInputCreate(hinst, DIRECTINPUT_VERSION, &di, NULL);

if (FAILED(hr)) {

 // error processing

}

That will put a valid DirectInput interface pointer into di. (Don’t forget to Release() it when your game ends!)

Now that we’ve got a DirectInput interface, let’s begin fleshing out our CMouse by implementing CMouse::Init().

bool CMouse::Init(LPDIRECTINPUT di) {

 // Obtain an interface to the system mouse device.

 hr = di-›CreateDevice(GUID_SysMouse, (LPDIRECTINPUTDEVICE*)&di_mouse, NULL);

 if (FAILED(hr)) {/* handle errors! */}

 // Set the data format to "mouse format".

 hr = m_mousedev-›SetDataFormat(&c_dfDIMouse);

 if (FAILED(hr)) {/* handle errors! */}

 // Set the cooperativity level

 hr = m_mousedev-›SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);

 if (FAILED(hr)) {/* handle errors! */}

}

That code does three important things. First, it gets a valid DirectInput mouse device interface, and puts it in di_mouse. Next, it sets the data format and the cooperative level for the device, basically letting windows know that we want to query the device as if it were a mouse, and that we don’t want to take exclusive ownership of it. (Exclusive ownership means that we’re the only app that can use the mouse - by specifying DISCL_NONEXCLUSIVE, we’ve told Windows that we’re going to be sharing the mouse with other applications.)

Now let’s flesh out CMouse::Refresh(), the function responsible for updating the CMouse’s internal button state and position variables. Here’s the code.

void CMouse::Refresh(void) {

 C done = 0;

 int q;

 HRESULT hr;

 POINT p;

 DIMOUSESTATE dims;

 if (!m_di) return;

 // clear our struct - eventually, directinput will fill this in

 memset(&dims, 0, sizeof(DIMOUSESTATE));

 if (!m_mousedev) return; // we don’t have a pointer! Bail!

 while (!done) {

  hr = m_mousedev-›GetDeviceState(sizeof(DIMOUSESTATE), &dims);

  if (FAILED(hr)) {

   if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED) {

    // device lost… reacquire

    hr = m_mousedev-›Acquire();

    if (FAILED(hr)) {

     // houston, we have a problem… clear & bail

     clear();

     done=1;

    }

   } else {

    // it’s some other error - clear and bail!

    m_mousedev.clear();

    done = 1;

   }

  } else // read mouse successfully!

  {

   done = 1;

  }

 } //while !done

 m_position.z += dims.lZ;

 if (m_vga-›isfullscreen()) {

  // we're in fullscreen, so this is easy… just copy the coords

  m_position.x += dims.lX;

  m_position.y += dims.lY;

 } else {

  // we're in window mode, so this is not-so-easy…

  // grab the relative mouse position

  GetCursorPos(&p);

  ScreenToClient((HWND)m_vga-›gethwnd(), &p);

  if (p.x ‹ 0 || p.y ‹ 0) {

   // the cursor is out of our window! "hide" it!

   m_mousedev.setposition(KJM_AXES_X, m_vga-›getscreendims().getwidth());

Перейти на страницу:

Похожие книги