2009-05-05 27 views
18

Tôi đang tạo một ứng dụng mà tôi tương tác với từng ứng dụng đang chạy. Ngay bây giờ, tôi cần một cách để có được thứ tự z của cửa sổ. Ví dụ, nếu Firefox và notepad đang chạy, tôi cần biết cái nào ở trước.Làm thế nào để có được thứ tự z trong cửa sổ?

Bất kỳ ý tưởng nào? Bên cạnh đó làm điều này cho cửa sổ chính của mỗi ứng dụng tôi cũng cần phải làm điều đó cho cửa sổ con và em gái của mình (cửa sổ thuộc cùng một quá trình).

Trả lời

10

Bạn có thể sử dụng chức năng GetTopWindow để tìm kiếm tất cả cửa sổ con của cửa sổ chính và trả về tay cầm cho cửa sổ con cao nhất theo thứ tự z. Hàm GetNextWindow truy xuất một tay cầm đến cửa sổ tiếp theo hoặc trước đó theo thứ tự z.

GetTopWindow: http://msdn.microsoft.com/en-us/library/ms633514(VS.85).aspx
GetNextWindow: http://msdn.microsoft.com/en-us/library/ms633509(VS.85).aspx

+3

Và "máy tính để bàn" có thể được sử dụng làm cửa sổ chính bằng cách chỉ định null cho cha mẹ. Do đó bạn có thể dễ dàng có được cửa sổ cấp cao nhất trên màn hình nền. –

+0

Điều này không đáng tin cậy. 'GetNextWindow' chỉ gọi' GetWindow'. Từ tham chiếu ['GetWindow'] (https://msdn.microsoft.com/en-us/library/ms633515 (v = vs.85) .aspx):" _An ứng dụng gọi GetWindow để thực hiện nhiệm vụ này, nguy cơ bị bắt trong một vòng lặp vô hạn hoặc tham chiếu đến một cửa sổ đã bị phá hủy._ " – zett42

1
  // Find z-order for window. 
      Process[] procs = Process.GetProcessesByName("notepad"); 
      Process top = null; 
      int topz = int.MaxValue; 
      foreach (Process p in procs) 
      { 
       IntPtr handle = p.MainWindowHandle; 
       int z = 0; 
       do 
       { 
        z++; 
        handle = GetWindow(handle, 3); 
       } while(handle != IntPtr.Zero); 

       if (z < topz) 
       { 
        top = p; 
        topz = z; 
       } 
      } 

      if(top != null) 
       Debug.WriteLine(top.MainWindowTitle); 
6

Nice và ngắn gọn:

int GetZOrder(IntPtr hWnd) 
{ 
    var z = 0; 
    for (var h = hWnd; h != IntPtr.Zero; h = GetWindow(h, GW.HWNDPREV)) z++; 
    return z; 
} 

Nếu bạn cần độ tin cậy hơn:

/// <summary> 
/// Gets the z-order for one or more windows atomically with respect to each other. In Windows, smaller z-order is higher. If the window is not top level, the z order is returned as -1. 
/// </summary> 
int[] GetZOrder(params IntPtr[] hWnds) 
{ 
    var z = new int[hWnds.Length]; 
    for (var i = 0; i < hWnds.Length; i++) z[i] = -1; 

    var index = 0; 
    var numRemaining = hWnds.Length; 
    EnumWindows((wnd, param) => 
    { 
     var searchIndex = Array.IndexOf(hWnds, wnd); 
     if (searchIndex != -1) 
     { 
      z[searchIndex] = index; 
      numRemaining--; 
      if (numRemaining == 0) return false; 
     } 
     index++; 
     return true; 
    }, IntPtr.Zero); 

    return z; 
} 

(Theo chú thích phần trên GetWindow, EnumChildWindows an toàn hơn gọi số GetWindow trong vòng lặp vì vòng lặp GetWindow của bạn không phải là nguyên tử đối với các thay đổi bên ngoài. Theo phần Tham số cho EnumChildWindows, gọi với cha mẹ null là tương đương với EnumWindows.)

Sau đó, thay vì một cuộc gọi riêng biệt để EnumWindows cho mỗi cửa sổ, mà cũng sẽ không thể nguyên tử và an toàn từ những thay đổi đồng thời, bạn gửi mỗi cửa sổ bạn muốn so sánh trong một mảng tham số để tất cả các đơn đặt hàng z của chúng đều có thể được truy xuất cùng một lúc.

+1

Không hoạt động, khi so sánh hai cửa sổ chồng lên nhau như một biểu mẫu và thanh tác vụ chẳng hạn. Khi cửa sổ trên thanh tác vụ, thứ tự z của thanh tác vụ cao hơn cửa sổ cho thấy thanh tác vụ ở trên đầu. – Codebeat

+0

Thực ra, tôi đã đổi ý. @Erwinus, [theo Microsoft] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms632599%28v=vs.85%29.aspx#zorder) cửa sổ cấp cao nhất xuất hiện trong z- thứ tự * trước * các cửa sổ khác, ngụ ý rằng số thứ tự z nhỏ hơn có nghĩa là cửa sổ thực sự cao hơn. Cách 'EnumWindows' và' GW_HWNDPREV' và 'GW_HWNDNEXT' làm việc này. Các câu trả lời khác ở đây đồng ý. Tôi không thích làm bộ đếm này với Windows API. – jnm2

+0

@ HansPassant, tôi tôn trọng ý kiến ​​của bạn về vấn đề này. Có bất kỳ gotchas nào khác không? – jnm2

0

Đây là giải pháp C# của tôi: Hàm trả về zIndex trong số các anh chị em của HWND đã cho, bắt đầu từ 0 cho zOrder thấp nhất.

using System; 
using System.Runtime.InteropServices; 

namespace Win32 
{ 
    public static class HwndHelper 
    { 
     [DllImport("user32.dll")] 
     private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); 

     public static bool GetWindowZOrder(IntPtr hwnd, out int zOrder) 
     { 
      const uint GW_HWNDPREV = 3; 
      const uint GW_HWNDLAST = 1; 

      var lowestHwnd = GetWindow(hwnd, GW_HWNDLAST); 

      var z = 0; 
      var hwndTmp = lowestHwnd; 
      while (hwndTmp != IntPtr.Zero) 
      { 
       if (hwnd == hwndTmp) 
       { 
        zOrder = z; 
        return true; 
       } 

       hwndTmp = GetWindow(hwndTmp, GW_HWNDPREV); 
       z++; 
      } 

      zOrder = int.MinValue; 
      return false; 
     } 
    } 
} 
Các vấn đề liên quan