#region --- License --- /* Copyright (c) 2007 Stefanos Apostolopoulos * See license.txt for license information */ #endregion using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using OpenTK.Input; using System.Diagnostics; namespace OpenTK.Platform.Windows { /// /// Input driver for legacy (pre XP) Windows platforms. /// internal sealed class WMInput : NativeWindow, IInputDriver { // Driver supports only one keyboard and mouse; KeyboardDevice keyboard = new KeyboardDevice(); MouseDevice mouse = new MouseDevice(); IList keyboards = new List(1); IList mice = new List(1); internal static readonly WinKeyMap KeyMap = new WinKeyMap(); #region --- Constructor --- public WMInput(WinWindowInfo parent) { Debug.WriteLine("Initalizing WMInput driver."); Debug.Indent(); AssignHandle(parent.WindowHandle); Debug.Print("Input window attached to parent {0}", parent); Debug.Unindent(); keyboard.Description = "Standard Windows keyboard"; keyboard.NumberOfFunctionKeys = 12; keyboard.NumberOfKeys = 101; keyboard.NumberOfLeds = 3; mouse.Description = "Standard Windows mouse"; mouse.NumberOfButtons = 3; mouse.NumberOfWheels = 1; keyboards.Add(keyboard); mice.Add(mouse); } #endregion #region protected override void WndProc(ref Message msg) protected override void WndProc(ref Message msg) { switch ((WindowMessage)msg.Msg) { // Mouse events: case WindowMessage.MOUSEMOVE: //case WindowMessage.NCMOUSEMOVE: mouse.X = msg.LParam.ToInt32() & 0x0000FFFF; mouse.Y = (int)(msg.LParam.ToInt32() & 0xFFFF0000) >> 16; return; case WindowMessage.MOUSEWHEEL: mouse.Wheel += (int)(msg.WParam.ToInt32() >> 16) / 120; return; case WindowMessage.LBUTTONDOWN: mouse[MouseButton.Left] = true; return; case WindowMessage.MBUTTONDOWN: mouse[MouseButton.Middle] = true; return; case WindowMessage.RBUTTONDOWN: mouse[MouseButton.Right] = true; return; case WindowMessage.XBUTTONDOWN: mouse[((msg.WParam.ToInt32() & 0xFFFF0000) >> 16) != (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = true; return; case WindowMessage.LBUTTONUP: mouse[MouseButton.Left] = false; return; case WindowMessage.MBUTTONUP: mouse[MouseButton.Middle] = false; return; case WindowMessage.RBUTTONUP: mouse[MouseButton.Right] = false; return; case WindowMessage.XBUTTONUP: // TODO: Is this correct? mouse[((msg.WParam.ToInt32() & 0xFFFF0000) >> 16) != (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = false; return; // Keyboard events: case WindowMessage.KEYDOWN: case WindowMessage.KEYUP: case WindowMessage.SYSKEYDOWN: case WindowMessage.SYSKEYUP: bool pressed = (WindowMessage)msg.Msg == WindowMessage.KEYDOWN || (WindowMessage)msg.Msg == WindowMessage.SYSKEYDOWN; //bool left = (((int)msg.LParam) & 0x100000) == 0; // valid for Shift, Control and Menu presses. switch ((VirtualKeys)msg.WParam) { case VirtualKeys.SHIFT: // Win95 does not distinguish left/right constants (GetAsyncKeyState returns 0). // In this case, report both keys as down. bool left = Functions.GetAsyncKeyState(VirtualKeys.LSHIFT) != 0; bool right = Functions.GetAsyncKeyState(VirtualKeys.RSHIFT) != 0; if (left) keyboard[Input.Key.ShiftLeft] = pressed; if (right) keyboard[Input.Key.ShiftRight] = pressed; if (!left && !right) keyboard[Input.Key.ShiftLeft] = keyboard[Input.Key.ShiftRight] = pressed; return; case VirtualKeys.CONTROL: left = Functions.GetAsyncKeyState(VirtualKeys.LCONTROL) != 0; right = Functions.GetAsyncKeyState(VirtualKeys.RCONTROL) != 0; if (left) keyboard[Input.Key.ControlLeft] = pressed; if (right) keyboard[Input.Key.ControlRight] = pressed; if (!left && !right) keyboard[Input.Key.ControlLeft] = keyboard[Input.Key.ControlRight] = pressed; return; case VirtualKeys.MENU: left = Functions.GetAsyncKeyState(VirtualKeys.LMENU) != 0; right = Functions.GetAsyncKeyState(VirtualKeys.RMENU) != 0; if (left) keyboard[Input.Key.AltLeft] = pressed; if (right) keyboard[Input.Key.AltRight] = pressed; if (!left && !right) keyboard[Input.Key.AltLeft] = keyboard[Input.Key.AltRight] = pressed; return; default: if (!WMInput.KeyMap.ContainsKey((VirtualKeys)msg.WParam)) { Debug.Print("Virtual key {0} ({1}) not mapped.", (VirtualKeys)msg.WParam, (int)msg.WParam); break; } else { keyboard[WMInput.KeyMap[(VirtualKeys)msg.WParam]] = pressed; return; } } break; case WindowMessage.DESTROY: Debug.Print("Input window detached from parent {0}.", Handle); ReleaseHandle(); break; case WindowMessage.QUIT: Debug.WriteLine("Input window quit."); this.Dispose(); break; } base.WndProc(ref msg); } #endregion #region IInputDriver Members public void Poll() { // No polling needed. } #endregion #region IKeyboardDriver Members public IList Keyboard { get { return keyboards; } } #endregion #region IMouseDriver Members public IList Mouse { get { return mice; } } #endregion #region --- IDisposable Members --- private bool disposed; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool manual) { if (!disposed) { if (manual) this.ReleaseHandle(); disposed = true; } } ~WMInput() { Dispose(false); } #endregion } }