Skip to content

Instantly share code, notes, and snippets.

@lfzawacki
Created July 13, 2012 19:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lfzawacki/3106806 to your computer and use it in GitHub Desktop.
Save lfzawacki/3106806 to your computer and use it in GitHub Desktop.
force feedback
From bd9e9c08082419828098ee7b327448725d1455ca Mon Sep 17 00:00:00 2001
From: Lucas Zawacki <lfzawacki@gmail.com>
Date: Wed, 11 Jul 2012 14:24:04 -0300
Subject: joy.cpl: Correct joystick testing thread behavior (try 2)
The problem with the original behavior is that it starts a new thread each time the test tab is switched to, but
only stopped them on PSN_RESET. Now when the window receives PSN_KILLACTIVE (cancel button, X button or tab switch) or
PSN_RESET (ok button), the thread will rightfully die.
---
dlls/joy.cpl/main.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/joy.cpl/main.c b/dlls/joy.cpl/main.c
index eb8f982..e9b3a72 100644
--- a/dlls/joy.cpl/main.c
+++ b/dlls/joy.cpl/main.c
@@ -424,9 +424,11 @@ static INT_PTR CALLBACK test_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
}
break;
- case PSN_RESET:
+ case PSN_RESET: /* intentional fall-through */
+ case PSN_KILLACTIVE:
/* Stop input thread */
data->stop = TRUE;
+ MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, 0);
CloseHandle(thread);
break;
}
--
1.7.9.5
From 11ce24ec3c54f1a84349b785ae6f69f679748415 Mon Sep 17 00:00:00 2001
From: Lucas Zawacki <lfzawacki@gmail.com>
Date: Mon, 2 Jul 2012 20:11:13 -0300
Subject: [PATCH 2/3] joy.cpl: Tab for force feedback tests (try 3)
* Minor corrections to the effect selection logic
* Using simple solution to stop threads
---
dlls/joy.cpl/joy.h | 18 ++++
dlls/joy.cpl/joy.rc | 4 +
dlls/joy.cpl/main.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 282 insertions(+), 2 deletions(-)
diff --git a/dlls/joy.cpl/joy.h b/dlls/joy.cpl/joy.h
index 07c13fa..13efe1b 100644
--- a/dlls/joy.cpl/joy.h
+++ b/dlls/joy.cpl/joy.h
@@ -29,11 +29,22 @@
extern HMODULE hcpl;
+struct Effect {
+ IDirectInputEffect *effect;
+ DIEFFECT params;
+ DIEFFECTINFOW info;
+};
+
struct Joystick {
IDirectInputDevice8W *device;
DIDEVICEINSTANCEW instance;
int num_buttons;
int num_axes;
+ BOOL forcefeedback;
+ int num_effects;
+ int cur_effect;
+ int chosen_effect;
+ struct Effect *effects;
};
#define TEST_MAX_BUTTONS 32
@@ -43,6 +54,7 @@ struct JoystickData {
IDirectInput8W *di;
struct Joystick *joysticks;
int num_joysticks;
+ int num_ff;
int cur_joystick;
int chosen_joystick;
HWND buttons[TEST_MAX_BUTTONS];
@@ -76,6 +88,9 @@ struct JoystickData {
#define IDC_JOYSTICKBUTTON 3000
#define IDC_JOYSTICKAXES 4000
+#define IDC_FFSELECTCOMBO 2009
+#define IDC_FFEFFECTLIST 2010
+
/* constants */
#define TEST_POLL_TIME 100
@@ -95,4 +110,7 @@ struct JoystickData {
#define TEST_AXIS_MIN -40
#define TEST_AXIS_MAX 40
+#define FF_PLAY_TIME 2*DI_SECONDS
+#define FF_PERIOD_TIME FF_PLAY_TIME/4
+
#endif
diff --git a/dlls/joy.cpl/joy.rc b/dlls/joy.cpl/joy.rc
index 22d9253..0eb4378 100644
--- a/dlls/joy.cpl/joy.rc
+++ b/dlls/joy.cpl/joy.rc
@@ -59,6 +59,10 @@ STYLE WS_CAPTION | WS_CHILD | WS_DISABLED
CAPTION "Test Force Feedback"
FONT 8, "Ms Shell Dlg"
{
+ COMBOBOX IDC_FFSELECTCOMBO, 5, 5, 100, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS
+ LTEXT "Available Effects", IDC_STATIC, 10, 30, 100, 10
+ LISTBOX IDC_FFEFFECTLIST, 10, 40, 180, 70, WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY
+ LTEXT "Press any button in the controller to activate the chosen effect.", IDC_STATIC, 10, 110, 210, 25
}
#define WINE_FILENAME_STR "joy.cpl"
diff --git a/dlls/joy.cpl/main.c b/dlls/joy.cpl/main.c
index e9b3a72..40a0f6f9 100644
--- a/dlls/joy.cpl/main.c
+++ b/dlls/joy.cpl/main.c
@@ -88,6 +88,9 @@ static BOOL CALLBACK enum_callback(const DIDEVICEINSTANCEW *instance, void *cont
joystick->num_buttons = caps.dwButtons;
joystick->num_axes = caps.dwAxes;
+ joystick->forcefeedback = caps.dwFlags & DIDC_FORCEFEEDBACK;
+
+ if (joystick->forcefeedback) data->num_ff++;
return DIENUM_CONTINUE;
}
@@ -111,10 +114,19 @@ static void initialize_joysticks(struct JoystickData *data)
*/
static void destroy_joysticks(struct JoystickData *data)
{
- int i;
+ int i, j;
for (i = 0; i < data->num_joysticks; i++)
{
+
+ if (data->joysticks[i].forcefeedback)
+ {
+ for (j = 0; j < data->joysticks[i].num_effects; j++)
+ IDirectInputEffect_Release(data->joysticks[i].effects[j].effect);
+
+ HeapFree(GetProcessHeap(), 0, data->joysticks[i].effects);
+ }
+
IDirectInputDevice8_Unacquire(data->joysticks[i].device);
IDirectInputDevice8_Release(data->joysticks[i].device);
}
@@ -437,6 +449,252 @@ static INT_PTR CALLBACK test_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
return FALSE;
}
+/*********************************************************************
+ * Joystick force feedback testing functions
+ *
+ */
+
+static void initialize_effects_list(HWND hwnd, struct Joystick* joy)
+{
+ int i;
+
+ SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_RESETCONTENT, 0, 0);
+
+ for (i=0; i < joy->num_effects; i++)
+ {
+ /* Effect names start with GUID_, so we'll skip this part */
+ WCHAR *name = joy->effects[i].info.tszName + 5;
+ SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_ADDSTRING, 0, (LPARAM) name);
+ }
+}
+
+static void ff_handle_joychange(HWND hwnd, struct JoystickData *data)
+{
+ int sel;
+
+ if (data->num_ff == 0) return;
+
+ sel = SendDlgItemMessageW(hwnd, IDC_FFSELECTCOMBO, CB_GETCURSEL, 0, 0);
+ data->chosen_joystick = SendDlgItemMessageW(hwnd, IDC_FFSELECTCOMBO, CB_GETITEMDATA, sel, 0);
+ initialize_effects_list(hwnd, &data->joysticks[data->chosen_joystick]);
+}
+
+static void ff_handle_effectchange(HWND hwnd, struct Joystick *joy)
+{
+ int sel = SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_GETCURSEL, 0, 0);
+
+ if (sel < 0) return;
+
+ joy->chosen_effect = sel;
+}
+
+static DWORD WINAPI ff_input_thread(void *param)
+{
+ struct JoystickData *data = param;
+ DIJOYSTATE state;
+
+ ZeroMemory(&state, sizeof(state));
+
+ while (!data->stop)
+ {
+ int i;
+ struct Joystick *joy = &data->joysticks[data->chosen_joystick];
+ int chosen_effect = joy->chosen_effect;
+
+ /* Skip this if we have no effects */
+ if (joy->num_effects == 0 || chosen_effect < 0) continue;
+
+ poll_input(joy, &state);
+
+ for (i=0; i < joy->num_buttons; i++)
+ if (state.rgbButtons[i])
+ {
+ IDirectInputEffect_Start(joy->effects[chosen_effect].effect, 1, 0);
+ break;
+ }
+
+ Sleep(TEST_POLL_TIME);
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ * ff_effects_callback [internal]
+ * Enumerates, creates, sets the some parameters and stores all ff effects
+ * supported by the joystick. Works like enum_callback, counting the effects
+ * first and then storing them.
+ */
+static BOOL CALLBACK ff_effects_callback(const DIEFFECTINFOW *pdei, void *pvRef)
+{
+ HRESULT hr;
+ DIEFFECT dieffect;
+ DWORD axes[2] = {DIJOFS_X, DIJOFS_Y};
+ int direction[2] = {0, 0};
+ struct Joystick *joystick = pvRef;
+
+ if (joystick->effects == NULL)
+ {
+ joystick->num_effects += 1;
+ return DIENUM_CONTINUE;
+ }
+
+ hr = IDirectInputDevice8_Acquire(joystick->device);
+
+ if (FAILED(hr)) return DIENUM_CONTINUE;
+
+ ZeroMemory(&dieffect, sizeof(dieffect));
+
+ dieffect.dwSize = sizeof(dieffect);
+ dieffect.dwFlags = DIEFF_CARTESIAN;
+ dieffect.dwDuration = FF_PLAY_TIME;
+
+ dieffect.cAxes = 2;
+ dieffect.rgdwAxes = axes;
+ dieffect.rglDirection = direction;
+
+ if (IsEqualGUID(&pdei->guid, &GUID_RampForce))
+ {
+ DIRAMPFORCE rforce;
+
+ rforce.lStart = 0;
+ rforce.lEnd = DI_FFNOMINALMAX;
+
+ dieffect.cbTypeSpecificParams = sizeof(rforce);
+ dieffect.lpvTypeSpecificParams = &rforce;
+ dieffect.dwFlags |= DIEP_TYPESPECIFICPARAMS;
+ }
+ else if (IsEqualGUID(&pdei->guid, &GUID_ConstantForce))
+ {
+ DICONSTANTFORCE cforce;
+
+ cforce.lMagnitude = DI_FFNOMINALMAX;
+
+ dieffect.cbTypeSpecificParams = sizeof(cforce);
+ dieffect.lpvTypeSpecificParams = &cforce;
+ dieffect.dwFlags |= DIEP_TYPESPECIFICPARAMS;
+ }
+ else if (IsEqualGUID(&pdei->guid, &GUID_Sine) ||
+ IsEqualGUID(&pdei->guid, &GUID_Square) ||
+ IsEqualGUID(&pdei->guid, &GUID_Triangle) ||
+ IsEqualGUID(&pdei->guid, &GUID_SawtoothUp) ||
+ IsEqualGUID(&pdei->guid, &GUID_SawtoothDown))
+ {
+ DIPERIODIC pforce;
+
+ pforce.dwMagnitude = DI_FFNOMINALMAX;
+ pforce.lOffset = 0;
+ pforce.dwPhase = 0;
+ pforce.dwPeriod = FF_PERIOD_TIME;
+
+ dieffect.cbTypeSpecificParams = sizeof(pforce);
+ dieffect.lpvTypeSpecificParams = &pforce;
+ dieffect.dwFlags |= DIEP_TYPESPECIFICPARAMS;
+ }
+
+ hr = IDirectInputDevice2_CreateEffect(
+ joystick->device, &pdei->guid, &dieffect, &joystick->effects[joystick->cur_effect].effect, NULL);
+
+ joystick->effects[joystick->cur_effect].params = dieffect;
+ joystick->effects[joystick->cur_effect].info = *pdei;
+ joystick->cur_effect += 1;
+
+ return DIENUM_CONTINUE;
+}
+
+/*********************************************************************
+ * ff_dlgproc [internal]
+ *
+ */
+static INT_PTR CALLBACK ff_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, cur = 0;
+
+ data = (struct JoystickData*) ((PROPSHEETPAGEW*)lparam)->lParam;
+
+ /* Add joysticks with FF support to the combobox and get the effects */
+ for (i = 0; i < data->num_joysticks; i++)
+ {
+ struct Joystick *joy = &data->joysticks[i];
+
+ if (joy->forcefeedback)
+ {
+ SendDlgItemMessageW(hwnd, IDC_FFSELECTCOMBO, CB_ADDSTRING, 0, (LPARAM) joy->instance.tszInstanceName);
+ SendDlgItemMessageW(hwnd, IDC_FFSELECTCOMBO, CB_SETITEMDATA, cur, i);
+
+ cur++;
+
+ /* Count device effects and then store them */
+ joy->num_effects = 0;
+ joy->effects = NULL;
+ IDirectInputDevice8_EnumEffects(joy->device, ff_effects_callback, (void *) joy, 0);
+ joy->effects = HeapAlloc(GetProcessHeap(), 0, sizeof(struct Effect) * joy->num_effects);
+
+ joy->cur_effect = 0;
+ IDirectInputDevice8_EnumEffects(joy->device, ff_effects_callback, (void*) joy, 0);
+ }
+ }
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ switch(wparam)
+ {
+ case MAKEWPARAM(IDC_FFSELECTCOMBO, CBN_SELCHANGE):
+ ff_handle_joychange(hwnd, data);
+
+ SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_SETCURSEL, 0, 0);
+ ff_handle_effectchange(hwnd, &data->joysticks[data->chosen_joystick]);
+ break;
+
+ case MAKEWPARAM(IDC_FFEFFECTLIST, LBN_SELCHANGE):
+ ff_handle_effectchange(hwnd, &data->joysticks[data->chosen_joystick]);
+ break;
+ }
+ return TRUE;
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lparam)->code)
+ {
+ case PSN_SETACTIVE:
+ if (data->num_ff > 0)
+ {
+ DWORD tid;
+
+ data->stop = FALSE;
+ /* Set the first joystick as default */
+ SendDlgItemMessageW(hwnd, IDC_FFSELECTCOMBO, CB_SETCURSEL, 0, 0);
+ ff_handle_joychange(hwnd, data);
+
+ SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_SETCURSEL, 0, 0);
+ ff_handle_effectchange(hwnd, &data->joysticks[data->chosen_joystick]);
+
+ thread = CreateThread(NULL, 0, ff_input_thread, (void*) data, 0, &tid);
+ }
+ break;
+
+ case PSN_RESET: /* intentional fall-through */
+ case PSN_KILLACTIVE:
+ /* Stop ff thread */
+ data->stop = TRUE;
+ MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, 0);
+ CloseHandle(thread);
+ break;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
/******************************************************************************
* propsheet_callback [internal]
*/
@@ -491,7 +749,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_FORCEFEEDBACK);
- psp[id].pfnDlgProc = NULL;
+ psp[id].pfnDlgProc = ff_dlgproc;
psp[id].lParam = (INT_PTR) data;
id++;
--
1.7.9.5
From 84088df48a88dbe95a1a1e0195cd542025accc60 Mon Sep 17 00:00:00 2001
From: Lucas Zawacki <lfzawacki@gmail.com>
Date: Mon, 2 Jul 2012 21:19:29 -0300
Subject: [PATCH 3/3] joy.cpl: Added force feedback direction control (try 2)
---
dlls/joy.cpl/joy.h | 7 +++++++
dlls/joy.cpl/joy.rc | 5 ++++-
dlls/joy.cpl/main.c | 51 +++++++++++++++++++++++++++++++++++----------------
3 files changed, 46 insertions(+), 17 deletions(-)
diff --git a/dlls/joy.cpl/joy.h b/dlls/joy.cpl/joy.h
index 13efe1b..e40a71b 100644
--- a/dlls/joy.cpl/joy.h
+++ b/dlls/joy.cpl/joy.h
@@ -59,6 +59,7 @@ struct JoystickData {
int chosen_joystick;
HWND buttons[TEST_MAX_BUTTONS];
HWND axes[TEST_MAX_AXES];
+ HWND ff_axis;
BOOL stop;
};
@@ -90,6 +91,7 @@ struct JoystickData {
#define IDC_FFSELECTCOMBO 2009
#define IDC_FFEFFECTLIST 2010
+#define IDC_FFAXIS 2011
/* constants */
#define TEST_POLL_TIME 100
@@ -110,6 +112,11 @@ struct JoystickData {
#define TEST_AXIS_MIN -40
#define TEST_AXIS_MAX 40
+#define FF_AXIS_X 373
+#define FF_AXIS_Y 98
+#define FF_AXIS_SIZE_X 5
+#define FF_AXIS_SIZE_Y 5
+
#define FF_PLAY_TIME 2*DI_SECONDS
#define FF_PERIOD_TIME FF_PLAY_TIME/4
diff --git a/dlls/joy.cpl/joy.rc b/dlls/joy.cpl/joy.rc
index 0eb4378..1bfcfee 100644
--- a/dlls/joy.cpl/joy.rc
+++ b/dlls/joy.cpl/joy.rc
@@ -62,7 +62,10 @@ FONT 8, "Ms Shell Dlg"
COMBOBOX IDC_FFSELECTCOMBO, 5, 5, 100, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS
LTEXT "Available Effects", IDC_STATIC, 10, 30, 100, 10
LISTBOX IDC_FFEFFECTLIST, 10, 40, 180, 70, WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY
- LTEXT "Press any button in the controller to activate the chosen effect.", IDC_STATIC, 10, 110, 210, 25
+ LTEXT "Press any button in the controller to activate the chosen effect." \
+ "The effect direction can be changed with the controller axis.", \
+ IDC_STATIC, 10, 110, 210, 25
+ GROUPBOX "Direction", IDC_STATIC, 220, 30, 60, 60
}
#define WINE_FILENAME_STR "joy.cpl"
diff --git a/dlls/joy.cpl/main.c b/dlls/joy.cpl/main.c
index 40a0f6f9..8e29612 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;
+ DIPROPRANGE proprange;
DIDEVCAPS caps;
if (data->joysticks == NULL)
@@ -92,6 +93,16 @@ static BOOL CALLBACK enum_callback(const DIDEVICEINSTANCEW *instance, void *cont
if (joystick->forcefeedback) data->num_ff++;
+ /* Set axis range to ease the GUI visualization */
+ proprange.diph.dwSize = sizeof(DIPROPRANGE);
+ proprange.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ proprange.diph.dwHow = DIPH_DEVICE;
+ proprange.diph.dwObj = 0;
+ proprange.lMin = TEST_AXIS_MIN;
+ proprange.lMax = TEST_AXIS_MAX;
+
+ IDirectInputDevice_SetProperty(joystick->device, DIPROP_RANGE, &proprange.diph);
+
return DIENUM_CONTINUE;
}
@@ -340,8 +351,6 @@ static void draw_joystick_buttons(HWND hwnd, struct JoystickData* data)
static void draw_joystick_axes(HWND hwnd, struct JoystickData* data)
{
int i;
- struct Joystick *joy;
- DIPROPRANGE propRange;
HINSTANCE hinst = (HINSTANCE) GetWindowLongPtrW(hwnd, GWLP_HINSTANCE);
static const WCHAR button_class[] = {'B','u','t','t','o','n','\0'};
static const WCHAR axes_names[TEST_MAX_AXES][7] = { {'X',',','Y','\0'}, {'R','x',',','R','y','\0'},
@@ -349,20 +358,6 @@ static void draw_joystick_axes(HWND hwnd, struct JoystickData* data)
static const DWORD axes_idc[TEST_MAX_AXES] = { IDC_TESTGROUPXY, IDC_TESTGROUPRXRY,
IDC_TESTGROUPZRZ, IDC_TESTGROUPPOV };
- /* Set axis range to ease the GUI visualization */
- for (i = 0; i < data->num_joysticks; i++)
- {
- joy = &data->joysticks[i];
- propRange.diph.dwSize = sizeof(DIPROPRANGE);
- propRange.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- propRange.diph.dwHow = DIPH_DEVICE;
- propRange.diph.dwObj = 0;
- propRange.lMin = TEST_AXIS_MIN;
- propRange.lMax = TEST_AXIS_MAX;
-
- IDirectInputDevice_SetProperty(joy->device, DIPROP_RANGE, &propRange.diph);
- }
-
for (i = 0; i < TEST_MAX_AXES; i++)
{
/* Set axis box name */
@@ -453,6 +448,17 @@ static INT_PTR CALLBACK test_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
* Joystick force feedback testing functions
*
*/
+static void draw_ff_axis(HWND hwnd, struct JoystickData *data)
+{
+ HINSTANCE hinst = (HINSTANCE) GetWindowLongPtrW(hwnd, GWLP_HINSTANCE);
+ static WCHAR button_class[] = {'B','u','t','t','o','n','\0'};
+
+ /* Draw direction axis */
+ data->ff_axis = CreateWindowW( button_class, NULL, WS_CHILD | WS_VISIBLE,
+ FF_AXIS_X, FF_AXIS_Y,
+ FF_AXIS_SIZE_X, FF_AXIS_SIZE_Y,
+ hwnd, (HMENU) IDC_FFAXIS, NULL, hinst);
+}
static void initialize_effects_list(HWND hwnd, struct Joystick* joy)
{
@@ -500,15 +506,26 @@ static DWORD WINAPI ff_input_thread(void *param)
int i;
struct Joystick *joy = &data->joysticks[data->chosen_joystick];
int chosen_effect = joy->chosen_effect;
+ DIEFFECT *dieffect;
+ DWORD flags = DIEP_AXES | DIEP_DIRECTION | DIEP_NORESTART;
/* Skip this if we have no effects */
if (joy->num_effects == 0 || chosen_effect < 0) continue;
poll_input(joy, &state);
+ /* Set ff parameters and draw the axis */
+ dieffect = &joy->effects[chosen_effect].params;
+ dieffect->rgdwAxes[0] = state.lX;
+ dieffect->rgdwAxes[1] = state.lY;
+
+ SetWindowPos(data->ff_axis, 0, FF_AXIS_X + state.lX, FF_AXIS_Y + state.lY,
+ 0, 0, SWP_NOZORDER | SWP_NOSIZE);
+
for (i=0; i < joy->num_buttons; i++)
if (state.rgbButtons[i])
{
+ IDirectInputEffect_SetParameters(joy->effects[chosen_effect].effect, dieffect, flags);
IDirectInputEffect_Start(joy->effects[chosen_effect].effect, 1, 0);
break;
}
@@ -643,6 +660,8 @@ static INT_PTR CALLBACK ff_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
}
}
+ draw_ff_axis(hwnd, data);
+
return TRUE;
}
--
1.7.9.5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment