예제 #1
0
        IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
        {
            bool mouse_about_to_enter = false;

            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 != null)
                {
                    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.
                timer_handle = Functions.SetTimer(handle, ModalLoopTimerId, ModalLoopTimerPeriod, ModalLoopCallback);
                if (timer_handle == UIntPtr.Zero)
                {
                    Debug.Print("[Warning] Failed to set modal loop timer callback ({0}:{1}->{2}).",
                                GetType().Name, handle, Marshal.GetLastWin32Error());
                }

                break;

            case WindowMessage.EXITMENULOOP:
            case WindowMessage.EXITSIZEMOVE:
                // ExitingmModal size/move loop: the timer callback is no longer
                // necessary.
                if (!Functions.KillTimer(handle, timer_handle))
                {
                    Debug.Print("[Warning] Failed to kill modal loop timer callback ({0}:{1}->{2}).",
                                GetType().Name, handle, Marshal.GetLastWin32Error());
                }
                timer_handle = UIntPtr.Zero;
                break;

            case WindowMessage.NCCALCSIZE:
                // Need to update the client rectangle, because it has the wrong size on Vista with Aero enabled.
                //if (m.WParam == new IntPtr(1))
                //{
                //    unsafe
                //    {
                //        NcCalculateSize* nc_calc_size = (NcCalculateSize*)m.LParam;
                //        //nc_calc_size->NewBounds = nc_calc_size->OldBounds;
                //        //nc_calc_size->OldBounds = nc_calc_size->NewBounds;
                //        //client_rectangle = rect.OldClientRectangle;
                //    }

                //    m.Result = new IntPtr((int)(NcCalcSizeOptions.ALIGNTOP | NcCalcSizeOptions.ALIGNLEFT/* | NcCalcSizeOptions.REDRAW*/));
                //}
                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;
                            if (Move != null)
                            {
                                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;

                            Rectangle 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 (Resize != null)
                            {
                                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;
                    if (WindowStateChanged != null)
                    {
                        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();
                }

                if (KeyPress != null)
                {
                    KeyPress(this, key_press);
                }
                break;

            //case WindowMessage.MOUSELEAVE:
            //    Cursor.Current = Cursors.Default;
            //    break;

            //case WindowMessage.MOUSE_ENTER:
            //    Cursor.Current = Cursors.Default;
            //    break;

            // Mouse events:
            case WindowMessage.NCMOUSEMOVE:
                mouse_about_to_enter = true;       // Used to simulate a mouse enter event.
                break;

            case WindowMessage.MOUSEMOVE:
                mouse.Position = new System.Drawing.Point(
                    (int)(lParam.ToInt32() & 0x0000FFFF),
                    (int)(lParam.ToInt32() & 0xFFFF0000) >> 16);
                if (mouse_about_to_enter)
                {
                    //Cursor.Current = Cursors.Default;
                    mouse_about_to_enter = false;
                }
                break;

            case WindowMessage.MOUSEWHEEL:
                // This is due to inconsistent behavior of the WParam value on 64bit arch, whese
                // wparam = 0xffffffffff880000 or wparam = 0x00000000ff100000
                mouse.Wheel += (int)((long)wParam << 32 >> 48) / 120;
                break;

            case WindowMessage.LBUTTONDOWN:
                mouse[MouseButton.Left] = true;
                break;

            case WindowMessage.MBUTTONDOWN:
                mouse[MouseButton.Middle] = true;
                break;

            case WindowMessage.RBUTTONDOWN:
                mouse[MouseButton.Right] = true;
                break;

            case WindowMessage.XBUTTONDOWN:
                mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = true;
                break;

            case WindowMessage.LBUTTONUP:
                mouse[MouseButton.Left] = false;
                break;

            case WindowMessage.MBUTTONUP:
                mouse[MouseButton.Middle] = false;
                break;

            case WindowMessage.RBUTTONUP:
                mouse[MouseButton.Right] = false;
                break;

            case WindowMessage.XBUTTONUP:
                // TODO: Is this correct?
                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 reliably 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.

                    // TODO: Not 100% reliable, when both keys are pressed at once.
                    if (ShiftRightScanCode != 0)
                    {
                        unchecked
                        {
                            if (((lParam.ToInt64() >> 16) & 0xFF) == ShiftRightScanCode)
                            {
                                keyboard[Input.Key.ShiftRight] = pressed;
                            }
                            else
                            {
                                keyboard[Input.Key.ShiftLeft] = pressed;
                            }
                        }
                    }
                    else
                    {
                        // Should only fall here on Windows 9x and NT4.0-
                        keyboard[Input.Key.ShiftLeft] = 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 (!WMInput.KeyMap.ContainsKey((VirtualKeys)wParam))
                    {
                        Debug.Print("Virtual key {0} ({1}) not mapped.", (VirtualKeys)wParam, (int)lParam);
                        break;
                    }
                    else
                    {
                        keyboard[WMInput.KeyMap[(VirtualKeys)wParam]] = 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;

                    Rectangle rect;
                    Functions.GetClientRect(handle, out rect);
                    client_rectangle = rect.ToRectangle();
                }
                break;

            case WindowMessage.CLOSE:
                System.ComponentModel.CancelEventArgs e = new System.ComponentModel.CancelEventArgs();

                if (Closing != null)
                {
                    Closing(this, e);
                }

                if (!e.Cancel)
                {
                    if (Unload != null)
                    {
                        Unload(this, EventArgs.Empty);
                    }

                    DestroyWindow();
                    break;
                }

                return(IntPtr.Zero);

            case WindowMessage.DESTROY:
                exists = false;

                Functions.UnregisterClass(ClassName, Instance);
                //Marshal.FreeHGlobal(ClassName);
                window.Dispose();
                child_window.Dispose();

                if (Closed != null)
                {
                    Closed(this, EventArgs.Empty);
                }

                break;

                #endregion
            }

            return(Functions.DefWindowProc(handle, message, wParam, lParam));
        }
예제 #2
0
        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 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.Handle)
                    {
                        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.Handle, IntPtr.Zero, 0, 0, ClientRectangle.Width, ClientRectangle.Height,
                                                   SetWindowPosFlags.NOZORDER | SetWindowPosFlags.NOOWNERZORDER |
                                                   SetWindowPosFlags.NOACTIVATE | SetWindowPosFlags.NOSENDCHANGING);

                            if (suppress_resize <= 0)
                            {
                                Resize(this, EventArgs.Empty);
                            }
                        }

                        // Ensure cursor remains grabbed
                        if (!CursorVisible)
                        {
                            GrabCursor();
                        }
                    }
                }
                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;
                        }
                    }
                }

                // Ensure cursor remains grabbed
                if (!CursorVisible)
                {
                    GrabCursor();
                }

                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);
                }

                // Ensure cursor remains grabbed
                if (!CursorVisible)
                {
                    GrabCursor();
                }

                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 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();

                    MouseEnter(this, EventArgs.Empty);
                }
                break;

            case WindowMessage.MOUSELEAVE:
                mouse_outside_window = true;
                // Mouse tracking is disabled automatically by the OS

                MouseLeave(this, EventArgs.Empty);
                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.Handle);
                mouse[MouseButton.Left] = true;
                break;

            case WindowMessage.MBUTTONDOWN:
                Functions.SetCapture(window.Handle);
                mouse[MouseButton.Middle] = true;
                break;

            case WindowMessage.RBUTTONDOWN:
                Functions.SetCapture(window.Handle);
                mouse[MouseButton.Right] = true;
                break;

            case WindowMessage.XBUTTONDOWN:
                Functions.SetCapture(window.Handle);
                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[GET_XBUTTON_WPARAM(wParam.ToInt32())] = 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;
                uint scancode = (uint)((lParam.ToInt64() >> 16) & 0xFF);
                Key  key      = Key.Unknown;
                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)
                    {
                        if (scancode == ShiftRightScanCode)
                        {
                            key = Input.Key.ShiftRight;
                        }
                        else
                        {
                            key = Input.Key.ShiftLeft;
                        }
                    }
                    else
                    {
                        // Windows 9x and NT4.0 or key release event.
                        keyboard.SetKey(Input.Key.ShiftLeft, ShiftLeftScanCode, pressed);
                        keyboard.SetKey(Input.Key.ShiftRight, ShiftRightScanCode, pressed);
                    }
                    break;

                case VirtualKeys.CONTROL:
                    if (extended)
                    {
                        key = Input.Key.ControlRight;
                    }
                    else
                    {
                        key = Input.Key.ControlLeft;
                    }
                    break;

                case VirtualKeys.MENU:
                    if (extended)
                    {
                        key = Input.Key.AltRight;
                    }
                    else
                    {
                        key = Input.Key.AltLeft;
                    }
                    break;

                case VirtualKeys.RETURN:
                    if (extended)
                    {
                        key = Key.KeypadEnter;
                    }
                    else
                    {
                        key = Key.Enter;
                    }
                    break;

                default:
                    if (!KeyMap.ContainsKey((VirtualKeys)wParam))
                    {
                        Debug.Print("Virtual key {0} ({1}) not mapped.", (VirtualKeys)wParam, (long)lParam);
                    }
                    else
                    {
                        key = KeyMap[(VirtualKeys)wParam];
                    }
                    break;
                }

                keyboard.SetKey(key, scancode, pressed);
                return(IntPtr.Zero);

            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;

                    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));
        }
