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.