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!
CodePudding user response:
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);
}
CodePudding user response:
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();
}