Спробуйте наступний підхід:
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);
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) {
}
...
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);
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):
- API нового шоу (IWin32Owner) для підтримки найбільш популярних сценаріїв (у контексті №1 );
- Новий API Factory () для забезпечення повного контролю над показом MessageBox;