通过hWnd获取WPF窗口

时间:2011-04-28 16:39:01

标签: .net wpf winapi

我希望得到一个WPF窗口并遍历它的控件。我能够获得hWnd,并且我在使用DependencyObject遍历控件时发现了其他帖子。如何从hWnd获取DependencyObject?它甚至可能吗?

4 个答案:

答案 0 :(得分:15)

Window window = (Window)HwndSource.FromHwnd(hWnd).RootVisual

答案 1 :(得分:3)

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

答案 2 :(得分:1)

在您获得窗口后(如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?

答案 3 :(得分:1)

此处尚未记录特殊情况。可能是顶层控件不是标准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属性,包含所有窗口的内容,从那里一切正常。