2014-02-04 6 views
1

Я кодирования Windows Forms в C# под Visual Studio 2012, и я хотел бы открыть несколько экземпляров MessageBox и автоматически закрывать их через несколько секунд.Открытие нескольких экземпляров MessageBox и закрываются автоматически через несколько секунд

Я нашел (и поддержал) этот ответ здесь: SO: Close a MessageBox after several seconds.

Однако это работает, если я открываю только 1 (один) MessageBox за раз, так как он использует функцию FindWindow, а несколько экземпляров моего MessageBox должны иметь одинаковый заголовок окна (подпись).

[Необязательно] Кроме того, я хотел бы представить пользователю обратный отсчет, как Это диалоговое окно закроется через 5 секунд, Это [...] за 4 секунды, Это [. ..] через 3 секунды, ..., Это [...] за 1 секунду, а затем, наконец, закрыть MessageBox.

Есть ли способ, чтобы однозначно ссылаться на мои многократные MessageBoxes и автоматически закрывать их (либо с помощью System.Timers.Timer или System.Threading.Timer или System.Windows.Forms.Timer - в зависимости от того лучше всего подходит для этого решения) по истечению определенного периода времени (скажем, 5 секунд)?

+0

Вы уверены, что текстовые сообщения являются правильным решением здесь? Похоже, вы пытаетесь повторно внедрить уведомления. –

+0

Привет @Damien_The_Unbeliever, я подумал и просмотрел уведомления, но в моем случае мне действительно нужны сообщения ... (: – Sebastian

ответ

3

Предлагаю не использовать MessageBox для этой задачи. Вместо этого создайте свою собственную форму. Сделайте его размером, формой и желанием выглядеть. Затем, в своем файле кода, вы можете создать таймер, уникальный для этого самого окна. Таким образом, вы можете создать столько из них, сколько захотите, и они будут управлять своими таймерами и закрываться, и вам не нужно ничего делать, как найти окно. Можно сделать форму очень похожей на MessageBox. И поскольку вы можете вызвать ShowDialog, вы можете заставить их вести себя аналогично MessageBoxes (хотя это будет несколько контрпродуктивно, потому что вы можете взаимодействовать только с одним диалогом за раз).

+0

Привет @Curtis Rutland благодарит вас за ваши мысли и идею имитации MessageBox с помощью пользовательской формы. Я определенно исследую эту идею дальше! – Sebastian

+1

Я принял этот ответ, потому что это действительно сложно реализовать (с помощью счетчика, а также с моим дополнительным требованием отображать/подсчитывать время в секундах). Еще раз спасибо @Curtis Rutland! – Sebastian

+1

Рад помочь. Я нахожу это чаще, чем нет, вторая перспектива дает вам простые решения, о которых вы иначе не подумали бы, особенно когда вы идете вниз по кроличьей дыре в другом направлении. –

1

В окнах есть недокументированная функция MessageBoxTimeout: MessageBoxTimeout в user32.dll (используйте с помощью PInvoke).

Пример:

public class MessageBoxWithTimeout 
{ 
    [DllImport("user32.dll", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.U4)] 
    private static extern uint MessageBoxTimeout(IntPtr hwnd, 
    [MarshalAs(UnmanagedType.LPTStr)] String text, 
    [MarshalAs(UnmanagedType.LPTStr)] String title, 
    [MarshalAs(UnmanagedType.U4)] uint type, 
    Int16 wLanguageId, 
    Int32 milliseconds); 

    public static uint Show(IntPtr hWnd, string message, string caption, uint messageBoxOptions,Int32 timeOutMilliSeconds) 
    { 
    return MessageBoxTimeout(hWnd, message, caption, messageBoxOptions, 0, timeOutMilliSeconds); 
    } 
} 

В коде:

MessageBoxWithTimeout.Show(your parameters here); 

Однако, вы должны думать о вашем дизайне. По умолчанию окно сообщения блокирует ваш диалог, поэтому несколько сообщений не имеют смысла. Если вы публикуете свою актуальную проблему, возможно, есть лучшее решение.

+0

Здравствуйте, @nvoigt, спасибо вам за ответ и пример кода. Мои приложения имеют два режима работы: 1) пользователь активно вводит данные в форму, а 2) приложения запускаются автоматически (отслеживает папку для изменений). В обоих режимах мне нужно показать диалог (MessageBox). Когда приложение находится в режиме 1), пользователь должен подтвердить, чтобы продолжить. Когда в режиме 2), диалог должен закрыться через 5 секунд автоматически. Следовательно, я доволен тем, что MessageBox блокирует мой диалог (это требуется), все остальные задачи выполняются в фоновом режиме с помощью Threads ... Я обязательно буду играть с вашим фрагментом кода (: – Sebastian

1

Следующий код может использоваться как отправная точка. Он основан на недавно опубликованном related answer.

async void MainForm_Load(object sender, EventArgs e) 
{ 
    Func<Func<Form>, Task<Form>> showAsync = (createForm) => 
    { 
     var tcs = new TaskCompletionSource<Form>(); 
     var form = createForm(); 
     form.Tag = Task.Factory.StartNew(
      () => form.ShowDialog(), 
      CancellationToken.None, 
      TaskCreationOptions.None, 
      TaskScheduler.FromCurrentSynchronizationContext()); 
     form.Load += (sIgnore, eIgnore) => 
      tcs.TrySetResult(form); 
     return tcs.Task; 
    }; 

    var forms = new Stack<Form>(); 
    for (var i = 0; i < 4; i++) 
     forms.Push(await showAsync((() => 
      new Form { Text = "Hello #" + i }))); 

    var closeFormTasks = forms.Select((form) => (Task)form.Tag); 

    var delay = Task.Delay(5000); 
    var task = await Task.WhenAny(delay, Task.WhenAll(closeFormTasks)); 

    if (task == delay) 
    { 
     while (forms.Any()) 
     { 
      var form = forms.Pop(); 
      form.Close(); 
      await (Task)form.Tag; 
     } 
    } 

    MessageBox.Show("All closed."); 
} 
+1

Привет @Noseratio, большое спасибо для обмена этим куском кода! Мне очень нравится эта концепция. Однако я пойду с решением, которое Куртис Ратленд предложил (имитируя MessageBoxes с простыми старыми формами). – Sebastian

Смежные вопросы