在Windows窗体应用程序中使用操纵杆

时间:2014-11-24 21:05:04

标签: c++ windows forms joystick directinput

我的申请遇到了问题。我编写了一个在控制台中运行良好的代码,但我需要创建一个GUI。这个应用程序让我用操纵杆控制鼠标。我使用的是Direcinput库。它是操纵杆的读取位置及其名称。

这是我的代码:

#ifndef D_INPUT
#define D_INPUT
#include <dinput.h>
#include <iostream>
#endif

LPDIRECTINPUT8 di;               
HRESULT hr;
LPDIRECTINPUTDEVICE8 joystick;
DIDEVICEINSTANCE pdidi;
DIDEVICEINSTANCE info;

BOOL CALLBACK
enumCallback(const DIDEVICEINSTANCE* instance, VOID* context)
{
    HRESULT hr;

    hr = di->CreateDevice(instance->guidInstance, &joystick, NULL);

    if (FAILED(hr)) {
        return DIENUM_CONTINUE;
    }
    return DIENUM_STOP;
}

BOOL CALLBACK
enumAxesCallback(const DIDEVICEOBJECTINSTANCE* instance, VOID* context)
{
    HWND hDlg = (HWND)context;

    DIPROPRANGE propRange;
    propRange.diph.dwSize = sizeof(DIPROPRANGE);
    propRange.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    propRange.diph.dwHow = DIPH_BYID;
    propRange.diph.dwObj = instance->dwType;
    propRange.lMin = -50;
    propRange.lMax = +50;

    if (FAILED(joystick->SetProperty(DIPROP_RANGE, &propRange.diph))) {
        return DIENUM_STOP;
    }

    return DIENUM_CONTINUE;
}

class Joy
{
public:

    HRESULT
    poll(DIJOYSTATE *js)
    {
        HRESULT    hr;

        if (joystick == NULL)
        {
            return S_OK;
        }

        // Poll the device to read the current state
        hr = joystick->Poll();
        if (FAILED(hr)) {
            // DInput is telling us that the input stream has been
            // interrupted. We aren't tracking any state between polls, so
            // we don't have any special reset that needs to be done. We
            // just re-acquire and try again.
            hr = joystick->Acquire();
            while (hr == DIERR_INPUTLOST) {
                hr = joystick->Acquire();
            }

            // If we encounter a fatal error, return failure.
            if ((hr == DIERR_INVALIDPARAM) || (hr == DIERR_NOTINITIALIZED)) {
                return E_FAIL;
            }

            // If another application has control of this device, return successfully.
            // We'll just have to wait our turn to use the joystick.
            if (hr == DIERR_OTHERAPPHASPRIO) {
                return S_OK;
            }
        }
        // Get the input's device state
        if (FAILED(hr = joystick->GetDeviceState(sizeof(DIJOYSTATE), js))) {
            return hr; // The device should have been acquired during the Poll()
        }

        return S_OK;
    }
    void GetDesktopResolution(int& horizontal, int& vertical)
    {
        RECT desktop;

        // Get a handle to the desktop window
        const HWND hDesktop = GetDesktopWindow();

        // Get the size of screen to the variable desktop
        GetWindowRect(hDesktop, &desktop);

        horizontal = desktop.right;
        vertical = desktop.bottom;
    }

    void moveMouse(int dx, int dy)
    {
        POINT pt;
        int horizontal = 0;
        int vertical = 0;

        GetDesktopResolution(horizontal, vertical);

        GetCursorPos(&pt);

        pt.x += dx;
        pt.y += dy;

        if (pt.x < 0)
        {
            pt.x = 0;
        }
        if (pt.x > horizontal)
        {
            pt.x = horizontal;
        }

        if (pt.y < 0)
        {
            pt.y = 0;
        }
        if (pt.y > vertical)
        {
            pt.y = vertical;
        }

        SetCursorPos(pt.x, pt.y);
    }

    void clickMouse()
    {
        if (GetKeyState(VK_LBUTTON) >= 0)
        {
            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
        }
    }
    void unclickMouse()
    {
        mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
    }

    void close()
    {
        if (joystick)
        {
            joystick->Unacquire();
        }
    }

    int start()
    {
        DIJOYSTATE js;                                        // struktura stanu joysticka

        // Create a DirectInput device
        if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
            IID_IDirectInput8, (VOID**)&di, NULL))) {
            return hr;
        }

        if (FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, enumCallback,
            NULL, DIEDFL_ATTACHEDONLY))) {
            return hr;
        }

        // sprawdzenie czy jest joystick
        if (joystick == NULL) {

            std::cout << "Joystick not found.\n";
            system("pause");
            return E_FAIL;
        }

        // ustawienia
        DIDEVCAPS capabilities;

        // zdefiniowanie formatu danych urzadzenia
        if (FAILED(hr = joystick->SetDataFormat(&c_dfDIJoystick)))
        {
            return hr;
        }

        // Powiazanie urzadzenia z oknem aplikacji
        if (FAILED(hr = joystick->SetCooperativeLevel(GetConsoleWindow(), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND))) {
            return hr;
        }

        // wczytanie ustawien joysticka
        capabilities.dwSize = sizeof(DIDEVCAPS);
        if (FAILED(hr = joystick->GetCapabilities(&capabilities))) {

            return hr;
        }

        // wyliczanie
        if (FAILED(hr = joystick->EnumObjects(enumAxesCallback, NULL, DIDFT_AXIS))) {
            return hr;
        }

        info.dwSize = sizeof(DIDEVICEINSTANCE);
        if (FAILED(hr = joystick->GetDeviceInfo(&info)))
        {
            return hr;
        }
        int i = 0;
        while (i < MAX_PATH && info.tszProductName[i] != 0)
        {
            std::cout << (char)info.tszProductName[i];
            i++;
        }
        std::cout << std::endl;
        system("pause");

        while (1)
        {
            poll(&js);

            if (js.rgbButtons[0] != 0)
                clickMouse();
            else
                unclickMouse();
            //clickMouse(js.rgbButtons[0]);

            for (int i = 0; i < 11; i++)
            {
                if (js.rgbButtons[i] != 0) std::cout << "Przycisk " << i + 1 << std::endl;
            }


            std::cout << "X: " << js.lX << std::endl;
            std::cout << "Y: " << js.lY << std::endl;
            std::cout << "Z: " << js.lZ << std::endl;

            moveMouse(js.lX, js.lY);

            //Sleep(400);
            std::cout << std::endl;
            system("cls");
        }

        close();

        system("pause");
    }
};

这就是我在MyForm.h中使用它的方式:

#pragma once
#include "Joy.cpp"

(...)
    public ref class MyForm : public System::Windows::Forms::Form
    {
    public:
        MyForm(void)
        {
            InitializeComponent(); 
            Joy joy;
            joy.start();
        }

这是我得到的errors

当我测试它时,我有一个main()函数而不是start()。我还尝试将enumCallback和enumAxesCallback函数放入类中,但它发生了其他错误。

有人看到我做错了吗?

感谢您的所有答案。

0 个答案:

没有答案