Russ Suter
asked on
How can I detect if a modal dialog is currently open in my application?
A while back I needed to add scroll wheel functionality to a panel. I am using this bit of code to capture and process the wheel messages and it works fine.
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == MSG.WM_MOUSEWHEEL)
{
if (recipientControl.Parent.ClientRectangle.Contains(recipientControl.PointToClient(System.Windows.Forms.Control.MousePosition)))
{
NativeMethods.SendMessage(recipientControl.Handle, m.Msg, m.WParam, m.LParam);
return true;
}
}
return false;
}
There's just one problem, it processes the message even if another window is open on top of the main window. If I open another window using the ShowDialog() method it should block mousewheel handling for the panel in the underlying form. I just don't know how to detect whether or not a dialog is currently open. Can anyone help with this?
Window.ShowModalDialog() ?
ASKER
Was that just a guess? Because that isn't even a method defined in the .NET library. If you mean Window.ShowModal() then that's used to display a form as a modal dialog. That won't tell me if a dialog is currently being displayed at the time of message capture.
You could pass an instance of the parent form to your filter and then check for the TopMost or ContainsFocus property, e.g. -
Form1.cs -
With Form1 focused and moving the mouse wheel -Opening the modal and moving the mouse wheel produces nothing -Bear in mind that this means your form must be focused and be top most in order to process mouse wheel messages.
-saige-
Form1.cs -
using System;
using System.Windows.Forms;
namespace EE_Q29148449
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Application.AddMessageFilter(new ScrollingFilter(this, richTextBox1));
}
private void OnClick(object sender, EventArgs e)
{
var frm2 = new Form2();
frm2.ShowDialog();
}
}
}
Form1.Designer.cs -
namespace EE_Q29148449
{
partial class Form1
{
/// <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()
{
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.button1 = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
this.SuspendLayout();
//
// richTextBox1
//
this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.richTextBox1.Location = new System.Drawing.Point(0, 0);
this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.Size = new System.Drawing.Size(800, 402);
this.richTextBox1.TabIndex = 0;
this.richTextBox1.Text = "";
//
// splitContainer1
//
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
this.splitContainer1.Name = "splitContainer1";
this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
//
// splitContainer1.Panel1
//
this.splitContainer1.Panel1.Controls.Add(this.richTextBox1);
//
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.button1);
this.splitContainer1.Size = new System.Drawing.Size(800, 450);
this.splitContainer1.SplitterDistance = 402;
this.splitContainer1.TabIndex = 1;
//
// button1
//
this.button1.Location = new System.Drawing.Point(339, 11);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(122, 23);
this.button1.TabIndex = 3;
this.button1.Text = "Open Modal";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.OnClick);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.splitContainer1);
this.Name = "Form1";
this.Text = "Form1";
this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
this.splitContainer1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.RichTextBox richTextBox1;
private System.Windows.Forms.SplitContainer splitContainer1;
private System.Windows.Forms.Button button1;
}
}
Form2.cs -
using System;
using System.Windows.Forms;
namespace EE_Q29148449
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void OnClick(object sender, EventArgs e)
{
Close();
}
}
}
Form2.Designer.cs -
namespace EE_Q29148449
{
partial class Form2
{
/// <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()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(54, 27);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 2;
this.button1.Text = "Close Modal";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.OnClick);
//
// Form2
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(182, 77);
this.Controls.Add(this.button1);
this.Name = "Form2";
this.Text = "Form2";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
}
}
ScrollingFilter.cs -
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace EE_Q29148449
{
class ScrollingFilter : IMessageFilter
{
const int WM_MOUSEWHEEL = 0x020A;
private Form instance;
private Control control;
[DllImport("user32.dll")]
static extern int SendMessage(IntPtr handle, int msg, int wParam, int lParam);
public ScrollingFilter(Form instance, Control control)
{
this.instance = instance;
this.control = control;
}
bool IMessageFilter.PreFilterMessage(ref Message m)
{
if (m.Msg == 0x020A && (instance.TopMost || instance.ContainsFocus))
{
MessageBox.Show($"{{ Handle: {m.HWnd}, LParam: {m.LParam}, Message: {m.Msg}, WParam: {m.WParam}, Result: {m.Result} }}{Environment.NewLine}");
return true;
}
return false;
}
}
}
Which produces the following results -With Form1 focused and moving the mouse wheel -Opening the modal and moving the mouse wheel produces nothing -Bear in mind that this means your form must be focused and be top most in order to process mouse wheel messages.
-saige-
ASKER
I've just stumbled upon an answer and it turns out it's ridiculously simple.
I can just use System.Windows.Forms.Appli cation.Ope nForms and look for the last one. If the last one in the collection isn't my main window then I know a dialog is showing.
I can just use System.Windows.Forms.Appli
Glad you got it sorted...
-saige-
-saige-
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
You could also use LINQ -
!Application.OpenForms.Cast<Form>().Any(f => f is MyForm)
-saige-