Pregunta

En mi aplicación C# .NET 4, uso WndProc Para procesar algunos mensajes que se trata principalmente de cambiar el tamaño de la aplicación desde y hacia la pantalla completa.

Ahora mismo estoy manejando SC_MAXIMIZE y WM_NCLBUTTONDBLCLK Para determinar si la ventana se redimensiona hacia o desde un estado maximizado (sé que no necesito WNDProc para manejar SC_MAXIMIZE, pero Form_Resize no parecía disparar por un WM_NCLBUTTONDBLCLK Mensaje cuando haga doble clic en la barra de título de la aplicación.

Ahora noté que si Aero rompo la ventana en la parte superior de la pantalla para maximizarla, ninguno de los mensajes anteriores se publican para que ciertas lógicas no se apliquen cuando la ventana se maximiza a Aero Snap. Solo quiero manejar el mensaje si la ventana se rompe en la parte superior de la pantalla en lugar de la derecha o izquierda, o si una ventana se ha apagado desde la posición maximizada.

No pude encontrar ninguno de los mensajes de la ventana relacionados con Aero Snap. ¿Alguien sabe de alguna referencia para esos mensajes?

¿Fue útil?

Solución

Supongo que no hay mensajes especiales aquí; Es probable que Aero solo use las API Win32 simples - Showwindow (sw_maximize) y similar.

Lo que hay que entender con los mensajes SC_ es que esos son Solicitudes de un menú Pidirle a la ventana que cambie/restaurar/etc., pero ese no es el único mecanismo para cambiar el tamaño de las ventanas. Lo que probablemente está sucediendo es que cuando una ventana se obtiene SC_maximize, el defwndproc implementa esto llamando a showwindow (sw_maximize).

Tu mejor mejor es escuchar el WM_SIZE Mensaje, que recibe la ventana, independientemente de lo que activara el cambio de tamaño: menú del sistema, API u otros medios. En particular, el LPARAM le informará si la ventana fue maximizada (size_maximized) o restaurada (size_restored).

Otros consejos

Aquí está el código para manejar Wm_windowPoschanging mensaje para maximizar en lugar de WM_SIZE mensaje. Gracias a las 20 o más preguntas sobre que tuve que leer para encontrar todos los bits para armarlo y hacer que funcione. Esto aborda los problemas que estaba teniendo con múltiples monitores utilizando diferentes resoluciones.

//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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top