2013-04-19 19 views
33

Gần đây tôi phát hiện ra rằng theo mặc định MessageBoxes không phải là hình thức hàng đầu nhất khi được hiển thị theo mặc định và tôi đã tự hỏi liệu có ai biết bất kỳ trường hợp nào khi bạn không muốn hộp thư hiển thị trên các cửa sổ khác không?Tại sao MessageBox không thuộc TopMost?

Tôi đã tìm thấy sự cố khi tôi bắt đầu hiển thị màn hình giật trong khi tải ứng dụng và có vẻ như chương trình của tôi vẫn đang chạy nhưng có một MessageBox phía sau màn hình splash đang chờ nhập. trên một chủ đề khác với chuỗi được gọi là hộp thư vì vậy tôi cho rằng đây là lý do tại sao nó không xuất hiện phía trên vùng giật gân; nhưng điều này vẫn không giải thích tại sao MessageBox không có cờ MB_TOPMOST theo mặc định?

Sửa

Để làm rõ hơn: cuối cùng tôi đã phải làm một cái gì đó tương tự như sau cuối cùng để thực hiện một bảng thông báo, mã không chính xác đúng như đã viết từ bộ nhớ)

[DllImport("User32.dll")] 
private int extern MessageBox(windowhandle, message, caption, flag); 
public static void MessageBox(windowhandle, string message, string caption) 
{ 
    MessageBox(windowhandle, message,caption, MB_TOPMOST); 
} 

Trả lời

22

Để hiển thị MessageBox trên đỉnh-nhất của tất cả các ứng dụng

//Should be MessageBox.Show() below 
MessageBox.Show(this, "My top most message"); 

Lý do vì không MB_TOPMOST theo mặc định

Nếu MB_TOPMOST sẽ mặc định thì MessageBox sẽ hiển thị ở chế độ 'chế độ hệ thống' và chế độ đó là wi sẽ chính xác ở trên trên biểu mẫu đó và các tác dụng phụ là chế độ 'hệ thống kiểu' sẽ gây ra MessageBox đến Chặn các cửa sổ cho đến khi thông báo bị loại bỏ bình thường, nó sẽ là chế độ 'ứng dụng phương thức'.

liên kết tham khảo

  1. MSDN forum - How to display a MessageBox as topmost window
  2. SO - C# MessageBox To Front When App is Minimized To Tray
+1

Câu trả lời này sẽ rất tuyệt! nhưng tôi nghĩ rằng hộp thư bị chặn các cửa sổ không? – Sayse

+0

Từ [diễn đàn msdn được đề cập trong câu trả lời] (http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/7a515f66-8818-4ec5-9213-7ee479f8fb18/) Tôi thấy rằng có một cái gì đó như 'hệ thống phương thức' và' phương thức ứng dụng'. Có thể tôi sẽ kiểm tra để biết thêm chi tiết về sau này .. –

+0

Chỉ các hộp thông báo dạng thức bock các biểu mẫu của chúng, biểu mẫu 'thông thường' có thể vẫn tồn tại ngay cả sau khi bạn thoát khỏi chương trình đã sinh ra nó. – Tory

2

Khi hiển thị MessageBox, hãy cung cấp chủ sở hữu làm đối số đầu tiên. Ví dụ khi gọi từ một cuộc gọi Form dụ:

MessageBox.Show(this, "Message"); 

Cung cấp một tham chiếu đến cửa sổ sở hữu nó như là đối số đầu tiên.

Hộp thư (và các dạng thức nói chung) làm không xuất hiện trên đầu tất cả các cửa sổ của ứng dụng của bạn. Chúng chỉ xuất hiện ở đầu chủ sở hữu của chúng. Nếu bạn muốn hộp thư của bạn (hoặc các hình thức khác) ở trên cùng của màn hình giật gân, hãy đặt chủ sở hữu của họ thành cá thể dạng giật gân.

+0

Tôi không hiểu câu trả lời của bạn .. sẽ như thế nào đây đảm bảo một hộp thông báo luôn ở trên tất cả các cửa sổ khác? hoặc điều này đạt được điều gì? – Sayse

+0

Nó sẽ không. Nó sẽ luôn luôn được trên đầu trang của chủ sở hữu của nó chỉ. Nếu bạn muốn nó xuất hiện trên đầu màn hình giật gân, hãy đặt chủ sở hữu của nó thành cá thể màn hình giật gân. –

52

Các giải pháp đề xuất làm việc nếu bạn có thể nhận được một xử lý hoặc tham chiếu đến cửa sổ hộp thoại được cho là xuất hiện trên đầu trang của.Tuy nhiên, điều này có thể không phải lúc nào có thể hoặc dễ dàng để đạt được:

  • cửa sổ là một màn hình giật gân và không nên kết hợp chặt chẽ với logic kinh doanh của bạn
  • cửa sổ được tạo ra bởi một lớp hoặc thư viện hơn so với hiện tại
  • cửa sổ là ngoài tầm kiểm soát của bạn, tức là từ một bên thứ ba (mẹ đẻ) thư viện

