Thứ Hai, 22 tháng 4, 2019

Đóng MessageBox sau vài giây

Đăng Bởi: Admin - tháng 4 22, 2019 - 0 Bình Luận


Hãy thử cách tiếp cận sau:
AutoClosingMessageBox.Show("Text", "Caption", 1000);
Trường hợp  AutoClosingMessageBox lớp thực hiện như sau:
public class AutoClosingMessageBox {
    System.Threading.Timer _timeoutTimer;
    string _caption;
    AutoClosingMessageBox(string text, string caption, int timeout) {
        _caption = caption;
        _timeoutTimer = new System.Threading.Timer(OnTimerElapsed,
            null, timeout, System.Threading.Timeout.Infinite);
        MessageBox.Show(text, caption);
    }
    public static void Show(string text, string caption, int timeout) {
        new AutoClosingMessageBox(text, caption, timeout);
    }
    void OnTimerElapsed(object state) {
        IntPtr mbWnd = FindWindow(null, _caption);
        if(mbWnd != IntPtr.Zero)
            SendMessage(mbWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        _timeoutTimer.Dispose();
    }
    const int WM_CLOSE = 0x0010;
    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
}


-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------


Bạn có thể thử điều này:
[DllImport("user32.dll", EntryPoint="FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.Dll")]
static extern int PostMessage(IntPtr hWnd, UInt32 msg, int wParam, int lParam);
private const UInt32 WM_CLOSE = 0x0010;
public void ShowAutoClosingMessageBox(string message, string caption)
{
    var timer = new System.Timers.Timer(5000) { AutoReset = false };
    timer.Elapsed += delegate
    {
        IntPtr hWnd = FindWindowByCaption(IntPtr.Zero, caption);
        if (hWnd.ToInt32() != 0) PostMessage(hWnd, WM_CLOSE, 0, 0);
    };
    timer.Enabled = true;
    MessageBox.Show(message, caption);
}


-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------


 
Nếu bạn không nhớ làm rối các tài liệu tham khảo của mình một chút, bạn có thể bao gồm  Microsoft.Visualbasic, và sử dụng cách rất ngắn này.
Hiển thị MessageBox
    (new System.Threading.Thread(CloseIt)).Start();
    MessageBox.Show("HI");
Chức năng CloseIt:
public void CloseIt()
{
    System.Threading.Thread.Sleep(2000);
    Microsoft.VisualBasic.Interaction.AppActivate( 
         System.Diagnostics.Process.GetCurrentProcess().Id);
    System.Windows.Forms.SendKeys.SendWait(" ");
}
Bây giờ đi rửa tay!


-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------


 Phương thức System.Windows.MessageBox.Show () có tình trạng quá tải, lấy một cửa sổ chủ sở hữu làm tham số đầu tiên. Nếu chúng ta tạo một Cửa sổ chủ sở hữu vô hình mà sau đó chúng ta sẽ đóng sau một thời gian xác định, hộp thông báo con cũng sẽ đóng.
Window owner = CreateAutoCloseWindow(dialogTimeout);
MessageBoxResult result = MessageBox.Show(owner, ...
Càng xa càng tốt. Nhưng làm thế nào để chúng ta đóng một cửa sổ nếu luồng UI bị chặn bởi hộp thông báo và các điều khiển UI không thể được truy cập từ một luồng công nhân? Câu trả lời là - bằng cách gửi thông báo cửa sổ WM_CLOSE đến tay cầm cửa sổ chủ sở hữu:
Window CreateAutoCloseWindow(TimeSpan timeout)
{
    Window window = new Window()
    {
        WindowStyle = WindowStyle.None,
        WindowState = System.Windows.WindowState.Maximized,
        Background =  System.Windows.Media.Brushes.Transparent, 
        AllowsTransparency = true,
        ShowInTaskbar = false,
        ShowActivated = true,
        Topmost = true
    };

    window.Show();

    IntPtr handle = new WindowInteropHelper(window).Handle;

    Task.Delay((int)timeout.TotalMilliseconds).ContinueWith(
        t => NativeMethods.SendMessage(handle, 0x10 /*WM_CLOSE*/, IntPtr.Zero, IntPtr.Zero));

    return window;
}
Và đây là cách nhập cho phương thức API SendMessage:
static class NativeMethods
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
}


-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------


Một giải pháp hoạt động trong WinForms:
var w = new Form() { Size = new Size(0, 0) };
Task.Delay(TimeSpan.FromSeconds(10))
    .ContinueWith((t) => w.Close(), TaskScheduler.FromCurrentSynchronizationContext());
MessageBox.Show(w, message, caption);
Dựa trên hiệu ứng đóng biểu mẫu sở hữu hộp thông báo cũng sẽ đóng hộp.
Các điều khiển Windows Forms có một yêu cầu là chúng phải được truy cập trên cùng một luồng đã tạo ra chúng. Việc sử dụng  TaskScheduler.FromCurrentSynchronizationContext() sẽ đảm bảo rằng, giả sử rằng mã ví dụ ở trên được thực thi trên luồng UI hoặc luồng do người dùng tạo. Ví dụ sẽ không hoạt động chính xác nếu mã được thực thi trên một luồng từ nhóm luồng (ví dụ: gọi lại bộ đếm thời gian) hoặc nhóm tác vụ (ví dụ: trên một tác vụ được tạo bằng  TaskFactory.StartNew hoặc  Task.Run với các tham số mặc định).

Phản Hồi Độc Giả

Một số lưu ý khi bình luận

Mọi bình luận sai nội quy sẽ bị xóa mà không cần báo trước (xem nội quy)

Bấm Thông báo cho tôi bên dưới khung bình luận để nhận thông báo khi admin trả lời

Để bình luận một đoạn code, hãy mã hóa code trước nhé