.NET批量操作窗口样式

1. 背景

我们在开发过程中,可能会遇到需要批量控制程序中窗体的大小或其它一些操作, 这些窗体有可能是属于程序本身的,也许是其它程序的窗口。本文就是基于此的一篇关于如何批量操作窗口样式的,我们主要是通过批量最小化窗体来阐述。

2. 窗体类别

  • 窗口属于程序自己的
  • 窗口不属于程序自己的

下面我们分别针对这两种情况来找出相应的解决方法

2.1 窗口属于程序自己的

具体的来说就是,将要操作的这些窗体或窗口都是由当前程序创建的。

利用Form的WindowState属性, WindowState属性的值是一个FormWindowState枚举值。

  • Maximized     窗口最大化状态
  • Minimized      窗口最小化状态
  • Normal          窗口正常状态

我们可以修改窗体的WindowState属性来变换窗口的状态。 下面是一个简单的例子。

using System;
using System.Windows.Forms;

public class Demo
{
    static void Main()
    {
        // Creat 3 Forms
for (int i = 1; i <= 3; i++) { CreateForm("Form " + i); } Console.WriteLine("Do you want to minizie all open windows? (Y/N)"); string minWindows = Console.ReadLine(); if (minWindows == "Y") { // 最小化次程序打开的窗口 foreach (Form frm in Application.OpenForms) { // Use property WindowState to minizie all opened forms. frm.WindowState = FormWindowState.Minimized; } } Console.WriteLine("Press any key to exit."); Console.ReadKey(); } static void CreateForm(string title) { Form aForm = new Form(); aForm.Text = title; aForm.Show(); } }

其实如果窗体时属于当前程序创建的话,建议可以使用MDI窗体来控制,所有子窗体会在父窗体最小化时也最小化。

2.2 窗体属于其他程序的

具体来讲,将要操作的这些窗口/窗体不光是由当前程序创建的,还有系统中其他程序或系统创建。对于自己创建的系统我们可以通过WindowState属性来操作,但外部程序创建的窗体则不能。我们可以在我们的.NET程序中, 通过P/Invoke调用Win32的API函数来实现。

最重要的一个函数就是ShowWindow

[DllImport("User32")] 
private static extern int ShowWindow(int hwnd, int nCmdShow);

下面这段代码会最小化目前系统中所有打开的窗体。

using System;
using System.Runtime.InteropServices;

namespace PInvokeApps
{
    /// <summary>
    /// EnumDesktopWindows Demo - shows the caption of all desktop windows, 
    /// and minimize all these windows
    /// Based on the code snippet: http://pinvoke.net/default.aspx/user32.EnumDesktopWindows.
    /// </summary>
    public class User32
    {
        /// <summary>
        /// filter function
        /// </summary>
        public delegate bool EnumDelegate(IntPtr hWnd, int lParam);

        /// <summary>
        /// check if windows visible
        /// </summary>
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool IsWindowVisible(IntPtr hWnd);

        /// <summary>
        /// return windows text
        /// </summary>
        [DllImport("user32.dll", EntryPoint = "GetWindowText",
        ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount);

        /// <summary>
        /// enumarator on all desktop windows
        /// </summary>
        [DllImport("user32.dll", EntryPoint = "EnumDesktopWindows",
        ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDelegate lpEnumCallbackFunction, IntPtr lParam);


        /// <summary>
        /// Sets the specified window's show state
        /// </summary>
        [DllImport("user32.dll", EntryPoint = "ShowWindow",
        ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        static void Main()
        {
            var collection = new List<string>();

            Console.WriteLine("Do you want to minizie all open windows? (Y/N)");
            string minWindows = Console.ReadLine();
            bool needsMinimize = !string.IsNullOrEmpty(minWindows) && minWindows == "Y";

            User32.EnumDelegate filter = delegate(IntPtr hWnd, int lParam)
            {
                StringBuilder strbTitle = new StringBuilder(255);
                int nLength = User32.GetWindowText(hWnd, strbTitle, strbTitle.Capacity + 1);
                string strTitle = strbTitle.ToString();

                if (User32.IsWindowVisible(hWnd) && string.IsNullOrEmpty(strTitle) == false)
                {
                    collection.Add(strTitle);

                    // Minimize visible windows if needs
                    if (needsMinimize)
                        User32.ShowWindow(hWnd, ShowWindowCommands.Minimized.ToInt());
                }

                return true;
            };

            if (User32.EnumDesktopWindows(IntPtr.Zero, filter, IntPtr.Zero))
            {
                foreach (var item in collection)
                {
                    Console.WriteLine(item);
                }
            }

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey(); 
        }
    }

    /// <summary>
    /// Here we can also directly define some const variable in User32 class.
    /// Example:
    /// private const int WmSize = 5;
    /// private const int SizeRestored = 0;
    /// private const int SizeMinimized = 1;
    /// private const int SizeMaximized = 2;
    /// private const int SizeShow = 3;
    /// private const int SizeHide = 4;
    /// </summary>
    internal enum ShowWindowCommands : int
    {
        Hide = 0,
        Normal = 1,
        Minimized = 2,
        Maximized = 3,
    }

    public static class EnumExtensions
    {
        public static int ToInt(this Enum enumValue)
        {
            return (int)((object)enumValue);
        }
    }
}

3. 延伸:最小化特定程序的窗口

假定我们有一个名叫 "notepad"的程序,我们还是可以利用P/Invoke来实现最小化其窗口。这个时候的难点是如何得到窗口句柄hWnd,我们可以通过下面这行语句得到窗口句柄:

Process[] p = Process.GetProcessesByName("notepad"); 
hWnd = (int)p[0].MainWindowHandle;

然后只要调用上面程序中的ShowWindow方法,

User32.ShowWindow(hWnd, ShowWindowCommands.Minimized.ToInt())

4. 参考:

原文地址:https://www.cnblogs.com/EasonWu/p/minimize-multiple-windows-in-apps.html