Activating a message box in .NET

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I have a .NET 2.0 form that parents a message box. Neither is currently
active. How can I programatically activate the message box? I can't seem to
do it via the .NET Framework, since message boxes aren't .NET forms, so I've
tried doing it via the Win32 API, but still no luck. Here's what I've tried
so far:

// First activate the parent form
parentForm.Activate();

// Now attempt to activate the message box itself
const int GW_CHILD = 5;
const int WM_ACTIVATE = 6;
const int WA_INACTIVE = 0;
const int WA_ACTIVE = 1;

int hwndParent = (int)parentForm.Handle;
int hwndMsgBox = GetWindow(hwndParent, GW_CHILD);

if (hwndMsgBox != 0)
{
SendMessage(hwndMsgBox, WM_ACTIVATE, WA_ACTIVE, hwndMsgBox);
SendMessage(hwndParent, WM_ACTIVATE, WA_INACTIVE, hwndMsgBox);
}

Regards,

Marcus Ogden
Software Development
QSR International Pty Ltd
 
Here is the way I display a custom Logon Dialog. It could be easily
modified to display a custom message box. The usage is:

//-------------------------------------
public bool GetLogonCredentials()
{
bool retVal = false;
DialogResult logon = frmLogon.ShowLogonDialog();
if (logon == DialogResult.OK)
{
this.logonName = frmLogon.userName;
this.password = frmLogon.password;
retVal = true;
}
return retVal;
}

//The CLASS is as follows:
//--------------------------------------

public partial class frmLogon : Form
{
public static string userName = string.Empty;
public static string password = string.Empty;

/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed;
otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && ( components != null ))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new
System.ComponentModel.ComponentResourceManager(typeof(frmLogon));
this.btnLogon = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.txtUserName = new System.Windows.Forms.TextBox();
this.txtPassword = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.btnCancel = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnLogon
//
this.btnLogon.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btnLogon.Location = new System.Drawing.Point(205, 58);
this.btnLogon.Name = "btnLogon";
this.btnLogon.Size = new System.Drawing.Size(75, 23);
this.btnLogon.TabIndex = 4;
this.btnLogon.Text = "Logon";
this.btnLogon.UseVisualStyleBackColor = true;
this.btnLogon.Click += new System.EventHandler(this.btnLogon_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(2, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(71, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Logon Name:";
//
// txtUserName
//
this.txtUserName.Location = new System.Drawing.Point(70, 6);
this.txtUserName.Name = "txtUserName";
this.txtUserName.Size = new System.Drawing.Size(210, 20);
this.txtUserName.TabIndex = 1;
//
// txtPassword
//
this.txtPassword.Location = new System.Drawing.Point(70, 32);
this.txtPassword.Name = "txtPassword";
this.txtPassword.PasswordChar = '*';
this.txtPassword.Size = new System.Drawing.Size(210, 20);
this.txtPassword.TabIndex = 3;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(17, 35);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(56, 13);
this.label2.TabIndex = 2;
this.label2.Text = "Password:";
//
// btnCancel
//
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(124, 58);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 5;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// frmLogon
//
this.AcceptButton = this.btnLogon;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(283, 86);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.txtPassword);
this.Controls.Add(this.label2);
this.Controls.Add(this.txtUserName);
this.Controls.Add(this.label1);
this.Controls.Add(this.btnLogon);
this.Icon = ( (System.Drawing.Icon)( resources.GetObject("$this.Icon") ) );
this.Name = "frmLogon";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Logon";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button btnLogon;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtUserName;
private System.Windows.Forms.TextBox txtPassword;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button btnCancel;

public frmLogon()
{
InitializeComponent();
}
private void btnLogon_Click(object sender, EventArgs e)
{
userName = txtUserName.Text;
password = txtPassword.Text;
this.Close();
}


public static DialogResult ShowLogonDialog()
{
frmLogon formLogon = new frmLogon();
DialogResult result = formLogon.ShowDialog();
return result;
}
public static DialogResult ShowLogonDialog(IWin32Window owner)
{
frmLogon formLogon = new frmLogon();
DialogResult result = formLogon.ShowDialog(owner);
return result;
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
}
 
Marcus,
Yes, windows form has no methods for activating window that is not a form or
a form from different application. To do that you need to go for PInvoke and
win32 API..

The only thing that I could suggest is changing the API that you use. Insted
of sending messages you can use API methods. Also I'd change the way handle
to the message box is taken.

Look at the following example (only the imports of both API and the last 2
lines are essential; the rest is obtaining hwnd to the main form, which can
be done differently depending on the current case):

[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);

[DllImport("user32.dll")]
private static extern IntPtr GetLastActivePopup(IntPtr hWnd);


private void button1_Click(object sender, System.EventArgs e)
{

// !!!!NOTE: The following 2 lines are code that I used in my test app to
get the
// The handle to the main of another application. Your case maight be
different.
Process p = Process.GetProcessesByName("WindowsApplication1")[0];
IntPtr targetHwnd = p.MainWindowHandle;

// I assume that you have handle to the main form. It might be not taken
in the
// same way I do.

// This is gets the hwnd of the message box if any.
targetHwnd = GetLastActivePopup(targetHwnd);
// Activates the window.
SetForegroundWindow(targetHwnd);



}
 
Thanks Stoitcho! That's exactly what I need.

Regards,

Marcus Ogden

Stoitcho Goutsev (100) said:
Marcus,
Yes, windows form has no methods for activating window that is not a form or
a form from different application. To do that you need to go for PInvoke and
win32 API..

The only thing that I could suggest is changing the API that you use. Insted
of sending messages you can use API methods. Also I'd change the way handle
to the message box is taken.

Look at the following example (only the imports of both API and the last 2
lines are essential; the rest is obtaining hwnd to the main form, which can
be done differently depending on the current case):

[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);

[DllImport("user32.dll")]
private static extern IntPtr GetLastActivePopup(IntPtr hWnd);


private void button1_Click(object sender, System.EventArgs e)
{

// !!!!NOTE: The following 2 lines are code that I used in my test app to
get the
// The handle to the main of another application. Your case maight be
different.
Process p = Process.GetProcessesByName("WindowsApplication1")[0];
IntPtr targetHwnd = p.MainWindowHandle;

// I assume that you have handle to the main form. It might be not taken
in the
// same way I do.

// This is gets the hwnd of the message box if any.
targetHwnd = GetLastActivePopup(targetHwnd);
// Activates the window.
SetForegroundWindow(targetHwnd);



}


--

Stoitcho Goutsev (100)

Marcus Ogden said:
I have a .NET 2.0 form that parents a message box. Neither is currently
active. How can I programatically activate the message box? I can't seem
to
do it via the .NET Framework, since message boxes aren't .NET forms, so
I've
tried doing it via the Win32 API, but still no luck. Here's what I've
tried
so far:

// First activate the parent form
parentForm.Activate();

// Now attempt to activate the message box itself
const int GW_CHILD = 5;
const int WM_ACTIVATE = 6;
const int WA_INACTIVE = 0;
const int WA_ACTIVE = 1;

int hwndParent = (int)parentForm.Handle;
int hwndMsgBox = GetWindow(hwndParent, GW_CHILD);

if (hwndMsgBox != 0)
{
SendMessage(hwndMsgBox, WM_ACTIVATE, WA_ACTIVE, hwndMsgBox);
SendMessage(hwndParent, WM_ACTIVATE, WA_INACTIVE, hwndMsgBox);
}

Regards,

Marcus Ogden
Software Development
QSR International Pty Ltd
 
Back
Top