C# 按名称/标题返回窗口句柄

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13547639/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 08:58:12  来源:igfitidea点击:

Return Window handle by it's name / title

c#windowtitlehandle

提问by VixinG

I can't solve this problem. I get an error:

我无法解决这个问题。我收到一个错误:

The name 'hWnd' does not exist in the current context

It sounds very easy and probably is... sorry for asking so obvious questions.

这听起来很容易,而且可能是......抱歉问了这么明显的问题。

Here's my code:

这是我的代码:

public static IntPtr WinGetHandle(string wName)
{
    foreach (Process pList in Process.GetProcesses())
    {
        if (pList.MainWindowTitle.Contains(wName))
        {
            IntPtr hWnd = pList.MainWindowHandle;
        }
    }
    return hWnd;
}

I tried with many different ways and each fails. Thanks in advance.

我尝试了许多不同的方法,但都失败了。提前致谢。

采纳答案by Basic

Don't forget you're declaring you hWndinside the loop - which means it's only visible inside the loop. What happens if the window title doesn't exist? If you want to do it with a foryou should declare it outside your loop, set it inside the loop then return it...

不要忘记你是hWnd在循环内声明你的——这意味着它只在循环内可见。如果窗口标题不存在会发生什么?如果你想用 a 来做,for你应该在循环之外声明它,将它设置在循环内然后返回它......

IntPtr hWnd = IntPtr.Zero;
foreach (Process pList in Process.GetProcesses())
{
    if (pList.MainWindowTitle.Contains(wName))
    {
        hWnd = pList.MainWindowHandle;
    }
}
return hWnd; //Should contain the handle but may be zero if the title doesn't match

Or in a more LINQ-y way....

或者以更 LINQ 的方式......

IntPtr? handle = Process
    .GetProcesses()
    .SingleOrDefault(x => x.MainWindowTitle.Contains(wName))
    ?.Handle;
return handle.HasValue ? handle.Value : IntPtr.Zero

回答by Shiplu Mokaddim

hWndis declared in the foreachloop. Its context is inside foeachloop. To get its value declare it outside foreachloop.

hWndforeach循环中声明。它的上下文在foeachloop 内。要获取其值,请在foreach循环外声明它。

Use it like this,

像这样使用它,

public static IntPtr WinGetHandle(string wName){
    IntPtr hWnd = NULL;

    foreach (Process pList in Process.GetProcesses())
        if (pList.MainWindowTitle.Contains(wName))
            hWnd = pList.MainWindowHandle;

    return hWnd;
}

回答by Mitch

Because you are declaring hWndinside the if block, it is inaccessible to the return statement which is outside it. See http://www.blackwasp.co.uk/CSharpVariableScopes.aspxfor clarification.

因为您是hWnd在 if 块内部声明的,所以它外部的 return 语句无法访问它。有关说明,请参阅http://www.blackwasp.co.uk/CSharpVariableScopes.aspx

The code you've provided can be fixed by moving the declaration of the hWnd variable:

您提供的代码可以通过移动 hWnd 变量的声明来修复:

public static IntPtr WinGetHandle(string wName)
{
    IntPtr hwnd = IntPtr.Zero;
    foreach (Process pList in Process.GetProcesses())
    {
        if (pList.MainWindowTitle.Contains(wName))
        {
            hWnd = pList.MainWindowHandle;
        }
    }
    return hWnd;
}

回答by Richard

Coming several years late to this but, as others have mentioned, the scope of hWndis only in the foreachloop.

对此晚了几年,但正如其他人所提到的,范围hWnd仅在foreach循环中。

However it's worth noting that, assuming you're doing nothing else with the function, then there are two issues with the answers others have provided:

但是值得注意的是,假设您对该函数没有做任何其他事情,那么其他人提供的答案存在两个问题:

  1. The variable hWndis actually unnecessary since it's only being for one thing (as the variable for the return)
  2. The foreachloop is inefficient as, even after you've found a match, you continue to search the rest of the processes. In actual fact, it'll return the last process it finds that matches.
  1. 该变量hWnd实际上是不必要的,因为它仅用于一件事(作为 的变量return
  2. foreach循环效率低下,因为即使找到匹配项后,您仍继续搜索其余进程。实际上,它会返回它找到的最后一个匹配的进程。

Assuming that you don't want to match the last process (point #2), then this is a cleaner and more efficient function:

假设您不想匹配最后一个进程(第 2 点),那么这是一个更清晰、更高效的函数:

public static IntPtr WinGetHandle(string wName)
{
    foreach (Process pList in Process.GetProcesses())
        if (pList.MainWindowTitle.Contains(wName))
            return pList.MainWindowHandle;

    return IntPtr.Zero;
}

回答by Wizard

As an option to solve this problem:

作为解决此问题的选项:

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

public IntPtr GetHandleWindow(string title)
{
    return FindWindow(null, title);
} 

回答by TheMaster Moh

#include <windows.h>
#using <System.dll>

using namespace System;
using namespace System::Diagnostics;
using namespace System::ComponentModel;

// get window handle from part of window title
public static IntPtr WinGetHandle(string wName)
{
    IntPtr hwnd = IntPtr.Zero;
    foreach (Process pList in Process.GetProcesses())
    {
        if (pList.MainWindowTitle.Contains(wName))
        {
            hWnd = pList.MainWindowHandle;
            return hWnd;
        }
    }
    return hWnd;
}

// get window handle from exact window title
[DllImport("user32.dll")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

public IntPtr GetHandleWindow(string title)
{
    return FindWindow(null, title);
}