博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#查找指定窗口的子窗口的句柄
阅读量:7050 次
发布时间:2019-06-28

本文共 7713 字,大约阅读时间需要 25 分钟。

用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会抛出异常)。 是个不错的网站,它包含了几乎所有的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); } /**/ /// /// Find the child window, if found m_classname will be assigned /// /// parent's handle /// the application value, nonuse ///
found or not found
//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 } }}

转载地址:http://xjpol.baihongyu.com/

你可能感兴趣的文章
GC overhead limit exceeded
查看>>
JDBC学习之三
查看>>
CSS3 渐变(Gradients)
查看>>
Windows7关机、重启、待机、休眠命令
查看>>
如何在Xcode8上安装插件
查看>>
JQuery对CheckBox的一些相关操作
查看>>
IIS应用程序池的作用
查看>>
Project configuration is not up-to-date with pom.xml
查看>>
查询批次上课时间
查看>>
Ext.data.Store 中 data 的克隆原理
查看>>
Linux文件内容去重
查看>>
设计模式 之 状态模式
查看>>
Java泛型(一)ArrayList和HashMap
查看>>
redis笔记 (番外篇)——从RDBMS到NoSQL的架构演化及CAP原理
查看>>
iOS中根据已有经纬度定位并显示在地图上
查看>>
Git同时使用多个 ssh key
查看>>
hdu 2501
查看>>
findbugs错误类型对照表
查看>>
Eclipse代码补全,修改 空格键 "=" 键不上屏
查看>>
01背包问题的java界面实现
查看>>