예제 #3
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));
        }
예제 #4
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 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 != null)
                {
                    FocusedChanged(this, EventArgs.Empty);
                }
                break;

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

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

            case WindowMessage.WINDOWPOSCHANGED:
                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;
                        if (Move != null)
                        {
                            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;
                        API.GetClientRect(handle, out rect);
                        client_rectangle = rect.ToRectangle();

                        API.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 != null)
                        {
                            Resize(this, EventArgs.Empty);
                        }
                    }
                }
                break;

            case WindowMessage.STYLECHANGED:
                if (wParam.ToInt64() == (long)GWL.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;
                    if (WindowStateChanged != null)
                    {
                        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();
                }

                if (KeyPress != null)
                {
                    KeyPress(this, key_press);
                }
                break;

            case WindowMessage.MOUSEMOVE:
                Point 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 (MouseEnter != null)
                    {
                        MouseEnter(this, EventArgs.Empty);
                    }
                }
                break;

            case WindowMessage.MOUSELEAVE:
                mouse_outside_window = true;
                // Mouse tracking is disabled automatically by the OS

                if (MouseLeave != null)
                {
                    MouseLeave(this, EventArgs.Empty);
                }
                // Set all mouse buttons to off when user leaves window, prevents them being stuck down.
                for (MouseButton btn = 0; btn < MouseButton.LastButton; btn++)
                {
                    mouse[btn] = false;
                }
                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;
                return(IntPtr.Zero);

            case WindowMessage.LBUTTONDOWN:
                mouse[MouseButton.Left] = true;
                break;

            case WindowMessage.MBUTTONDOWN:
                mouse[MouseButton.Middle] = true;
                break;

            case WindowMessage.RBUTTONDOWN:
                mouse[MouseButton.Right] = true;
                break;

            case WindowMessage.XBUTTONDOWN:
                mouse[(((ulong)wParam.ToInt64() >> 16) & 0xFFFF) != (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = true;
                break;

            case WindowMessage.LBUTTONUP:
                mouse[MouseButton.Left] = false;
                break;

            case WindowMessage.MBUTTONUP:
                mouse[MouseButton.Middle] = false;
                break;

            case WindowMessage.RBUTTONUP:
                mouse[MouseButton.Right] = false;
                break;

            case WindowMessage.XBUTTONUP:
                mouse[(((ulong)wParam.ToInt64() >> 16) & 0xFFFF) != (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).
                    bool lShiftDown = (API.GetKeyState((int)VirtualKeys.LSHIFT) >> 15) == 1;
                    bool rShiftDown = (API.GetKeyState((int)VirtualKeys.RSHIFT) >> 15) == 1;

                    if (!pressed || lShiftDown != rShiftDown)
                    {
                        Keyboard[Input.Key.ShiftLeft]  = lShiftDown;
                        Keyboard[Input.Key.ShiftRight] = rShiftDown;
                    }
                    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:
                    Key tkKey;
                    if (!KeyMap.TryGetMappedKey((VirtualKeys)wParam, out tkKey))
                    {
                        Debug.Print("Virtual key {0} ({1}) not mapped.", (VirtualKeys)wParam, lParam.ToInt64());
                        break;
                    }
                    else
                    {
                        keyboard[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;

                    Win32Rectangle rect;
                    API.GetClientRect(handle, out rect);
                    client_rectangle = rect.ToRectangle();

                    invisible_since_creation = true;
                }
                break;

            case WindowMessage.CLOSE:
                System.ComponentModel.CancelEventArgs e = new System.ComponentModel.CancelEventArgs();

                if (Closing != null)
                {
                    Closing(this, e);
                }

                if (!e.Cancel)
                {
                    if (Unload != null)
                    {
                        Unload(this, EventArgs.Empty);
                    }

                    DestroyWindow();
                    break;
                }

                return(IntPtr.Zero);

            case WindowMessage.DESTROY:
                exists = false;

                API.UnregisterClass(ClassName, Instance);
                window.Dispose();
                child_window.Dispose();

                if (Closed != null)
                {
                    Closed(this, EventArgs.Empty);
                }

                break;

                #endregion
            }
            return(API.DefWindowProc(handle, message, wParam, lParam));
        }
예제 #5
0
        private unsafe IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam)
        {
            switch (message)
            {
            case WindowMessage.MOUSEMOVE:
                this.mouse.Position = new Point((int)(short)(lParam.ToInt32() & (int)ushort.MaxValue), (int)(short)((uint)(lParam.ToInt32() & -65536) >> 16));
                if (this.mouse_outside_window)
                {
                    this.mouse_outside_window = false;
                    this.EnableMouseTracking();
                    this.MouseEnter((object)this, EventArgs.Empty);
                    break;
                }
                else
                {
                    break;
                }

            case WindowMessage.LBUTTONDOWN:
                Functions.SetCapture(this.window.WindowHandle);
                this.mouse[MouseButton.Left] = true;
                break;

            case WindowMessage.LBUTTONUP:
                Functions.ReleaseCapture();
                this.mouse[MouseButton.Left] = false;
                break;

            case WindowMessage.RBUTTONDOWN:
                Functions.SetCapture(this.window.WindowHandle);
                this.mouse[MouseButton.Right] = true;
                break;

            case WindowMessage.RBUTTONUP:
                Functions.ReleaseCapture();
                this.mouse[MouseButton.Right] = false;
                break;

            case WindowMessage.MBUTTONDOWN:
                Functions.SetCapture(this.window.WindowHandle);
                this.mouse[MouseButton.Middle] = true;
                break;

            case WindowMessage.MBUTTONUP:
                Functions.ReleaseCapture();
                this.mouse[MouseButton.Middle] = false;
                break;

            case WindowMessage.MOUSEWHEEL:
                this.mouse.WheelPrecise += (float)((long)wParam << 32 >> 48) / 120f;
                break;

            case WindowMessage.XBUTTONDOWN:
                Functions.SetCapture(this.window.WindowHandle);
                this.mouse[((long)wParam.ToInt32() & 4294901760L) >> 16 != 32L ? MouseButton.Button1 : MouseButton.Button2] = true;
                break;

            case WindowMessage.XBUTTONUP:
                Functions.ReleaseCapture();
                this.mouse[((long)wParam.ToInt32() & 4294901760L) >> 16 != 32L ? MouseButton.Button1 : MouseButton.Button2] = false;
                break;

            case WindowMessage.ENTERMENULOOP:
            case WindowMessage.ENTERSIZEMOVE:
                this.StartTimer(handle);
                break;

            case WindowMessage.EXITMENULOOP:
            case WindowMessage.EXITSIZEMOVE:
                this.StopTimer(handle);
                break;

            case WindowMessage.MOUSELEAVE:
                this.mouse_outside_window = true;
                this.MouseLeave((object)this, EventArgs.Empty);
                break;

            case WindowMessage.STYLECHANGED:
                if (wParam.ToInt64() == -16L)
                {
                    WindowStyle windowStyle = ((StyleStruct *)(void *)lParam)->New;
                    if ((windowStyle & WindowStyle.Popup) != WindowStyle.Overlapped)
                    {
                        this.windowBorder = WindowBorder.Hidden;
                    }
                    else if ((windowStyle & WindowStyle.ThickFrame) != WindowStyle.Overlapped)
                    {
                        this.windowBorder = WindowBorder.Resizable;
                    }
                    else if ((windowStyle & ~(WindowStyle.ThickFrame | WindowStyle.TabStop)) != WindowStyle.Overlapped)
                    {
                        this.windowBorder = WindowBorder.Fixed;
                    }
                }
                if (!this.CursorVisible)
                {
                    this.GrabCursor();
                    break;
                }
                else
                {
                    break;
                }

            case WindowMessage.KEYDOWN:
            case WindowMessage.KEYUP:
            case WindowMessage.SYSKEYDOWN:
            case WindowMessage.SYSKEYUP:
                bool flag1 = message == WindowMessage.KEYDOWN || message == WindowMessage.SYSKEYDOWN;
                bool flag2 = (lParam.ToInt64() & 16777216L) != 0L;
                switch ((short)(int)wParam)
                {
                case (short)13:
                    if (flag2)
                    {
                        this.keyboard[Key.KeypadEnter] = flag1;
                    }
                    else
                    {
                        this.keyboard[Key.Enter] = flag1;
                    }
                    return(IntPtr.Zero);

                case (short)16:
                    if ((int)WinGLNative.ShiftRightScanCode != 0 && flag1)
                    {
                        if ((lParam.ToInt64() >> 16 & (long)byte.MaxValue) == (long)WinGLNative.ShiftRightScanCode)
                        {
                            this.keyboard[Key.ShiftRight] = flag1;
                        }
                        else
                        {
                            this.keyboard[Key.ShiftLeft] = flag1;
                        }
                    }
                    else
                    {
                        this.keyboard[Key.ShiftLeft] = this.keyboard[Key.ShiftRight] = flag1;
                    }
                    return(IntPtr.Zero);

                case (short)17:
                    if (flag2)
                    {
                        this.keyboard[Key.ControlRight] = flag1;
                    }
                    else
                    {
                        this.keyboard[Key.ControlLeft] = flag1;
                    }
                    return(IntPtr.Zero);

                case (short)18:
                    if (flag2)
                    {
                        this.keyboard[Key.AltRight] = flag1;
                    }
                    else
                    {
                        this.keyboard[Key.AltLeft] = flag1;
                    }
                    return(IntPtr.Zero);

                default:
                    if (WinGLNative.KeyMap.ContainsKey((VirtualKeys)(int)wParam))
                    {
                        this.keyboard[WinGLNative.KeyMap[(VirtualKeys)(int)wParam]] = flag1;
                        return(IntPtr.Zero);
                    }
                    else
                    {
                        break;
                    }
                }

            case WindowMessage.CHAR:
                this.key_press.KeyChar = IntPtr.Size != 4 ? (char)wParam.ToInt64() : (char)wParam.ToInt32();
                this.KeyPress((object)this, this.key_press);
                break;

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

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

            case WindowMessage.WINDOWPOSCHANGED:
                WindowPosition *windowPositionPtr = (WindowPosition *)(void *)lParam;
                if (this.window != null && windowPositionPtr->hwnd == this.window.WindowHandle)
                {
                    Point point = new Point(windowPositionPtr->x, windowPositionPtr->y);
                    if (this.Location != point)
                    {
                        this.bounds.Location = point;
                        this.Move((object)this, EventArgs.Empty);
                    }
                    if (this.Size != new Size(windowPositionPtr->cx, windowPositionPtr->cy))
                    {
                        this.bounds.Width  = windowPositionPtr->cx;
                        this.bounds.Height = windowPositionPtr->cy;
                        Win32Rectangle clientRectangle;
                        Functions.GetClientRect(handle, out clientRectangle);
                        this.client_rectangle = clientRectangle.ToRectangle();
                        Functions.SetWindowPos(this.child_window.WindowHandle, IntPtr.Zero, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, SetWindowPosFlags.NOZORDER | SetWindowPosFlags.NOACTIVATE | SetWindowPosFlags.NOOWNERZORDER | SetWindowPosFlags.NOSENDCHANGING);
                        if (this.suppress_resize <= 0)
                        {
                            this.Resize((object)this, EventArgs.Empty);
                        }
                    }
                    if (!this.CursorVisible)
                    {
                        this.GrabCursor();
                        break;
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }

            case WindowMessage.CREATE:
                CreateStruct createStruct = (CreateStruct)Marshal.PtrToStructure(lParam, typeof(CreateStruct));
                if (createStruct.hwndParent == IntPtr.Zero)
                {
                    this.bounds.X      = createStruct.x;
                    this.bounds.Y      = createStruct.y;
                    this.bounds.Width  = createStruct.cx;
                    this.bounds.Height = createStruct.cy;
                    Win32Rectangle clientRectangle;
                    Functions.GetClientRect(handle, out clientRectangle);
                    this.client_rectangle         = clientRectangle.ToRectangle();
                    this.invisible_since_creation = true;
                    break;
                }
                else
                {
                    break;
                }

            case WindowMessage.DESTROY:
                this.exists = false;
                int num = (int)Functions.UnregisterClass(this.ClassName, this.Instance);
                this.window.Dispose();
                this.child_window.Dispose();
                this.Closed((object)this, EventArgs.Empty);
                break;

            case WindowMessage.SIZE:
                SizeMessage sizeMessage = (SizeMessage)wParam.ToInt64();
                WindowState windowState = this.windowState;
                switch (sizeMessage)
                {
                case SizeMessage.RESTORED:
                    windowState = this.borderless_maximized_window_state ? WindowState.Maximized : WindowState.Normal;
                    break;

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

                case SizeMessage.MAXIMIZED:
                    windowState = this.WindowBorder == WindowBorder.Hidden ? WindowState.Fullscreen : WindowState.Maximized;
                    break;
                }
                if (windowState != this.windowState)
                {
                    this.windowState = windowState;
                    this.WindowStateChanged((object)this, EventArgs.Empty);
                }
                if (!this.CursorVisible)
                {
                    this.GrabCursor();
                    break;
                }
                else
                {
                    break;
                }

            case WindowMessage.ACTIVATE:
                bool focused = this.Focused;
                this.focused = IntPtr.Size != 4 ? (wParam.ToInt64() & (long)ushort.MaxValue) != 0L : (wParam.ToInt32() & (int)ushort.MaxValue) != 0;
                if (focused != this.Focused)
                {
                    this.FocusedChanged((object)this, EventArgs.Empty);
                    break;
                }
                else
                {
                    break;
                }

            case WindowMessage.KILLFOCUS:
                this.keyboard.ClearKeys();
                break;

            case WindowMessage.CLOSE:
                CancelEventArgs e = new CancelEventArgs();
                this.Closing((object)this, e);
                if (e.Cancel)
                {
                    return(IntPtr.Zero);
                }
                this.DestroyWindow();
                break;
            }
            return(Functions.DefWindowProc(handle, message, wParam, lParam));
        }