2012-02-17 12 views
5

W mojej aplikacji C# .NET 4 używam WndProc do przetwarzania niektórych wiadomości, głównie dotyczących zmiany rozmiaru aplikacji na iz pełnego ekranu.Obsługa komunikatu AeroSnap w WndProc

Teraz jestem po prostu obsługi SC_MAXIMIZE i WM_NCLBUTTONDBLCLK aby określić, czy okno jest zmniejszane do lub z zmaksymalizowanego (wiem, że nie trzeba WndProc obsłużyć SC_MAXIMIZE, ale Form_Resize nie wydają się ognia dla WM_NCLBUTTONDBLCLK wiadomość po dwukrotnym kliknięciu na pasku tytułowym aplikacji

Teraz zauważyłem, że jeśli Aero Przyciągnę okno do górnej części ekranu, aby je zmaksymalizować, żaden z powyższych komunikatów nie zostanie opublikowany, więc pewna logika nie zostanie zastosowana gdy okno jest zmaksymalizowane za pomocą Aero Snap, chcę obsłużyć wiadomość tylko wtedy, gdy okno jest przyciągane do górnej części ekranu, zamiast do prawej lub lewej strony, lub jeśli okno nie jest wyłączone z maksymalnego p osycja.

Nie można znaleźć żadnych komunikatów okna związanych z przystawką Aero. Czy ktokolwiek wie o jakichkolwiek odniesieniach do tych wiadomości?

+0

Zastanawiam się również nad tym ... Jednak nigdy nie byłem w stanie tego rozgryźć. – aboveyou00

Odpowiedz

7

Zgaduję, że nie ma tu żadnych specjalnych wiadomości; Aero prawdopodobnie używa zwykłych interfejsów API Win32 - ShowWindow(SW_MAXIMIZE) i podobnych.

Rzeczą, której można się nauczyć z wiadomościami SC_, jest to, że są to żądania z menu z prośbą o zmianę rozmiaru okna/przywrócenie/itp., Ale nie jest to jedyny mechanizm zmiany rozmiaru okna. Prawdopodobnie dzieje się tak, że gdy okno dostaje SC_MAXIMIZE, DefWndProc implementuje to przez wywołanie ShowWindow (SW_MAXIMIZE).

Najlepiej jest słuchać wiadomości WM_SIZE, którą otrzymuje okno, niezależnie od tego, co spowodowało zmianę rozmiaru: menu systemu, API lub w inny sposób. W szczególności, lParam poinformuje Cię, czy okno zostało zmaksymalizowane (SIZE_MAXIMIZED) lub przywrócone (SIZE_RESTORED).

+3

To się zgadza. Nie ma specjalnych powiadomień wysłanych w wyniku Aero Snap. Używa standardowych wiadomości 'WM_MOVING' /' WM_MOVE' i 'WM_SIZING' /' WM_SIZE'. Jeśli przetwarzasz je bez wywoływania 'DefWindowProc', Aero Snap nie będzie działać dla twojego okna. Tak, możesz posłuchać 'WM_SIZE', ale prawdopodobnie lepiej się na ogół używasz [' WM_WINDOWPOSCHANGED'] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms632652.aspx) . Jest to "nowa" funkcja, wprowadzona, err, Windows 3.1. :-) [Właściwe czytanie] (http://blogs.msdn.com/b/oldnewthing/archive/2008/01/15/7113860.aspx). –

+1

Połów z POSCHANGED dostajesz go za * dowolne * przesunięcie/zmianę rozmiaru w ogóle, także gdy okno jest przesuwane przed "przyciąganiem", więc musisz zrobić więcej filtrowania. I nie wiem, czy można określić maksymalne "przyciąganie" z jego parametrów - nie ma oczywistego wskaźnika "okno zostało zmaksymalizowane". Z WM_SIZE, sprawdź lParam i gotowe! – BrendanMcK

+0

Tak, musisz wykonać filtrowanie. Zasadniczo jest to nieuniknione, będziesz musiał filtrować "WM_SIZE", aby mieć pewność, że zajmujesz się tylko zdarzeniami zmiany wielkości zainicjowanymi przez Aero Snap. Chodzi o to, że cały kod obsługi jest w jednym miejscu. Naprawdę nie widzę różnicy między instrukcją 'switch' wewnątrz programu obsługi wiadomości' WM_WINDOWPOSCHANGED' i instrukcją 'switch' wewnątrz procedury okna, która obsługuje' WM_MOVE', 'WM_SIZE' itd.Przypuszczam, że z wielką siłą wiąże się wielka odpowiedzialność; każdy z nich zadziała. –

2

Oto kod do obsługi wiadomości WM_WINDOWPOSCHANGING dla wiadomości Maksymalizuj zamiast WM_SIZE. Dzięki 20 lub więcej pytań na temat SO musiałem przeczytać, aby znaleźć wszystkie bity, aby je połączyć i sprawić, żeby działało. Rozwiązuje to problemy, które miałem z wieloma monitorami używającymi różnych rozdzielczości.

//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; 
} 
+0

Upoważniono wyłącznie do komentarza "wszyscy pomocnicy, którzy mają do czynienia z tym gównem COM" ... –

Powiązane problemy