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就是查找到的窗口的句柄。

完整的类如下: 

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

C#查找指定窗口的子窗口的句柄    class FindWindow
C#查找指定窗口的子窗口的句柄    
{
C#查找指定窗口的子窗口的句柄        [DllImport(
"user32")]
C#查找指定窗口的子窗口的句柄        [
return: MarshalAs(UnmanagedType.Bool)]
C#查找指定窗口的子窗口的句柄        
//IMPORTANT : LPARAM  must be a pointer (InterPtr) in VS2005, otherwise an exception will be thrown
C#查找指定窗口的子窗口的句柄
        private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);
C#查找指定窗口的子窗口的句柄        
//the callback function for the EnumChildWindows
C#查找指定窗口的子窗口的句柄
        private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
C#查找指定窗口的子窗口的句柄
C#查找指定窗口的子窗口的句柄        
//if found  return the handle , otherwise return IntPtr.Zero
C#查找指定窗口的子窗口的句柄
        [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
C#查找指定窗口的子窗口的句柄        
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
C#查找指定窗口的子窗口的句柄
C#查找指定窗口的子窗口的句柄  
private string m_classname; // class name to look for
C#查找指定窗口的子窗口的句柄
       
C#查找指定窗口的子窗口的句柄        
private IntPtr m_hWnd; // HWND if found
C#查找指定窗口的子窗口的句柄
        public IntPtr FoundHandle
C#查找指定窗口的子窗口的句柄        
{
C#查找指定窗口的子窗口的句柄            
get return m_hWnd; }
C#查找指定窗口的子窗口的句柄        }

C#查找指定窗口的子窗口的句柄  
// ctor does the work--just instantiate and go
C#查找指定窗口的子窗口的句柄
  public FindWindow(IntPtr hwndParent, string classname)  
C#查找指定窗口的子窗口的句柄  
{            
C#查找指定窗口的子窗口的句柄            m_hWnd 
= IntPtr.Zero;
C#查找指定窗口的子窗口的句柄            m_classname 
= classname;
C#查找指定窗口的子窗口的句柄            FindChildClassHwnd(hwndParent, IntPtr.Zero);
C#查找指定窗口的子窗口的句柄  }

C#查找指定窗口的子窗口的句柄
C#查找指定窗口的子窗口的句柄        
/// <summary>
C#查找指定窗口的子窗口的句柄        
/// Find the child window, if found m_classname will be assigned 
C#查找指定窗口的子窗口的句柄        
/// </summary>
C#查找指定窗口的子窗口的句柄        
/// <param name="hwndParent">parent's handle</param>
C#查找指定窗口的子窗口的句柄        
/// <param name="lParam">the application value, nonuse</param>
C#查找指定窗口的子窗口的句柄        
/// <returns>found or not found</returns>

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

C#查找指定窗口的子窗口的句柄            EnumChildWindows(hwndParent, childProc, IntPtr.Zero); 
// recurse  redo FindChildClassHwnd
C#查找指定窗口的子窗口的句柄
            return true;// keep looking
C#查找指定窗口的子窗口的句柄
        }

C#查找指定窗口的子窗口的句柄    }

C#查找指定窗口的子窗口的句柄}

C#查找指定窗口的子窗口的句柄

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

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

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

C#查找指定窗口的子窗口的句柄  EnumChildWindows(hwndParent, FindChildClassHwnd, lParam); 
// recurse
C#查找指定窗口的子窗口的句柄
  return TRUE; // keep looking
C#查找指定窗口的子窗口的句柄
  }

C#查找指定窗口的子窗口的句柄  
public:
C#查找指定窗口的子窗口的句柄  LPCSTR m_classname; 
// class name to look for
C#查找指定窗口的子窗口的句柄
  HWND m_hWnd; // HWND if found
C#查找指定窗口的子窗口的句柄  
// ctor does the work--just instantiate and go
C#查找指定窗口的子窗口的句柄
  CFindWnd(HWND hwndParent, LPCSTR classname)
C#查找指定窗口的子窗口的句柄  : m_hWnd(NULL), m_classname(classname)
C#查找指定窗口的子窗口的句柄  
{
C#查找指定窗口的子窗口的句柄  FindChildClassHwnd(hwndParent, (LPARAM)
this);
C#查找指定窗口的子窗口的句柄  }

C#查找指定窗口的子窗口的句柄  }
;
C#查找指定窗口的子窗口的句柄
C#查找指定窗口的子窗口的句柄

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

        }

    }

}

你可能感兴趣的:(C#)