2024年2月8日发(作者:)

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 = andle;//FindWindow的公共属性FoundHandle就是查找到的窗口的句柄。

完整的类如下:

using System;

using c;

using ;

using pServices;

namespace y

{

///

/// 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 = andle;

/// 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.

/// is a great includes almost all the API fuctoin to be used in C#.

///

class FindWindow

{

[DllImport("user32")]

[return: MarshalAs()]

//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

[DllImport("", 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 = ;

m_classname = classname;

FindChildClassHwnd(hwndParent, );

}

///

/// 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, , this.m_classname, );

if (hwnd != )

{

this.m_hWnd = hwnd; // found: save it

return false; // stop enumerating

}

EnumChildWindows(hwndParent, childProc, ); // 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)查找窗口,且如果第一个参数传的话,将从Windows最顶层窗口开始查找,但是窗口很多的话这样会非常的慢,所以加入Timeout的判断,如果超时还没找到,返回false。

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

代码如下:

using System;

using c;

using ;

using ;

using pServices;

namespace Util

{

class FindWindow

{

[DllImport("user32")]

[return: MarshalAs()]

//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

[DllImport("", 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 = ;

m_classname = classname;

m_caption = caption;

m_timeout = timeout;

start = ;

FindChildClassHwnd(hwndParent, );

}

/**/

///

/// 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, ,

m_classname, m_caption);

if (hwnd != )

{

this.m_hWnd = hwnd; // found: save it

m_IsTimeOut = false;

return false; // stop enumerating

}

DateTime end = ;

if (onds(m_timeout) < end)

{

m_IsTimeOut = true;

return false;

}

EnumChildWindows(hwndParent, childProc, ); //

recurse redo FindChildClassHwnd

return true;// keep looking

}

}

}