2012-02-17 21 views
5

Trong ứng dụng C# .NET 4 của tôi, tôi sử dụng WndProc để xử lý một số thông điệp chủ yếu là xử lý việc thay đổi kích thước ứng dụng đến và từ toàn màn hình.Xử lý tin nhắn AeroSnap trong WndProc

Ngay bây giờ tôi chỉ xử lý SC_MAXIMIZEWM_NCLBUTTONDBLCLK để xác định xem các cửa sổ đang được thay đổi kích cỡ hoặc từ một trạng thái tối đa (Tôi biết tôi không cần WndProc để xử lý SC_MAXIMIZE, nhưng Form_Resize dường như không để bắn cho một WM_NCLBUTTONDBLCLK tin nhắn khi tôi bấm đúp vào thanh tiêu đề của ứng dụng

Bây giờ tôi nhận thấy rằng nếu tôi Aero Snap cửa sổ lên trên cùng của màn hình để tối đa hóa nó, không phải các thông báo trên được đăng để logic nhất định không được áp dụng khi cửa sổ được phóng to qua Aero Snap, tôi chỉ muốn xử lý thông báo nếu cửa sổ được chụp ở phía trên cùng của màn hình thay vì sang phải hoặc trái, hoặc nếu cửa sổ không bị xóa từ p được tối đa vị trí.

Tôi không thể tìm thấy bất kỳ thông báo cửa sổ nào liên quan đến Aero Snap. Có ai biết về bất kỳ tài liệu tham khảo cho những tin nhắn?

+0

Tôi cũng đã tự hỏi điều này ... Tôi chưa bao giờ có thể đoán được điều đó. – aboveyou00

Trả lời

7

Tôi đoán không có bất kỳ thông điệp đặc biệt nào ở đây; Aero có khả năng chỉ sử dụng các API Win32 đơn giản - ShowWindow(SW_MAXIMIZE) và tương tự.

Điều cần biết với các thông điệp SC_ là các yêu cầu từ một menu yêu cầu cửa sổ đổi kích thước/khôi phục/etc, nhưng đó không phải là cơ chế duy nhất để thay đổi kích thước của cửa sổ. Những gì có thể xảy ra là khi một cửa sổ được SC_MAXIMIZE, DefWndProc thực hiện điều này bằng cách gọi ShowWindow (SW_MAXIMIZE).

Tốt nhất là lắng nghe thông báo WM_SIZE, cửa sổ nhận được, bất kể điều gì đã kích hoạt thay đổi kích thước: menu hệ thống, API hoặc các phương tiện khác. Đặc biệt, lParam sẽ cho bạn biết nếu cửa sổ được phóng to (SIZE_MAXIMIZED) hoặc được khôi phục (SIZE_RESTORED).

+3

Điều này là chính xác. Không có thông báo đặc biệt nào được gửi do Aero Snap. Nó sử dụng thông điệp 'WM_MOVING' /' WM_MOVE' và 'WM_SIZING' /' WM_SIZE' chuẩn. Nếu bạn xử lý chúng mà không gọi 'DefWindowProc', Aero Snap sẽ không hoạt động cho cửa sổ của bạn. Có, bạn có thể nghe 'WM_SIZE', nhưng bạn có thể nói chung tốt hơn bằng cách sử dụng [' WM_WINDOWPOSCHANGED'] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms632652.aspx) . Đó là một chức năng "mới", được giới thiệu trong, err, Windows 3.1. :-) [Đọc có liên quan] (http://blogs.msdn.com/b/oldnewthing/archive/2008/01/15/7113860.aspx). –

+1

Bắt với POSCHANGED là bạn nhận được nó cho * bất kỳ * di chuyển/kích thước thay đổi ở tất cả, bao gồm cả khi cửa sổ đang được di chuyển xung quanh trước khi "snap", vì vậy bạn cần phải làm nhiều hơn lọc. Và tôi không biết nếu bạn có thể xác định một tối đa 'snap' từ các thông số của nó - không có chỉ số "cửa sổ đã được tối đa hóa" rõ ràng. Với WM_SIZE, hãy kiểm tra lParam và bạn đã hoàn tất! – BrendanMcK

+0

Có, bạn cần thực hiện một số chức năng lọc. Đó là cơ bản không thể tránh khỏi, bạn sẽ phải lọc 'WM_SIZE' để đảm bảo rằng bạn chỉ đối phó với các sự kiện thay đổi kích thước được khởi tạo bởi Aero Snap. Vấn đề là tất cả mã xử lý của bạn đều ở một nơi. Tôi không thực sự thấy sự khác biệt giữa câu lệnh 'switch' bên trong trình xử lý tin nhắn' WM_WINDOWPOSCHANGED' của bạn và câu lệnh 'switch' bên trong thủ tục cửa sổ của bạn xử lý' WM_MOVE', 'WM_SIZE', v.v.Tôi cho rằng với sức mạnh to lớn có trách nhiệm lớn lao; một trong hai sẽ hoạt động. –

2

Đây là mã để xử lý thông báo WM_WINDOWPOSCHANGING cho Tối đa hóa thay vì thông báo WM_SIZE. Nhờ có 20 câu hỏi trở lên trên SO mà tôi đã phải đọc để tìm tất cả các bit để đặt nó lại với nhau và làm cho nó hoạt động. Điều này giải quyết các vấn đề mà tôi đã gặp phải với nhiều màn hình bằng cách sử dụng các độ phân giải khác nhau.

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

Upvoted hoàn toàn cho bình luận của bạn "tất cả những người giúp đỡ để đối phó với điều này crap COM" ... –