【问题标题】:Return Window handle by it's name / title按名称/标题返回窗口句柄
【发布时间】:2012-11-12 21:56:07
【问题描述】:

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

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

这听起来很简单,可能是……抱歉问了这么明显的问题。

这是我的代码:

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

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

【问题讨论】:

    标签: c# window title handle


    【解决方案1】:

    更新:请参阅 Richard's Answer 了解更优雅的方法。

    不要忘记您在循环内声明了 hWnd - 这意味着它仅在循环内可见。如果窗口标题不存在怎么办?如果你想用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
    

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

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

    【讨论】:

    • 我尝试在 foreach 之前声明它,我在return hWnd 行中得到了Use of unassigned local variable 'hWnd',这就是我在这里问的原因。
    • 那么你应该将它初始化为IntPtr.Zero(见我的编辑)。这是因为窗口标题不匹配 - 所以你永远不会设置指向具有未定义内容的内存区域的变量。
    • 不能为空,因为Cannot convert null to 'System.IntPtr' because it is a non-nullable value type
    • @VixinG 谢谢,不错的收获 - 显然已经太晚了,我喝了太多咖啡,无法在没有 IDE 的情况下输入代码 :) 已修复
    • 你应该在 if 中添加一个中断,否则你会浪费很多处理器时间。
    【解决方案2】:

    作为解决此问题的一个选项:

    [DllImport("user32.dll")]
    private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
    public IntPtr GetHandleWindow(string title)
    {
        return FindWindow(null, title);
    } 
    

    【讨论】:

    • 一个更好的解决方案,其他人建议用GetProcesses()MainWindowTitle 回答(有时会失败)。
    【解决方案3】:

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

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

    1. 变量hWnd 实际上是不必要的,因为它只是为了一件事(作为return 的变量)
    2. foreach 循环效率低下,因为即使在找到匹配项之后,您仍会继续搜索其余进程。实际上,它会返回找到匹配的最后一个进程。

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

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

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        【解决方案5】:

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

        这样使用,

        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;
        }
        

        【讨论】:

          【解决方案6】:
          #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);
          } 
          

          【讨论】:

            猜你喜欢
            • 2017-06-19
            • 1970-01-01
            • 2014-08-02
            • 1970-01-01
            • 2011-02-26
            • 1970-01-01
            • 2014-01-28
            • 1970-01-01
            • 2013-12-08
            相关资源
            最近更新 更多