public unsafe virtual void CreateWindow() { _keyboadHandler?.SetNativeHost(this); _windowFrameless = _options.WindowFrameless; _wndProc = WndProc; _consoleParentInstance = GetConsoleWindow(); _options.WindowState = (_options.Fullscreen || _options.KioskMode) ? WindowState.Fullscreen : _options.WindowState; _windoStylePlacement = new WindowStylePlacement(_options); User32.WNDCLASS wcex = new User32.WNDCLASS(); wcex.style = User32.CS.HREDRAW | User32.CS.VREDRAW; wcex.lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_wndProc); wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hIcon = GetIconHandle(); wcex.hCursor = User32.LoadCursorW(IntPtr.Zero, (IntPtr)CursorResourceId.IDC_ARROW); wcex.hbrBackground = Gdi32.GetStockObject(Gdi32.StockObject.WHITE_BRUSH); wcex.lpszMenuName = null; wcex.hInstance = _consoleParentInstance; fixed(char *c = Chromely_WINDOW_CLASS) { wcex.lpszClassName = c; } if (User32.RegisterClassW(ref wcex) == 0) { Logger.Instance.Log.LogError("Chromelywindow registration failed"); return; } var stylePlacement = GetWindowStylePlacement(_options.WindowState); var hWnd = User32.CreateWindowExW( stylePlacement.ExStyles, Chromely_WINDOW_CLASS, _options.Title, stylePlacement.Styles, stylePlacement.RECT.left, stylePlacement.RECT.top, stylePlacement.RECT.Width, stylePlacement.RECT.Height, IntPtr.Zero, IntPtr.Zero, _consoleParentInstance, null); if (hWnd == IntPtr.Zero) { Logger.Instance.Log.LogError("Chromelywindow creation failed"); return; } PlaceWindow(hWnd, stylePlacement); InstallHooks(hWnd); ShowWindow(hWnd, stylePlacement.ShowCommand); UpdateWindow(hWnd); RegisterHotKeys(hWnd); }
/// <summary> /// Once the classname and style bits have been set, this can be called to register the class. /// </summary> private unsafe void RegisterClass() { User32.WNDCLASS windowClass = new User32.WNDCLASS(); string localClassName = _className; if (localClassName == null) { // If we don't use a hollow brush here, Windows will "pre paint" us with COLOR_WINDOW which // creates a little bit if flicker. This happens even though we are overriding wm_erasebackgnd. // Make this hollow to avoid all flicker. windowClass.hbrBackground = Gdi32.GetStockObject(Gdi32.StockObject.HOLLOW_BRUSH); windowClass.style = _classStyle; _defaultWindProc = DefaultWindowProc; localClassName = "Window." + Convert.ToString((int)_classStyle, 16); } else { // A system defined Window class was specified, get its info if (!User32.GetClassInfoW(NativeMethods.NullHandleRef, _className, ref windowClass)) { throw new Win32Exception(Marshal.GetLastWin32Error(), SR.InvalidWndClsName); } localClassName = _className; _defaultWindProc = windowClass.lpfnWndProc; } _windowClassName = GetFullClassName(localClassName); _windProc = new User32.WNDPROC(Callback); windowClass.lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_windProc); windowClass.hInstance = Kernel32.GetModuleHandleW(null); fixed(char *c = _windowClassName) { windowClass.lpszClassName = c; if (User32.RegisterClassW(ref windowClass) == 0) { _windProc = null; throw new Win32Exception(); } } }
/// <summary> /// Constructor. /// </summary> /// <param name="className">Name, or default will be generated.</param> /// <param name="moduleInstance">Module to associate with the window. The entry assembly is the default.</param> /// <param name="backgroundBrush">Use (IntPtr)(-1) for no background brush.</param> /// <param name="icon">Use (IntPtr)(-1) for no icon.</param> /// <param name="cursor">Use (IntPtr)(-1) for no cursor.</param> /// <param name="menuName">Menu name, can not set with <paramref name="menuId"/>.</param> /// <param name="menuId">Menu id, can not set with <paramref name="menuName"/>.</param> public unsafe WindowClass( string className = default, IntPtr moduleInstance = default, User32.CS classStyle = User32.CS.HREDRAW | User32.CS.VREDRAW, IntPtr backgroundBrush = default, IntPtr icon = default, IntPtr cursor = default, string menuName = null, int menuId = 0, int classExtraBytes = 0, int windowExtraBytes = 0) { // Handle default values className ??= Guid.NewGuid().ToString(); if (backgroundBrush == default) { backgroundBrush = User32.GetSysColorBrush(COLOR_WINDOW); } else if (backgroundBrush == (IntPtr)(-1)) { backgroundBrush = default; } if (icon == default) { icon = LoadIconW(IntPtr.Zero, (IntPtr)IDI_APPLICATION); } else if (icon == (IntPtr)(-1)) { icon = default; } if (cursor == default) { cursor = User32.LoadCursorW(IntPtr.Zero, (IntPtr)User32.CursorResourceId.IDC_ARROW); } else if (cursor == (IntPtr)(-1)) { cursor = default; } if (moduleInstance == IntPtr.Zero) { Marshal.GetHINSTANCE(Assembly.GetCallingAssembly().Modules.First()); } if (menuId != 0 && menuName != null) { throw new ArgumentException($"Can't set both {nameof(menuName)} and {nameof(menuId)}."); } _windowProcedure = WNDPROC; ModuleInstance = moduleInstance; _className = className; _menuName = menuName ?? string.Empty; _wndClass = new User32.WNDCLASS { style = classStyle, lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_windowProcedure), cbClsExtra = classExtraBytes, cbWndExtra = windowExtraBytes, hInstance = moduleInstance, hIcon = icon, hCursor = cursor, hbrBackground = backgroundBrush, lpszMenuName = (char *)menuId }; }