Using Joystick in Windows Forms application

﹥>﹥吖頭↗ 提交于 2019-12-25 04:47:14

问题


I've got a problem with my application. I wrote a code that works fine in console, but I need to make a GUI. This application let me control a mouse with joystick. I'm using Direcinput library. It is reading position of joystick and its name.

Here is my code:

#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");
    }
};

This is how I'm using it in MyForm.h:

#pragma once
#include "Joy.cpp"

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

Here is the errors that I get.

When I was testing it, I had an main() function instead of start(). I also tried to put enumCallback and enumAxesCallback function into class, but it occured other errors.

Does anybody sees what am I doing wrong?

Thanks for all your answers.

来源:https://stackoverflow.com/questions/27114150/using-joystick-in-windows-forms-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!