By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,761 Members | 1,188 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,761 IT Pros & Developers. It's quick & easy.

Joystick reading in Form Application

P: 52
Hi,

I have a Windows Form Application with one button and a textbox. How should I approach if I want the program to display the X value of a joystick plugged in the USB port of the PC when the button is pressed? I heard from a friend it should only take around 20 lines to do so.

At first I tried using an open source library called libusb-win32; but even though I could get the program to find the device according to its IDs I wasn't able to read values off it. Then I tried to use DirectInput in DirectX SDK and followed the tutorial on msdn, but the callback functions in it didn't work because that tutorial seems to be for MFC applications or Windows API.

The problem is basically "Joystick reading in Form Application"; sounds simple but I've stucked on this for at least 30 hours :(. If you know ways of doing this or sample code on the net, please give some advices.

Thanks in advance



ps. new thread 'cause the problem's no longer limited to DirectInput...
Oct 6 '08 #1
Share this Question
Share on Google+
1 Reply


P: 52
I think I also have it now. This is just a form with a textbox and a button which when pressed updates the X-axis value of joystick to the textbox.

Althought it doesn't seem to do anythinghh most of the time, I did encounter for once or twice that the value was updated correctly when the button is pressed. It seems completely random.

Expand|Select|Wrap|Line Numbers
  1. #define DIRECTINPUT_VERSION 0x0800
  2. #include <windows.h>
  3. #include <commctrl.h>
  4. #include <basetsd.h>
  5. #include <dinput.h>
  6. #include <dinputd.h>
  7. #include <assert.h>
  8. #include <oleauto.h>
  9. #include <shellapi.h>
  10. #pragma warning( disable : 4996 ) // disable deprecated warning 
  11. #pragma managed(push, off)
  12. #include <strsafe.h>
  13. #pragma managed(pop)
  14. #pragma warning( default : 4996 ) 
  15. #include "resource.h"
  16.  
  17. // global variables
  18. HINSTANCE  g_hinst = GetModuleHandle(NULL);
  19. HRESULT         hr = CoInitialize(0); 
  20. LPDIRECTINPUT8  g_pDI = NULL;
  21. LPDIRECTINPUTDEVICE8 joystick = NULL;
  22. HWND hDlg = NULL;
  23.  
  24. int valueX = 0;
  25.  
  26.  
  27. HRESULT CreateDevice(
  28.     REFGUID rguid,
  29.     LPDIRECTINPUTDEVICE * lplpDirectInputDevice,
  30.     LPUNKNOWN pUnkOuter
  31. );
  32.  
  33. HRESULT EnumDevices(
  34.     DWORD dwDevType,
  35.     LPDIENUMDEVICESCALLBACK lpCallback,
  36.     LPVOID pvRef,
  37.     DWORD dwFlags
  38. );
  39.  
  40. void initialise_global_vars_of_joystick()
  41. {
  42.     g_hinst = GetModuleHandle(NULL);
  43.     hr = CoInitialize(0); 
  44.     g_pDI = NULL;
  45.     joystick = NULL;
  46.     HWND hDlg = NULL;
  47. }
  48.  
  49. BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext)
  50. {
  51.     // Obtain an interface to the enumerated joystick.
  52.     hr = g_pDI->CreateDevice(pdidInstance->guidInstance, &joystick, NULL);
  53.     if(FAILED(hr)) 
  54.         return DIENUM_CONTINUE;
  55.  
  56.     return DIENUM_STOP;
  57. }
  58.  
  59. BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* instance, VOID* context)
  60. {
  61.     hDlg = (HWND)context;
  62.  
  63.     DIPROPRANGE propRange; 
  64.     propRange.diph.dwSize       = sizeof(DIPROPRANGE); 
  65.     propRange.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
  66.     propRange.diph.dwHow        = DIPH_BYID; 
  67.     propRange.diph.dwObj        = instance->dwType;
  68.     propRange.lMin              = 0; 
  69.     propRange.lMax              = +255; 
  70.  
  71.     // Set the range for the axis
  72.     if (FAILED(joystick->SetProperty(DIPROP_RANGE, &propRange.diph))) {
  73.         return DIENUM_STOP;
  74.     }
  75.  
  76.     return DIENUM_CONTINUE;
  77. }
  78.  
  79. HRESULT UpdateInputState(HWND hDlg)
  80. {
  81.     CHAR        strText[128]; // Device state text
  82.     DIJOYSTATE2 js;           // Direct Input joystick state 
  83.     CHAR*       str;
  84.  
  85.     if (NULL == joystick) 
  86.         return S_OK;
  87.  
  88.     // Poll the device to read the current state
  89.     hr = joystick->Poll(); 
  90.     if (FAILED(hr))  
  91.     {
  92.         // Attempt to reacquire joystick
  93.     }
  94.     hr = joystick->GetDeviceState(sizeof(DIJOYSTATE2), &js);
  95.     if (FAILED(hr))
  96.         return hr;
  97.  
  98.     valueX = js.lX;
  99.     js.lY;
  100.     js.rglSlider;
  101.  
  102.     return hr;
  103. }
  104.  
  105.  
  106. #pragma once
  107.  
  108.  
  109. namespace test {
  110.  
  111.     using namespace System;
  112.     using namespace System::ComponentModel;
  113.     using namespace System::Collections;
  114.     using namespace System::Windows::Forms;
  115.     using namespace System::Data;
  116.     using namespace System::Drawing;
  117.  
  118.     /// <summary>
  119.     /// Summary for Form1
  120.     ///
  121.     /// WARNING: If you change the name of this class, you will need to change the
  122.     ///          'Resource File Name' property for the managed resource compiler tool
  123.     ///          associated with all .resx files this class depends on.  Otherwise,
  124.     ///          the designers will not be able to interact properly with localized
  125.     ///          resources associated with this form.
  126.     /// </summary>
  127.     public ref class Form1 : public System::Windows::Forms::Form
  128.     {
  129.     public:
  130.         Form1(void)
  131.         {
  132.             InitializeComponent();
  133.             //
  134.             //TODO: Add the constructor code here
  135.             //
  136.  
  137.         }
  138.  
  139.         /*virtual void WndProc(Message% m) override { 
  140.             if(m.Msg == WM_DEVICECHANGE) { 
  141.                  //do stuff 
  142.             }
  143.         }*/
  144.  
  145.         void detect(void)
  146.         {
  147.             hr = DirectInput8Create(g_hinst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&g_pDI, NULL);
  148.             if FAILED(hr) 
  149.             { 
  150.                 // DirectInput not available; take appropriate action 
  151.             }
  152.  
  153.             //g_pDI is an initialized pointer to IDirectInput8
  154.             g_pDI->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY);
  155.  
  156.             if (FAILED(hr = joystick->SetDataFormat(&c_dfDIJoystick2)))
  157.             {
  158.                 // DirectInput not available; take appropriate action
  159.             }
  160.  
  161.             if (FAILED(hr = joystick->SetCooperativeLevel(NULL, DISCL_EXCLUSIVE | DISCL_FOREGROUND)))
  162.             {
  163.  
  164.             }
  165.  
  166.             DIDEVCAPS g_diDevCaps;
  167.             g_diDevCaps.dwSize = sizeof(DIDEVCAPS);
  168.             if (FAILED(hr = joystick->GetCapabilities(&g_diDevCaps)))
  169.             {
  170.  
  171.             }
  172.  
  173.             if (FAILED(hr = joystick->EnumObjects(EnumAxesCallback, NULL, DIDFT_AXIS)))
  174.             {
  175.  
  176.             }
  177.  
  178.             hr = joystick->Poll(); 
  179.             if (FAILED(hr)) 
  180.             {
  181.                 hr = joystick->Acquire();
  182.                 while(hr == DIERR_INPUTLOST) 
  183.                     hr = joystick->Acquire();
  184.                 // return S_OK; 
  185.             }
  186.  
  187.             hr = UpdateInputState(hDlg);
  188.         }
  189.  
  190.  
  191.     protected:
  192.         /// <summary>
  193.         /// Clean up any resources being used.
  194.         /// </summary>
  195.         ~Form1()
  196.         {
  197.             if (components)
  198.             {
  199.                 delete components;
  200.             }
  201.         }
  202.     private: System::Windows::Forms::TextBox^  textBox1;
  203.     protected: 
  204.     private: System::Windows::Forms::Button^  button1;
  205.  
  206.     private:
  207.         /// <summary>
  208.         /// Required designer variable.
  209.         /// </summary>
  210.         System::ComponentModel::Container ^components;
  211.  
  212.  
  213.  
  214. #pragma region Windows Form Designer generated code
  215.         /// <summary>
  216.         /// Required method for Designer support - do not modify
  217.         /// the contents of this method with the code editor.
  218.         /// </summary>
  219.         void InitializeComponent(void)
  220.         {
  221.             this->textBox1 = (gcnew System::Windows::Forms::TextBox());
  222.             this->button1 = (gcnew System::Windows::Forms::Button());
  223.             this->SuspendLayout();
  224.             // 
  225.             // textBox1
  226.             // 
  227.             this->textBox1->Location = System::Drawing::Point(112, 101);
  228.             this->textBox1->Name = L"textBox1";
  229.             this->textBox1->Size = System::Drawing::Size(100, 22);
  230.             this->textBox1->TabIndex = 0;
  231.             this->textBox1->Text = L"default";
  232.             // 
  233.             // button1
  234.             // 
  235.             this->button1->Location = System::Drawing::Point(82, 147);
  236.             this->button1->Name = L"button1";
  237.             this->button1->Size = System::Drawing::Size(75, 23);
  238.             this->button1->TabIndex = 1;
  239.             this->button1->Text = L"button1";
  240.             this->button1->UseVisualStyleBackColor = true;
  241.             this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
  242.             // 
  243.             // Form1
  244.             // 
  245.             this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
  246.             this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
  247.             this->ClientSize = System::Drawing::Size(292, 266);
  248.             this->Controls->Add(this->button1);
  249.             this->Controls->Add(this->textBox1);
  250.             this->Name = L"Form1";
  251.             this->Text = L"Form1";
  252.             this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
  253.             this->ResumeLayout(false);
  254.             this->PerformLayout();
  255.  
  256.         }
  257. #pragma endregion
  258.     private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
  259.              }
  260.     private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
  261.                  try {
  262.                      initialise_global_vars_of_joystick();
  263.                      detect();
  264.                  } catch (Exception ^ex) {
  265.                      MessageBox:: Show("No device detected!", "Error");
  266.                  }
  267.                  textBox1->Text = valueX + "";
  268.              }
  269. };
  270. }
I also heard that overriding WndProc(Message% m) is a way to go, but I don't know how to do that...
Oct 9 '08 #2

Post your reply

Sign in to post your reply or Sign up for a free account.