Beispiel #1
0
        /// <summary>
        ///   Overridden window message callback used to capture input for the window
        /// </summary>
        /// <param name="message">Window message sent to the window</param>
        protected override void WndProc(ref Message message)
        {
            base.WndProc(ref message);

            // Process the message differently based on its message id
            switch (message.Msg)
            {
            // Window is being asked which types of input it can process
            case (int)UnsafeNativeMethods.WindowMessages.WM_GETDLGCODE: {
                int returnCode = message.Result.ToInt32();
                returnCode    |= DlgCodeFlags;
                message.Result = new IntPtr(returnCode);
                break;
            }

#if USE_WM_INPUT
            // Raw input data is being sent to the window
            case (int)UnsafeNativeMethods.WindowMessages.WM_INPUT: {
                processWmInput(ref message);
                break;
            }
#endif
            // Key on the keyboard was pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_KEYDOWN: {
                int virtualKeyCode = message.WParam.ToInt32();
                // bool repetition = (message.LParam.ToInt32() & WM_KEYDOWN_WASDOWN) != 0;
                OnKeyPressed((Keys)virtualKeyCode);
                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_KEYUP: {
                int virtualKeyCode = message.WParam.ToInt32();
                OnKeyReleased((Keys)virtualKeyCode);
                break;
            }

            // Character has been entered on the keyboard
            case (int)UnsafeNativeMethods.WindowMessages.WM_CHAR: {
                char character = (char)message.WParam.ToInt32();
                OnCharacterEntered(character);
                break;
            }

            // Mouse has been moved
            case (int)UnsafeNativeMethods.WindowMessages.WM_MOUSEMOVE: {
                if (!this.trackingMouse)
                {
                    int result = UnsafeNativeMethods.TrackMouseEvent(ref this.mouseEventTrackData);
                    Debug.Assert(
                        result != 0,
                        "Could not set up registration for mouse events",
                        "The TrackMouseEvent() function failed, which means the game will not " +
                        "detect when the mouse leaves the game window. This might result in " +
                        "the assumed mouse position remaining somewhere near the window border " +
                        "even though the mouse has been moved away from the game window."
                        );
                    this.trackingMouse = (result != 0);
                }

                short x = (short)(message.LParam.ToInt32() & 0xFFFF);
                short y = (short)(message.LParam.ToInt32() >> 16);
                OnMouseMoved((float)x, (float)y);
                break;
            }

            // Left mouse button pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_LBUTTONDOWN:
            case (int)UnsafeNativeMethods.WindowMessages.WM_LBUTTONDBLCLK: {
                OnMouseButtonPressed(MouseButtons.Left);
                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_LBUTTONUP: {
                OnMouseButtonReleased(MouseButtons.Left);
                break;
            }

            // Right mouse button pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_RBUTTONDOWN:
            case (int)UnsafeNativeMethods.WindowMessages.WM_RBUTTONDBLCLK: {
                OnMouseButtonPressed(MouseButtons.Right);
                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_RBUTTONUP: {
                OnMouseButtonReleased(MouseButtons.Right);
                break;
            }

            // Middle mouse button pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_MBUTTONDOWN:
            case (int)UnsafeNativeMethods.WindowMessages.WM_MBUTTONDBLCLK: {
                OnMouseButtonPressed(MouseButtons.Middle);
                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_MBUTTONUP: {
                OnMouseButtonReleased(MouseButtons.Middle);
                break;
            }

            // Extended mouse button pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_XBUTTONDOWN:
            case (int)UnsafeNativeMethods.WindowMessages.WM_XBUTTONDBLCLK: {
                short button = (short)(message.WParam.ToInt32() >> 16);
                if (button == 1)
                {
                    OnMouseButtonPressed(MouseButtons.X1);
                }
                if (button == 2)
                {
                    OnMouseButtonPressed(MouseButtons.X2);
                }

                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_XBUTTONUP: {
                short button = (short)(message.WParam.ToInt32() >> 16);
                if (button == 1)
                {
                    OnMouseButtonReleased(MouseButtons.X1);
                }
                if (button == 2)
                {
                    OnMouseButtonReleased(MouseButtons.X2);
                }

                break;
            }

            // Mouse wheel rotated
            case (int)UnsafeNativeMethods.WindowMessages.WM_MOUSEHWHEEL: {
                short ticks = (short)(message.WParam.ToInt32() >> 16);
                OnMouseWheelRotated((float)ticks / 120.0f);
                break;
            }

            // Mouse has left the window's client area
            case (int)UnsafeNativeMethods.WindowMessages.WM_MOUSELEAVE: {
                OnMouseMoved(-1.0f, -1.0f);
                this.trackingMouse = false;
                break;
            }
            }
        }
        /// <summary>Filters out a message before it is dispatched</summary>
        /// <param name="message">
        ///   Message that will be dispatched. You must not modify this message.
        /// </param>
        /// <returns>
        ///   True if the message has been processed by the filter and should not be
        ///   dispatched or false to continue processing of the message.
        /// </returns>
        bool IMessageFilter.PreFilterMessage(ref Message message)
        {
            // Process the message differently based on its message id
            switch (message.Msg)
            {
            // Key on the keyboard was pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_KEYDOWN: {
                int virtualKeyCode = message.WParam.ToInt32();
                // bool repetition = (message.LParam.ToInt32() & WM_KEYDOWN_WASDOWN) != 0;
                OnKeyPressed((Keys)virtualKeyCode);

                if (virtualKeyCode == 17)
                {
                    ctrlKeyDown = true;
                }
                if (virtualKeyCode == 18)
                {
                    altKeyDown = true;
                }

                UnsafeNativeMethods.TranslateMessage(ref message);

                return(true); // consumed!
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_KEYUP: {
                int virtualKeyCode = message.WParam.ToInt32();
                OnKeyReleased((Keys)virtualKeyCode);

                // Workaround for strange behavior of ctrl and alt key combinations
                // Pressing & releasing both generates two keydowns but only one keyup.
                if (virtualKeyCode == 17)
                {
                    ctrlKeyDown = false;
                    if (altKeyDown)
                    {
                        OnKeyReleased((Keys)18);
                        altKeyDown = false;
                    }
                }
                else if (virtualKeyCode == 18)
                {
                    altKeyDown = false;
                    if (ctrlKeyDown)
                    {
                        OnKeyReleased((Keys)17);
                        ctrlKeyDown = false;
                    }
                }

                return(true); // consumed!
            }

            // Character has been entered on the keyboard
            case (int)UnsafeNativeMethods.WindowMessages.WM_CHAR: {
                char character = (char)message.WParam.ToInt32();
                OnCharacterEntered(character);
                return(true); // consumed!
            }


            // Mouse has been moved
            case (int)UnsafeNativeMethods.WindowMessages.WM_MOUSEMOVE: {
                if (!this.trackingMouse)
                {
                    int result = UnsafeNativeMethods.TrackMouseEvent(ref this.mouseEventTrackData);
                    Debug.Assert(
                        result != 0,
                        "Could not set up registration for mouse events",
                        "The TrackMouseEvent() function failed, which means the game will not " +
                        "detect when the mouse leaves the game window. This might result in " +
                        "the assumed mouse position remaining somewhere near the window border " +
                        "even though the mouse has been moved away from the game window."
                        );
                    this.trackingMouse = (result != 0);
                }

                short x = (short)(message.LParam.ToInt32() & 0xFFFF);
                short y = (short)(message.LParam.ToInt32() >> 16);
                OnMouseMoved((float)x, (float)y);
                break;
            }

            // Left mouse button pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_LBUTTONDOWN:
            case (int)UnsafeNativeMethods.WindowMessages.WM_LBUTTONDBLCLK: {
                OnMouseButtonPressed(MouseButtons.Left);
                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_LBUTTONUP: {
                OnMouseButtonReleased(MouseButtons.Left);
                break;
            }

            // Right mouse button pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_RBUTTONDOWN:
            case (int)UnsafeNativeMethods.WindowMessages.WM_RBUTTONDBLCLK: {
                OnMouseButtonPressed(MouseButtons.Right);
                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_RBUTTONUP: {
                OnMouseButtonReleased(MouseButtons.Right);
                break;
            }

            // Middle mouse button pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_MBUTTONDOWN:
            case (int)UnsafeNativeMethods.WindowMessages.WM_MBUTTONDBLCLK: {
                OnMouseButtonPressed(MouseButtons.Middle);
                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_MBUTTONUP: {
                OnMouseButtonReleased(MouseButtons.Middle);
                break;
            }

            // Extended mouse button pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_XBUTTONDOWN:
            case (int)UnsafeNativeMethods.WindowMessages.WM_XBUTTONDBLCLK: {
                short button = (short)(message.WParam.ToInt32() >> 16);
                if (button == 1)
                {
                    OnMouseButtonPressed(MouseButtons.X1);
                }
                if (button == 2)
                {
                    OnMouseButtonPressed(MouseButtons.X2);
                }

                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_XBUTTONUP: {
                short button = (short)(message.WParam.ToInt32() >> 16);
                if (button == 1)
                {
                    OnMouseButtonReleased(MouseButtons.X1);
                }
                if (button == 2)
                {
                    OnMouseButtonReleased(MouseButtons.X2);
                }

                break;
            }

            // Mouse wheel rotated
            case (int)UnsafeNativeMethods.WindowMessages.WM_MOUSEHWHEEL: {
                short ticks = (short)(message.WParam.ToInt32() >> 16);
                OnMouseWheelRotated((float)ticks / 120.0f);
                break;
            }

            // Mouse has left the window's client area
            case (int)UnsafeNativeMethods.WindowMessages.WM_MOUSELEAVE: {
                OnMouseMoved(-1.0f, -1.0f);
                this.trackingMouse = false;
                break;
            }
            }

            return(false);
        }
        /// <summary>Filters out a message before it is dispatched</summary>
        /// <param name="message">
        ///   Message that will be dispatched. You must not modify this message.
        /// </param>
        /// <returns>
        ///   True if the message has been processed by the filter and should not be
        ///   dispatched or false to continue processing of the message.
        /// </returns>
        bool IMessageFilter.PreFilterMessage(ref Message message)
        {
            // Process the message differently based on its message id
            switch (message.Msg)
            {
            case (int)UnsafeNativeMethods.WindowMessages.WM_SYSKEYDOWN: {
                int virtualKeyCode = message.WParam.ToInt32();

                // Don't handle these Alt+key presses because they'd block Windows' shortcuts
                bool dontHandle =
                    (virtualKeyCode == (int)Keys.F4) ||
                    (virtualKeyCode == (int)Keys.Escape) ||
                    (virtualKeyCode == (int)Keys.Space);

                if (dontHandle)
                {
                    break;
                }

                goto case (int)UnsafeNativeMethods.WindowMessages.WM_KEYDOWN;
            }

            // Key on the keyboard was pressed
            case (int)UnsafeNativeMethods.WindowMessages.WM_KEYDOWN: {
                int virtualKeyCode = message.WParam.ToInt32();
                switch (virtualKeyCode)
                {
#if false                    // XNA doesn't want to distinguish Return and Enter
                case 0x0D: { // VK_ENTER
                    bool extended = (message.LParam.ToInt32() & 0x01000000) != 0;
                    if (extended)
                    {
                        OnKeyPressed(Keys.Enter);
                    }
                    else
                    {
                        OnKeyPressed(Keys.??);
                    }

                    break;
                }
#endif
                case 0x10: { // VK_SHIFT
                    OnKeyPressed(
                        (Keys)UnsafeNativeMethods.MapVirtualKey(
                            (uint)(message.LParam.ToInt32() & 0x00FF0000) >> 16,
                            (uint)UnsafeNativeMethods.MapType.ScanCodeToVirtualKeyEx
                            )
                        );
                    break;
                }

                case 0x11: { // VK_CONTROL
                    bool extended = (message.LParam.ToInt32() & 0x01000000) != 0;
                    if (extended)
                    {
                        OnKeyPressed(Keys.RightControl);
                    }
                    else
                    {
                        OnKeyPressed(Keys.LeftControl);
                    }

                    break;
                }

                case 0x12: { // VK_MENU
                    bool extended = (message.LParam.ToInt32() & 0x01000000) != 0;
                    if (extended)
                    {
                        OnKeyPressed(Keys.RightAlt);
                    }
                    else
                    {
                        OnKeyPressed(Keys.LeftAlt);
                    }
                    break;
                }

                default: {
                    OnKeyPressed((Keys)virtualKeyCode);
                    break;
                }
                }

                UnsafeNativeMethods.TranslateMessage(ref message);

                return(true); // consumed!
            }

            // Key on the keyboard was released
            case (int)UnsafeNativeMethods.WindowMessages.WM_SYSKEYUP:
            case (int)UnsafeNativeMethods.WindowMessages.WM_KEYUP: {
                int virtualKeyCode = message.WParam.ToInt32();
                switch (virtualKeyCode)
                {
#if false                    // We could, but XNA doesn't want to distinguish Return and Enter
                case 0x0D: { // VK_ENTER
                    bool extended = (message.LParam.ToInt32() & 0x01000000) != 0;
                    if (extended)
                    {
                        OnKeyReleased(Keys.Enter);
                    }
                    else
                    {
                        OnKeyReleased(Keys.??);
                    }

                    break;
                }
#endif
                case 0x10: { // VK_SHIFT
                    OnKeyReleased(
                        (Keys)UnsafeNativeMethods.MapVirtualKey(
                            (uint)(message.LParam.ToInt32() & 0x00FF0000) >> 16,
                            (uint)UnsafeNativeMethods.MapType.ScanCodeToVirtualKeyEx
                            )
                        );
                    break;
                }

                case 0x11: { // VK_CONTROL
                    bool isExtendedKey = (message.LParam.ToInt32() & (1 << 24)) != 0;
                    if (isExtendedKey)
                    {
                        OnKeyReleased(Keys.RightControl);
                    }
                    else
                    {
                        OnKeyReleased(Keys.LeftControl);
                    }

                    break;
                }

                case 0x12: { // VK_MENU
                    bool isExtendedKey = (message.LParam.ToInt32() & (1 << 24)) != 0;
                    if (isExtendedKey)
                    {
                        OnKeyReleased(Keys.RightAlt);
                    }
                    else
                    {
                        OnKeyReleased(Keys.LeftAlt);
                    }

                    break;
                }

                default: {
                    OnKeyReleased((Keys)virtualKeyCode);
                    break;
                }
                }

                return(true); // consumed!
            }

            // Character has been entered on the keyboard
            case (int)UnsafeNativeMethods.WindowMessages.WM_CHAR: {
                char character = (char)message.WParam.ToInt32();
                OnCharacterEntered(character);
                return(true); // consumed!
            }


            // Mouse has been moved
            case (int)UnsafeNativeMethods.WindowMessages.WM_MOUSEMOVE: {
                if (!this.trackingMouse)
                {
                    int result = UnsafeNativeMethods.TrackMouseEvent(ref this.mouseEventTrackData);
                    Debug.Assert(
                        result != 0,
                        "Could not set up registration for mouse events",
                        "The TrackMouseEvent() function failed, which means the game will not " +
                        "detect when the mouse leaves the game window. This might result in " +
                        "the assumed mouse position remaining somewhere near the window border " +
                        "even though the mouse has been moved away from the game window."
                        );
                    this.trackingMouse = (result != 0);
                }

                short x = (short)(message.LParam.ToInt32() & 0xFFFF);
                short y = (short)(message.LParam.ToInt32() >> 16);
                OnMouseMoved((float)x, (float)y);
                break;
            }

            // Left mouse button pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_LBUTTONDOWN:
            case (int)UnsafeNativeMethods.WindowMessages.WM_LBUTTONDBLCLK: {
                OnMouseButtonPressed(MouseButtons.Left);
                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_LBUTTONUP: {
                OnMouseButtonReleased(MouseButtons.Left);
                break;
            }

            // Right mouse button pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_RBUTTONDOWN:
            case (int)UnsafeNativeMethods.WindowMessages.WM_RBUTTONDBLCLK: {
                OnMouseButtonPressed(MouseButtons.Right);
                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_RBUTTONUP: {
                OnMouseButtonReleased(MouseButtons.Right);
                break;
            }

            // Middle mouse button pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_MBUTTONDOWN:
            case (int)UnsafeNativeMethods.WindowMessages.WM_MBUTTONDBLCLK: {
                OnMouseButtonPressed(MouseButtons.Middle);
                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_MBUTTONUP: {
                OnMouseButtonReleased(MouseButtons.Middle);
                break;
            }

            // Extended mouse button pressed / released
            case (int)UnsafeNativeMethods.WindowMessages.WM_XBUTTONDOWN:
            case (int)UnsafeNativeMethods.WindowMessages.WM_XBUTTONDBLCLK: {
                short button = (short)(message.WParam.ToInt32() >> 16);
                if (button == 1)
                {
                    OnMouseButtonPressed(MouseButtons.X1);
                }
                if (button == 2)
                {
                    OnMouseButtonPressed(MouseButtons.X2);
                }

                break;
            }

            case (int)UnsafeNativeMethods.WindowMessages.WM_XBUTTONUP: {
                short button = (short)(message.WParam.ToInt32() >> 16);
                if (button == 1)
                {
                    OnMouseButtonReleased(MouseButtons.X1);
                }
                if (button == 2)
                {
                    OnMouseButtonReleased(MouseButtons.X2);
                }

                break;
            }

            // Mouse wheel rotated
            case (int)UnsafeNativeMethods.WindowMessages.WM_MOUSEHWHEEL: {
                short ticks = (short)(message.WParam.ToInt32() >> 16);
                OnMouseWheelRotated((float)ticks / 120.0f);
                break;
            }

            // Mouse has left the window's client area
            case (int)UnsafeNativeMethods.WindowMessages.WM_MOUSELEAVE: {
                OnMouseMoved(-1.0f, -1.0f);
                this.trackingMouse = false;
                break;
            }
            }

            return(false);
        }