private void RegisterWindowClass()
        {
            _wndProcDelegate = WndProc;
            var wc = new WindowClassEx
            {
                Styles         = WindowClassStyles.CS_HREDRAW | WindowClassStyles.CS_VREDRAW | WindowClassStyles.CS_OWNDC,
                WindowProc     = _wndProcDelegate,
                InstanceHandle = Kernel32.GetModuleHandle(null),
                CursorHandle   = User32.LoadCursor(IntPtr.Zero, (IntPtr)SystemCursor.IDC_ARROW),
                ClassName      = CLASS_NAME
            };

            wc.Size = (uint)Marshal.SizeOf(wc);

            // Load user icon - if any.
            wc.IconHandle = User32.LoadImage(Kernel32.GetModuleHandle(null), "#32512", ResourceImageType.IMAGE_ICON, 0, 0, LoadResourceFlags.LR_DEFAULTSIZE | LoadResourceFlags.LR_SHARED);
            if (wc.IconHandle == IntPtr.Zero)
            {
                Kernel32.SetLastError(0);

                // None loaded - load default.
                wc.IconHandle = User32.LoadImage(IntPtr.Zero, (IntPtr)SystemIcon.IDI_APPLICATION, ResourceImageType.IMAGE_ICON, 0, 0, LoadResourceFlags.LR_DEFAULTSIZE | LoadResourceFlags.LR_SHARED);
            }

            ushort windowClass = User32.RegisterClassEx(ref wc);

            if (windowClass == 0)
            {
                CheckError("Win32: Failed to register window class.", true);
            }

            CheckError("Win32: Could not register class.");
        }
Example #2
0
        public static bool GetIsProcessorAMD64()
        {
            SystemInfo info;

            Kernel32Methods.GetNativeSystemInfo(out info);
            return(info.ProcessorArchitecture == (uint)ProcessArchitecture.PROCESSOR_ARCHITECTURE_AMD64);
        }
        /// <summary>
        /// Check for a Win32 error.
        /// </summary>
        /// <param name="msg">A message to display with the error.</param>
        /// <param name="sureError">Whether you are sure an error occured.</param>
        public static void CheckError(string msg, bool sureError = false)
        {
            uint errorCheck = Kernel32.GetLastError();

            if (errorCheck == 0 && !sureError)
            {
                return;
            }

            // Check predefined errors.
            switch (errorCheck)
            {
            case ERROR_INVALID_VERSION_ARB:
                Engine.SubmitError(new Exception($"Driver doesn't support version of {msg}"));
                break;

            case ERROR_INVALID_PROFILE_ARB:
                Engine.SubmitError(new Exception($"Driver doesn't support profile of {msg}"));
                break;

            default:
                Engine.SubmitError(new Exception(msg, new Win32Exception((int)errorCheck)));
                break;
            }
        }
