private void UpdateWindowState() { // we should wait until window's not fullscreen to resize if (updateClientBounds) { window.ClientRectangle = new System.Drawing.Rectangle(clientBounds.X, clientBounds.Y, clientBounds.Width, clientBounds.Height); updateClientBounds = false; // if the window-state is set from the outside (maximized button pressed) we have to update it here. // if it was set from the inside (.IsFullScreen changed), we have to change the window. // this code might not cover all corner cases // window was maximized if ((windowState == WindowState.Normal && window.WindowState == WindowState.Maximized) || (windowState == WindowState.Maximized && window.WindowState == WindowState.Normal)) { windowState = window.WindowState; // maximize->normal and normal->maximize are usually set from the outside } else { window.WindowState = windowState; // usually fullscreen-stuff is set from the code } // fixes issue on linux (and windows?) that AllowUserResizing is not set any more when exiting fullscreen mode WindowBorder desired = AllowUserResizing ? WindowBorder.Resizable : WindowBorder.Fixed; if (desired != window.WindowBorder && window.WindowState != WindowState.Fullscreen) { window.WindowBorder = desired; } } }
/// <summary> /// Creates a new WindowOptions struct. /// </summary> public WindowOptions ( bool isVisible, bool useSingleThreadedWindow, Point position, Size size, double framesPerSecond, double updatesPerSecond, GraphicsAPI api, string title, WindowState windowState, WindowBorder windowBorder, VSyncMode vSync, int isRunningSlowlyThreshold, bool shouldSwapAutomatically, VideoMode videoMode, int?preferredDepthBufferBits = null ) { IsVisible = isVisible; UseSingleThreadedWindow = useSingleThreadedWindow; Position = position; Size = size; FramesPerSecond = framesPerSecond; UpdatesPerSecond = updatesPerSecond; API = api; Title = title; WindowState = windowState; WindowBorder = windowBorder; VSync = vSync; RunningSlowTolerance = isRunningSlowlyThreshold; ShouldSwapAutomatically = shouldSwapAutomatically; VideoMode = videoMode; PreferredDepthBufferBits = preferredDepthBufferBits; }
/// <summary> /// Create a new GlfwWindow. /// </summary> /// <param name="options">The options to use for this window.</param> public unsafe GlfwWindow(WindowOptions options, GlfwWindow parent, GlfwMonitor monitor) { // Title and Size must be set before the window is created. _title = options.Title; _size = options.Size; _windowBorder = WindowBorder; FramesPerSecond = options.FramesPerSecond; UpdatesPerSecond = options.UpdatesPerSecond; RunningSlowTolerance = options.RunningSlowTolerance; UseSingleThreadedWindow = options.UseSingleThreadedWindow; ShouldSwapAutomatically = options.ShouldSwapAutomatically; _initialOptions = options; _initialMonitor = monitor; Parent = (IWindowHost)parent ?? _initialMonitor; GlfwProvider.GLFW.Value.GetVersion(out var major, out var minor, out _); if (new Version(major, minor) < new Version(3, 3)) { throw new NotSupportedException("GLFW 3.3 or later is required for Silk.NET.Windowing.Desktop."); } }
private void UpdateWindowState() { if (!this.updateClientBounds) { return; } this.updateClientBounds = false; if (this.windowState == WindowState.Normal && this.window.WindowState == WindowState.Maximized || this.windowState == WindowState.Maximized && this.window.WindowState == WindowState.Normal) { this.windowState = this.window.WindowState; } else { this.window.WindowState = this.windowState; } WindowBorder windowBorder = !this._isBorderless ? (this._isResizable ? WindowBorder.Resizable : WindowBorder.Fixed) : WindowBorder.Hidden; if (windowBorder != this.window.WindowBorder && this.window.WindowState != WindowState.Fullscreen) { this.window.WindowBorder = windowBorder; } this.window.ClientRectangle = new System.Drawing.Rectangle(this.targetBounds.X, this.targetBounds.Y, this.targetBounds.Width, this.targetBounds.Height); DisplayDevice display = DisplayDevice.GetDisplay(DisplayIndex.Primary); this.window.X = (display.Width - this.window.Width) / 2; this.window.Y = (display.Height - this.window.Height) / 2; }
/// <summary> /// Creates a new WindowOptions struct. /// </summary> public WindowOptions ( bool isVisible, Vector2D <int> position, Vector2D <int> size, double framesPerSecond, double updatesPerSecond, GraphicsAPI api, string title, WindowState windowState, WindowBorder windowBorder, bool isVSync, bool shouldSwapAutomatically, VideoMode videoMode, int?preferredDepthBufferBits = null, bool transparentFramebuffer = false, bool isEventDriven = false ) { IsVisible = isVisible; Position = position; Size = size; FramesPerSecond = framesPerSecond; UpdatesPerSecond = updatesPerSecond; API = api; Title = title; WindowState = windowState; WindowBorder = windowBorder; ShouldSwapAutomatically = shouldSwapAutomatically; VideoMode = videoMode; PreferredDepthBufferBits = preferredDepthBufferBits; TransparentFramebuffer = transparentFramebuffer; IsEventDriven = isEventDriven; VSync = isVSync; }
private void OnUserDataChanged(object sender, EventArgs e) { // Early-out, if no display is connected / available anyway if (DisplayDevice.Default == null) { return; } // Determine the target state for our window MouseCursor targetCursor = DualityApp.UserData.SystemCursorVisible ? MouseCursor.Default : MouseCursor.Empty; WindowState targetWindowState = this.internalWindow.WindowState; WindowBorder targetWindowBorder = this.internalWindow.WindowBorder; Size targetSize = this.internalWindow.ClientSize; switch (DualityApp.UserData.WindowMode) { case ScreenMode.Window: targetWindowState = WindowState.Normal; targetWindowBorder = WindowBorder.Resizable; targetSize = new Size(DualityApp.UserData.WindowSize.X, DualityApp.UserData.WindowSize.Y); break; case ScreenMode.FixedWindow: targetWindowState = WindowState.Normal; targetWindowBorder = WindowBorder.Fixed; targetSize = new Size(DualityApp.UserData.WindowSize.X, DualityApp.UserData.WindowSize.Y); break; case ScreenMode.FullWindow: case ScreenMode.Fullscreen: targetWindowState = WindowState.Fullscreen; targetWindowBorder = WindowBorder.Hidden; targetSize = new Size(DisplayDevice.Default.Width, DisplayDevice.Default.Height); break; default: throw new ArgumentOutOfRangeException(); } // Apply the target state to the game window wherever values changed if (this.internalWindow.WindowState != targetWindowState) { this.internalWindow.WindowState = targetWindowState; } if (this.internalWindow.WindowBorder != targetWindowBorder) { this.internalWindow.WindowBorder = targetWindowBorder; } if (this.internalWindow.ClientSize != targetSize) { this.internalWindow.ClientSize = targetSize; } if (this.internalWindow.Cursor != targetCursor) { this.internalWindow.Cursor = targetCursor; } DualityApp.WindowSize = new Point2(this.internalWindow.ClientSize.Width, this.internalWindow.ClientSize.Height); }
public AGSGameSettings(string title, AGS.API.Size virtualResolution, WindowState windowState = WindowState.Maximized, AGS.API.Size?windowSize = null, VsyncMode vsync = VsyncMode.Adaptive, bool preserveAspectRatio = true, WindowBorder windowBorder = WindowBorder.Resizable) { Title = title; VirtualResolution = virtualResolution; WindowState = windowState; WindowSize = windowSize.HasValue ? windowSize.Value : virtualResolution; Vsync = vsync; PreserveAspectRatio = preserveAspectRatio; WindowBorder = windowBorder; }
public AGSGameSettings(string title, AGS.API.Size virtualResolution, WindowState windowState = WindowState.Maximized, AGS.API.Size? windowSize = null, VsyncMode vsync = VsyncMode.Adaptive, bool preserveAspectRatio = true, WindowBorder windowBorder = WindowBorder.Resizable) { Title = title; VirtualResolution = virtualResolution; WindowState = windowState; WindowSize = windowSize.HasValue ? windowSize.Value : virtualResolution; Vsync = vsync; PreserveAspectRatio = preserveAspectRatio; WindowBorder = windowBorder; }
private static NSWindowStyle GetStyleMask(WindowBorder windowBorder) { switch (windowBorder) { case WindowBorder.Resizable: return(NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Titled | NSWindowStyle.Resizable); case WindowBorder.Fixed: return(NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Titled); case WindowBorder.Hidden: return(NSWindowStyle.Borderless); } return((NSWindowStyle)0); }
public Sdl2NativeWindow(int x, int y, int width, int height, string title, GameWindowFlags options, DisplayDevice device) { lock (sync) { SDL.DisableScreenSaver(); var bounds = device.Bounds; var flags = TranslateFlags(options); flags |= WindowFlags.OPENGL; #if TIZEN flags |= WindowFlags.SHOWN; #else flags |= WindowFlags.HIDDEN; #endif if (Toolkit.Options.EnableHighResolution) { flags |= WindowFlags.ALLOW_HIGHDPI; } if ((flags & WindowFlags.FULLSCREEN_DESKTOP) != 0 || (flags & WindowFlags.FULLSCREEN) != 0) { window_state = WindowState.Fullscreen; } if ((flags & WindowFlags.RESIZABLE) == 0) { window_border = WindowBorder.Fixed; } IntPtr handle; lock (SDL.Sync) { handle = SDL.CreateWindow(title, bounds.Left + x, bounds.Top + y, width, height, flags); exists = true; } ProcessEvents(); window = new Sdl2WindowInfo(handle, null); window_id = SDL.GetWindowID(handle); windows.Add(window_id, this); #if TIZEN SDL.SetHint("SDL_IOS_ORIENTATIONS", "Portrait LandscapeLeft LandscapeRight PortraitUpsideDown"); #endif } }
/// <summary> /// Creates a new WindowOptions struct. /// </summary> public WindowOptions ( bool isVisible, Vector2D <int> position, Vector2D <int> size, double framesPerSecond, double updatesPerSecond, GraphicsAPI api, string title, WindowState windowState, WindowBorder windowBorder, bool isVSync, bool shouldSwapAutomatically, VideoMode videoMode, int?preferredDepthBufferBits = null, int?preferredStencilBufferBits = null, Vector4D <int>?preferredBitDepth = null, bool transparentFramebuffer = false, bool isEventDriven = false, IGLContext?sharedContext = null, int?samples = null, string?windowClass = null, bool isContextControlDisabled = false ) { IsVisible = isVisible; Position = position; Size = size; FramesPerSecond = framesPerSecond; UpdatesPerSecond = updatesPerSecond; API = api; Title = title; WindowState = windowState; WindowBorder = windowBorder; ShouldSwapAutomatically = shouldSwapAutomatically; VideoMode = videoMode; PreferredDepthBufferBits = preferredDepthBufferBits; TransparentFramebuffer = transparentFramebuffer; IsEventDriven = isEventDriven; VSync = isVSync; SharedContext = sharedContext; PreferredDepthBufferBits = preferredDepthBufferBits; PreferredStencilBufferBits = preferredStencilBufferBits; PreferredBitDepth = preferredBitDepth; Samples = samples; WindowClass = windowClass; IsContextControlDisabled = isContextControlDisabled; }
public AGSGameSettings(string title, Size virtualResolution, WindowState windowState = WindowState.Maximized, Size?windowSize = null, VsyncMode vsync = VsyncMode.Adaptive, bool preserveAspectRatio = true, WindowBorder windowBorder = WindowBorder.Resizable) { Title = title; VirtualResolution = virtualResolution; WindowState = windowState; WindowSize = windowSize.HasValue ? windowSize.Value : virtualResolution; Vsync = vsync; PreserveAspectRatio = preserveAspectRatio; WindowBorder = windowBorder; var fonts = new AGSDefaultFonts(); var dialogs = new AGSDialogSettings(AGSGame.Device, fonts); Defaults = new AGSDefaultsSettings(fonts, dialogs); }
/// <summary> /// Create and open a new GlfwWindow. /// </summary> /// <param name="options">The options to use for this window.</param> public GlfwWindow(WindowOptions options) { // Title and Size must be set before the window is created. _title = options.Title; _size = options.Size; _windowBorder = WindowBorder; FramesPerSecond = options.FramesPerSecond; UpdatesPerSecond = options.UpdatesPerSecond; RunningSlowTolerance = options.RunningSlowTolerance; UseSingleThreadedWindow = options.UseSingleThreadedWindow; initialOptions = options; }
/// <summary> /// Creates a new WindowOptions struct, with sensible defaults. /// </summary> public WindowOptions(bool isVisible, bool useSingleThreadedWindow, Point position, Size size, double framesPerSecond, double updatesPerSecond, GraphicsAPI api, string title, WindowState windowState, WindowBorder windowBorder, VSyncMode vSync, int isRunningSlowlyThreshold) { IsVisible = isVisible; UseSingleThreadedWindow = useSingleThreadedWindow; Position = position; Size = size; FramesPerSecond = framesPerSecond; UpdatesPerSecond = updatesPerSecond; API = api; Title = title; WindowState = windowState; WindowBorder = windowBorder; VSync = vSync; RunningSlowTolerance = isRunningSlowlyThreshold; }
public Sdl2NativeWindow(int x, int y, int width, int height, string title, GameWindowFlags options, DisplayDevice device) { lock (sync) { SDL.DisableScreenSaver(); var bounds = device.Bounds; var flags = TranslateFlags(options); flags |= WindowFlags.OPENGL; flags |= WindowFlags.HIDDEN; if (Toolkit.Options.EnableHighResolution) { flags |= WindowFlags.ALLOW_HIGHDPI; } if ((flags & WindowFlags.FULLSCREEN_DESKTOP) != 0 || (flags & WindowFlags.FULLSCREEN) != 0) { window_state = WindowState.Fullscreen; } if ((flags & WindowFlags.RESIZABLE) == 0) { window_border = WindowBorder.Fixed; } IntPtr handle; lock (SDL.Sync) { Console.Error.WriteLine($"Window Bound: [{bounds.Left + x}, {bounds.Top + y}, {width}, {height}]"); handle = SDL.CreateWindow(title, bounds.Left + x, bounds.Top + y, width, height, flags); exists = true; } #if !TIZEN ProcessEvents(); #endif window = new Sdl2WindowInfo(handle, null); window_id = SDL.GetWindowID(handle); windows.Add(window_id, this); } }
/// <summary> /// Creates a new instance of <see cref="WindowCreateInfo"/> struct. /// </summary> /// <param name="position">The window position.</param> /// <param name="size">The window size.</param> /// <param name="initialState">The window state.</param> /// <param name="title">The window title.</param> /// <param name="api">The graphics API.</param> /// <param name="cursorMode">The cursor mode.</param> /// <param name="windowBorder">The window border.</param> /// <param name="opacity">The window opacity.</param> /// <param name="multisamples">The number of samples in window.</param> /// <param name="apiVersion">The version of the graphics API.</param> /// <param name="flags">The context flags.</param> /// <param name="profile">The context profile.</param> public WindowCreateInfo( Point position, Size size, WindowState initialState, string title, ContextAPI api, CursorMode cursorMode = CursorMode.Visible, WindowBorder windowBorder = WindowBorder.Resizable, float opacity = 1f, byte multisamples = 16, Version apiVersion = default, ContextFlags flags = ContextFlags.Default, ContextProfile profile = ContextProfile.Core) { (Position, Size, WindowState, Title, WindowBorder, Multisamples, API, APIVersion, Flags, Profile, CursorMode, Opacity) = (position, size, initialState, title, windowBorder, multisamples, api, apiVersion, flags, profile, cursorMode, opacity); if (APIVersion == null) { APIVersion = new Version(3, 3); } }
/// <summary> /// Create a new GlfwWindow. /// </summary> /// <param name="options">The options to use for this window.</param> public GlfwWindow(WindowOptions options, GlfwWindow parent, GlfwMonitor monitor) { // Title and Size must be set before the window is created. _title = options.Title; _size = options.Size; _windowBorder = WindowBorder; _vSync = options.VSync; FramesPerSecond = options.FramesPerSecond; UpdatesPerSecond = options.UpdatesPerSecond; RunningSlowTolerance = options.RunningSlowTolerance; UseSingleThreadedWindow = options.UseSingleThreadedWindow; ShouldSwapAutomatically = options.ShouldSwapAutomatically; _initialOptions = options; _initialMonitor = monitor; Parent = (IWindowHost)parent ?? _initialMonitor; IsEventDriven = options.IsEventDriven; GlfwProvider.GLFW.Value.GetVersion(out var major, out var minor, out _); if (new Version(major, minor) < new Version(3, 3)) { throw new NotSupportedException("GLFW 3.3 or later is required for Silk.NET.Windowing.Desktop."); } if (options.API.API == ContextAPI.Vulkan) { VkSurface = new Surface(this); } else if (options.API.API == ContextAPI.OpenGL || options.API.API == ContextAPI.OpenGLES) { GLContext = new Context(this); } Glfw.ThrowExceptions(); }
private static WindowState OpenTKToVeldridState(OpenTK.WindowState openTKState, WindowBorder border) { switch (openTKState) { case OpenTK.WindowState.Normal: return(border == WindowBorder.Hidden ? WindowState.BorderlessFullScreen : WindowState.Normal); case OpenTK.WindowState.Minimized: return(WindowState.Minimized); case OpenTK.WindowState.Maximized: return(WindowState.Maximized); case OpenTK.WindowState.Fullscreen: return(WindowState.FullScreen); default: throw Illegal.Value <WindowState>(); } }
public static void setWindowBorder(WindowBorder v) { g_ctx.implementation.WindowBorder = v; }
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); }
public static void Main() { Console.Title = "Instant Gameworks"; Console.WriteLine("Instant Gameworks (c) 2018"); Logging.LogEvent("Main thread startup"); // Set window settings DisplayDevice DefaultDisplay = DisplayDevice.Default; GameWindowRefreshRate = 0;//DefaultDisplay.RefreshRate; GameWindowSize = new OpenTK.Vector2(1920, 1080); GameWindowPosition = new OpenTK.Vector2(0, 0); GameWindowBorder = WindowBorder.Hidden; GameWindowState = WindowState.Fullscreen; // Create window Logging.LogEvent("Initializing GameworksWindow"); ThreadStart GameThread = new ThreadStart(CreateGameworksWindow); Thread RunGame = new Thread(GameThread); RunGame.Start(); // Wait for window to initialize SpinWait.SpinUntil(() => GameWindow != null && GameWindow.Exists); // // // // Game logic // // // Logging.LogEvent("Importing resources"); // Initialize camera StudioCamera Camera = new StudioCamera { MoveSensitivity = 0.01f }; GameWindow.Camera = Camera; // Establish lighting StudioCamera SunLook = new StudioCamera(); SunLook.Orientation = new Vector2(0, (float)-Math.PI / 2); // look down var Sun = GameWindow.AddDirectionalLight(); Sun.Name = "Sun"; Sun.RelativeDirection = SunLook.LookAt; Sun.Intensity = 128; Sun.Enabled = true; Sun.DiffuseColor = Color4.Black; // Import objects var Land = GameWindow.AddObject(@"Testing\dragon.igwo"); Land.DiffuseColor = Color4.DarkRed; Land.AmbientColor = new Color4(30, 0, 0, 0); Land.SpecularColor = Color4.White; Land.Scale = new Vector3(1.5f, 1.5f, 1.5f); var GuiHolder = GameWindow.AddGui(); GuiHolder.Color = new Color4(128, 128, 128, 255); GuiHolder.AbsoluteSize = new Vector2(32f / 1920f, 2f / 1080f); GuiHolder.AbsolutePosition = new Vector2(0.5f - 16f / 1920f, 0.5f - 1f / 1080f); var G2 = GameWindow.AddGui(); G2.Color = new Color4(128, 128, 128, 255); G2.AbsoluteSize = new Vector2(2f / 1920f, 32f / 1080f); G2.AbsolutePosition = new Vector2(0.5f - 1f / 1920f, 0.5f - 16f / 1080f); double _lastTime = 0; double _time = 0; float AdjustedSpeedForFramerate = 1f; void OnUpdateFrameTimer(object sender, FrameEventArgs e) { _lastTime = _time; _time += e.Time; } void ObjectUpdateFrame(object sender, FrameEventArgs e) { Sun.RelativeDirection = SunLook.LookAt; Land.Rotation += new Vector3(0, 0.005f * AdjustedSpeedForFramerate, 0); GuiHolder.Color = Color4.FromHsv(new Vector4(DateTime.Now.Millisecond / 1000f, 0.8f, 1f, 0.5f)); G2.Color = Color4.FromHsv(new Vector4(DateTime.Now.Millisecond / 1000f, 0.8f, 1f, 0.5f)); } // Camera implementation Dictionary <Key, bool> KeysDown = new Dictionary <Key, bool>() { [Key.W] = false, [Key.A] = false, [Key.S] = false, [Key.D] = false }; OpenTK.Vector2 LastMousePosition = new OpenTK.Vector2(0, 0); bool IsRightMouseDown = false; bool IsLeftMouseDown = false; bool IsSettingMousePosition = false; Vector2 CurrentMousePosition = new Vector2(0, 0); void CameraUpdateFrame(object sender, FrameEventArgs e) { if (IsRightMouseDown || IsLeftMouseDown) { IsSettingMousePosition = true; Mouse.SetPosition(LastMousePosition.X + GameWindow.X, LastMousePosition.Y + GameWindow.Y); } AdjustedSpeedForFramerate = 144f / (1f / ((float)_time - (float)_lastTime)); if (KeysDown[Key.W] == true) { Camera.Move(0, 0, -AdjustedSpeedForFramerate); } if (KeysDown[Key.A] == true) { Camera.Move(AdjustedSpeedForFramerate, 0, 0); } if (KeysDown[Key.S] == true) { Camera.Move(0, 0, AdjustedSpeedForFramerate); } if (KeysDown[Key.D] == true) { Camera.Move(-AdjustedSpeedForFramerate, 0, 0); } Vector2 mousePos = new Vector2(CurrentMousePosition.X + GameWindow.X, CurrentMousePosition.Y + GameWindow.Y); GuiHolder.AbsolutePosition = new Vector2((mousePos.X / 1920f) - (16 / 1920f), (mousePos.Y / 1080f) - (1 / 1080f)); G2.AbsolutePosition = new Vector2((mousePos.X / 1920f) - (1 / 1920f), (mousePos.Y / 1080f) - (16 / 1080f)); } void MouseDown(object sender, MouseButtonEventArgs e) { if (e.Button == MouseButton.Right) { if (!IsRightMouseDown) { IsRightMouseDown = true; LastMousePosition = new OpenTK.Vector2(e.X, e.Y); } } if (e.Button == MouseButton.Left) { if (!IsLeftMouseDown) { IsLeftMouseDown = true; LastMousePosition = new OpenTK.Vector2(e.X, e.Y); } } } void MouseUp(object sender, MouseButtonEventArgs e) { if (e.Button == MouseButton.Right) { IsRightMouseDown = false; } if (e.Button == MouseButton.Left) { IsLeftMouseDown = false; } } void MouseMove(object sender, MouseMoveEventArgs e) { if (GameWindow.Focused && IsRightMouseDown && !IsSettingMousePosition) { Camera.AddRotation(e.XDelta, e.YDelta); } if (GameWindow.Focused && IsLeftMouseDown && !IsSettingMousePosition) { SunLook.AddRotation(e.XDelta, e.YDelta); } IsSettingMousePosition = false; CurrentMousePosition = new Vector2(e.X, e.Y); } void KeyDown(object sender, KeyboardKeyEventArgs e) { switch (e.Key) { case Key.W: KeysDown[Key.W] = true; break; case Key.A: KeysDown[Key.A] = true; break; case Key.S: KeysDown[Key.S] = true; break; case Key.D: KeysDown[Key.D] = true; break; case Key.Escape: GameWindow.Exit(); break; } } void KeyUp(object sender, KeyboardKeyEventArgs e) { switch (e.Key) { case Key.W: KeysDown[Key.W] = false; break; case Key.A: KeysDown[Key.A] = false; break; case Key.S: KeysDown[Key.S] = false; break; case Key.D: KeysDown[Key.D] = false; break; } } void MouseWheel(object sender, MouseWheelEventArgs e) { Camera.Move(0, 0, -e.Delta / Camera.MoveSensitivity * 0.25f); } //assign OnUpdateFrame Logging.LogEvent("Adding update frame events"); GameWindow.UpdateFrame += OnUpdateFrameTimer; GameWindow.UpdateFrame += ObjectUpdateFrame; GameWindow.UpdateFrame += CameraUpdateFrame; //assign input events Logging.LogEvent("Adding input events"); GameWindow.MouseDown += MouseDown; GameWindow.MouseUp += MouseUp; GameWindow.MouseMove += MouseMove; GameWindow.KeyDown += KeyDown; GameWindow.KeyUp += KeyUp; GameWindow.MouseWheel += MouseWheel; //Exit RunGame.Join(); NativeMethods.ConsoleApp.ShowConsole(); Logging.LogEvent("Shutting down"); /*Logging.WriteToFile(); * Logging.DisplayLog().Join(); *///end of thread }
void ChangeWindowBorder(WindowBorder value, int width, int height) { if (WindowBorder == WindowBorder.Hidden) EnableWindowDecorations(); switch (value) { case WindowBorder.Fixed: Debug.Print("Making WindowBorder fixed."); SetWindowMinMax((short)width, (short)height, (short)width, (short)height); break; case WindowBorder.Resizable: Debug.Print("Making WindowBorder resizable."); SetWindowMinMax(_min_width, _min_height, -1, -1); break; case WindowBorder.Hidden: Debug.Print("Making WindowBorder hidden."); // Make the hidden border resizable, otherwise // we won't be able to maximize the window or // enter fullscreen mode. SetWindowMinMax(_min_width, _min_height, -1, -1); DisableWindowDecorations(); break; } ProcessEvents(); }
private static NSWindowStyle GetStyleMask(WindowBorder windowBorder) { switch (windowBorder) { case WindowBorder.Resizable: return NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Titled | NSWindowStyle.Resizable; case WindowBorder.Fixed: return NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Titled; case WindowBorder.Hidden: return NSWindowStyle.Borderless; } return (NSWindowStyle)0; }
void HandleStyleChanged(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) { WindowBorder old_border = windowBorder; WindowBorder new_border = old_border; unsafe { GWL get_window_style = (GWL)unchecked(wParam.ToInt32()); if ((get_window_style & (GWL.STYLE | GWL.EXSTYLE)) != 0) { WindowStyle style = ((StyleStruct*)lParam)->New; if ((style & WindowStyle.Popup) != 0) new_border = WindowBorder.Hidden; else if ((style & WindowStyle.ThickFrame) != 0) new_border = WindowBorder.Resizable; else if ((style & ~(WindowStyle.ThickFrame | WindowStyle.MaximizeBox)) != 0) new_border = WindowBorder.Fixed; } } if (new_border != windowBorder) { // Ensure cursor remains grabbed if (!CursorVisible) GrabCursor(); windowBorder = new_border; WindowBorderChanged(this, EventArgs.Empty); } }
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)); }
private void SetWindowBorder(WindowBorder windowBorder) { this.windowBorder = windowBorder; UpdateWindowBorder(); }
GameObject BorderDummy; //The border dummy is simply a gameobject with recttransform and a WindowBorder script component. void Awake() { BorderDummy = GameObject.FindGameObjectWithTag("Border"); BorderDummy.SetActive(false); //need to rework this for multiple windows, as other WindowBases won't be able to find it with tag if it's disabled. Transform borders = GameObject.Find("Borders").transform; rectTransform = GetComponent <RectTransform>(); verticalResize = rectTransform.rect.height; horizontalResize = rectTransform.rect.width; if (topResizer) { topRectTransform = (Instantiate(BorderDummy) as GameObject).GetComponent <RectTransform>(); topRectTransform.SetParent(borders); topRectTransform.gameObject.SetActive(true); topRectTransform.anchorMax = new Vector2(1f, 1f); topRectTransform.anchorMin = new Vector2(0f, 1f); topRectTransform.position = new Vector3(rectTransform.position.x, topRectTransform.position.y, topRectTransform.position.z); topRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, rectTransform.rect.width); topRectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, -10f, 10f); topWindowBorder = topRectTransform.GetComponent <WindowBorder>(); topWindowBorder.window = this; topWindowBorder.border = WindowBorder.Border.top; topWindowBorder.gameObject.name = "TopWindowBorder"; } if (bottomResizer) { bottomRectTransform = (Instantiate(BorderDummy) as GameObject).GetComponent <RectTransform>(); bottomRectTransform.SetParent(borders); bottomRectTransform.gameObject.SetActive(true); bottomRectTransform.anchorMax = new Vector2(1f, 0f); bottomRectTransform.anchorMin = new Vector2(0f, 0f); bottomRectTransform.position = new Vector3(rectTransform.position.x, bottomRectTransform.position.y, bottomRectTransform.position.z); bottomRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, rectTransform.rect.width); bottomRectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Bottom, -10f, 10f); bottomWindowBorder = bottomRectTransform.GetComponent <WindowBorder>(); bottomWindowBorder.window = this; bottomWindowBorder.border = WindowBorder.Border.bottom; bottomWindowBorder.gameObject.name = "BottomWindowBorder"; } if (leftResizer) { leftRectTransform = (Instantiate(BorderDummy) as GameObject).GetComponent <RectTransform>(); leftRectTransform.SetParent(borders); leftRectTransform.gameObject.SetActive(true); leftRectTransform.anchorMax = new Vector2(0f, 1f); leftRectTransform.anchorMin = new Vector2(0f, 0f); leftRectTransform.position = new Vector3(leftRectTransform.position.x, rectTransform.position.y, leftRectTransform.position.z); leftRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, rectTransform.rect.height); leftRectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, -10f, 10f); leftWindowBorder = leftRectTransform.GetComponent <WindowBorder>(); leftWindowBorder.window = this; leftWindowBorder.border = WindowBorder.Border.left; leftWindowBorder.gameObject.name = "LeftWindowBorder"; } if (rightResizer) { rightRectTransform = (Instantiate(BorderDummy) as GameObject).GetComponent <RectTransform>(); rightRectTransform.SetParent(borders); rightRectTransform.gameObject.SetActive(true); rightRectTransform.anchorMax = new Vector2(1f, 1f); rightRectTransform.anchorMin = new Vector2(1f, 0f); rightRectTransform.position = new Vector3(rightRectTransform.position.x, rectTransform.position.y, rightRectTransform.position.z); rightRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, rectTransform.rect.height); rightRectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Right, -10f, 10f); rightWindowBorder = rightRectTransform.GetComponent <WindowBorder>(); rightWindowBorder.window = this; rightWindowBorder.border = WindowBorder.Border.right; rightWindowBorder.gameObject.name = "RightWindowBorder"; } if (topLeftResizer) { topLeftRectTransform = (Instantiate(BorderDummy) as GameObject).GetComponent <RectTransform>(); topLeftRectTransform.SetParent(borders); topLeftRectTransform.gameObject.SetActive(true); topLeftRectTransform.anchorMax = new Vector2(0f, 1f); topLeftRectTransform.anchorMin = new Vector2(0f, 1f); topLeftRectTransform.anchoredPosition = new Vector2(-5f, 5f); topLeftRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 10f); topLeftRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 10f); topLeftWindowBorder = topLeftRectTransform.GetComponent <WindowBorder>(); topLeftWindowBorder.window = this; topLeftWindowBorder.border = WindowBorder.Border.topLeft; topLeftWindowBorder.gameObject.name = "TopLeftWindowBorder"; } if (topRightResizer) { topRightRectTransform = (Instantiate(BorderDummy) as GameObject).GetComponent <RectTransform>(); topRightRectTransform.SetParent(borders); topRightRectTransform.gameObject.SetActive(true); topRightRectTransform.anchorMax = new Vector2(1f, 1f); topRightRectTransform.anchorMin = new Vector2(1f, 1f); topRightRectTransform.anchoredPosition = new Vector2(5f, 5f); topRightRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 10f); topRightRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 10f); topRightWindowBorder = topRightRectTransform.GetComponent <WindowBorder>(); topRightWindowBorder.window = this; topRightWindowBorder.border = WindowBorder.Border.topRight; topRightWindowBorder.gameObject.name = "TopRightWindowBorder"; } if (bottomLeftResizer) { bottomLeftRectTransform = (Instantiate(BorderDummy) as GameObject).GetComponent <RectTransform>(); bottomLeftRectTransform.SetParent(borders); bottomLeftRectTransform.gameObject.SetActive(true); bottomLeftRectTransform.anchorMax = new Vector2(0f, 0f); bottomLeftRectTransform.anchorMin = new Vector2(0f, 0f); bottomLeftRectTransform.anchoredPosition = new Vector2(-5f, -5f); bottomLeftRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 10f); bottomLeftRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 10f); bottomLeftWindowBorder = bottomLeftRectTransform.GetComponent <WindowBorder>(); bottomLeftWindowBorder.window = this; bottomLeftWindowBorder.border = WindowBorder.Border.bottomLeft; bottomLeftWindowBorder.gameObject.name = "BottomLeftWindowBorder"; } if (bottomRightResizer) { bottomRightRectTransform = (Instantiate(BorderDummy) as GameObject).GetComponent <RectTransform>(); bottomRightRectTransform.SetParent(borders); bottomRightRectTransform.gameObject.SetActive(true); bottomRightRectTransform.anchorMax = new Vector2(1f, 0f); bottomRightRectTransform.anchorMin = new Vector2(1f, 0f); bottomRightRectTransform.anchoredPosition = new Vector2(5f, -5f); bottomRightRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 10f); bottomRightRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 10f); bottomRightWindowBorder = bottomRightRectTransform.GetComponent <WindowBorder>(); bottomRightWindowBorder.window = this; bottomRightWindowBorder.border = WindowBorder.Border.bottomRight; bottomRightWindowBorder.gameObject.name = "BottomRightWindowBorder"; } }
public GameBuilder SetWindowBorder(WindowBorder border) { _game.WindowBorder = border; return(this); }
public Sdl2NativeWindow(int x, int y, int width, int height, string title, GameWindowFlags options, DisplayDevice device) { lock (sync) { var bounds = device.Bounds; var flags = TranslateFlags(options); flags |= WindowFlags.OPENGL; flags |= WindowFlags.HIDDEN; if (Toolkit.Options.EnableHighResolution) { flags |= WindowFlags.ALLOW_HIGHDPI; } if ((flags & WindowFlags.FULLSCREEN_DESKTOP) != 0 || (flags & WindowFlags.FULLSCREEN) != 0) window_state = WindowState.Fullscreen; if ((flags & WindowFlags.RESIZABLE) == 0) window_border = WindowBorder.Fixed; IntPtr handle; lock (SDL.Sync) { handle = SDL.CreateWindow(title, bounds.Left + x, bounds.Top + y, width, height, flags); exists = true; } ProcessEvents(); window = new Sdl2WindowInfo(handle, null); window_id = SDL.GetWindowID(handle); windows.Add(window_id, this); } }
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)); }
protected override void OnUpdateFrame(FrameEventArgs e) { if (_TitleChanged) { _TitleChanged = false; base.Title = _Title; } if (_VSyncChanged) { _VSyncChanged = false; base.VSync = (OpenTK.VSyncMode) this._VSync; } if (_SurfaceFixedResolutionChanged) { _SurfaceFixedResolutionChanged = false; if (_Resizable) { base.ClientSize = new Size(_SurfaceFixedResolution.X, _SurfaceFixedResolution.Y); } } if (_WindowStateChanged) { _WindowStateChanged = false; base.WindowState = (OpenTK.WindowState) this.WindowState; } if (_ResizableChanged) { _ResizableChanged = false; base.WindowBorder = _Resizable ? WindowBorder.Resizable : WindowBorder.Fixed; if (!_Resizable) { base.ClientSize = new Size(_SurfaceFixedResolution.X, _SurfaceFixedResolution.Y); } } if (_CursorVisibleChanged) { _CursorVisibleChanged = false; //base.CursorVisible = _CursorVisible; } if (_PreviousBorder != base.WindowBorder) { _PreviousBorder = base.WindowBorder; OnResizing?.Invoke(this, new EventArgs()); } // if not focused cursor always visible. base.CursorVisible = base.Focused ? _CursorVisible : true; Action doUpdateOnce; lock (_InvokeUpdateLocker) { doUpdateOnce = _InvokeOnUpdate; _InvokeOnUpdate = null; } doUpdateOnce?.Invoke(); MouseState state = Mouse.GetState(); Input.SetMouseScroll(state.WheelPrecise, state.Wheel); Time.FrameTimer.Stop(); Time.DeltaUnscaled = Time.FrameTimer.Elapsed.TotalSeconds;//e.Time * Time.TimeScale; Time.FrameTimer.Reset(); Time.FrameTimer.Start(); MouseState ms = Mouse.GetState(); Vector2D delta = new Vector2D(this._PreviousMouseState.X - ms.X, this._PreviousMouseState.Y - ms.Y); this._PreviousMouseState = ms; //Layer.PhysicsEvent.WaitOne(); // wait for physics to be free //Layer.UpdateRenderEvent.Reset(); // set update/render as busy OnUpdate?.Invoke(new UpdateEventArgs(e.Time)); base.OnUpdateFrame(e); ++Time.Frame; }
void ChangeWindowBorder(WindowBorder value) { ChangeWindowBorder(value, Width, Height); }
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. is_in_modal_loop = true; StartTimer(handle); if (!CursorVisible) UngrabCursor(); break; case WindowMessage.EXITMENULOOP: case WindowMessage.EXITSIZEMOVE: // Exiting from Modal size/move loop: the timer callback is no longer // necessary. is_in_modal_loop = false; StopTimer(handle); // Ensure cursor remains grabbed if (!CursorVisible) GrabCursor(); 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); } if (!is_in_modal_loop) { // If we are in a modal resize/move loop, cursor grabbing is // handled inside [ENTER|EXIT]SIZEMOVE case above. // If not, then we have to handle cursor grabbing here. 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[((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; short scancode = (short)((lParam.ToInt64() >> 16) & 0xFF); VirtualKeys vkey = (VirtualKeys)wParam; bool is_valid; Key key = KeyMap.TranslateKey(scancode, vkey, extended, false, out is_valid); if (is_valid) { keyboard.SetKey(key, (byte)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); }
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)); }
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); }
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.WindowHandle) { Point new_location = new Point(pos->x, pos->y); if (Location != new_location) { bounds.Location = new_location; Move(this, EventArgs.Empty); } Size new_size = new Size(pos->cx, pos->cy); if (Size != new_size) { bounds.Width = pos->cx; bounds.Height = pos->cy; Win32Rectangle rect; Functions.GetClientRect(handle, out rect); client_rectangle = rect.ToRectangle(); Functions.SetWindowPos(child_window.WindowHandle, IntPtr.Zero, 0, 0, ClientRectangle.Width, ClientRectangle.Height, SetWindowPosFlags.NOZORDER | SetWindowPosFlags.NOOWNERZORDER | SetWindowPosFlags.NOACTIVATE | SetWindowPosFlags.NOSENDCHANGING); if (suppress_resize <= 0) Resize(this, EventArgs.Empty); } } } break; case WindowMessage.STYLECHANGED: unsafe { if (wParam.ToInt64() == (long)GWL.STYLE) { WindowStyle style = ((StyleStruct*)lParam)->New; if ((style & WindowStyle.Popup) != 0) windowBorder = WindowBorder.Hidden; else if ((style & WindowStyle.ThickFrame) != 0) windowBorder = WindowBorder.Resizable; else if ((style & ~(WindowStyle.ThickFrame | WindowStyle.MaximizeBox)) != 0) windowBorder = WindowBorder.Fixed; } } break; case WindowMessage.SIZE: SizeMessage state = (SizeMessage)wParam.ToInt64(); WindowState new_state = windowState; switch (state) { case SizeMessage.RESTORED: new_state = borderless_maximized_window_state ? WindowState.Maximized : WindowState.Normal; break; case SizeMessage.MINIMIZED: new_state = WindowState.Minimized; break; case SizeMessage.MAXIMIZED: new_state = WindowBorder == WindowBorder.Hidden ? WindowState.Fullscreen : WindowState.Maximized; break; } if (new_state != windowState) { windowState = new_state; WindowStateChanged(this, EventArgs.Empty); } break; #endregion #region Input events case WindowMessage.CHAR: if (IntPtr.Size == 4) key_press.KeyChar = (char)wParam.ToInt32(); else key_press.KeyChar = (char)wParam.ToInt64(); KeyPress(this, key_press); break; case WindowMessage.MOUSEMOVE: Point point = new Point( (short)((uint)lParam.ToInt32() & 0x0000FFFF), (short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16)); mouse.Position = point; if (!CursorVisible) HideCursor(); 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 if (!CursorVisible) ShowCursor(); 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.WindowHandle); mouse[MouseButton.Left] = true; break; case WindowMessage.MBUTTONDOWN: Functions.SetCapture(window.WindowHandle); mouse[MouseButton.Middle] = true; break; case WindowMessage.RBUTTONDOWN: Functions.SetCapture(window.WindowHandle); mouse[MouseButton.Right] = true; break; case WindowMessage.XBUTTONDOWN: Functions.SetCapture(window.WindowHandle); mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = true; break; case WindowMessage.LBUTTONUP: Functions.ReleaseCapture(); mouse[MouseButton.Left] = false; break; case WindowMessage.MBUTTONUP: Functions.ReleaseCapture(); mouse[MouseButton.Middle] = false; break; case WindowMessage.RBUTTONUP: Functions.ReleaseCapture(); mouse[MouseButton.Right] = false; break; case WindowMessage.XBUTTONUP: Functions.ReleaseCapture(); mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = false; break; // Keyboard events: case WindowMessage.KEYDOWN: case WindowMessage.KEYUP: case WindowMessage.SYSKEYDOWN: case WindowMessage.SYSKEYUP: bool pressed = message == WindowMessage.KEYDOWN || message == WindowMessage.SYSKEYDOWN; // Shift/Control/Alt behave strangely when e.g. ShiftRight is held down and ShiftLeft is pressed // and released. It looks like neither key is released in this case, or that the wrong key is // released in the case of Control and Alt. // To combat this, we are going to release both keys when either is released. Hacky, but should work. // Win95 does not distinguish left/right key constants (GetAsyncKeyState returns 0). // In this case, both keys will be reported as pressed. bool extended = (lParam.ToInt64() & ExtendedBit) != 0; switch ((VirtualKeys)wParam) { case VirtualKeys.SHIFT: // The behavior of this key is very strange. Unlike Control and Alt, there is no extended bit // to distinguish between left and right keys. Moreover, pressing both keys and releasing one // may result in both keys being held down (but not always). // The only reliable way to solve this was reported by BlueMonkMN at the forums: we should // check the scancodes. It looks like GLFW does the same thing, so it should be reliable. // Note: we release both keys when either shift is released. // Otherwise, the state of one key might be stuck to pressed. if (ShiftRightScanCode != 0 && pressed) { unchecked { if (((lParam.ToInt64() >> 16) & 0xFF) == ShiftRightScanCode) keyboard[Input.Key.ShiftRight] = pressed; else keyboard[Input.Key.ShiftLeft] = pressed; } } else { // Windows 9x and NT4.0 or key release event. keyboard[Input.Key.ShiftLeft] = keyboard[Input.Key.ShiftRight] = pressed; } return IntPtr.Zero; case VirtualKeys.CONTROL: if (extended) keyboard[Input.Key.ControlRight] = pressed; else keyboard[Input.Key.ControlLeft] = pressed; return IntPtr.Zero; case VirtualKeys.MENU: if (extended) keyboard[Input.Key.AltRight] = pressed; else keyboard[Input.Key.AltLeft] = pressed; return IntPtr.Zero; case VirtualKeys.RETURN: if (extended) keyboard[Key.KeypadEnter] = pressed; else keyboard[Key.Enter] = pressed; return IntPtr.Zero; default: if (!KeyMap.ContainsKey((VirtualKeys)wParam)) { Debug.Print("Virtual key {0} ({1}) not mapped.", (VirtualKeys)wParam, (long)lParam); break; } else { keyboard[KeyMap[(VirtualKeys)wParam]] = pressed; } return IntPtr.Zero; } break; case WindowMessage.SYSCHAR: return IntPtr.Zero; case WindowMessage.KILLFOCUS: keyboard.ClearKeys(); 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); }
protected override void OnUpdateFrame(FrameEventArgs e) { if (_TitleChanged) { _TitleChanged = false; base.Title = _Title; } if (_VSyncChanged) { _VSyncChanged = false; base.VSync = (OpenTK.VSyncMode) this._VSync; } if (_SurfaceFixedResolutionChanged) { _SurfaceFixedResolutionChanged = false; if (_Resizable) { base.ClientSize = new Size(_SurfaceFixedResolution.X, _SurfaceFixedResolution.Y); } } if (_WindowStateChanged) { _WindowStateChanged = false; base.WindowState = (OpenTK.WindowState) this.WindowState; } if (_ResizableChanged) { _ResizableChanged = false; base.WindowBorder = _Resizable ? WindowBorder.Resizable : WindowBorder.Fixed; if (!_Resizable) { base.ClientSize = new Size(_SurfaceFixedResolution.X, _SurfaceFixedResolution.Y); } } if (_CursorVisibleChanged) { _CursorVisibleChanged = false; //base.CursorVisible = _CursorVisible; } if (_PreviousBorder != base.WindowBorder) { _PreviousBorder = base.WindowBorder; OnResizing?.Invoke(this, new EventArgs()); } // if not focused cursor always visible. base.CursorVisible = base.Focused ? _CursorVisible : true; Action doUpdateOnce; lock (_InvokeUpdateLocker) { doUpdateOnce = _InvokeOnUpdate; _InvokeOnUpdate = null; } doUpdateOnce?.Invoke(); Input.SetMouseScroll(Mouse.GetState().WheelPrecise); Time.DeltaTime = e.Time * Time.TimeScale; MouseState ms = Mouse.GetState(); Vector2D delta = new Vector2D(this._PreviousMouseState.X - ms.X, this._PreviousMouseState.Y - ms.Y); this._PreviousMouseState = ms; OnUpdate?.Invoke(new UpdateEventArgs(e.Time)); base.OnUpdateFrame(e); }
private void Window_Loaded_1(object sender, RoutedEventArgs e) { DoubleAnimation da = new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(300)); WindowBorder.BeginAnimation(OpacityProperty, da); }
private void OnUserDataChanged(object sender, EventArgs e) { // Early-out, if no display is connected / available anyway if (DisplayDevice.Default == null) { return; } // Determine the target state for our window MouseCursor targetCursor = DualityApp.UserData.SystemCursorVisible ? MouseCursor.Default : MouseCursor.Empty; WindowState targetWindowState = this.internalWindow.WindowState; WindowBorder targetWindowBorder = this.internalWindow.WindowBorder; Size targetSize = this.internalWindow.ClientSize; bool enforceRes = false; switch (DualityApp.UserData.GfxMode) { case ScreenMode.Window: targetWindowState = WindowState.Normal; targetWindowBorder = WindowBorder.Resizable; targetSize = new Size(DualityApp.UserData.GfxWidth, DualityApp.UserData.GfxHeight); break; case ScreenMode.FixedWindow: targetWindowState = WindowState.Normal; targetWindowBorder = WindowBorder.Fixed; targetSize = new Size(DualityApp.UserData.GfxWidth, DualityApp.UserData.GfxHeight); break; case ScreenMode.FullWindow: targetWindowState = WindowState.Fullscreen; targetWindowBorder = WindowBorder.Hidden; targetSize = new Size(DisplayDevice.Default.Width, DisplayDevice.Default.Height); break; case ScreenMode.Native: case ScreenMode.Fullscreen: targetWindowState = WindowState.Fullscreen; targetWindowBorder = WindowBorder.Hidden; targetSize = new Size(DualityApp.UserData.GfxWidth, DualityApp.UserData.GfxHeight); enforceRes = true; break; default: throw new ArgumentOutOfRangeException(); } // Enforce the specified screen resolution when requested if (enforceRes) { DisplayDevice.Default.ChangeResolution( targetSize.Width, targetSize.Height, DisplayDevice.Default.BitsPerPixel, DisplayDevice.Default.RefreshRate); } else { DisplayDevice.Default.RestoreResolution(); } // Apply the target state to the game window wherever values changed if (this.internalWindow.WindowState != targetWindowState) { this.internalWindow.WindowState = targetWindowState; } if (this.internalWindow.WindowBorder != targetWindowBorder) { this.internalWindow.WindowBorder = targetWindowBorder; } if (this.internalWindow.ClientSize != targetSize) { this.internalWindow.ClientSize = targetSize; } if (this.internalWindow.Cursor != targetCursor) { this.internalWindow.Cursor = targetCursor; } DualityApp.TargetResolution = new Vector2(this.internalWindow.ClientSize.Width, this.internalWindow.ClientSize.Height); }