protected virtual IntPtr WndProc(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam)
        {
            WM wmMsg = (WM)message;

            switch (wmMsg)
            {
            case WM.NCCREATE:
            {
                NativeInstance = this;
                _handle        = hWnd;
                PreCreated(hWnd);
                break;
            }

            case WM.CREATE:
            {
                OnCreated(hWnd);
                var createdEvent = new CreatedEventArgs(_handle, _handle);
                HostCreated?.Invoke(this, createdEvent);
                _isInitialized = true;
                break;
            }

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

            case WM.NCHITTEST:
                if (_options.WindowFrameless)
                {
                    return((IntPtr)HT.CAPTION);
                }
                break;

            case WM.MOVING:
            case WM.MOVE:
            {
                HostMoving?.Invoke(this, new MovingEventArgs());
                return(IntPtr.Zero);
            }

            case WM.SIZING:
            case WM.SIZE:
            {
                var size = GetClientSize();
                OnSizeChanged(size.Width, size.Height);
                break;
            }

            case WM.GETMINMAXINFO:
            {
                if (HandleMinMaxSizes(lParam))
                {
                    return(IntPtr.Zero);
                }
                break;
            }

            case WM.CLOSE:
            {
                if (_handle != IntPtr.Zero && _isInitialized)
                {
                    HostClose?.Invoke(this, new CloseEventArgs());
                }

                DetachHooks();
                DestroyWindow(_handle);
                break;
            }

            case WM.DESTROY:
            {
                if (_options.UseOnlyCefMessageLoop)
                {
                    Cef.QuitMessageLoop();
                }
                PostQuitMessage(0);
                break;
            }

            default:
                break;
            }

            return(DefWindowProcW(hWnd, wmMsg, wParam, lParam));
        }