【问题标题】:Get WPF window by hWnd通过 hWnd 获取 WPF 窗口
【发布时间】:2011-08-14 21:19:00
【问题描述】:

我正在寻找一个 WPF 窗口并遍历它的控件。我能够获得 hWnd,并且我发现了有关使用 DependencyObject 遍历控件的其他帖子。如何从 hWnd 获取 DependencyObject?有可能吗?

【问题讨论】:

  • 您是在同一个进程中执行此操作,还是从一个单独的进程执行此操作?您通常只能访问同一 AppDomain 中的 WPF 对象(这反过来又将您限制在同一进程中)。您能否提供更多关于为什么要遍历控件的背景信息 - 也许是自动化/测试?

标签: .net wpf winapi


【解决方案1】:
Window window = (Window)HwndSource.FromHwnd(hWnd).RootVisual

【讨论】:

  • 这是我正在尝试的,但 RootVisual 始终为空。
  • 也许您的 hWnd 目标窗口不属于 WPF?如何获得 hWnd?
  • 使用 FindWindowEx 获得了 hwnd,我也使用 EnvDTE.Window.HWnd 属性获得了相同的值。 Spy++ 显示的 hwnd 与我得到的不同。
  • 你能告诉我们为什么你需要找到这个窗口吗?也许会有另一种解决方案,而不是使用原生句柄;)
  • Visual Studio 中的解决方案资源管理器。制作折叠所有功能。它没有内置的,EnvDTE 也没有,它只有 ExpandView() 当然可以打开所有内容。
【解决方案2】:

据我所知,WPF 完全用所有 HWND 替换了 WinApi 模型。主窗口当然有 HWND,因为它作为 WinApi 和 WPF 之间的容器服务。您可以使用WindowInteropHelper Class 访问HWND,例如this。但是您将无法像使用本机或 WinForms 应用程序那样遍历控件。检查 VisualTreeHelper 在 WPF 中遍历控制树。

【讨论】:

    【解决方案3】:

    在获得窗口本身之后(正如 Marat 指出的那样),您需要搜索可视化树。这里有两个辅助函数

    找到一个类型的所有子节点

    public static IEnumerable<T> FindChildren<T>(this DependencyObject source) where T : DependencyObject
        {
          if (source != null)
          {
            var childs = GetChildObjects(source);
            foreach (DependencyObject child in childs)
            {
              //analyze if children match the requested type
              if (child != null && child is T)
              {
                yield return (T)child;
              }
    
              //recurse tree
              foreach (T descendant in FindChildren<T>(child))
              {
                yield return descendant;
              }
            }
          }
        }
    

    https://sites.google.com/site/bobstechwiki/home/wpf-ji-shu-1/find-element-by-visual-tree

    按名字查找孩子:

     public static T FindChild<T>(DependencyObject parent, string childName)
           where T : DependencyObject
        {    
          // Confirm parent and childName are valid. 
          if (parent == null) return null;
    
          T foundChild = null;
    
          int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
          for (int i = 0; i < childrenCount; i++)
          {
            var child = VisualTreeHelper.GetChild(parent, i);
            // If the child is not of the request child type child
            T childType = child as T;
            if (childType == null)
            {
              // recursively drill down the tree
              foundChild = FindChild<T>(child, childName);
    
              // If the child is found, break so we do not overwrite the found child. 
              if (foundChild != null) break;
            }
            else if (!string.IsNullOrEmpty(childName))
            {
              var frameworkElement = child as FrameworkElement;
              // If the child's name is set for search
              if (frameworkElement != null && frameworkElement.Name == childName)
              {
                // if the child's name is of the request name
                foundChild = (T)child;
                break;
              }
            }
            else
            {
              // child element found.
              foundChild = (T)child;
              break;
            }
          }
    
          return foundChild;
        }
    

    How can I find WPF controls by name or type?

    【讨论】:

    • 我已经有这个问题了。我正在尝试从 hWnd 获取窗口,以便我可以达到这一点。
    • 确实,Marat 的回答应该做到这一点。只是为了完整性而添加了这个,以防有人偶然发现这个并需要知道其余部分:)
    【解决方案4】:

    这里还没有记录一个特殊情况。可能是顶层控件不是标准的 WPF Window。在 Visual Studio 2010 中就是这种情况(例如)。我在编写 Visual Studio 插件时发现了这一点:我想在可视化树中注入一些 WPF 控件,但您需要 WPF 树的开头。

    还好有办法:

      var hwnd = _dte.MainWindow.HWnd;
      var window = HwndSource.FromHwnd((IntPtr)hwnd);
      dynamic customWindow = window.RootVisual;
      UIElement content = customWindow.Content;
    

    诀窍在于,通过将customWindow 声明为dynamic,您无需知道或指定其类型。以良好的 WPF 方式,它有一个 Content 属性,其中包含所有窗口的内容,并且从那里一切正常。

    【讨论】:

      猜你喜欢
      • 2012-10-28
      • 2013-07-13
      • 2013-01-17
      • 2020-02-03
      • 1970-01-01
      • 1970-01-01
      • 2019-03-28
      • 1970-01-01
      • 2010-11-20
      相关资源
      最近更新 更多