правильно изменить размер на дополнительном мониторе при нажатии на значок панели задач wpf - PullRequest
1 голос
/ 14 июля 2020

У меня есть приложение wpf, и я управляю максимальным размером с помощью WmGetMinMaxInfo:

private static void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
{
    MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
    IntPtr monitorContainingApplication = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);

    if (monitorContainingApplication != System.IntPtr.Zero)
    {
        MONITORINFO monitorInfo = new MONITORINFO();
        GetMonitorInfo(monitorContainingApplication, monitorInfo);
        RECT rcWorkArea = monitorInfo.rcWork;
        RECT rcMonitorArea = monitorInfo.rcMonitor;

        mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left);
        mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top);

        mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left);
        mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top);

        mmi.ptMaxTrackSize.x = mmi.ptMaxSize.x;
        mmi.ptMaxTrackSize.y = mmi.ptMaxSize.y;
        
    }

    Marshal.StructureToPtr(mmi, lParam, true);
}

В моем окне установлено значение:

WindowStyle="None"
ResizeMode="CanResizeWithGrip" 
AllowsTransparency="True"

У меня возникла странная проблема, когда я свернул приложение в развернутом состоянии и при нажатии для возврата на значок панели задач, чтобы вернуться в приложение развернутого окна.

Он не занимает весь экран, кажется, используется разрешение основного экрана. У меня такой случай, когда у меня нет одинакового разрешения между основным и второстепенным экраном (очевидно, что мой вторичный экран больше первого).

У вас есть идеи, в чем проблема? Windows особенности? Есть какая-то работа?

РЕШЕНИЕ: Я решил свою проблему с идеей Keithe rnet, чтобы не пересчитывать, когда windowState свернуто. Спасибо!

private static void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
{
    MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
    IntPtr monitorContainingApplication = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);

    if (monitorContainingApplication != System.IntPtr.Zero)
    {
        MONITORINFO monitorInfo = new MONITORINFO();
        GetMonitorInfo(monitorContainingApplication, monitorInfo);
        RECT rcWorkArea = monitorInfo.rcWork;
        RECT rcMonitorArea = monitorInfo.rcMonitor;

        if (Application.Current.MainWindow.WindowState != WindowState.Minimized)
        {
            mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left);
            mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top);

            mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left);
            mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top);

            mmi.ptMaxTrackSize.x = mmi.ptMaxSize.x;
            mmi.ptMaxTrackSize.y = mmi.ptMaxSize.y;
            lastGoodMaxTrackSize = mmi.ptMaxTrackSize;
            lastGoodMaxPosition = mmi.ptMaxPosition;
            lastGoodMaxSize = mmi.ptMaxSize;
        }
        else
        {
            mmi.ptMaxPosition = lastGoodMaxPosition;
            mmi.ptMaxSize = lastGoodMaxSize;
            mmi.ptMaxTrackSize = lastGoodMaxTrackSize;
        }
        mmi = AdjustWorkingAreaForAutoHide(monitorContainingApplication, mmi);
    }

    Marshal.StructureToPtr(mmi, lParam, true);
}

1 Ответ

1 голос
/ 16 июля 2020

У меня есть настраиваемый элемент управления окнами, который я писал много лет как go. Его до сих пор активно используют. Windows обрабатываются правильно, независимо от того, на каком дисплее они находятся и каково индивидуальное разрешение.

Вот моя реализация WmGetMinMaxInfo.

Надеюсь, это поможет.

private void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
{
    var mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
    var hMonitor = Win32.MonitorFromWindow(hwnd, 1);
    
    if (hMonitor != IntPtr.Zero)
    {
        var monitorInfo = new Win32.MONITORINFO();
        
        Win32.GetMonitorInfo(hMonitor, monitorInfo);
        
        var rcWorkArea = monitorInfo.rcWork;
        var rcMonitorArea = monitorInfo.rcMonitor;
        
        mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.Left - rcMonitorArea.Left);
        mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.Top - rcMonitorArea.Top);
        
        mmi.ptMaxSize.x = Math.Abs(rcWorkArea.Right - rcWorkArea.Left);
        mmi.ptMaxSize.y = Math.Abs(rcWorkArea.Bottom - rcWorkArea.Top);
        
        mmi.ptMinTrackSize.x = (int)(minWidth * hidpiX);
        mmi.ptMinTrackSize.y = (int)(minHeight * hidpiY);

        var window = (Window)HwndSource.FromHwnd(hwnd)?.RootVisual;

        if (window != null)
        {
            if (window.WindowState != WindowState.Minimized)
            {
                mmi.ptMaxTrackSize.x = Win32.GetSystemMetrics(Win32.SystemMetric.SM_CXVIRTUALSCREEN);
                mmi.ptMaxTrackSize.y = Win32.GetSystemMetrics(Win32.SystemMetric.SM_CYVIRTUALSCREEN);
                
                lastGoodMaxTrackSize = mmi.ptMaxTrackSize;
            }
            else if (lastGoodMaxTrackSize.x > 0 && lastGoodMaxTrackSize.y > 0)
            {
                mmi.ptMaxTrackSize = lastGoodMaxTrackSize;
            }
        }
    
        mmi = AdjustWorkingAreaForAutoHide(hMonitor, mmi);
    }

    Marshal.StructureToPtr(mmi, lParam, true);
}

Для hidpiX и hidpiY я получаю их в обработчике события OnSourceInitialized.

private void OnSourceInitialized(object sender, EventArgs e)
{
    ...

    var source = PresentationSource.FromVisual((Visual)sender);

    if (source == null) return;

    // Get the X and Y HiDPI factors from the media matrix
    if (source.CompositionTarget != null)
    {
        hidpiX = source.CompositionTarget.TransformToDevice.M11;
        hidpiY = source.CompositionTarget.TransformToDevice.M22;
    }

    ...
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...