private static IntPtr HandleKeyboardEvent(int nCode, IntPtr wParam, IntPtr lParam) { try { var keyboardStructure = (LowLevelKeyboardStructure)(Marshal.PtrToStructure(lParam, typeof(LowLevelKeyboardStructure)) ?? throw new NullReferenceException("keyboard structure was null")); // if the event is of type key down or alt key down add them to a the corresponding // dictionary of the CurrentProfile and to a dictionary containing all the pressed keys // one of the values is for a normal key down, the other is for the alt-key down since they have different codes if ((int)wParam == 256 || (int)wParam == 260) { if (!_currentlyPressed.Contains((Keys)keyboardStructure.VirtualKeyCode)) { //for some reason gamepads report the middle button as a keypress, so check for that if (((Keys)keyboardStructure.VirtualKeyCode).ToString() != "LButton, XButton2") { ProfileManager.KeyboardInputUpdate(((Keys)keyboardStructure.VirtualKeyCode).ToString()); _currentlyPressed.Add((Keys)keyboardStructure.VirtualKeyCode); } else { ProfileManager.GamepadInputUpdate(new List <string>() { "LButton, XButton2" }); } } } // if the event is "key up" remove the key from the dictionary as it was released and now can be pressed physically again else if ((int)wParam == 257) { _currentlyPressed.Remove((Keys)keyboardStructure.VirtualKeyCode); } return(CallNextHookEx(_keyboardHookId, nCode, wParam, lParam)); } catch (Exception e) { if (e is ChainingException exception) { exception.AddErrorToChain("While trying reading keyboard input"); } else { exception = new ChainingException(e.Message); exception.AddErrorToChain("While trying reading keyboard input"); } throw exception; } }
/// <summary> /// verify if a gamepad is connected, if it is then check which buttons are pressed and the directions of the thumb sticks, /// if no gamepad is connected change the timer to 1 every 5 seconds /// </summary> /// <param name="sender"></param> /// <param name="eventArgs"></param> static void CheckGamepad(object?sender, EventArgs eventArgs) { try { //Console.WriteLine("checked for gamepad input"); switch (XInputGetState(0, out CurrentState)) { case ERROR_SUCCESS: { // if a controller was just connected go back to checking for input ~60 times per second if (frameTimer.Interval == 5000) { frameTimer.Interval = 15; } if (CurrentState.dwPacketNumber != LastState.dwPacketNumber) { var listOfButtonPresses = new List <string>(); //apply the bitmask for each button and take it as a press only if the result is not equal to 0 and if the previous state was equal to 0 if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) == 0) { listOfButtonPresses.Add("D_pad_up"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) == 0) { listOfButtonPresses.Add("D_pad_down"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) == 0) { listOfButtonPresses.Add("D_pad_right"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) == 0) { listOfButtonPresses.Add("D_pad_left"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_START) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_START) == 0) { listOfButtonPresses.Add("start"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) == 0) { listOfButtonPresses.Add("back"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) == 0) { listOfButtonPresses.Add("left_shoulder"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) == 0) { listOfButtonPresses.Add("right_shoulder"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) == 0) { listOfButtonPresses.Add("left_thumb"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) == 0) { listOfButtonPresses.Add("right_thumb"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_A) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_A) == 0) { listOfButtonPresses.Add("a"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_B) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_B) == 0) { listOfButtonPresses.Add("b"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_X) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_X) == 0) { listOfButtonPresses.Add("x"); } if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_Y) != 0 && (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_Y) == 0) { listOfButtonPresses.Add("y"); } if (CurrentState.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD && LastState.Gamepad.bLeftTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD) { listOfButtonPresses.Add("left_trigger"); } if (CurrentState.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD && LastState.Gamepad.bRightTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD) { listOfButtonPresses.Add("right_trigger"); } //take care of the cases where the absolute would underflow if (CurrentState.Gamepad.sThumbLY == short.MinValue) { CurrentState.Gamepad.sThumbLY = short.MinValue + 2; } if (CurrentState.Gamepad.sThumbLX == short.MinValue) { CurrentState.Gamepad.sThumbLX = short.MinValue + 2; } var directionL = MouseHookClass.MovementDirection( new Point(CurrentState.Gamepad.sThumbLX, CurrentState.Gamepad.sThumbLY), new Point(0, 0)); // update the direction of the left thumb stick only if it is outside of the dead zone and the previous state was inside the dead zone // or if the direction is different if ((Math.Abs(CurrentState.Gamepad.sThumbLY) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE || Math.Abs(CurrentState.Gamepad.sThumbLX) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) && !(Math.Abs(LastState.Gamepad.sThumbLY) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE || Math.Abs(LastState.Gamepad.sThumbLX) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) || (directionL != null && directionL != LastDirectionL)) { if (directionL != null) { listOfButtonPresses.Add("left_thumb_move_" + directionL); LastDirectionL = directionL; } } //take care of the cases where the absolute would underflow if (CurrentState.Gamepad.sThumbRY == short.MinValue) { CurrentState.Gamepad.sThumbRY = short.MinValue + 2; } if (CurrentState.Gamepad.sThumbRX == short.MinValue) { CurrentState.Gamepad.sThumbRX = short.MinValue + 2; } var directionR = MouseHookClass.MovementDirection( new Point(CurrentState.Gamepad.sThumbRX, CurrentState.Gamepad.sThumbRY), new Point(0, 0)); // update the direction of the right thumb stick only if it is outside of the dead zone and the previous state was inside the dead zone // or if the direction is different if ((Math.Abs(CurrentState.Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE || Math.Abs(CurrentState.Gamepad.sThumbRY) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) && !(Math.Abs(LastState.Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE || Math.Abs(LastState.Gamepad.sThumbRY) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) || (directionR != null && directionR != LastDirectionR)) { if (directionR != null) { listOfButtonPresses.Add("right_thumb_move_" + directionR); LastDirectionR = directionR; } } if (listOfButtonPresses.Count > 0) { ProfileManager.GamepadInputUpdate(listOfButtonPresses); } LastState = CurrentState; } break; } case ERROR_DEVICE_NOT_CONNECTED: { // if no gamepad is connected then search for input only once every 5 seconds if (frameTimer.Interval != 5000) { frameTimer.Interval = 5000; } break; } } } catch (Exception e) { if (e is ChainingException exception) { exception.AddErrorToChain("While trying to read gamepad input"); } else { exception = new ChainingException(e.Message); exception.AddErrorToChain("While trying to read gamepad input"); } throw exception; } }