zoukankan      html  css  js  c++  java
  • C#查找指定窗口的子窗口的句柄

    用axWebBrowser加载HTML网页时,真正显示内容的窗体并不是axWebBrowser,而是其子窗口的子窗口一个名为Internet Explorer_Server的类。从spy++可知:

     

    公司需要在网页上进行手写,需要对Internet Explorer_Server进行操作,而通过axWebBrowser的Handle不能直接操作Internet Explorer_Server。于是在网上搜到Paul DiLascia写的一个CFindWnd类,是用C++写的,由于我用C#进行了改写。

    这个类主要用的的API 是EnumChildWindows和FindWindowEx,第一个遍历指定窗口下的子窗口,第二个查找指定名称的窗口,如果找到返回此窗口Handle。

    该类的用法:

    FindWindow fw = new FindWindow(wndHandle, "ChildwndClassName"); //实例化,第一个参数是要查找的起始窗口的句柄;第二个参数是要查找的窗口的类的名称。现在我们需要的传的是"Internet Explorer_Server"。

    IntPtr ip = fw.FoundHandle;//FindWindow的公共属性FoundHandle就是查找到的窗口的句柄。

    完整的类如下: 

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;

    namespace SystemManager.Utility
    {
        
    /// <summary>
        
    /// This class is to find the given window's child window accroding to the given child window's name.
        
    /// The useage: FindWindow fw = new FindWindow(wndHandle, "ChildwndClassName"); IntPtr ip = fw.FoundHandle;
        
    /// I adapt the code from Paul DiLascia,who is the MSDN Magazine's writer.
        
    /// The original class is named CFindWnd which is written in C++, and you could get it on Internet.
        
    /// www.pinvoke.net is a great website.It includes almost all the API fuctoin to be used in C#.
        
    /// </summary>

        class FindWindow
        
    {
            [DllImport(
    "user32")]
            [
    return: MarshalAs(UnmanagedType.Bool)]
            
    //IMPORTANT : LPARAM  must be a pointer (InterPtr) in VS2005, otherwise an exception will be thrown
            private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);
            
    //the callback function for the EnumChildWindows
            private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);

            
    //if found  return the handle , otherwise return IntPtr.Zero
            [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
            
    private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

      
    private string m_classname; // class name to look for
           
            
    private IntPtr m_hWnd; // HWND if found
            public IntPtr FoundHandle
            
    {
                
    get return m_hWnd; }
            }

      
    // ctor does the work--just instantiate and go
      public FindWindow(IntPtr hwndParent, string classname)  
      
    {            
                m_hWnd 
    = IntPtr.Zero;
                m_classname 
    = classname;
                FindChildClassHwnd(hwndParent, IntPtr.Zero);
      }


            
    /// <summary>
            
    /// Find the child window, if found m_classname will be assigned 
            
    /// </summary>
            
    /// <param name="hwndParent">parent's handle</param>
            
    /// <param name="lParam">the application value, nonuse</param>
            
    /// <returns>found or not found</returns>

            //The C++ code is that  lParam is the instance of FindWindow class , if found assign the instance's m_hWnd
            private bool FindChildClassHwnd(IntPtr hwndParent, IntPtr lParam)
            
    {
                EnumWindowProc childProc 
    = new EnumWindowProc(FindChildClassHwnd);
                IntPtr hwnd 
    = FindWindowEx(hwndParent, IntPtr.Zero, this.m_classname, string.Empty);
                
    if (hwnd != IntPtr.Zero)
                
    {
                    
    this.m_hWnd = hwnd; // found: save it
                    return false// stop enumerating
                }

                EnumChildWindows(hwndParent, childProc, IntPtr.Zero); 
    // recurse  redo FindChildClassHwnd
                return true;// keep looking
            }

        }

    }

     注意:在VS2005中,MDA检查的很严格,LPARAM是64位,要用IntPtr表示(网上有人用long来表示,我试了,MDA会抛出异常)。http://pinvoke.net/ 是个不错的网站,它包含了几乎所有的API在.NET中的调用说明,还有例子。

    附Paul DiLascia用C++写的CFindWnd类: 

     ////////////////////////////////////////////////////////////////
      // MSDN Magazine -- August 2003
      
    // If this code works, it was written by Paul DiLascia.
      
    // If not, I don't know who wrote it.
      
    // Compiles with Visual Studio .NET on Windows XP. Tab size=3.
      
    //
      
    // ---
      
    // This class encapsulates the process of finding a window with a given class name
      
    // as a descendant of a given window. To use it, instantiate like so:
      
    //
      
    // CFindWnd fw(hwndParent,classname);
      
    //
      
    // fw.m_hWnd will be the HWND of the desired window, if found.
      
    //
      class CFindWnd {
      
    private:
      
    //////////////////
      // This private function is used with EnumChildWindows to find the child
      
    // with a given class name. Returns FALSE if found (to stop enumerating).
      
    //
      static BOOL CALLBACK FindChildClassHwnd(HWND hwndParent, LPARAM lParam) {
      CFindWnd 
    *pfw = (CFindWnd*)lParam;
      HWND hwnd 
    = FindWindowEx(hwndParent, NULL, pfw->m_classname, NULL);
      
    if (hwnd) {
      pfw
    ->m_hWnd = hwnd; // found: save it
      return FALSE; // stop enumerating
      }

      EnumChildWindows(hwndParent, FindChildClassHwnd, lParam); 
    // recurse
      return TRUE; // keep looking
      }

      
    public:
      LPCSTR m_classname; 
    // class name to look for
      HWND m_hWnd; // HWND if found
      
    // ctor does the work--just instantiate and go
      CFindWnd(HWND hwndParent, LPCSTR classname)
      : m_hWnd(NULL), m_classname(classname)
      
    {
      FindChildClassHwnd(hwndParent, (LPARAM)
    this);
      }

      }
    ;

    2009年更新
    通过实验得知,FindWindowEx可以通过classname或caption(也就是窗口的title)查找窗口,且如果第一个参数传IntPtr.Zero的话,将从Windows最顶层窗口开始查找,但是窗口很多的话这样会非常的慢,所以加入Timeout的判断,如果超时还没找到,返回false。

    用法:FindWindow fw = new FindWindow(IntPtr.Zero, null, "ThunderDFrame", 10);//查找Title为ThunderDFrame的窗口,如果10秒内还没找到,返回false

    代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace Util
    {
        class FindWindow
        {
            [DllImport("user32")]
            [return: MarshalAs(UnmanagedType.Bool)]
            //IMPORTANT : LPARAM  must be a pointer (InterPtr) in VS2005, otherwise an exception will be thrown
            private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);
            //the callback function for the EnumChildWindows
            private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
    
            //if found  return the handle , otherwise return IntPtr.Zero
            [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
            private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
    
            private string m_classname; // class name to look for
            private string m_caption; // caption name to look for
    
            private DateTime start;
            private int m_timeout;//If exceed the time. Indicate no windows found.
    
            private IntPtr m_hWnd; // HWND if found
            public IntPtr FoundHandle
            {
                get { return m_hWnd; }
            }
    
            private bool m_IsTimeOut;
            public bool IsTimeOut
            {
                get{return m_IsTimeOut;}
                set { m_IsTimeOut = value; }
            }
    
            // ctor does the work--just instantiate and go
            public FindWindow(IntPtr hwndParent, string classname, string caption, int timeout)
            {
                m_hWnd = IntPtr.Zero;
                m_classname = classname;
                m_caption = caption;
                m_timeout = timeout;
                start = DateTime.Now;
                FindChildClassHwnd(hwndParent, IntPtr.Zero);
            }
    
            /**/
            /// <summary>
            /// Find the child window, if found m_classname will be assigned 
            /// </summary>
            /// <param name="hwndParent">parent's handle</param>
            /// <param name="lParam">the application value, nonuse</param>
            /// <returns>found or not found</returns>
            //The C++ code is that  lParam is the instance of FindWindow class , if found assign the instance's m_hWnd
            private bool FindChildClassHwnd(IntPtr hwndParent, IntPtr lParam)
            {
                EnumWindowProc childProc = new EnumWindowProc(FindChildClassHwnd);
                IntPtr hwnd = FindWindowEx(hwndParent, IntPtr.Zero, m_classname, m_caption);
                if (hwnd != IntPtr.Zero)
                {
                    this.m_hWnd = hwnd; // found: save it
                    m_IsTimeOut = false;
                    return false; // stop enumerating
                }
    
                DateTime end = DateTime.Now;
    
                if (start.AddSeconds(m_timeout) > end)
                {
                    m_IsTimeOut = true;
                    return false;
                }
    
                EnumChildWindows(hwndParent, childProc, IntPtr.Zero); // recurse  redo FindChildClassHwnd
                return true;// keep looking
            }
        }
    }
  • 相关阅读:
    HDU 1068
    hdu6447
    HDU 6438
    网络赛的个人反思总结
    Bellman-ford 模板
    Pairs Forming LCM LightOJ
    POJ
    链式前向星
    POJ 3281 Dining
    游标遍历所有数据库循环执行修改数据库的sql命令
  • 原文地址:https://www.cnblogs.com/MaxWoods/p/1708048.html
Copyright © 2011-2022 走看看