trong tình huống như vậy, bạn có thể sử dụng API Win232 MessageBox từ User32.dll, nhưng một si mpler, giải pháp quản lý cũng có sẵn:

MessageBox.Show(new Form { TopMost = true }, "Hello, I'm on top!"); 

new Form { TopMost = true } sẽ tạo ra một biểu mẫu ẩn với MB_TOPMOST tài sản, được thừa hưởng bởi các cửa sổ hộp thoại MessageBox. Kết quả là, nó sẽ xuất hiện trên đầu trang của tất cả các cửa sổ khác của bạn. Sử dụng new Form() nội tuyến không có tác dụng phụ, không có ngoại hình trực quan và nó sẽ bị phá hủy bình thường thông qua bộ thu gom rác.

Lưu ý: nếu bạn không ở trong một biểu mẫu, đừng quên không gian tên, đây là System.Windows.Forms.MessageBox, không phải System.Windows.MessageBox! (cảm ơn, user1).

+1

Cách tiếp cận thú vị, câu trả lời đã chọn được thực hiện vì sự khác biệt giữa phương thức ứng dụng và phương thức hệ thống. Cách tiếp cận của bạn tôi giả định sẽ vẫn giữ cho các ứng dụng hộp thư phương thức và sẽ hữu ích trong các trường hợp bạn đã vạch ra.+1 – Sayse

+0

@Sayse: thực sự, nó giữ phương thức ứng dụng hộp thư. Chúng tôi sử dụng nó rất nhiều trong các phương thức thư viện logic nghiệp vụ được phép mở một hộp thư, nhưng nó chỉ là cồng kềnh để luôn phải chuyển biểu mẫu hiện tại làm tham số. – Abel

+4

Chỉ cần làm rõ cho những người khác đây là 'System.Windows.Forms.MessageBox' không phải' System.Windows.MessageBox' – user1

0

Câu trả lời được đưa ra ở trên rõ ràng là chính xác trừ đi thực tế là nó cần gọi System.iDisposable.Dispose trên đối tượng Biểu mẫu mới.

MessageBoxButtons buttons = MessageBoxButtons.YesNo; 
MessageBoxIcon icon = MessageBoxIcon.Error; 
string message = Resources.ResourceManager.GetString("MESSAGE"); 
string caption = Resources.ResourceManager.GetString("TITLE"); 
DialogResult result; 
Form form; 
using (form = new Form()) 
{ 
    form.TopMost = true; 
    result = MessageBox.Show(form, caption, message, buttons, icon); 
} 
if (result == DialogResult.Yes) 
{ 
    // do something with the result 
} 

Để biết thêm:

Top-Most-MessageBox Examples

1

tôi cố gắng để dán một miếng mã hoàn chỉnh hơn, nó chắc chắn làm việc

[CLSCompliant(false)] 
    [DllImport("user32.dll", EntryPoint = "MessageBox")] 
    public static extern int MessageBoxUser32(int hWnd, String text, String caption, uint type); 

    const uint MB_TOPMOST = 0x00040000; 
    const uint MB_OK = 0x00000000; 
    const uint MB_OKCANCEL = 0x00000001; 
    const uint MB_ABORTRETRYIGNORE = 0x00000002; 
    const uint MB_YESNOCANCEL = 0x00000003; 
    const uint MB_YESNO = 0x00000004; 
    const uint MB_RETRYCANCEL = 0x00000005; 

    public static void ShowMessageBox(string message, bool topMost = true 
     , string title = null, MessageBoxButtons buttons = MessageBoxButtons.OK) 
    { 
     if(topMost) 
     { 
      uint mbv = MB_TOPMOST; 

      if (buttons == MessageBoxButtons.OK) 
       mbv |= MB_OK; 
      if (buttons == MessageBoxButtons.OKCancel) 
       mbv |= MB_OKCANCEL; 
      if (buttons == MessageBoxButtons.AbortRetryIgnore) 
       mbv |= MB_ABORTRETRYIGNORE; 
      if (buttons == MessageBoxButtons.YesNoCancel) 
       mbv |= MB_YESNOCANCEL; 
      if (buttons == MessageBoxButtons.YesNo) 
       mbv |= MB_YESNO; 
      if (buttons == MessageBoxButtons.RetryCancel) 
       mbv |= MB_RETRYCANCEL; 

      MessageBoxUser32(0, message, title == null ? string.Empty : title, MB_TOPMOST); 
     } 
     else 
     { 
      MessageBox.Show(message, title == null ? string.Empty : title, buttons); 
     } 
    }