[PATCH 1/3] joy.cpl: Joystick testing tab and button tests

Lucas Fialho Zawacki lfzawacki at gmail.com
Thu Jun 7 12:44:12 CDT 2012


From: Lucas Fialho Zawacki <lfzawacki at gmail.com>

---
 dlls/joy.cpl/joy.h  |   18 +++++
 dlls/joy.cpl/joy.rc |    2 +
 dlls/joy.cpl/main.c |  181 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 200 insertions(+), 1 deletion(-)

diff --git a/dlls/joy.cpl/joy.h b/dlls/joy.cpl/joy.h
index be7907a..e860b1b 100644
--- a/dlls/joy.cpl/joy.h
+++ b/dlls/joy.cpl/joy.h
@@ -36,12 +36,16 @@ struct Joystick {
     int num_axes;
 };
 
+#define TEST_MAX_BUTTONS    32
+
 struct JoystickData {
     IDirectInput8W *di;
     struct Joystick *joysticks;
     int num_joysticks;
     int cur_joystick;
     int chosen_joystick;
+    HWND buttons[TEST_MAX_BUTTONS];
+    BOOL stop;
 };
 
 #define NUM_PROPERTY_PAGES 3
@@ -61,5 +65,19 @@ struct JoystickData {
 #define IDC_BUTTONDISABLE   2001
 #define IDC_BUTTONENABLE    2002
 #define IDC_DISABLEDLIST    2003
+#define IDC_TESTSELECTCOMBO 2004
+
+#define IDC_JOYSTICKBUTTON  3000
+
+/* constants */
+#define TEST_POLL_TIME      100
+
+#define TEST_BUTTON_COL_MAX 8
+#define TEST_BUTTON_X       15
+#define TEST_BUTTON_Y       200
+#define TEST_NEXT_BUTTON_X  45
+#define TEST_NEXT_BUTTON_Y  30
+#define TEST_BUTTON_SIZE_X  30
+#define TEST_BUTTON_SIZE_Y  25
 
 #endif
diff --git a/dlls/joy.cpl/joy.rc b/dlls/joy.cpl/joy.rc
index a2e1441..ba341f9 100644
--- a/dlls/joy.cpl/joy.rc
+++ b/dlls/joy.cpl/joy.rc
@@ -46,6 +46,8 @@ STYLE WS_CAPTION | WS_CHILD | WS_DISABLED
 CAPTION "Test Joystick"
 FONT 8, "Ms Shell Dlg"
 {
+    COMBOBOX        IDC_TESTSELECTCOMBO, 5, 5, 100, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS
+    GROUPBOX        "Buttons", IDC_STATIC, 0, 110, 250, 90
 }
 
 IDD_FORCEFEEDBACK DIALOG 0, 0, 250, 200
diff --git a/dlls/joy.cpl/main.c b/dlls/joy.cpl/main.c
index db72281..2e8be0a 100644
--- a/dlls/joy.cpl/main.c
+++ b/dlls/joy.cpl/main.c
@@ -67,6 +67,7 @@ static BOOL CALLBACK enum_callback(const DIDEVICEINSTANCEW *instance, void *cont
 {
     struct JoystickData *data = context;
     struct Joystick *joystick;
+    DIDEVCAPS caps;
 
     if (data->joysticks == NULL)
     {
@@ -82,6 +83,12 @@ static BOOL CALLBACK enum_callback(const DIDEVICEINSTANCEW *instance, void *cont
 
     joystick->instance = *instance;
 
+    caps.dwSize = sizeof(caps);
+    IDirectInputDevice8_GetCapabilities(joystick->device, &caps);
+
+    joystick->num_buttons = caps.dwButtons;
+    joystick->num_axes = caps.dwAxes;
+
     return DIENUM_CONTINUE;
 }
 
@@ -163,6 +170,178 @@ INT_PTR CALLBACK list_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
     return FALSE;
 }
 
+/*********************************************************************
+ * Joystick testing functions
+ *
+ */
+static void poll_input(const struct Joystick *joy, DIJOYSTATE *state)
+{
+    HRESULT  hr;
+
+    hr = IDirectInputDevice8_Poll(joy->device);
+
+    /* If it failed, try to acquire the joystick */
+    if (FAILED(hr))
+    {
+        hr = IDirectInputDevice8_Acquire(joy->device);
+        while (hr == DIERR_INPUTLOST) hr = IDirectInputDevice8_Acquire(joy->device);
+    }
+
+    if (hr == DIERR_OTHERAPPHASPRIO) return;
+
+    IDirectInputDevice8_GetDeviceState(joy->device, sizeof(DIJOYSTATE), state);
+}
+
+static DWORD WINAPI input_thread(void *param)
+{
+    DIJOYSTATE state;
+    struct JoystickData *data = param;
+
+    ZeroMemory(&state, sizeof(state));
+
+    while (!data->stop)
+    {
+        int i;
+        poll_input(&data->joysticks[data->chosen_joystick], &state);
+
+        /* Indicate pressed buttons */
+        for (i = 0; i < data->joysticks[data->chosen_joystick].num_buttons; i++)
+            if (state.rgbButtons[i])
+                SendMessageW(data->buttons[i], BM_SETSTATE, TRUE, 0);
+
+        Sleep(TEST_POLL_TIME);
+
+        /* Reset button state */
+        for (i = 0; i < data->joysticks[data->chosen_joystick].num_buttons; i++)
+            SendMessageW(data->buttons[i], BM_SETSTATE, FALSE, 0);
+    }
+
+    return 0;
+}
+
+static void test_handle_joychange(HWND hwnd, struct JoystickData *data)
+{
+    int i;
+
+    if (data->num_joysticks == 0) return;
+
+    data->chosen_joystick = SendDlgItemMessageW(hwnd, IDC_TESTSELECTCOMBO, CB_GETCURSEL, 0, 0);
+
+    /* Enable only  buttons present in the device */
+    for (i = 0; i < TEST_MAX_BUTTONS; i++)
+        ShowWindow(data->buttons[i], i <= data->joysticks[data->chosen_joystick].num_buttons);
+}
+
+/*********************************************************************
+ * button_number_to_wchar [internal]
+ *  Transforms an integer in the interval [0,99] into a 2 character WCHAR string
+ */
+static void button_number_to_wchar(int n, WCHAR str[3])
+{
+    str[1] = n % 10 + '0';
+    n /= 10;
+    str[0] = n % 10 + '0';
+    str[2] = '\0';
+}
+
+static void draw_joystick_buttons(HWND hwnd, struct JoystickData* data)
+{
+    int i;
+    int row = 0, col = 0;
+    WCHAR button_label[3];
+    HINSTANCE hinst = (HINSTANCE) GetWindowLongPtrW(hwnd, GWLP_HINSTANCE);
+    static WCHAR button_class[] = {'B','u','t','t','o','n','\0'};
+
+    for (i = 0; i < TEST_MAX_BUTTONS; i++)
+    {
+        if ((i % TEST_BUTTON_COL_MAX) == 0 && i != 0)
+        {
+            row += 1;
+            col = 0;
+        }
+
+        button_number_to_wchar(i + 1, button_label);
+
+        data->buttons[i] = CreateWindowW(button_class, button_label, WS_CHILD,
+            TEST_BUTTON_X + TEST_NEXT_BUTTON_X*col, TEST_BUTTON_Y + TEST_NEXT_BUTTON_Y*row,
+            TEST_BUTTON_SIZE_X, TEST_BUTTON_SIZE_Y,
+            hwnd, NULL, NULL, hinst);
+
+        col += 1;
+    }
+}
+
+/*********************************************************************
+ * test_dlgproc [internal]
+ *
+ */
+INT_PTR CALLBACK test_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+    static HANDLE thread;
+    static struct JoystickData *data;
+    TRACE("(%p, 0x%08x/%d, 0x%lx)\n", hwnd, msg, msg, lparam);
+
+    switch (msg)
+    {
+        case WM_INITDIALOG:
+        {
+            int i;
+
+            data = (struct JoystickData*) ((PROPSHEETPAGEW*)lparam)->lParam;
+
+            /* Add enumerated joysticks to the combobox */
+            for (i = 0; i < data->num_joysticks; i++)
+            {
+                struct Joystick *joy = &data->joysticks[i];
+                SendDlgItemMessageW(hwnd, IDC_TESTSELECTCOMBO, CB_ADDSTRING, 0, (LPARAM) joy->instance.tszInstanceName);
+            }
+
+            draw_joystick_buttons(hwnd, data);
+
+            return TRUE;
+        }
+
+        case WM_COMMAND:
+            switch(wparam)
+            {
+                case MAKEWPARAM(IDC_TESTSELECTCOMBO, CBN_SELCHANGE):
+                    test_handle_joychange(hwnd, data);
+                break;
+            }
+            return TRUE;
+
+        case WM_NOTIFY:
+            switch(((LPNMHDR)lparam)->code)
+            {
+                case PSN_SETACTIVE:
+                {
+                    DWORD tid;
+
+                    /* Initialize input thread */
+                    if (data->num_joysticks > 0)
+                    {
+                        data->stop = FALSE;
+
+                        /* Set the first joystick as default */
+                        SendDlgItemMessageW(hwnd, IDC_TESTSELECTCOMBO, CB_SETCURSEL, 0, 0);
+                        test_handle_joychange(hwnd, data);
+
+                        thread = CreateThread(NULL, 0, input_thread, (void*) data, 0, &tid);
+                    }
+                }
+                break;
+
+                case PSN_RESET:
+                    /* Stop input thread */
+                    data->stop = TRUE;
+                    CloseHandle(thread);
+                break;
+            }
+            return TRUE;
+    }
+    return FALSE;
+}
+
 /******************************************************************************
  * propsheet_callback [internal]
  */
@@ -210,7 +389,7 @@ static void display_cpl_sheets(HWND parent, struct JoystickData *data)
     psp[id].dwSize = sizeof (PROPSHEETPAGEW);
     psp[id].hInstance = hcpl;
     psp[id].u.pszTemplate = MAKEINTRESOURCEW(IDD_TEST);
-    psp[id].pfnDlgProc = NULL;
+    psp[id].pfnDlgProc = test_dlgproc;
     psp[id].lParam = (INT_PTR) data;
     id++;
 
-- 
1.7.9.5




More information about the wine-patches mailing list