예제 #1
0
 void UpdateKeyboard()
 {
     for (byte i = 0; i < byte.MaxValue; i++)
     {
         bool pressed = (Functions.GetAsyncKeyState((VirtualKeys)i) >> 8) != 0;
         Key  key;
         KeyMap.TryGetValue((VirtualKeys)i, out key);
         keyboard.SetKeyState(key, i, pressed);
     }
 }
예제 #2
0
        unsafe IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
        {
            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 wasFocused = Focused;
                Focused = (wParam.ToInt64() & 0xFFFF) != 0;
                if (Focused != wasFocused)
                {
                    RaiseFocusedChanged();
                }
                break;

            case WindowMessage.ENTERMENULOOP:
            case WindowMessage.ENTERSIZEMOVE:
            case WindowMessage.EXITMENULOOP:
            case WindowMessage.EXITSIZEMOVE:
                break;

            case WindowMessage.ERASEBKGND:
                RaiseRedraw();
                return(new IntPtr(1));

            case WindowMessage.WINDOWPOSCHANGED:
                WindowPosition *pos = (WindowPosition *)lParam;
                if (pos->hwnd == WinHandle)
                {
                    Point new_location = new Point(pos->x, pos->y);
                    if (Location != new_location)
                    {
                        bounds.Location = new_location;
                        RaiseMove();
                    }

                    Size new_size = new Size(pos->cx, pos->cy);
                    if (Size != new_size)
                    {
                        bounds.Width  = pos->cx;
                        bounds.Height = pos->cy;
                        UpdateClientSize(handle);

                        API.SetWindowPos(WinHandle, IntPtr.Zero,
                                         bounds.X, bounds.Y, bounds.Width, bounds.Height,
                                         SetWindowPosFlags.NOZORDER | SetWindowPosFlags.NOOWNERZORDER |
                                         SetWindowPosFlags.NOACTIVATE | SetWindowPosFlags.NOSENDCHANGING);

                        if (suppress_resize <= 0)
                        {
                            RaiseResize();
                        }
                    }
                }
                break;

            case WindowMessage.STYLECHANGED:
                if (wParam.ToInt64() == (long)GetWindowLong.STYLE)
                {
                    WindowStyle style = ((StyleStruct *)lParam)->New;
                    if ((style & WindowStyle.Popup) != 0)
                    {
                        hiddenBorder = true;
                    }
                    else if ((style & WindowStyle.ThickFrame) != 0)
                    {
                        hiddenBorder = false;
                    }
                }
                break;

            case WindowMessage.SIZE:
                SizeMessage state     = (SizeMessage)wParam.ToInt64();
                WindowState new_state = windowState;
                switch (state)
                {
                case SizeMessage.RESTORED: new_state = WindowState.Normal; break;

                case SizeMessage.MINIMIZED: new_state = WindowState.Minimized; break;

                case SizeMessage.MAXIMIZED: new_state = hiddenBorder ?
                                                        WindowState.Fullscreen : WindowState.Maximized;
                    break;
                }

                if (new_state != windowState)
                {
                    windowState = new_state;
                    RaiseWindowStateChanged();
                }
                break;

                #endregion

                #region Input events

            case WindowMessage.CHAR:
                RaiseKeyPress((char)wParam.ToInt64());
                break;

            case WindowMessage.MOUSEMOVE:
                // set before position change, in case mouse buttons changed when outside window
                uint mouse_flags = (uint)wParam.ToInt64();
                Mouse.Set(MouseButton.Left, (mouse_flags & 0x01) != 0);
                Mouse.Set(MouseButton.Right, (mouse_flags & 0x02) != 0);
                Mouse.Set(MouseButton.Middle, (mouse_flags & 0x10) != 0);
                // TODO: do we need to set XBUTTON1 / XBUTTON 2 here

                uint mouse_xy = (uint)lParam.ToInt32();
                Mouse.SetPos((short)(mouse_xy & 0x0000FFFF),
                             (short)((mouse_xy & 0xFFFF0000) >> 16));
                break;

            case WindowMessage.MOUSEWHEEL:
                // This is due to inconsistent behavior of the WParam value on 64bit arch, whese
                // wparam = 0xffffffffff880000 or wparam = 0x00000000ff100000
                Mouse.SetWheel(Mouse.Wheel + (((long)wParam << 32 >> 48) / 120.0f));
                return(IntPtr.Zero);

            case WindowMessage.LBUTTONDOWN:
                Mouse.Set(MouseButton.Left, true);
                break;

            case WindowMessage.MBUTTONDOWN:
                Mouse.Set(MouseButton.Middle, true);
                break;

            case WindowMessage.RBUTTONDOWN:
                Mouse.Set(MouseButton.Right, true);
                break;

            case WindowMessage.XBUTTONDOWN:
                Keyboard.Set((((ulong)wParam.ToInt64() >> 16) & 0xFFFF) == 1 ? Key.XButton1 : Key.XButton2, true);
                break;

            case WindowMessage.LBUTTONUP:
                Mouse.Set(MouseButton.Left, false);
                break;

            case WindowMessage.MBUTTONUP:
                Mouse.Set(MouseButton.Middle, false);
                break;

            case WindowMessage.RBUTTONUP:
                Mouse.Set(MouseButton.Right, false);
                break;

            case WindowMessage.XBUTTONUP:
                Keyboard.Set((((ulong)wParam.ToInt64() >> 16) & 0xFFFF) == 1 ? Key.XButton1 : Key.XButton2, 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 ((int)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).
                    bool lShiftDown = (API.GetKeyState((int)VirtualKeys.LSHIFT) >> 15) == 1;
                    bool rShiftDown = (API.GetKeyState((int)VirtualKeys.RSHIFT) >> 15) == 1;

                    if (!pressed || lShiftDown != rShiftDown)
                    {
                        Keyboard.Set(Key.ShiftLeft, lShiftDown);
                        Keyboard.Set(Key.ShiftRight, rShiftDown);
                    }
                    return(IntPtr.Zero);

                case VirtualKeys.CONTROL:
                    if (extended)
                    {
                        Keyboard.Set(Key.ControlRight, pressed);
                    }
                    else
                    {
                        Keyboard.Set(Key.ControlLeft, pressed);
                    }
                    return(IntPtr.Zero);

                case VirtualKeys.MENU:
                    if (extended)
                    {
                        Keyboard.Set(Key.AltRight, pressed);
                    }
                    else
                    {
                        Keyboard.Set(Key.AltLeft, pressed);
                    }
                    return(IntPtr.Zero);

                case VirtualKeys.RETURN:
                    if (extended)
                    {
                        Keyboard.Set(Key.KeypadEnter, pressed);
                    }
                    else
                    {
                        Keyboard.Set(Key.Enter, pressed);
                    }
                    return(IntPtr.Zero);

                default:
                    Key tkKey;
                    if (!KeyMap.TryGetValue((int)wParam, out tkKey))
                    {
                        Debug.Print("Virtual key {0} ({1}) not mapped.", wParam, lParam.ToInt64());
                        break;
                    }
                    else
                    {
                        Keyboard.Set(tkKey, pressed);
                    }
                    return(IntPtr.Zero);
                }
                break;

            case WindowMessage.SYSCHAR:
                return(IntPtr.Zero);

            case WindowMessage.KILLFOCUS:
                Keyboard.ClearKeys();
                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;
                    UpdateClientSize(handle);
                    invisible_since_creation = true;
                }
                break;

            case WindowMessage.CLOSE:
                RaiseClosing();
                DestroyWindow();
                break;

            case WindowMessage.DESTROY:
                Exists = false;
                API.UnregisterClass(ClassName, Instance);
                Dispose();
                RaiseClosed();
                break;

                #endregion
            }
            return(API.DefWindowProc(handle, message, wParam, lParam));
        }
