【问题标题】:How to minimize/maximize opened Applications如何最小化/最大化打开的应用程序
【发布时间】:2013-09-06 07:23:30
【问题描述】:

我有打开的应用程序列表。为了获得这个列表,我使用了以下代码

 internal static class NativeMethods
{
    public static readonly Int32 GWL_STYLE = -16;
    public static readonly UInt64 WS_VISIBLE = 0x10000000L;
    public static readonly UInt64 WS_BORDER = 0x00800000L;
    public static readonly UInt64 DESIRED_WS = WS_BORDER | WS_VISIBLE;

    public delegate Boolean EnumWindowsCallback(IntPtr hwnd, Int32 lParam);

    public static List<WindowWrapper> GetAllWindows()
    {
        List<WindowWrapper> windows = new List<WindowWrapper>();
        StringBuilder buffer = new StringBuilder(100);
        EnumWindows(delegate(IntPtr hwnd, Int32 lParam)
        {
            if ((GetWindowLongA(hwnd, GWL_STYLE) & DESIRED_WS) == DESIRED_WS)
            {
                GetWindowText(hwnd, buffer, buffer.Capacity);
                WindowWrapper wnd = new WindowWrapper();
                wnd.handle = hwnd;
                wnd.title = buffer.ToString();
                windows.Add(wnd);
            }
            return true;
        }, 0);

        return windows;
    }

    [DllImport("user32.dll")]
    static extern Int32 EnumWindows(EnumWindowsCallback lpEnumFunc, Int32 lParam);

    [DllImport("user32.dll")]
    public static extern void GetWindowText(IntPtr hWnd, StringBuilder lpString, Int32 nMaxCount);

    [DllImport("user32.dll")]
    static extern UInt64 GetWindowLongA(IntPtr hWnd, Int32 nIndex);
}

public class WindowWrapper : IWin32Window
{
    internal IntPtr handle;
    internal String title;

    public IntPtr Handle
    {
        get { return handle; }
    }

    public String Title
    {
        get { return title; }
    }
}

为了调用它,我使用了以下代码

foreach (var wnd in NativeMethods.GetAllWindows())
       {
               string caption = wnd.title;
               string handle = wnd.Handle
               // Add this caption and handle to list
       }

现在,用户将从列表中选择任何打开的窗口,我的任务是读取所选窗口的标题、获取进程句柄以及最大化/最小化或关闭窗口。我该怎么做。

【问题讨论】:

标签: c#


【解决方案1】:

您可以使用findwindowbycaption 获取句柄,然后使用showwindow 最大化或最小化

private const int SW_MAXIMIZE = 3;
private const int SW_MINIMIZE = 6;
// more here: http://www.pinvoke.net/default.aspx/user32.showwindow

[DllImport("user32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

然后在你的代码中使用这个:

IntPtr hwnd = FindWindowByCaption(IntPtr.Zero, "The window title");
ShowWindow(hwnd, SW_MAXIMIZE);

虽然您似乎已经使用EnumWindows 获得了窗口句柄,但在这种情况下您只需要:

ShowWindow(windows[i].handle, SW_MAXIMIZE);

i是窗口的索引。


关闭您将使用的窗口:

[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DestroyWindow(IntPtr hwnd);

在代码中:

DestroyWindow(hwnd) //or DestroyWindow(windows[i].handle)

这是system.windows.forms.form.close()的非托管版本


或者你可以使用:

Process [] proc Process.GetProcessesByName("process name");
proc[0].Kill();

或者你可以使用:

static uint WM_CLOSE = 0x0010;
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

在代码中:

PostMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);

【讨论】:

  • DestroyWindow/CloseWindow 不关闭窗口,为什么?
  • 如果窗口句柄正确,它应该关闭窗口。如果窗口句柄等于IntPtr.Zero,则它的句柄无效。如果您销毁父窗口,所有子窗口也将关闭。
  • 没有句柄不是 IntPtr.Zero。最小化和最大化都正常工作,只有关闭不工作,还有其他方法吗?
  • 我尝试了 PostMessage 和 PostQuitMessage 方法,但不是关闭而是恢复
  • Nicolas Tyler,我在你提供的链接上得到了答案,非常感谢
【解决方案2】:

你可以使用 ShowWindowAsync

private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
private const int SW_SHOWMAXIMIZED = 3;

[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);


ShowWindowAsync(wnd.Handle, SW_SHOWMINIMIZED );

而且更好用

    var openWindows = Process.GetProcesses().Where(process=> String.IsNullOrEmpty(process.MainWindowTitle)==false);

打开窗口

我在 Porcess 中测试了 MainWindowTitle,它有助于在给定标题的情况下搜索窗口。

 var handles = Process.GetProcesses().Where(x => x.MainWindowTitle == "Untitled - Notepad").Select(y=>y.Handle).ToList();

【讨论】:

  • 如果我们只知道它的标题,你知道获取窗口句柄的代码
  • 唯一适用于我的 WPF 应用程序的方法,谢谢!
【解决方案3】:

您可以将本机方法 ShowWindow 与 SW_MAXIMIZE、SW_MINIMIZE 用于 ncmdShow 看看http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx

private const int SW_MAXIMIZE = 3;
private const int SW_MINIMIZE = 6;

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);


// in your code
ShowWindow(wnd.Handle, SW_MAXIMIZE);

【讨论】:

  • 你能告诉我如何使用它吗?
  • 你的回答是对的。如果我们只知道它的标题,我们可以得到句柄或窗口吗
  • 您在 WindowWrapper 中有句柄,将它们存储起来会更有效,因为窗口标题可以由在后台运行的应用程序本身更改。
  • 实际上我正在创建一个应用程序,该用户将存储他/她想要在指定时间最大化/最小化/关闭的窗口的标题,直到该窗口打开。我的代码将从数据库中读取标题。同样的事情可能发生在另一台打开相同窗口的机器上。现在另一台机器将没有与本地机器相同的句柄代码,所以我需要通过其标题处理进程代码
  • 我明白了,有 Windows API 函数 FindWindow 可以做到这一点msdn.microsoft.com/en-us/library/windows/desktop/… 只需将 ClassName 设置为 NULL 并使用 WindowsName 的标题
猜你喜欢
  • 2016-08-15
  • 1970-01-01
  • 2017-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
相关资源
最近更新 更多