private UnregisterClass ( IntPtr className, IntPtr instance ) : short | ||
className | IntPtr | |
instance | IntPtr | |
Результат | short |
public WinGLContext(GraphicsMode format, WinWindowInfo window, IGraphicsContext sharedContext, int major, int minor, GraphicsContextFlags flags) { // There are many ways this code can break when accessed by multiple threads. The biggest offender is // the sharedContext stuff, which will only become valid *after* this constructor returns. // The easiest solution is to serialize all context construction - hence the big lock, below. lock (LoadLock) { if (window == null) { throw new ArgumentNullException("window", "Must point to a valid window."); } if (window.Handle == IntPtr.Zero) { throw new ArgumentException("window", "Must be a valid window."); } IntPtr current_context = Wgl.GetCurrentContext(); ExtendedWindowClass wc = new ExtendedWindowClass(); wc.Size = ExtendedWindowClass.SizeInBytes; wc.Style = ClassStyle.OwnDC; wc.Instance = Instance; wc.WndProc = WindowProcedure; wc.ClassName = ClassName; ushort atom = Functions.RegisterClassEx(ref wc); IntPtr window_name = Marshal.StringToHGlobalAuto("temp"); var temp_window = Functions.CreateWindowEx(ExtendedWindowStyle.WindowEdge | ExtendedWindowStyle.ApplicationWindow, ClassName, window_name, WindowStyle.OverlappedWindow | WindowStyle.ClipChildren, 0, 0, 10, 10, IntPtr.Zero, IntPtr.Zero, Instance, IntPtr.Zero); var error = Marshal.GetLastWin32Error(); TemporaryContext temp_context = null; try { if (current_context == IntPtr.Zero) { // Create temporary context to load WGL extensions temp_context = new TemporaryContext(temp_window); current_context = Wgl.GetCurrentContext(); if (current_context != IntPtr.Zero && current_context == temp_context.Context.Handle) { new Wgl().LoadEntryPoints(); } } Debug.Print("OpenGL will be bound to window:{0} on thread:{1}", window.Handle, System.Threading.Thread.CurrentThread.ManagedThreadId); ModeSelector = new WinGraphicsMode(window.DeviceContext); Mode = SetGraphicsModePFD(ModeSelector, format, (WinWindowInfo)window); if (Wgl.SupportsFunction("wglCreateContextAttribsARB")) { try { Debug.Write("Using WGL_ARB_create_context... "); List <int> attributes = new List <int>(); attributes.Add((int)ArbCreateContext.MajorVersion); attributes.Add(major); attributes.Add((int)ArbCreateContext.MinorVersion); attributes.Add(minor); if (flags != 0) { attributes.Add((int)ArbCreateContext.ContextFlags); attributes.Add((int)GetARBContextFlags(flags)); attributes.Add((int)ArbCreateContext.ProfileMask); attributes.Add((int)GetARBContextProfile(flags)); } // According to the docs, " <attribList> specifies a list of attributes for the context. // The list consists of a sequence of <name,value> pairs terminated by the // value 0. [...]" // Is this a single 0, or a <0, 0> pair? (Defensive coding: add two zeroes just in case). attributes.Add(0); attributes.Add(0); Handle = new ContextHandle( Wgl.wglCreateContextAttribs( window.DeviceContext, sharedContext != null ? (sharedContext as IGraphicsContextInternal).Context.Handle : IntPtr.Zero, attributes.ToArray())); if (Handle == ContextHandle.Zero) { Debug.Print("failed. (Error: {0})", Marshal.GetLastWin32Error()); } } catch (Exception e) { Debug.Print(e.ToString()); } } if (Handle == ContextHandle.Zero) { // Failed to create GL3-level context, fall back to GL2. Debug.Write("Falling back to GL2... "); Handle = new ContextHandle(Wgl.CreateContext(window.DeviceContext)); if (Handle == ContextHandle.Zero) { Handle = new ContextHandle(Wgl.CreateContext(window.DeviceContext)); } if (Handle == ContextHandle.Zero) { throw new GraphicsContextException( String.Format("Context creation failed. Wgl.CreateContext() error: {0}.", Marshal.GetLastWin32Error())); } } Debug.WriteLine(String.Format("success! (id: {0})", Handle)); } finally { if (temp_context != null) { temp_context.Dispose(); temp_context = null; } if (temp_window != null) { error = Marshal.GetLastWin32Error(); Functions.DestroyWindow(temp_window); Functions.UnregisterClass(ClassName, Instance); error = Marshal.GetLastWin32Error(); } } } // Todo: is this comment still true? // On intel drivers, wgl entry points appear to change // when creating multiple contexts. As a workaround, // we reload Wgl entry points every time we create a // new context - this solves the issue without any apparent // side-effects (i.e. the old contexts can still be handled // using the new entry points.) // Sigh... MakeCurrent(window); new Wgl().LoadEntryPoints(); if (sharedContext != null) { Marshal.GetLastWin32Error(); Debug.Write(String.Format("Sharing state with context {0}: ", sharedContext)); bool result = Wgl.ShareLists((sharedContext as IGraphicsContextInternal).Context.Handle, Handle.Handle); Debug.WriteLine(result ? "success!" : "failed with win32 error " + Marshal.GetLastWin32Error()); } }
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)); }
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)); }