internal void RegisterRawDevice(OpenTK.Input.MouseDevice mouse) { RawInputDevice[] rid = new RawInputDevice[1]; // Mouse is 1/2 (page/id). See http://www.microsoft.com/whdc/device/input/HID_HWID.mspx rid[0] = new RawInputDevice(); rid[0].UsagePage = 1; rid[0].Usage = 2; rid[0].Flags = RawInputDeviceFlags.INPUTSINK; rid[0].Target = window; if (!Functions.RegisterRawInputDevices(rid, 1, API.RawInputDeviceSize)) { throw new ApplicationException( String.Format( "Raw input registration failed with error: {0}. Device: {1}", Marshal.GetLastWin32Error(), rid[0].ToString()) ); } else { Debug.Print("Registered mouse {0}", mouse.ToString()); System.Drawing.Point p = new System.Drawing.Point(); if (Functions.GetCursorPos(ref p)) { mouse.Position = p; } } }
private void UpdateMouse() { POINT point = new POINT(); Functions.GetCursorPos(ref point); this.mouse.X = point.X; this.mouse.Y = point.Y; this.mouse[MouseButton.Left] = (int)Functions.GetAsyncKeyState(VirtualKeys.LBUTTON) >> 8 != 0; this.mouse[MouseButton.Middle] = (int)Functions.GetAsyncKeyState(VirtualKeys.RBUTTON) >> 8 != 0; this.mouse[MouseButton.Right] = (int)Functions.GetAsyncKeyState(VirtualKeys.MBUTTON) >> 8 != 0; this.mouse[MouseButton.Button1] = (int)Functions.GetAsyncKeyState(VirtualKeys.XBUTTON1) >> 8 != 0; this.mouse[MouseButton.Button2] = (int)Functions.GetAsyncKeyState(VirtualKeys.XBUTTON2) >> 8 != 0; }
public MouseState GetCursorState() { // For simplicity, get hardware state // and simply overwrite its x and y location POINT p = new POINT(); Functions.GetCursorPos(ref p); var state = GetState(); state.X = p.X; state.Y = p.Y; return(state); }
void UpdateMouse() { POINT p = new POINT(); Functions.GetCursorPos(ref p); mouse.X = p.X; mouse.Y = p.Y; // Note: we cannot poll the mouse wheel mouse[MouseButton.Left] = (Functions.GetAsyncKeyState(VirtualKeys.LBUTTON) >> 8) != 0; mouse[MouseButton.Middle] = (Functions.GetAsyncKeyState(VirtualKeys.RBUTTON) >> 8) != 0; mouse[MouseButton.Right] = (Functions.GetAsyncKeyState(VirtualKeys.MBUTTON) >> 8) != 0; mouse[MouseButton.Button1] = (Functions.GetAsyncKeyState(VirtualKeys.XBUTTON1) >> 8) != 0; mouse[MouseButton.Button2] = (Functions.GetAsyncKeyState(VirtualKeys.XBUTTON2) >> 8) != 0; }
IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) { Point point; switch (message) { #region Size / Move / Style events case WindowMessage.ACTIVATE: // See http://msdn.microsoft.com/en-us/library/ms646274(VS.85).aspx (WM_ACTIVATE notification): // wParam: The low-order word specifies whether the window is being activated or deactivated. bool new_focused_state = Focused; if (IntPtr.Size == 4) { focused = (wParam.ToInt32() & 0xFFFF) != 0; } else { focused = (wParam.ToInt64() & 0xFFFF) != 0; } if (new_focused_state != Focused) { FocusedChanged(this, EventArgs.Empty); } break; case WindowMessage.ENTERMENULOOP: case WindowMessage.ENTERSIZEMOVE: // Entering the modal size/move loop: we don't want rendering to // stop during this time, so we register a timer callback to continue // processing from time to time. StartTimer(handle); break; case WindowMessage.EXITMENULOOP: case WindowMessage.EXITSIZEMOVE: // ExitingmModal size/move loop: the timer callback is no longer // necessary. StopTimer(handle); break; case WindowMessage.ERASEBKGND: return(new IntPtr(1)); case WindowMessage.WINDOWPOSCHANGED: unsafe { WindowPosition *pos = (WindowPosition *)lParam; if (window != null && pos->hwnd == window.WindowHandle) { Point new_location = new Point(pos->x, pos->y); if (Location != new_location) { bounds.Location = new_location; Move(this, EventArgs.Empty); } Size new_size = new Size(pos->cx, pos->cy); if (Size != new_size) { bounds.Width = pos->cx; bounds.Height = pos->cy; Win32Rectangle rect; Functions.GetClientRect(handle, out rect); client_rectangle = rect.ToRectangle(); Functions.SetWindowPos(child_window.WindowHandle, IntPtr.Zero, 0, 0, ClientRectangle.Width, ClientRectangle.Height, SetWindowPosFlags.NOZORDER | SetWindowPosFlags.NOOWNERZORDER | SetWindowPosFlags.NOACTIVATE | SetWindowPosFlags.NOSENDCHANGING); if (suppress_resize <= 0) { Resize(this, EventArgs.Empty); } } } } break; case WindowMessage.STYLECHANGED: unsafe { if (wParam.ToInt64() == (long)GWL.STYLE) { WindowStyle style = ((StyleStruct *)lParam)->New; if ((style & WindowStyle.Popup) != 0) { windowBorder = WindowBorder.Hidden; } else if ((style & WindowStyle.ThickFrame) != 0) { windowBorder = WindowBorder.Resizable; } else if ((style & ~(WindowStyle.ThickFrame | WindowStyle.MaximizeBox)) != 0) { windowBorder = WindowBorder.Fixed; } } } break; case WindowMessage.SIZE: SizeMessage state = (SizeMessage)wParam.ToInt64(); WindowState new_state = windowState; switch (state) { case SizeMessage.RESTORED: new_state = borderless_maximized_window_state ? WindowState.Maximized : WindowState.Normal; break; case SizeMessage.MINIMIZED: new_state = WindowState.Minimized; break; case SizeMessage.MAXIMIZED: new_state = WindowBorder == WindowBorder.Hidden ? WindowState.Fullscreen : WindowState.Maximized; break; } if (new_state != windowState) { windowState = new_state; WindowStateChanged(this, EventArgs.Empty); } break; #endregion #region Input events case WindowMessage.CHAR: if (IntPtr.Size == 4) { key_press.KeyChar = (char)wParam.ToInt32(); } else { key_press.KeyChar = (char)wParam.ToInt64(); } KeyPress(this, key_press); break; case WindowMessage.MOUSEMOVE: point = new Point( (short)((uint)lParam.ToInt32() & 0x0000FFFF), (short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16)); mouse.Position = point; if (mouse_outside_window) { // Once we receive a mouse move event, it means that the mouse has // re-entered the window. mouse_outside_window = false; EnableMouseTracking(); } if (this.client_rectangle.Contains(lastCursorPos) && !this.client_rectangle.Contains(point)) { if (!CursorVisible) { ShowCursor(); } mouse.NotifyLeave(); MouseLeave(this, EventArgs.Empty); } if (!this.client_rectangle.Contains(lastCursorPos) && this.client_rectangle.Contains(point)) { if (!CursorVisible) { HideCursor(); } mouse.NotifyEnter(); MouseEnter(this, EventArgs.Empty); } lastCursorPos = point; break; case WindowMessage.MOUSELEAVE: mouse_outside_window = true; // Mouse tracking is disabled automatically by the OS Functions.GetCursorPos(out point); point = this.PointToClient(point); if (this.client_rectangle.Contains(lastCursorPos) && !this.client_rectangle.Contains(point)) { if (!CursorVisible) { ShowCursor(); } mouse.NotifyLeave(); MouseLeave(this, EventArgs.Empty); } lastCursorPos = point; break; case WindowMessage.MOUSEWHEEL: // This is due to inconsistent behavior of the WParam value on 64bit arch, whese // wparam = 0xffffffffff880000 or wparam = 0x00000000ff100000 mouse.WheelPrecise += ((long)wParam << 32 >> 48) / 120.0f; break; case WindowMessage.LBUTTONDOWN: Functions.SetCapture(window.WindowHandle); mouse[MouseButton.Left] = true; break; case WindowMessage.MBUTTONDOWN: Functions.SetCapture(window.WindowHandle); mouse[MouseButton.Middle] = true; break; case WindowMessage.RBUTTONDOWN: Functions.SetCapture(window.WindowHandle); mouse[MouseButton.Right] = true; break; case WindowMessage.XBUTTONDOWN: Functions.SetCapture(window.WindowHandle); mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = true; break; case WindowMessage.LBUTTONUP: Functions.ReleaseCapture(); mouse[MouseButton.Left] = false; break; case WindowMessage.MBUTTONUP: Functions.ReleaseCapture(); mouse[MouseButton.Middle] = false; break; case WindowMessage.RBUTTONUP: Functions.ReleaseCapture(); mouse[MouseButton.Right] = false; break; case WindowMessage.XBUTTONUP: Functions.ReleaseCapture(); mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = false; break; // Keyboard events: case WindowMessage.KEYDOWN: case WindowMessage.KEYUP: case WindowMessage.SYSKEYDOWN: case WindowMessage.SYSKEYUP: bool pressed = message == WindowMessage.KEYDOWN || message == WindowMessage.SYSKEYDOWN; // Shift/Control/Alt behave strangely when e.g. ShiftRight is held down and ShiftLeft is pressed // and released. It looks like neither key is released in this case, or that the wrong key is // released in the case of Control and Alt. // To combat this, we are going to release both keys when either is released. Hacky, but should work. // Win95 does not distinguish left/right key constants (GetAsyncKeyState returns 0). // In this case, both keys will be reported as pressed. bool extended = (lParam.ToInt64() & ExtendedBit) != 0; switch ((VirtualKeys)wParam) { case VirtualKeys.SHIFT: // The behavior of this key is very strange. Unlike Control and Alt, there is no extended bit // to distinguish between left and right keys. Moreover, pressing both keys and releasing one // may result in both keys being held down (but not always). // The only reliable way to solve this was reported by BlueMonkMN at the forums: we should // check the scancodes. It looks like GLFW does the same thing, so it should be reliable. // Note: we release both keys when either shift is released. // Otherwise, the state of one key might be stuck to pressed. if (ShiftRightScanCode != 0 && pressed) { unchecked { if (((lParam.ToInt64() >> 16) & 0xFF) == ShiftRightScanCode) { keyboard[Input.Key.ShiftRight] = pressed; } else { keyboard[Input.Key.ShiftLeft] = pressed; } } } else { // Windows 9x and NT4.0 or key release event. keyboard[Input.Key.ShiftLeft] = keyboard[Input.Key.ShiftRight] = pressed; } return(IntPtr.Zero); case VirtualKeys.CONTROL: if (extended) { keyboard[Input.Key.ControlRight] = pressed; } else { keyboard[Input.Key.ControlLeft] = pressed; } return(IntPtr.Zero); case VirtualKeys.MENU: if (extended) { keyboard[Input.Key.AltRight] = pressed; } else { keyboard[Input.Key.AltLeft] = pressed; } return(IntPtr.Zero); case VirtualKeys.RETURN: if (extended) { keyboard[Key.KeypadEnter] = pressed; } else { keyboard[Key.Enter] = pressed; } return(IntPtr.Zero); default: if (!KeyMap.ContainsKey((VirtualKeys)wParam)) { Debug.Print("Virtual key {0} ({1}) not mapped.", (VirtualKeys)wParam, (long)lParam); break; } else { keyboard[KeyMap[(VirtualKeys)wParam]] = pressed; } return(IntPtr.Zero); } break; case WindowMessage.SYSCHAR: return(IntPtr.Zero); case WindowMessage.KILLFOCUS: keyboard.ClearKeys(); keyboard.NotifyLostFocus(); break; case WindowMessage.SETFOCUS: keyboard.NotifyGotFocus(); break; #endregion #region Creation / Destruction events case WindowMessage.CREATE: CreateStruct cs = (CreateStruct)Marshal.PtrToStructure(lParam, typeof(CreateStruct)); if (cs.hwndParent == IntPtr.Zero) { bounds.X = cs.x; bounds.Y = cs.y; bounds.Width = cs.cx; bounds.Height = cs.cy; Win32Rectangle rect; Functions.GetClientRect(handle, out rect); client_rectangle = rect.ToRectangle(); invisible_since_creation = true; } break; case WindowMessage.CLOSE: System.ComponentModel.CancelEventArgs e = new System.ComponentModel.CancelEventArgs(); Closing(this, e); if (!e.Cancel) { DestroyWindow(); break; } return(IntPtr.Zero); case WindowMessage.DESTROY: exists = false; Functions.UnregisterClass(ClassName, Instance); window.Dispose(); child_window.Dispose(); Closed(this, EventArgs.Empty); break; #endregion } return(Functions.DefWindowProc(handle, message, wParam, lParam)); }