Example #4
0
        public static Version GetVersion()
        {
            var dwVersion = Kernel32Methods.GetVersion();
            var build     = dwVersion < 0x80000000 ? dwVersion.HighAsUInt() : 0; // (DWORD) (HIWORD(dwVersion))
            var v         = new Version(
                (byte)dwVersion.Low(),                                           // (DWORD)(LOBYTE(LOWORD(dwVersion)))
                (dwVersion.Low() >> 8) & 0xff,
                (int)build                                                       // (DWORD)(HIBYTE(LOWORD(dwVersion)))
                );

            return(v);
        }
        /// <summary>
        /// Updates key names according to the current keyboard layout.
        /// </summary>
        private void PopulateKeyNames()
        {
            var state = new byte[256];

            // Initialize the key names array.
            _keyNames = new string[_scanCodes.Length];

            for (var key = (int)Key.Space; key < (int)Key.Last; key++)
            {
                uint vk;

                int scanCode = _scanCodes[key];
                if (scanCode == -1)
                {
                    continue;
                }

                if (key >= (int)Key.Kp0 && key <= (int)Key.KpAdd)
                {
                    uint[] vks =
                    {
                        (uint)VirtualKey.NUMPAD0,  (uint)VirtualKey.NUMPAD1,  (uint)VirtualKey.NUMPAD2, (uint)VirtualKey.NUMPAD3,
                        (uint)VirtualKey.NUMPAD4,  (uint)VirtualKey.NUMPAD5,  (uint)VirtualKey.NUMPAD6, (uint)VirtualKey.NUMPAD7,
                        (uint)VirtualKey.NUMPAD8,  (uint)VirtualKey.NUMPAD9,  (uint)VirtualKey.DECIMAL, (uint)VirtualKey.DIVIDE,
                        (uint)VirtualKey.MULTIPLY, (uint)VirtualKey.SUBTRACT, (uint)VirtualKey.ADD
                    };

                    vk = vks[key - (int)Key.Kp0];
                }
                else
                {
                    vk = User32.MapVirtualKey((uint)scanCode, VirtualKeyMapType.MAPVK_VSC_TO_VK);
                }

                var chars  = new StringBuilder(16);
                int length = User32.ToUnicode(vk, (uint)scanCode, state, chars, chars.Capacity, 0);
                if (length == -1)
                {
                    length = User32.ToUnicode(vk, (uint)scanCode, state, chars, chars.Capacity, 0);
                }

                if (length < 1)
                {
                    continue;
                }

                var keyName = new char[5];
                Kernel32.WideCharToMultiByte(CodePage.CpUtf8, 0, chars, 1, keyName, keyName.Length, IntPtr.Zero, out bool _);

                _keyNames[key] = NativeHelpers.StringFromNullTerminated(keyName);
            }
        }
        private void CreateHelperWindow()
        {
            HelperWindowHandle = User32.CreateWindowEx(
                WindowExStyles.WS_EX_OVERLAPPEDWINDOW,
                CLASS_NAME,
                "Emotion Helper Window",
                WindowStyles.WS_CLIPSIBLINGS | WindowStyles.WS_CLIPCHILDREN,
                0, 0, 100, 100,
                IntPtr.Zero, IntPtr.Zero,
                Kernel32.GetModuleHandle(null),
                IntPtr.Zero
                );

            if (HelperWindowHandle == IntPtr.Zero)
            {
                CheckError("Win32: Failed to create helper window.", true);
            }

            // HACK: The command to the first ShowWindow call is ignored if the parent
            //       process passed along a STARTUPINFO, so clear that with a no-op call
            User32.ShowWindow(HelperWindowHandle, ShowWindowCommands.SW_HIDE);

            // Register for HID device notifications
            var dbi = new DevBroadcastDeviceInterfaceW();

            dbi.DbccSize              = (uint)Marshal.SizeOf(dbi);
            dbi.DbccDeviceType        = DeviceType.DeviceInterface;
            dbi.DbccClassGuid         = User32Guids.GuidDevInterfaceHid;
            _deviceNotificationHandle = User32.RegisterDeviceNotificationW(HelperWindowHandle, ref dbi, DeviceNotificationFlags.WindowHandle);

            CheckError("Registering for device notifications.");

            while (User32.PeekMessage(out Message msg, HelperWindowHandle, 0, 0, PeekMessageFlags.PM_REMOVE))
            {
                User32.TranslateMessage(ref msg);
                User32.DispatchMessage(ref msg);
            }

            Kernel32.SetLastError(0);

            CheckError("Creating helper window.");
        }
        /// <inheritdoc />
        protected override void SetupPlatform(Configurator config)
        {
            // todo: load libraries - if any
            // probably XInput

            // Initialize audio - Try to create WasApi - otherwise return the fake context so execution can go on.
            Audio = WasApiAudioContext.TryCreate() ?? (AudioContext) new NullAudioContext();
            Engine.Log.Trace("Audio init complete.", MessageSource.Win32);

            PopulateKeyNames();

            if (IsWindows10CreatorsUpdateOrGreaterWin32)
            {
                User32.SetProcessDpiAwarenessContext(DpiAwarenessContext.DpiAwarenessContextPerMonitorAwareV2);
            }
            else if (IsWindows81OrGreater)
            {
                User32.SetProcessDpiAwareness(ProcessDpiAwareness.ProcessPerMonitorDpiAware);
            }
            else
            {
                User32.SetProcessDPIAware();
            }

            RegisterWindowClass();
            CreateHelperWindow();
            PollMonitors();
            Engine.Log.Trace("Platform init complete.", MessageSource.Win32);

            var windowInitialSize = new Rect
            {
                Right  = (int)config.HostSize.X,
                Bottom = (int)config.HostSize.Y
            };

            Win32Window.GetFullWindowRect(Win32Window.DEFAULT_WINDOW_STYLE, Win32Window.DEFAULT_WINDOW_STYLE_EX, DEFAULT_DPI, ref windowInitialSize);
            int    initialWidth  = windowInitialSize.Right - windowInitialSize.Left;
            int    initialHeight = windowInitialSize.Bottom - windowInitialSize.Top;
            IntPtr handle        = User32.CreateWindowEx(
                Win32Window.DEFAULT_WINDOW_STYLE_EX,
                CLASS_NAME,
                config.HostTitle,
                Win32Window.DEFAULT_WINDOW_STYLE,
                (int)CreateWindowFlags.CW_USEDEFAULT, (int)CreateWindowFlags.CW_USEDEFAULT, // Position - default
                initialWidth, initialHeight,                                                // Size - initial
                IntPtr.Zero,                                                                // No parent window
                IntPtr.Zero,                                                                // No window menu
                Kernel32.GetModuleHandle(null),
                IntPtr.Zero
                );

            if (handle == IntPtr.Zero)
            {
                CheckError("Couldn't create window.", true);
                return;
            }

            Engine.Log.Trace("Window created.", MessageSource.Win32);

            // Create graphics context - OpenGL.
            GraphicsContext context = null;

            try
            {
                var wgl = new WglGraphicsContext();
                wgl.Init(handle, this);
                if (wgl.Valid)
                {
                    context = wgl;
                }
            }
            catch (Exception ex)
            {
                Engine.Log.Warning($"Couldn't create WGL context, falling back to MESA if possible.\n{ex}", MessageSource.Win32);
            }

            if (context == null)
            {
                try
                {
                    var gallium = new GalliumGraphicsContext();
                    gallium.Init(handle, this);
                    if (gallium.Valid)
                    {
                        context = gallium;
                    }
                }
                catch (Exception ex)
                {
                    Engine.SubmitError(new Exception("Couldn't create MESA context.", ex));
                }
            }

            if (context == null)
            {
                Engine.SubmitError(new Exception("Couldn't create graphics context!"));
                return;
            }

            // Create Emotion representation of the window.
            var windowInstance = new Win32Window(handle, context, this);

            // Adjust window size to account for DPI scaling of the window frame and optionally DPI scaling of the content area.
            // This cannot be done until we know what monitor it was placed on - so it's done post creation.
            var rect = new Rect
            {
                Right  = (int)config.HostSize.X,
                Bottom = (int)config.HostSize.Y
            };

            rect.ClientToScreen(windowInstance.Handle);
            windowInstance.GetFullWindowRect(ref rect);
            User32.SetWindowPos(windowInstance.Handle, IntPtr.Zero,
                                rect.Left, rect.Top,
                                rect.Right - rect.Left, rect.Bottom - rect.Top,
                                WindowPositionFlags.SWP_NOACTIVATE | WindowPositionFlags.SWP_NOZORDER);
            Window = windowInstance;
        }
 /// <inheritdoc />
 public override IntPtr GetLibrarySymbolPtr(IntPtr library, string symbolName)
 {
     return(Kernel32.GetProcAddress(library, symbolName));
 }
 /// <inheritdoc />
 public override IntPtr LoadLibrary(string path)
 {
     return(Kernel32.LoadLibrary(path));
 }