2009-06-16 37 views
8

Tôi có một ứng dụng WinForm có các biểu mẫu con khác (không phải là mdi). Nếu người dùng nhấn "Esc", biểu mẫu trên cùng phải được đóng ngay cả khi nó không có tiêu điểm.Làm thế nào để có được xử lý của các hình thức trên cùng trong một ứng dụng WinForm?

Tôi có thể sử dụng móc nối bàn phím để nắm bắt Escape trên toàn cầu nhưng tôi cũng cần xử lý biểu mẫu sẽ bị đóng.

Tôi đoán có một cách để làm điều đó bằng cách sử dụng Win32 API, nhưng có một giải pháp sử dụng mã được quản lý không?

Trả lời

7

Dưới đây là một cách để lấy mẫu đơn trên cùng có sử dụng Win32 (không phải là rất tao nhã, nhưng nó hoạt động):

public const int GW_HWNDNEXT = 2; // The next window is below the specified window 
public const int GW_HWNDPREV = 3; // The previous window is above 

[DllImport("user32.dll")] 
static extern IntPtr GetTopWindow(IntPtr hWnd); 

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool IsWindowVisible(IntPtr hWnd); 

[DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetWindow", SetLastError = true)] 
public static extern IntPtr GetNextWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.U4)] int wFlag); 

/// <summary> 
/// Searches for the topmost visible form of your app in all the forms opened in the current Windows session. 
/// </summary> 
/// <param name="hWnd_mainFrm">Handle of the main form</param> 
/// <returns>The Form that is currently TopMost, or null</returns> 
public static Form GetTopMostWindow(IntPtr hWnd_mainFrm) 
{ 
    Form frm = null; 

    IntPtr hwnd = GetTopWindow((IntPtr)null); 
    if (hwnd != IntPtr.Zero) 
    { 
     while ((!IsWindowVisible(hwnd) || frm == null) && hwnd != hWnd_mainFrm) 
     { 
      // Get next window under the current handler 
      hwnd = GetNextWindow(hwnd, GW_HWNDNEXT); 

      try 
      { 
       frm = (Form)Form.FromHandle(hwnd); 
      } 
      catch 
      { 
       // Weird behaviour: In some cases, trying to cast to a Form a handle of an object 
       // that isn't a form will just return null. In other cases, will throw an exception. 
      } 
     } 
    } 

    return frm; 
} 
1

FormCollection được sử dụng bởi các đối tượng ứng dụng để liệt kê các hình thức hiện đang mở trong một ứng dụng thông qua thuộc tính OpenForms

Xem http://msdn.microsoft.com/en-us/library/system.windows.forms.application.openforms.aspx

Sau đó, bạn có thể kiểm tra trên cùng() tài sản của mỗi hình thức. Và khi bạn tìm thấy một hình thức trên cùng, bạn đóng nó lại.

+2

Bất hạnh thuộc tính Form.TopMost nhận hoặc đặt giá trị cho biết biểu mẫu có được hiển thị dưới dạng trên cùng không. Điều này không cho tôi biết nếu biểu mẫu đứng đầu nhiều nhất. – tzup

1

Bạn có thể triển khai mẫu giống như đơn ở dạng trên cùng và cung cấp thuộc tính tĩnh trả về một thể hiện của chính nó và chỉ cần đóng nó.

public class MainForm : Form 
    { 
     private static MainForm mainForm; 

     public static MainForm { get { return mainForm; } } 

     public MainForm() 
     { 
     mainForm = this; 
     } 
    } 


    // When the ESC key is pressed... 
    MainForm.MainForm.Close(); 
+0

Tôi nghĩ rằng bạn hiểu nhầm câu hỏi. Hãy tưởng tượng một ứng dụng WinForm với một hình thức chính được tối đa hóa và nhiều hình thức nhỏ hơn khác xếp chồng lên trên biểu mẫu chính. Mỗi lần bạn nhấn Esc hình thức trên cùng sẽ đóng lại (hãy nhớ rằng nó có thể không có tiêu điểm). Hy vọng điều này làm cho mọi thứ rõ ràng hơn. – tzup

+0

Tôi nghĩ rằng bạn có thể đã hiểu lầm phản ứng của mình. Chỉ có một MainForm mở tại một thời điểm, phải không? Mẫu đơn này trình bày một núm điều khiển tĩnh cho biểu mẫu từ bất kỳ đâu trong ứng dụng, kể cả móc nối bàn phím của bạn. –

+0

@Zachary Yates, yêu cầu là có thể đóng các biểu mẫu con, chứ không phải hình thức chính. – tzup

3

Làm thế nào về vấn đề này bằng Application.Openforms

Form GetTopMostForm() 
{ 
    return Application.OpenForms 
     .Cast<Form>() 
     .First(x => x.Focused); 
} 
+0

Yêu cầu là đóng biểu mẫu ở trên cùng, có thể không có tiêu điểm. – tzup

2

tôi biết đây là một 4 năm cũ thread, nhưng tôi đã có một vấn đề tương tự và chỉ đưa ra một giải pháp thay thế chỉ trong trường hợp bất cứ ai khác stumbles về câu hỏi này và không muốn mess xung quanh với các cuộc gọi Win32.

Tôi giả định hình thức cao nhất sẽ là biểu mẫu được kích hoạt lần cuối. Vì vậy, bạn có thể giữ một bộ sưu tập riêng biệt của các hình thức, tương tự như Application.OpenForms, ngoại trừ bộ sưu tập này sẽ được đặt hàng khi mỗi lần được kích hoạt lần cuối. Bất cứ khi nào một biểu mẫu được kích hoạt, hãy di chuyển nó đến mục đầu tiên của bộ sưu tập. Bất cứ khi nào bạn nhìn thấy phím ESC, bạn sẽ đóng bộ sưu tập [0] và xóa nó.

+2

Hoặc sử dụng một ngăn xếp, nó tự nhiên hơn một bộ sưu tập cho điều này –

Các vấn đề liên quan