QA@IT

MessageBoxのハンドラ

6415 PV

不定のタイミングでMessageBoxの表示を中断したのですが、

IWin32Window、NaveWindowの辺りを調べても
その方法がわかりませんでした。

NaveWindowのクラスにReleaseHandlerメソッドやDestroyHandlerメソッドがあるので
コノメソッドをうまく使えばメッセージを終了できるのではないかと思うのですがいかがでしょうか。

わかる方がいらっしゃれば教えていただければ幸いです。
それでは失礼します。

回答

環境も不明ですし「不定のタイミング」というのがイマイチどういうことかわかりませんが…

仮に MessageBox を表示して一定時間経過後に自動的に閉じたい、ということであれば
以下のような感じでいかがでしょう。
(Visual Studio 2012 Pro & .Net Framework 4.0 で確認。)

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll")]
        static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); 

        const int WM_CLOSE = 0x10;


        private string caption = "テスト";
        private int limit = 5000; // msec.

        public Form1()
        {
            InitializeComponent();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            using (var timer = new System.Threading.Timer(s =>
            {
                var hWnd = FindWindow(null, this.caption);
                if (hWnd != IntPtr.Zero)
                {
                    SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
                }
            }, null, this.limit, Timeout.Infinite))

            MessageBox.Show(this, "メッセージ", this.caption);
        }
    }
}

キャプションを指定してメッセージボックスを表示するその直前にタイマーを作成して、
limit だけ(例では5秒)時間が経過した際に指定したキャプションのウィンドウがあればそれを閉じる。

ご覧のとおり、Win32 API を使用しています。
ご提示の NativeWindow に関しては、私はわかりません。

2013/07/10 追記

正直、MessageBox 風のダイアログウィンドウを自作してしまったほうがいいのではないかとも思いますが、
まぁそれぞれ事情はあろうかと思いますので…

MessageBoxButtons.YesNo などのケースでメッセージボックスが閉じないとのことですが、
WM_CLOSE の代わりに

        const int WM_NCDESTROY = 0x0082;

を送りつけるとどうでしょうか。

私自身ウィンドウメッセージ等に関して精通しているわけではないので(^_^;)
副作用等が生じないことは保証できませんが…

編集 履歴 (2)
  • ありがとうございます。
    なるほど、Win32APIにこんな処理があるのですね。
    いただいたソースを改造すればいけそうです
    回答ありがとうございました。
    -
  • すみません。追加でお聞きしたいのですが、
    MessageBoxでButtonsType.YesNoなどにした場合
    上記の方法では消えないのですがどうすればよろしいでしょうか。
    どなたかわかる方がいらっしゃればおしえてください。

    環境は C# 2010です
    -
  • 一番手っ取り早いのはYesNoCancelにすることです。 -
  • YesNo などで閉じない件について追記しました。ご確認いただければ幸いです。 -
  • flied_onionさんの方法で試してみました。ありがとうございます。
    yitoさんのほうも後日確認します。
    それにしても、どうしてボタンの数が変わることによって
    メッセージで閉じる方法が変わってしまうのでしょうか。
    -
  • YesNoはユーザーに必ず回答を求めていて(YesかNoかどちらか欲しい)閉じれるとどっちだか判断できないから閉じさせない、Cancelがあるというのはユーザーが「回答しない->回答するのキャンセル」というのを許容するというスタンスなので「閉じる=回答をキャンセルした」とできるので閉じれる。と思ってます。OKCancelも閉じることができます。そして戻り値もDialogResult.Cancel。 -
  • ちなみにボタン指定しない(OKボタンしかない)状態で閉じるとDialogResult.Cancelじゃないです。 -
  • なるほどなるほど。
    皆様ありがとうございます。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。