I have been given a application to multi-thread and this has been done. All message boxes in this application are correctly called by a single static
method in a utility class. This method is:
public static void ErrMsg(String strMsg, Exception ex = null)
{
...
if (ex == null)
MessageBox.Show(strMsg, "MyApp", MessageBoxButtons.OK, MessageBoxIcon.Warning);
...
}
Clearly this does not provide the IWin32Window
owner and this is now causing me a problem when I invoke an error message from a background thread-pool thread using this method. The problem is a known one of the message box showing behind my main form. See:
et al. I could pass in the SynchronisationContext
of the current thread to ErrMsg
and do
synchronizationContext.Send(callback =>
MessageBox.Show("Some error message for the user"), null);
But there are 700+ calls to this method, the majority of which are on the UI thread and do not cause a problem. My question is: how can I amend the ErrMsg
method so that my message box appears in front reguardless of the current SynchronisationContex
and without having to ammend all 700+ calls to the method?
Thanks for your time.
Edit. @Dmitry's idea was great. However, if the active form does not have focus or is an MdiChild form then the Form.ActiveForm
will return null. To get around this I use Application.OpenForms.Cast<Form>().Last()
to get the last active form, beit MdiChild or whatever. The code is now...
Form activeForm = Application.OpenForms.Cast<Form>().Last();
if (ex == null)
{
activeForm.Invoke(new ShowErrMsg(text =>
MessageBox.Show(activeForm,
text,
"UserCost",
MessageBoxButtons.OK,
MessageBoxIcon.Warning)),
strMsg);
}
Try to use the Form.ActiveForm static property as a first argument for MessageBox.Show(...). Also the thread-safe invocation should be used.
Example:
private delegate void ShowErrMsgMethod(string text);
public static void ErrMsg(String strMsg, Exception ex = null)
{
...
if (ex == null)
{
Form activeForm = Form.ActiveForm ?? Application.OpenForms.Cast<Form>().Last();
activeForm.Invoke(new ShowErrMsgMethod(text => MessageBox.Show(activeForm, text, "MyApp", MessageBoxButtons.OK, MessageBoxIcon.Warning)), strMsg);
}
...
}
EDIT: Improved for a circumstances when other forms are opened. The reference to main form was eliminated.
EDIT2: Improved for a circumstances when Form.ActiveForm == null
.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments