C#:从外部强制关闭用ShowDialog方法打开的模态窗口

在写C#程序时,一般我们不需要从外部强行关闭用ShowDialog方法打开的模态窗口。但在实际工作中,我遇到了一个非常坑爹的场景,需要在控制一个客户端程序锁屏前强制关闭由客户端程序打开的“打开”、“另存为”等窗口。因为这几个窗口是三方库打开的,我只能自己找方法手动关闭这几个窗口。

后来在网上找了一些资料,发现如下方法可以从外部关闭其他方法使用ShowDialog打开的模态窗口:

1、使用DllImport加载函数FindWindow和PostMessage

[DllImport("user32.dll")]
private static extern IntPtr FindWindow(string a, string b);

[DllImport("user32.dll")]
private static extern IntPtr PostMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);

2、使用下面方法关闭标题为指定文字窗口(需要将“窗体标题”替换为要关闭的窗体的标题)

IntPtr ptr1 = FindWindow(null, "窗体标题");
if (ptr1 != IntPtr.Zero)
{
    PostMessage(ptr1, 0x0010, IntPtr.Zero, IntPtr.Zero);
}

需要注意的是:

1、PostMessage函数执行后,指定要关闭的窗口并不会被立即关闭,而是有一个极短时间的延迟,所以若想在PostMessage函数调用后进行其他操作(如锁屏操作),建议先让程序Sleep约0.5秒的时间。

2、我做的用于输入密码的解锁窗体,在使用此方法关闭了指定模态窗口后虽然可以弹出,但并没有弹出到界面的最前面。此时需要在程序的其他部位点一下鼠标,解锁窗体才会蹦到前面来。于是我想了一个办法,使用SwitchToThisWindow方法将解锁窗体在Load函数执行完毕0.2秒后强制放到界面最前。

函数声明:

/// <summary>
/// 将窗体调整至界面最前
/// </summary>
/// <param name="hWnd"></param>
/// <param name="fAltTab"></param>
/// <returns></returns>
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool SwitchToThisWindow(IntPtr hWnd, bool fAltTab);

/// <summary>
/// 定时器,本窗口打开后,如未到界面最前,则在指定时间后强制调到界面最前 liwh - 20161215
/// </summary>
System.Windows.Forms.Timer timerSwitchToThisWindow = new System.Windows.Forms.Timer();

Load函数的末尾添加下面这句话:

//2秒后将窗体调整至界面最前 liwh - 20161215
timerSwitchToThisWindow.Tick += (obj, arg) =>
{
	SwitchToThisWindow(this.Handle, true);
	timerSwitchToThisWindow.Stop();
};
timerSwitchToThisWindow.Interval = 2000;
timerSwitchToThisWindow.Start();

下面放一个例子,我写了一个DEMO程序,测试此函数

界面上含有8个Button和1个TextBox用于输出文字

本DEMO程序针对ColorDialog、FolderBrowserDialog、FontDialog、OpenFileDialog、SaveFileDialog、MessageBox、使用Show方法打开的自定义窗体、使用ShowDialog方法打开的自定义窗体八种情况分别做了测试。点击8个按钮分别打开这八类窗体,有一个Timer每5秒检查一下这些窗口,如检测到这些窗口被打开了就关闭它们。

代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace CloseDialogTest
{
    public partial class FormMain : Form
    {
        [DllImport("user32.dll")]
        private static extern IntPtr FindWindow(string a, string b);

        [DllImport("user32.dll")]
        private static extern IntPtr PostMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);

        public FormMain()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Load函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormMain_Load(object sender, EventArgs e)
        {
            Timer timer = new Timer();
            timer.Tick += (obj, arg) =>
                {
                    //1、尝试关闭ColorDialog
                    IntPtr ptr1 = FindWindow(null, "颜色");
                    if (ptr1 != IntPtr.Zero)
                    {
                        PostMessage(ptr1, 0x0010, IntPtr.Zero, IntPtr.Zero);
                        SetInfoBar("ColorDialog已关闭");
                    }
                    //2、尝试关闭FolderBrowserDialog
                    IntPtr ptr2 = FindWindow(null, "浏览文件夹");
                    if (ptr2 != IntPtr.Zero)
                    {
                        PostMessage(ptr2, 0x0010, IntPtr.Zero, IntPtr.Zero);
                        SetInfoBar("FolderBrowserDialog已关闭");
                    }
                    //3、尝试关闭FontDialog
                    IntPtr ptr3 = FindWindow(null, "字体");
                    if (ptr3 != IntPtr.Zero)
                    {
                        PostMessage(ptr3, 0x0010, IntPtr.Zero, IntPtr.Zero);
                        SetInfoBar("FontDialog已关闭");
                    }
                    //4、尝试关闭OpenFileDialog
                    IntPtr ptr4 = FindWindow(null, "打开");
                    if (ptr4 != IntPtr.Zero)
                    {
                        PostMessage(ptr4, 0x0010, IntPtr.Zero, IntPtr.Zero);
                        SetInfoBar("OpenFileDialog已关闭");
                    }
                    //5、尝试关闭SaveFileDialog
                    IntPtr ptr5 = FindWindow(null, "另存为");
                    if (ptr5 != IntPtr.Zero)
                    {
                        PostMessage(ptr5, 0x0010, IntPtr.Zero, IntPtr.Zero);
                        SetInfoBar("SaveFileDialog已关闭");
                    }
                    //6、尝试关闭MessageBox
                    IntPtr ptr6 = FindWindow(null, "测试消息");
                    if (ptr6 != IntPtr.Zero)
                    {
                        PostMessage(ptr6, 0x0010, IntPtr.Zero, IntPtr.Zero);
                        SetInfoBar("MessageBox已关闭");
                    }
                    //7、尝试关闭自定义窗口(Show)
                    IntPtr ptr7 = FindWindow(null, "自定义窗口(Show)");
                    if (ptr7 != IntPtr.Zero)
                    {
                        PostMessage(ptr7, 0x0010, IntPtr.Zero, IntPtr.Zero);
                        SetInfoBar("自定义窗口(Show)已关闭");
                    }
                    //8、尝试关闭自定义窗口(ShowDialog)
                    IntPtr ptr8 = FindWindow(null, "自定义窗口(ShowDialog)");
                    if (ptr8 != IntPtr.Zero)
                    {
                        PostMessage(ptr8, 0x0010, IntPtr.Zero, IntPtr.Zero);
                        SetInfoBar("自定义窗口(ShowDialog)已关闭");
                    }
                };
            timer.Interval = 5000;
            timer.Enabled = true;
            timer.Start();
        }

        /// <summary>
        /// 1、打开ColorDialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenColorDialg_Click(object sender, EventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            if (colorDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                Color selectedColor = colorDialog.Color;
                SetInfoBar("你选择了颜色:" + selectedColor.ToString());
            }
        }

        /// <summary>
        /// 2、打开FolderBrowserDialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenFolderBrowserDialog_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
            if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string selectedPath = folderBrowserDialog.SelectedPath;
                SetInfoBar("你选择了目录:" + selectedPath);
            }
        }

        /// <summary>
        /// 3、打开FontDialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenFontDialog_Click(object sender, EventArgs e)
        {
            FontDialog fontDialog = new FontDialog();
            if (fontDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                Font selectedFont = fontDialog.Font;
                SetInfoBar("你选择了字体:" + selectedFont);
            }
        }

        /// <summary>
        /// 4、打开OpenFileDialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenOpenFileDialog_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string selectedFile = openFileDialog.FileName;
                SetInfoBar("你选择了文件:" + selectedFile);
            }
        }

        /// <summary>
        /// 5、打开SaveFileDialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenSaveFileDialog_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            if (saveFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string selectedPath = saveFileDialog.FileName;
                SetInfoBar("你选择了路径:" + selectedPath);
            }
        }

        /// <summary>
        /// 6、打开MessageBox
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenMessageBox_Click(object sender, EventArgs e)
        {
            MessageBox.Show("测试消息内容", "测试消息");
        }

        /// <summary>
        /// 7、通过Show打开自定义窗口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenCustomWindowByShow_Click(object sender, EventArgs e)
        {
            //CustomForm构造函数接收的参数决定了该窗体的标题
            CustomForm costumForm = new CustomForm("自定义窗口(Show)");
            costumForm.Show();
        }

        /// <summary>
        /// 8、通过ShowDialog打开自定义窗口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenCustomWindowByShowDialog_Click(object sender, EventArgs e)
        {
            //CustomForm构造函数接收的参数决定了该窗体的标题
            CustomForm costumForm = new CustomForm("自定义窗口(ShowDialog)");
            costumForm.ShowDialog();
        }

        /// <summary>
        /// 在文本框内显示指定文字
        /// </summary>
        /// <param name="info"></param>
        private void SetInfoBar(string info)
        {
            this.txtInfoBar.Text = info;
        }
    }
}

这个DEMO程序需要使用VS2012以上版本打开,可在此位置下载到:

https://pan.baidu.com/s/1gfhx0P1

END

转载于:https://my.oschina.net/Tsybius2014/blog/817910

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值