INT_PTR CALLBACK DialogProc()

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;
}