Обработка сообщения AeroSnap в WndProc - PullRequest
5 голосов
/ 17 февраля 2012

В моем приложении на C # .NET 4 я использую WndProc для обработки некоторых сообщений, в основном касающихся изменения размера приложения в полноэкранном режиме и из него.

Сейчас я просто обрабатываю SC_MAXIMIZE и WM_NCLBUTTONDBLCLK чтобы определить, изменяется ли окно до или из максимизированного состояния (я знаю, мне не нужен WndProc для обработки SC_MAXIMIZE, но Form_Resize, похоже, не срабатывает для сообщения WM_NCLBUTTONDBLCLK, когда я дваждынажмите на строку заголовка приложения.

Теперь я заметил, что если я Aero Snap окно в верхней части экрана, чтобы развернуть его, ни одно из вышеуказанных сообщений не публикуется, поэтому определенная логика не применяется, когда окноразвернуто с помощью Aero Snap. Я хочу обрабатывать сообщение только в том случае, если окно привязано к верхней части экрана, а не вправо или влево, или если окно отсоединено от развернутой позиции.

Я не смогнайти какие-либо сообщения в окне, относящиеся к Aero Snap. Кто-нибудь знает какие-либо ссылки на эти сообщения?

Ответы [ 2 ]

7 голосов
/ 17 февраля 2012

Полагаю, здесь нет особых сообщений;Aero, скорее всего, просто использует простые API Win32 - ShowWindow (SW_MAXIMIZE) и аналогичные.

В сообщениях SC_ нужно понимать, что это запросы из меню попросить окно изменить размер / восстановить / и т.д., но это не единственный механизм изменения размера окна.Вероятно, происходит то, что когда окно получает SC_MAXIMIZE, DefWndProc реализует это, вызывая ShowWindow (SW_MAXIMIZE).

Лучше всего слушать сообщение WM_SIZE , которое получает окнонезависимо от того, что вызвало изменение размера: системное меню, API или другие средства.В частности, lParam сообщит вам, было ли окно развернуто (SIZE_MAXIMIZED) или восстановлено (SIZE_RESTORED).

2 голосов
/ 06 марта 2014

Вот код для обработки WM_WINDOWPOSCHANGING сообщения «Развернуть» вместо WM_SIZE .Спасибо за 20 или более вопросов по SO, которые мне пришлось прочитать, чтобы найти все кусочки, чтобы собрать его и заставить его работать.Это решает проблемы, которые у меня были с несколькими мониторами с разными разрешениями.

//register the hook
public static void WindowInitialized(Window window)
{
    IntPtr handle = (new WindowInteropHelper(window)).Handle;
    var hwndSource = HwndSource.FromHwnd(handle);
    if (hwndSource != null) 
    {
        hwndSource.AddHook(WindowProc);
    }
}

//the important bit
private static IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    switch (msg)
    {
        case 0x0046: //WINDOWPOSCHANGING
            var winPos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));
            var monitorInfo = new MONITORINFO();
            IntPtr monitorContainingApplication = MonitorFromWindow(hwnd, MonitorDefaultToNearest);
            GetMonitorInfo(monitorContainingApplication, monitorInfo);
            RECT rcWorkArea = monitorInfo.rcWork;
            //check for a framechange - but ignore initial draw. x,y is top left of current monitor so must be a maximise
            if (((winPos.flags & SWP_FRAMECHANGED) == SWP_FRAMECHANGED) && (winPos.flags & SWP_NOSIZE) != SWP_NOSIZE && winPos.x == rcWorkArea.left && winPos.y == rcWorkArea.top)
            {
                //set max size to the size of the *current* monitor
                var width = Math.Abs(rcWorkArea.right - rcWorkArea.left);
                var height = Math.Abs(rcWorkArea.bottom - rcWorkArea.top);
                winPos.cx = width;
                winPos.cy = height;
                Marshal.StructureToPtr(winPos, lParam, true);
                handled = true;
            }                       
            break;
    }
    return (IntPtr)0;
}


//all the helpers for dealing with this COM crap
[DllImport("user32")]
internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);

[DllImport("user32")]
internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);

private const int MonitorDefaultToNearest = 0x00000002;

[StructLayout(LayoutKind.Sequential)]
public struct WINDOWPOS
{
    public IntPtr hwnd;
    public IntPtr hwndInsertAfter;
    public int x;
    public int y;
    public int cx;
    public int cy;
    public int flags;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class MONITORINFO
{
    public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
    public RECT rcMonitor;
    public RECT rcWork;
    public int dwFlags;
}

[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct RECT
{
    public int left;
    public int top;
    public int right;
    public int bottom;
}
...