Get WPF window by hWnd

后端 未结 4 814
臣服心动
臣服心动 2020-12-17 16:42

I am looking to get a WPF window and traverse it\'s controls. I\'m able to get the hWnd and i\'ve found other posts on traversing the controls using a DependencyObject. How

相关标签:
4条回答
  • 2020-12-17 17:02

    As far as I know WPF completely replaces WinApi model with all that HWNDs. Main window has HWND of course, because it servers as container between WinApi and WPF. You can access HWND using WindowInteropHelper Class, like this. But you will not be able to traverse controls the same way you would do it with native or WinForms app. Check VisualTreeHelper for traversing control trees in WPF.

    0 讨论(0)
  • 2020-12-17 17:02

    There is a special case not documented here yet. It could be that the toplevel control is not a standard WPF Window. This is the case (for instance) in Visual Studio 2010. I discovered this when writing a visual studio Add-in: I wanted to inject some WPF controls in the visual tree, but you need the start of the WPF tree.

    Fortunately, there is a solution:

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

    The trick is that by declaring the customWindow as dynamic you don't need to know or specify its type. In good WPF fashion it has a Content property that contains all the window's content and everything is normal from there.

    0 讨论(0)
  • 2020-12-17 17:07

    After you get the window itself (as Marat points out how to do that) you need to search the visual tree. Here are two helper functions

    find all children of a type

    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

    to find a child by name:

     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?

    0 讨论(0)
  • 2020-12-17 17:10
    Window window = (Window)HwndSource.FromHwnd(hWnd).RootVisual
    
    0 讨论(0)
提交回复
热议问题