如何通过窗口名称关闭窗口?

19

我想关闭某些应用程序窗口(比如计算器等),该怎么在C#中实现?需要导入WinAPI函数吗?


3
http://www.codeproject.com/Articles/22257/Find-and-Close-the-Window-using-Win-API ... 谷歌真不错,你知道的。 - m0s
可能是重复的问题。https://dev59.com/LXVD5IYBdhLWcg3wBWzd - Lloyd
@Lloyd:不是重复的问题,结束一个进程和关闭一个窗口不是同一件事情。 - Cody Gray
@CodyGray 我认为用户提到“任何应用程序”是因为他在谈论一个进程。 - Lloyd
2个回答

33

是的,你应该导入Windows API函数:FindWindow()SendMessage();和WM_CLOSE常量。

Windows API函数的本地定义:

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

/// <summary>
/// Find window by Caption only. Note you must pass IntPtr.Zero as the first parameter.
/// </summary>
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

const UInt32 WM_CLOSE = 0x0010;

客户端代码:

IntPtr windowPtr = FindWindowByCaption(IntPtr.Zero, "Untitled - Notepad");
if (windowPtr == IntPtr.Zero)
{
    Console.WriteLine("Window not found");
    return;
}

SendMessage(windowPtr, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);

1
是的,这对记事本来说完全没问题(当然,假设窗口标题正好是你在这里给出的那样,但大多数情况下可能不是)。但对于具有多个顶级窗口的应用程序而言,除非它们已经专门设计为在关闭单个顶级窗口后关闭整个应用程序,否则它将无法工作。否则,您需要向每个顶级窗口发送WM_CLOSE以确保应用程序被关闭。 - Cody Gray
1
此外,应用程序可以选择以任何方式响应 WM_CLOSE。例如,一些程序选择在接收到此消息时将自己最小化到任务栏的通知区域,而不是真正关闭。由于您无法控制应用程序对消息的响应方式,因此需要广泛测试此方法并意识到在处理未知和未经测试的应用程序时它可能是多么脆弱。 - Cody Gray
@Artem:不是的。你有没有阅读CloseWindow函数的文档?它会最小化指定的窗口,即到任务栏。 - Cody Gray
@CodyGray,问题是如何关闭窗口,而不是如何关闭该应用程序。这个答案似乎正是被问到的。 - svick
1
@svick:我并不是在反对,事实上我已经点赞了这个答案。但问题并不是完全清楚的。我只是澄清了一些重要的注意事项。 - Cody Gray
1
请注意,即使是记事本,如果内容自上次保存以来已更改,您也会收到“是否要保存更改...?”对话框 - 同样适用于许多其他应用程序,每个应用程序可能具有不同的确认对话框样式。此外,在使用SendMessage时要小心:在某些应用程序中,它可能会阻塞,直到确认对话框处理完毕 - 例如,如果目标应用程序在其WM_CLOSE处理程序中调用MessageBox;如果您不想阻塞,则PostMessage可能是更安全的选择。 - BrendanMcK

-1

你正在尝试关闭属于其他进程的窗口。这不是你可以假定会可靠进行的事情。首先,你不拥有那些窗口,所以你没有任何自动权利去干扰其他进程的窗口。

正如其他答案所建议的那样,你可以尝试向窗口发送WM_CLOSE消息,但它带有一个警告,即其他进程并没有真正有义务予以执行。对WM_CLOSE的响应可以是接受和干净的关闭,也可以是彻底拒绝。在后一种情况下,你真的没有选择。这不是你的进程。在中间,就像你已经看到的那样,可能会出现各种中间窗口、对话框等问题。

那么你在这里想要实现什么?为什么要尝试关闭属于其他进程的窗口?这可能有助于澄清目标。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接