0

I've got stuck with automatical closing of the MessageBox after expiration of the timer. I use static variable of type Timer(not System.Windows.Forms.Timer) which is defined in the special class(definition of the class is not static).

Timer is calling with the help of the reference to name of the class because of static keyword. My class where this timer defined as static called Helper. So the calling I produce using next code

Helper.timer.Interval = 300000;
Helper.timer.Enable = true;

timer is the name of this variable

The task is to handle time when the MessageBox appeared and after the time expiry, close this MessageBox automatically if none of the buttons inside it weren't clicked. Is it possible to do this operation without using and defining AutoClosingMessageBox class like I've seen in the simular questions?

I've got tried some of methods including checking whether user clicked some of the buttons of MessageBox but it didn't give me a required result.

I would be grateful if someone could show me the realization :) If it's required I can fill up the question with the code template of my whole project. This all I need to create on the C# programming language.

Thanks in advance!

  • But you still need to use something of the solution presented there. That incorporates using a threaded timer. Your main thread is hanging in the messagebox code and does nothing while the messagebox is shown and you need something like the SendMessage WindowsAPI to send a close message to the messagebox. Alternatively just don't use the winforms messagebox and create a dialog looking exactly like a messagebox but isn't. – Ralf Nov 24 '22 at 21:04
  • Agreed. Creating a Form that looks like a MessageBox is the way to go. Then the code to close said Form will all be contained within that Form, nice and clean. The amount of work you'd need to do to close a "normal" MessageBox is not worth the time and effort... – Idle_Mind Nov 25 '22 at 01:19

2 Answers2

1

One approach that has worked for me is to create a temporary (invisible) window to host the MessageBox. This temporary window is passed as the owner argument to the Show method. When the owner Form is disposed after awaiting the Task.Delay then the message box should dispose also.

public MainForm()
{
    InitializeComponent();
    buttonHelp.Click += onHelp;
}

private async void onHelp(object sender, EventArgs e)
{
    var owner = new Form { Visible = false };
    // Force the creation of the window handle.
    // Otherwise the BeginInvoke will not work.
    var handle = owner.Handle;
    owner.BeginInvoke((MethodInvoker)delegate 
    {
        MessageBox.Show(owner, text: "Help message", "Timed Message");
    });
    await Task.Delay(TimeSpan.FromSeconds(2));
    owner.Dispose();
}
IVSoftware
  • 5,732
  • 2
  • 12
  • 23
0

Would this link help you?

This link imports and implements "User32.dll" for automatic closing of message boxes. User32.dll is a library that provides functions for controlling items such as windows or menus in the OS.

If the time is exceeded, you can obtain the handle of the message box through "FindWindow" and then close the message box through "SendMessage".

I wrote a simple example program referring to the contents of the link.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private Timer CloseTimer { get; } = new Timer();
    private string Caption { get; set; }

    private void Form1_Load(object sender, EventArgs e)
    {
        CloseTimer.Tick += CloseTimerOnTick;
        CloseTimer.Interval = 100;
    }

    private void CloseTimerOnTick(object sender, EventArgs e)
    {
        // find window
        var mbWnd = FindWindow("#32770", Caption);
        // check window
        if (mbWnd == IntPtr.Zero)
        {
            // stop timer
            CloseTimer.Enabled = false;
        }
        else
        {
            // check timeout
            if ((DateTime.Now - Time).TotalMilliseconds < Timeout)
                return;
            // close
            SendMessage(mbWnd, 0x0010, IntPtr.Zero, IntPtr.Zero);
            // stop timer
            CloseTimer.Enabled = false;
        }
    }

    private void btMessage_Click(object sender, EventArgs e)
    {
        Show(@"Caption", @"Auto close message", 3000);
    }

    private void Show(string caption, string message, int timeout)
    {
        // start
        CloseTimer.Enabled = true;
        // set timeout
        Timeout = timeout;
        // set time
        Time = DateTime.Now;
        // set caption
        Caption = caption;
        // show 
        MessageBox.Show(message, Caption);
    }

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
}
eloiz
  • 81
  • 9
  • Have you tried with a MessageBox configured with, e.g., `MessageBoxButtons.YesNo`? Sending `WM_CLOSE` won't do much, I think... – Jimi Nov 25 '22 at 01:56
  • @eloiz Sorry but your code is not working. I will show the realization of my code to build a clear picture of the problem – NULL_PTR_T Nov 25 '22 at 13:39