1. ホーム
  2. c#

[解決済み] MessageBoxを数秒後に閉じる

2023-04-07 11:49:44

質問

WindowsフォームアプリケーションVS2010 C#で、メッセージを表示するためにMessageBoxを表示しています。

OKボタンがありますが、相手が立ち去った場合、タイムアウトして5秒後にメッセージボックスを自動的に閉じたいと思います。

フォームを継承したカスタムメッセージボックスや、レポーターフォームなどがありますが、フォームでなくても面白いかもしれません。

何か提案やサンプルはありますか?

更新しました。

WPF用

C#でメッセージボックスを自動で閉じる

カスタムメッセージボックス (フォーム継承を使用)

http://www.codeproject.com/Articles/17253/A-Custom-Message-Box

http://www.codeproject.com/Articles/327212/Custom-Message-Box-in-VC

http://tutplusplus.blogspot.com.es/2010/07/c-tutorial-create-your-own-custom.html

http://medmondson2011.wordpress.com/2010/04/07/easy-to-use-custom-c-message-box-with-a-configurable-checkbox/

スクロール可能なメッセージボックス

C#でスクロール可能なメッセージボックス

例外報告

https://stackoverflow.com/questions/49224/good-crash-reporting-library-in-c-sharp

http://www.codeproject.com/Articles/6895/A-Reusable-Flexible-Error-Reporting-Framework

解答です。

多分、以下の回答がフォームを使わない良い解決策だと思います。

https://stackoverflow.com/a/14522902/206730

https://stackoverflow.com/a/14522952/206730

どのように解決するのですか?

以下の方法を試してみてください。

AutoClosingMessageBox.Show("Text", "Caption", 1000);

ここで AutoClosingMessageBox クラスは以下のように実装されています。

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);
        using(_timeoutTimer)
            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("#32770", _caption); // lpClassName is #32770 for MessageBox
        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);
}

更新しました。 もし、タイムアウト前にユーザーが何かを選択したときに、基礎となるMessageBoxの戻り値を取得したい場合は、このコードの次のバージョンを使用することができます。

var userResult = AutoClosingMessageBox.Show("Yes or No?", "Caption", 1000, MessageBoxButtons.YesNo);
if(userResult == System.Windows.Forms.DialogResult.Yes) { 
    // do something
}
...
public class AutoClosingMessageBox {
    System.Threading.Timer _timeoutTimer;
    string _caption;
    DialogResult _result;
    DialogResult _timerResult;
    AutoClosingMessageBox(string text, string caption, int timeout, MessageBoxButtons buttons = MessageBoxButtons.OK, DialogResult timerResult = DialogResult.None) {
        _caption = caption;
        _timeoutTimer = new System.Threading.Timer(OnTimerElapsed,
            null, timeout, System.Threading.Timeout.Infinite);
        _timerResult = timerResult;
        using(_timeoutTimer)
            _result = MessageBox.Show(text, caption, buttons);
    }
    public static DialogResult Show(string text, string caption, int timeout, MessageBoxButtons buttons = MessageBoxButtons.OK, DialogResult timerResult = DialogResult.None) {
        return new AutoClosingMessageBox(text, caption, timeout, buttons, timerResult)._result;
    }
    void OnTimerElapsed(object state) {
        IntPtr mbWnd = FindWindow("#32770", _caption); // lpClassName is #32770 for MessageBox
        if(mbWnd != IntPtr.Zero)
            SendMessage(mbWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        _timeoutTimer.Dispose();
        _result = _timerResult;
    }
    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);
}

もう一つの更新

Jackのケースを確認しました。 YesNo ボタンを送信する方法を発見しました。 WM_CLOSE メッセージを送信するアプローチはまったく機能しないことがわかりました。

を提供します。 修正 のコンテキストで、別の AutoclosingMessageBox というライブラリがあります。このライブラリは再設計されたアプローチを含んでおり、誰かの役に立つと信じています。

また、このライブラリは NuGetパッケージ :

Install-Package AutoClosingMessageBox

リリースノート (v1.0.0.2)。

- 新しいShow(IWin32Owner) APIは、最も一般的なシナリオをサポートします( のコンテキストで #1 );

- MessageBoxの表示を完全に制御するための新しいFactory() APIです。