in Lilypad/Config.cpp [1279:1622]
INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM lParam) {
int index = (hWnd == PropSheet_IndexToHwnd(hWndProp, 1));
int slot;
int port = GetPort(hWnd, &slot);
HWND hWndList = GetDlgItem(hWnd, IDC_LIST);
switch (msg) {
case WM_INITDIALOG:
{
ListView_SetExtendedListViewStyleEx(hWndList, LVS_EX_DOUBLEBUFFER, LVS_EX_DOUBLEBUFFER);
LVCOLUMN c;
c.mask = LVCF_TEXT | LVCF_WIDTH;
c.cx = 101;
c.pszText = L"Device";
ListView_InsertColumn(hWndList, 0, &c);
c.cx = 70;
c.pszText = L"PC Control";
ListView_InsertColumn(hWndList, 1, &c);
c.cx = 84;
c.pszText = L"PS2 Control";
ListView_InsertColumn(hWndList, 2, &c);
selected = 0;
port = (int)((PROPSHEETPAGE *)lParam)->lParam & 1;
slot = (int)((PROPSHEETPAGE *)lParam)->lParam >> 1;
hWnds[port][slot] = hWnd;
SendMessage(hWndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
SetupLogSlider(GetDlgItem(hWnd, IDC_SLIDER1));
SetupLogSlider(GetDlgItem(hWnd, IDC_SLIDER_DEADZONE));
if (port || slot)
EnableWindow(GetDlgItem(hWnd, ID_IGNORE), 0);
Populate(port, slot);
}
break;
case WM_DEVICECHANGE:
if (wParam == DBT_DEVNODES_CHANGED) {
EndBinding(hWnd);
RefreshEnabledDevicesAndDisplay(1, hWndGeneral, 1);
}
break;
case WM_TIMER:
// ignore generic timer callback and handle the hwnd-specific one which comes later
if(hWnd == 0) return 0;
if (!selected || selected == 0xFF) {
// !selected is mostly for device added/removed when binding.
selected = 0xFF;
EndBinding(hWnd);
}
else {
unsigned int uid;
int value;
// The old code re-bound our button hWndProcEater to GetDlgItem(hWnd, selected). But at best hWnd
// was null (WM_TIMER is passed twice, once with a null parameter, and a second time that is hWnd
// specific), and at worst 'selected' is a post-processed code "based" on cmd, so GetDlgItem
// *always* returned NULL anyway. This resulted in hWndButton being null, which meant Device code
// used hWnd instead. This may have caused odd behavior since the callbacks were still all eaten
// by the initial GetDlgItem(hWnd, cmd) selection made when the timer was initialized.
InitInfo info = {selected==0x7F, 1, hWndProp, &hWndButtonProc};
Device *dev = dm->GetActiveDevice(&info, &uid, &index, &value);
if (dev) {
int command = selected;
// Good idea to do this first, as BindCommand modifies the ListView, which will
// call it anyways, which is a bit funky.
EndBinding(hWnd);
UnselectAll(hWndList);
int index = -1;
if (command == 0x7F && dev->api == IGNORE_KEYBOARD) {
index = BindCommand(dev, uid, 0, 0, command, BASE_SENSITIVITY, 0, 0);
}
else if (command < 0x30) {
index = BindCommand(dev, uid, port, slot, command, BASE_SENSITIVITY, 0, 0);
}
if (index >= 0) {
PropSheet_Changed(hWndProp, hWnds[port][slot]);
ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED);
ListView_EnsureVisible(hWndList, index, 0);
}
}
}
break;
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
EndBinding(hWnd);
break;
case PSM_CANCELTOCLOSE:
// Load();
break;
case WM_ACTIVATE:
EndBinding(hWnd);
break;
case WM_NOTIFY:
{
PSHNOTIFY* n = (PSHNOTIFY*) lParam;
if (n->hdr.hwndFrom == hWndProp) {
switch(n->hdr.code) {
case PSN_QUERYCANCEL:
case PSN_KILLACTIVE:
EndBinding(hWnd);
return 0;
case PSN_SETACTIVE:
return 0;
case PSN_APPLY:
SetWindowLong(hWnd, DWL_MSGRESULT, PSNRET_NOERROR);
return 1;
}
break;
}
else if (n->hdr.idFrom == IDC_LIST) {
static int NeedUpdate = 0;
if (n->hdr.code == LVN_KEYDOWN) {
NMLVKEYDOWN *key = (NMLVKEYDOWN *) n;
if (key->wVKey == VK_DELETE ||
key->wVKey == VK_BACK) {
if (DeleteSelected(port, slot))
PropSheet_Changed(hWndProp, hWnds[0]);
}
}
// Update sensitivity and motor/binding display on redraw
// rather than on itemchanged. This reduces blinking, as
// I get 3 LVN_ITEMCHANGED messages, and first is sent before
// the new item is set as being selected.
else if (n->hdr.code == LVN_ITEMCHANGED) {
NeedUpdate = 1;
}
else if (n->hdr.code == NM_CUSTOMDRAW && NeedUpdate) {
NeedUpdate = 0;
SelChanged(port, slot);
}
}
}
break;
case WM_HSCROLL:
{
int id = GetDlgCtrlID((HWND)lParam);
int val = GetLogSliderVal(hWnd, id);
if (id == IDC_SLIDER1) {
ChangeValue(port, slot, &val, 0, 0);
}
else if (id == IDC_SLIDER_DEADZONE) {
ChangeValue(port, slot, 0, 0, &val);
}
else {
ChangeEffect(port, slot, id, &val, 0);
}
}
break;
case WM_COMMAND:
if (HIWORD(wParam)==CBN_SELCHANGE && LOWORD(wParam) == IDC_AXIS_DIRECTION) {
int index = ListView_GetNextItem(hWndList, -1, LVNI_SELECTED);
if (index >= 0) {
int cbsel = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0);
if (cbsel >= 0) {
ForceFeedbackBinding *ffb;
Binding *b;
Device *dev;
if (GetBinding(port, slot, index, dev, b, ffb)) {
const static unsigned int axisUIDs[3] = {UID_AXIS_NEG, UID_AXIS_POS, UID_AXIS};
int uid = dev->virtualControls[b->controlIndex].uid;
uid = (uid&0x00FFFFFF) | axisUIDs[cbsel];
Binding backup = *b;
DeleteSelected(port, slot);
int index = BindCommand(dev, uid, port, slot, backup.command, backup.sensitivity, backup.turbo, backup.deadZone);
ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED);
PropSheet_Changed(hWndProp, hWnd);
}
}
}
}
else if (HIWORD(wParam)==CBN_SELCHANGE && LOWORD(wParam) == IDC_FF_EFFECT) {
int typeIndex = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0);
if (typeIndex >= 0)
ChangeEffect(port, slot, 0, 0, (unsigned int*)&typeIndex);
}
else if (HIWORD(wParam)==BN_CLICKED) {
EndBinding(hWnd);
int cmd = LOWORD(wParam);
if (cmd == ID_DELETE) {
if (DeleteSelected(port, slot))
PropSheet_Changed(hWndProp, hWnd);
}
else if (cmd == ID_CLEAR) {
while (DeleteByIndex(port, slot, 0)) PropSheet_Changed(hWndProp, hWnd);
}
else if (cmd == ID_BIG_MOTOR || cmd == ID_SMALL_MOTOR) {
int i = (int)SendMessage(GetDlgItem(hWnd, IDC_FORCEFEEDBACK), CB_GETCURSEL, 0, 0);
if (i >= 0) {
unsigned int index = (unsigned int)SendMessage(GetDlgItem(hWnd, IDC_FORCEFEEDBACK), CB_GETITEMDATA, i, 0);
if (index < (unsigned int) dm->numDevices) {
Device *dev = dm->devices[index];
ForceFeedbackBinding *b;
wchar_t *effectID = 0;
if (dev->api == DI) {
// Constant effect.
if (cmd == ID_BIG_MOTOR) effectID = L"13541C20-8E33-11D0-9AD0-00A0C9A06E35";
// Square.
else effectID = L"13541C22-8E33-11D0-9AD0-00A0C9A06E35";
}
int count = CreateEffectBinding(dev, effectID, port, slot, cmd-ID_BIG_MOTOR, &b);
if (b) {
int needSet = 1;
if (dev->api == XINPUT && dev->numFFAxes == 2) {
needSet = 0;
if (cmd == ID_BIG_MOTOR) {
b->axes[0].force = BASE_SENSITIVITY;
}
else {
b->axes[1].force = BASE_SENSITIVITY;
}
}
else if (dev->api == DS3 && dev->numFFAxes == 2) {
needSet = 0;
if (cmd == ID_BIG_MOTOR) {
b->axes[0].force = BASE_SENSITIVITY;
}
else {
b->axes[1].force = BASE_SENSITIVITY;
}
}
else if (dev->api == DI) {
int bigIndex=0, littleIndex=0;
int j;
for (j=0; j<dev->numFFAxes; j++) {
// DI object instance. 0 is x-axis, 1 is y-axis.
int instance = (dev->ffAxes[j].id>>8)&0xFFFF;
if (instance == 0) {
bigIndex = j;
}
else if (instance == 1) {
littleIndex = j;
}
}
needSet = 0;
if (cmd == ID_BIG_MOTOR) {
b->axes[bigIndex].force = BASE_SENSITIVITY;
b->axes[littleIndex].force = 1;
}
else {
b->axes[bigIndex].force = 1;
b->axes[littleIndex].force = BASE_SENSITIVITY;
}
}
if (needSet) {
for (int j=0; j<2 && j <dev->numFFAxes; j++) {
b->axes[j].force = BASE_SENSITIVITY;
}
}
UnselectAll(hWndList);
ListView_SetItemState(hWndList, count, LVIS_SELECTED, LVIS_SELECTED);
ListView_EnsureVisible(hWndList, count, 0);
}
PropSheet_Changed(hWndProp, hWnd);
}
}
}
else if (cmd == ID_CONTROLS) {
UnselectAll(hWndList);
}
else if (cmd == ID_TEST) {
// Just in case...
if (selected) break;
Device *dev;
Binding *b;
ForceFeedbackBinding *ffb = 0;
int selIndex = ListView_GetNextItem(hWndList, -1, LVNI_SELECTED);
if (selIndex >= 0) {
if (GetBinding(port, slot, selIndex, dev, b, ffb)) {
selected = 0xFF;
hWndButtonProc.SetWndHandle(GetDlgItem(hWnd, cmd));
InitInfo info = {0, 1, hWndProp, &hWndButtonProc};
for (int i=0; i<dm->numDevices; i++) {
if (dm->devices[i] != dev) {
dm->DisableDevice(i);
}
}
dm->Update(&info);
dm->PostRead();
dev->SetEffect(ffb, 255);
Sleep(200);
dm->Update(&info);
SetTimer(hWnd, 1, 3000, 0);
}
}
}
else if ((cmd >= ID_LOCK_BUTTONS && cmd <= ID_ANALOG) || cmd == ID_IGNORE) {// || cmd == ID_FORCE_FEEDBACK) {
// Messes up things, unfortunately.
// End binding on a bunch of notification messages, and
// this will send a bunch.
// UnselectAll(hWndList);
EndBinding(hWnd);
if (cmd != ID_IGNORE) {
selected = cmd-(ID_SELECT-0x10);
}
else {
selected = 0x7F;
for (int i=0; i<dm->numDevices; i++) {
if (dm->devices[i]->api != IGNORE_KEYBOARD) {
dm->DisableDevice(i);
}
else {
dm->EnableDevice(i);
}
}
}
hWndButtonProc.SetWndHandle(GetDlgItem(hWnd, cmd));
hWndButtonProc.Eat(DoNothingWndProc, 0);
InitInfo info = {selected==0x7F, 1, hWndProp, &hWndButtonProc};
int w = timeGetTime();
dm->Update(&info);
dm->PostRead();
// Workaround for things that return 0 on first poll and something else ever after.
Sleep(80);
dm->Update(&info);
dm->PostRead();
SetTimer(hWnd, 1, 30, 0);
}
if (cmd == IDC_TURBO) {
// Don't allow setting it back to indeterminate.
SendMessage(GetDlgItem(hWnd, IDC_TURBO), BM_SETSTYLE, BS_AUTOCHECKBOX, 0);
int turbo = (IsDlgButtonChecked(hWnd, IDC_TURBO) == BST_CHECKED);
ChangeValue(port, slot, 0, &turbo, 0);
}
else if (cmd == IDC_FLIP1) {
int val = GetLogSliderVal(hWnd, IDC_SLIDER1);
ChangeValue(port, slot, &val, 0, 0);
}
else if (cmd >= IDC_FF_AXIS1_ENABLED && cmd < IDC_FF_AXIS8_ENABLED + 16) {
int index = (cmd - IDC_FF_AXIS1_ENABLED)/16;
int val = GetLogSliderVal(hWnd, 16*index + IDC_FF_AXIS1);
if (IsDlgButtonChecked(hWnd, 16*index + IDC_FF_AXIS1_ENABLED) != BST_CHECKED) {
val = 0;
}
ChangeEffect(port, slot, cmd, &val, 0);
}
}
break;
default:
break;
}
return 0;
}