예제 #3
0
        public bool ProcessKeyboardEvent(RawInput rin)
        {
            bool processed = false;

            bool pressed =
                rin.Data.Keyboard.Message == (int)WindowMessage.KEYDOWN ||
                rin.Data.Keyboard.Message == (int)WindowMessage.SYSKEYDOWN;

            ContextHandle handle = new ContextHandle(rin.Header.Device);
            KeyboardState keyboard;

            if (!rawids.ContainsKey(handle))
            {
                RefreshDevices();
            }

            if (keyboards.Count == 0)
            {
                return(false);
            }

            // Note:For some reason, my Microsoft Digital 3000 keyboard reports 0
            // as rin.Header.Device for the "zoom-in/zoom-out" buttons.
            // That's problematic, because no device has a "0" id.
            // As a workaround, we'll add those buttons to the first device (if any).
            int keyboard_handle = rawids.ContainsKey(handle) ? rawids[handle] : 0;

            keyboard = keyboards[keyboard_handle];

            // Generic control, shift, alt keys may be sent instead of left/right.
            // It seems you have to explicitly register left/right events.
            switch (rin.Data.Keyboard.VKey)
            {
            case VirtualKeys.SHIFT:
                keyboard.SetKeyState(Key.ShiftLeft, (byte)WinGLNative.ShiftLeftScanCode, pressed);
                keyboard.SetKeyState(Key.ShiftRight, (byte)WinGLNative.ShiftRightScanCode, pressed);
                processed = true;
                break;

            case VirtualKeys.CONTROL:
                keyboard.SetKeyState(Key.ControlLeft, (byte)WinGLNative.ControlLeftScanCode, pressed);
                keyboard.SetKeyState(Key.ControlRight, (byte)WinGLNative.ControlRightScanCode, pressed);
                processed = true;
                break;

            case VirtualKeys.MENU:
                keyboard.SetKeyState(Key.AltLeft, (byte)WinGLNative.AltLeftScanCode, pressed);
                keyboard.SetKeyState(Key.AltRight, (byte)WinGLNative.AltRightScanCode, pressed);
                processed = true;
                break;

            default:
                Key key;
                KeyMap.TryGetValue(rin.Data.Keyboard.VKey, out key);
                if (key == Key.Unknown)
                {
                    Debug.Print("Virtual key {0} ({1}) not mapped.", rin.Data.Keyboard.VKey, (int)rin.Data.Keyboard.VKey);
                }
                keyboard.SetKeyState(key, BitConverter.GetBytes(rin.Data.Keyboard.MakeCode)[0], pressed);
                processed = true;
                break;
            }

            lock (UpdateLock)
            {
                keyboards[keyboard_handle] = keyboard;
                return(processed);
            }
        }