2012-02-17 22 views
5

C# .NET 4 uygulamamda, çoğunlukla uygulamayı tam ekrandan ve tam ekrandan yeniden boyutlandırmakla ilgili bazı iletileri işlemek için WndProc kullanıyorum. Pencere veya bir ekranı kaplamış durumda (ben SC_MAXIMIZE işlemek için WndProc gerekmez biliyorum ama Form_Resize bir yangına görünmüyordu gelen resized olup olmadığını SağWndProc'de AeroSnap iletisinin işlenmesi

şimdi sadece belirlemek için SC_MAXIMIZE ve WM_NCLBUTTONDBLCLK taşıma ediyorum Uygulamanın başlık çubuğuna çift tıklattığımda WM_NCLBUTTONDBLCLK iletisi

Şimdi, şunu farkettim: Aero'yu ekranın üst kısmına genişletmek için ekranın üstüne yapıştırın, yukarıdaki iletilerin hiçbiri gönderilmeyecek şekilde belirli bir mantık uygulanmadı. Eğer pencere Aero Snap üzerinden maksimize edildiğinde, sadece pencerenin ekranın sağına veya soluna değil ekranın üstüne kaydırılması veya bir pencerenin maksimum p'den ayrılmaması durumunda mesajı işlemek istiyorum. zayıfsa.

Aero Snap ile ilgili herhangi bir mesaj bulamadık. Bu mesajlar için herhangi bir referans bilen var mı?

+0

Ben de bunu merak ettim ... Ancak, bunu asla çözemedim. – aboveyou00

cevap

7

Sanırım burada özel mesaj yok; Aero sadece düz Win32 API'lerini kullanıyor - ShowWindow(SW_MAXIMIZE) ve benzeri.

SC_ mesajları ile uderstand gereken şey bu etc/kendini/boyutlandırmak geri pencereyi soran bir menü dan istekleri olduğunu, ama bu pencereler boyutunu değiştirmek için tek mekanizma değildir. Muhtemelen, bir pencere SC_MAXIMIZE olduğunda DefWndProc bunu ShowWindow (SW_MAXIMIZE) çağırarak uygular.

En iyi seçeneğiniz, boyut değiştirmeyi tetikleyen şeyden bağımsız olarak pencerenin aldığı WM_SIZE mesajını dinlemek: sistem menüsü, API veya diğer araçlar. Özellikle, pencere en üst düzeye çıkarıldıysa (SIZE_MAXIMIZED) veya geri yüklendiğinde (SIZE_RESTORED) lParam size bildirir.

+3

Bu doğru. Aero Snap'in bir sonucu olarak gönderilen özel bir bildirim yok. “WM_MOVING”/“WM_MOVE” ve “WM_SIZING”/“WM_SIZE” mesajlarını kullanır. Bunları 'DefWindowProc' çağırmadan işlerseniz, Aero Snap pencereniz için çalışmaz. Evet, “WM_SIZE” yi dinleyebilirsiniz, ancak muhtemelen ['WM_WINDOWPOSCHANGED'] kullanarak daha iyi durumdasınız (http://msdn.microsoft.com/en-us/library/windows/desktop/ms632652.aspx) . Windows 3.1 'de tanıtılan "yeni" bir işlev. :-) [İlgili okuma] (http://blogs.msdn.com/b/oldnewthing/archive/2008/01/15/7113860.aspx). –

+1

POSCHANGED ile yakalama, pencere "snap" dan önce hareket ettirildiği zaman da dahil olmak üzere * herhangi bir * move/size değişikliği için aldığınızdan, daha fazla filtreleme yapmanız gerekir. Ve eğer parametrelerden bir 'snap' maksimize edip edemeyeceğinizi - bariz bir "pencerenin maksimize edilmiş" göstergesi olup olmadığını bilmiyorum. WM_SIZE ile lParam'ı kontrol edin ve işiniz bitti! – BrendanMcK

+0

Evet, biraz filtreleme yapmanız gerekiyor. Bu temel olarak kaçınılmaz olanıdır, sadece Aero Snap tarafından başlatılan yeniden boyutlandırma olaylarıyla uğraştığınızdan emin olmak için 'WM_SIZE' filtrelemelisiniz. Önemli olan, tüm işlem kodunuzun tek bir yerde olmasıdır. "WM_WINDOWPOSCHANGED" ileti işleyicinizin içindeki '' switch' deyimi ile 'WM_MOVE',' WM_SIZE 'vb.Sanırım büyük güçle büyük sorumluluk gelir; ya biri çalışır. –

2

WM_SIZE iletisi yerine Maksimize için WM_WINDOWPOSCHANGING mesajının işleneceği kod. SO ile ilgili 20 ya da daha fazla soruya cevaben, tüm bitleri bir araya getirmek ve çalışmasını sağlamak için okumam gerekti. Bu, farklı çözünürlükler kullanarak birden çok monitörle yaşadığım sorunları ele alıyor.

//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

Yorumunuz için tamamen yorumda bulunuldu "bu COM ile uğraşmak için tüm yardımcılar" ... –

İlgili konular