Пример #1
0
        internal void Initialize(Window window, FrameworkElement element = null)
        {
            if (window == null)
            {
                throw new ArgumentNullException(nameof(window));
            }

            if (!window.IsInitialized)
            {
                throw new InvalidOperationException("Target Window has not been initialized.");
            }

            _targetWindow  = window;
            _targetElement = element;

            ForbearScaling = WillForbearScalingIfUnnecessary && BuiltinFunction.IsScalingSupported(_targetWindow);

            if (IsPerMonitorDpiAware)
            {
                MonitorDpi = DpiChecker.GetDpiFromVisual(_targetWindow);

                if (MonitorDpi.Equals(SystemDpi) || ForbearScaling)
                {
                    WindowDpi = MonitorDpi;
                }
                else
                {
                    var newInfo = new WindowInfo
                    {
                        Dpi    = MonitorDpi,
                        Width  = _targetWindow.Width * (double)MonitorDpi.X / SystemDpi.X,
                        Height = _targetWindow.Height * (double)MonitorDpi.Y / SystemDpi.Y,
                    };

                    Interlocked.Exchange(ref _dueInfo, newInfo);

                    ChangeDpi();
                }
            }
            else
            {
                MonitorDpi = SystemDpi;
                WindowDpi  = MonitorDpi;
            }

            ColorProfilePath = ColorProfileChecker.GetColorProfilePath(_targetWindow);

            _targetSource = PresentationSource.FromVisual(_targetWindow) as HwndSource;
            _targetSource?.AddHook(WndProc);
        }
Пример #2
0
        /// <summary>
        /// Handles window messages.
        /// </summary>
        /// <param name="hwnd">The window handle</param>
        /// <param name="msg">The message ID</param>
        /// <param name="wParam">The message's wParam value</param>
        /// <param name="lParam">The message's lParam value</param>
        /// <param name="handled">Whether the message was handled</param>
        /// <returns>Return value depending on the particular message</returns>
        /// <remarks>This is an implementation of System.Windows.Interop.HwndSourceHook.</remarks>
        protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg)
            {
            case (int)WindowMessage.WM_DPICHANGED:
                var newDpi = new Dpi(
                    NativeMacro.GetLoWord((uint)wParam),
                    NativeMacro.GetHiWord((uint)wParam));

                Debug.WriteLine($"DPICHANGED: {MonitorDpi.X} -> {newDpi.X}");

                if (MonitorDpi.Equals(newDpi))
                {
                    break;
                }

                var oldDpi = MonitorDpi;
                MonitorDpi = newDpi;

                if (ForbearScaling)
                {
                    WindowDpi = MonitorDpi;
                    break;
                }

                _isDpiChanged = true;

                var newInfo = new WindowInfo {
                    Dpi = MonitorDpi
                };

                switch (_currentStatus)
                {
                case WindowStatus.None:
                case WindowStatus.LocationChanged:
                    if ((_baseSize == Size.Empty) || (_currentStatus == WindowStatus.None))
                    {
                        _baseSize = new Size(_targetWindow.Width, _targetWindow.Height);
                    }

                    _baseSize = new Size(
                        _baseSize.Width * (double)MonitorDpi.X / oldDpi.X,
                        _baseSize.Height * (double)MonitorDpi.Y / oldDpi.Y);

                    newInfo.Size = _baseSize;
                    break;

                case WindowStatus.SizeChanged:
                    // None.
                    break;
                }

                Interlocked.Exchange(ref _dueInfo, newInfo);

                switch (_currentStatus)
                {
                case WindowStatus.None:
                    ChangeDpi();
                    break;

                case WindowStatus.LocationChanged:
                    // None.
                    break;

                case WindowStatus.SizeChanged:
                    ChangeDpi(WindowStatus.SizeChanged);
                    break;
                }

                handled = true;
                break;

            case (int)WindowMessage.WM_ENTERSIZEMOVE:
                Debug.WriteLine("ENTERSIZEMOVE");

                if (!IsPerMonitorDpiAware || ForbearScaling)
                {
                    break;
                }

                _baseSize = new Size(_targetWindow.Width, _targetWindow.Height);

                _isEnteredSizeMove    = true;
                _isDpiChanged         = false;
                _countLocationChanged = 0;
                _countSizeChanged     = 0;
                break;

            case (int)WindowMessage.WM_EXITSIZEMOVE:
                Debug.WriteLine("EXITSIZEMOVE");

                if (_isEnteredSizeMove)
                {
                    _isEnteredSizeMove = false;

                    // Last stand!!!
                    if (_isDpiChanged && (_currentStatus == WindowStatus.LocationChanged))
                    {
                        var lastInfo = new WindowInfo
                        {
                            Dpi  = MonitorDpi,
                            Size = _baseSize,
                        };

                        Interlocked.Exchange(ref _dueInfo, lastInfo);

                        ChangeDpi(WindowStatus.LocationChanged);
                    }

                    _currentStatus = WindowStatus.None;
                }

                ChangeColorProfilePath();
                break;

            case (int)WindowMessage.WM_MOVE:
                Debug.WriteLine("MOVE");

                if (_isEnteredSizeMove)
                {
                    _countLocationChanged++;
                    if (_countLocationChanged > _countSizeChanged)
                    {
                        _currentStatus = WindowStatus.LocationChanged;
                    }

                    ChangeDpi(WindowStatus.LocationChanged);
                }
                break;

            case (int)WindowMessage.WM_SIZE:
                if ((uint)wParam != NativeMethod.SIZE_RESTORED)
                {
                    break;
                }

                Debug.WriteLine("SIZE");

                if (_isEnteredSizeMove)
                {
                    _countSizeChanged++;
                    if (_countLocationChanged < _countSizeChanged)
                    {
                        _currentStatus = WindowStatus.SizeChanged;
                    }

                    // DPI change by resize will be managed when WM_DPICHANGED comes.
                }
                break;
            }
            return(IntPtr.Zero);
        }