常用的处理窗体的API函数如下(注意:API函数必须放在窗体中...):

使用C#语言,要引用DllImport,必须要添加using System.Runtime.InteropServices命名空间

(1)获得当前前台窗体句柄

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetForegroundWindow();

返回值类型是IntPtr,即为当前获得焦点窗口的句柄

使用方法 :

IntPtr myPtr=GetForegroundWindow();

(2)枚举所有屏幕上的顶层窗口,并将窗口句柄传送给应用程序定义的回调函数,利用该法可以获得所有当前打开的窗体的句柄信息

[DllImport("user32.dll")]
public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc,LPARAM lParam);

其中lpEnumFunc指向一个应用程序定义的回调函数指针;

lparam指向一个传递给回调函数的应用程序的定义值;

回调函数原型

bool CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lparam);

其中hwnd是一个顶层窗口的句柄

lparam是一个应用程序定义的一个值(即EnumWindows中lParam)

下面用一个例子对该方法说明

程序中要实现一个功能:可以在当前打开的窗体中找到目标窗体,并在需要时将其激活,置为前台窗体

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;//调用DLLIMPORT namespace EmuWindowInfor
{
/// <summary>
/// 调用API的EnumWindows来枚举窗口
/// </summary>
class Program
{
//定义句柄的全局变量
public int HANDLE;
//定义回调函数的委托
public delegate bool CALLBACK(int hwnd,int lparm); //用于获取前台窗口句柄,设置当前窗口句柄
[DllImport("user32.dll")]
public static extern int EnumWindows(CALLBACK x, int y); [DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int GetWindowText(int hWnd, StringBuilder lpText, int nCount); static void Main(string[] args)
{
CALLBACK myCallBack = new CALLBACK(Report);
EnumWindows(myCallBack, );
Console.ReadKey();
} //实例化回调函数(可以在回调函数中根据窗体名称找到目标窗体句柄)
public static bool Report(int hwnd,int lparm)
{
//分配空间
var sb = new StringBuilder();
GetWindowText(hwnd, sb, sb.Capacity);
//注意某些窗口没有标题
if (sb.ToString() != String.Empty)
Console.WriteLine(sb.ToString());
//if (sb.ToString() == "Microsoft PowerPoint - [les_03_使用_rman [兼容模式]]")
// Console.WriteLine(hwnd.ToString());
//回调函数有返回值
return true;
}
}
}

以上代码实现了通过窗体名称找到目标窗体的句柄,再利用API函数SetForegroundWindow来将该窗体激活并前置

[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(int hWnd);

其中hWnd就是目标窗体的句柄

(3)根据窗体的类名和窗口的名称获得目标窗体

[DllImport("coredll.dll", EntryPoint = "FindWindow")]
private extern static IntPtr FindWindow(string lpClassName, string lpWindowName);

如果coredll.dll,出现找不到,可以使用user32.dll代替

[DllImport("user32.dll", EntryPoint = "FindWindow")]
private extern static IntPtr FindWindow(string lpClassName, string lpWindowName);

其中lpClassName是要找的窗口的类

lpWindowName是要找的窗口的标题,当然在搜索的时候不一定两者都要知道,但至少要知道一个。根据窗口标题查找的一般多用在多窗口的应用程序中,因为程序中的窗体标题固定,方便搜索。但要是对于系统中的一些窗体,例如记事本窗体,PPT等,窗体的标题是不定的,所以用窗口类搜索更方便。当然有关常见的窗口类可以很方便找到,下面是一个搜索当前打开文本文档的窗口句柄的代码

IntPtr ParenthWnd = new IntPtr();
ParenthWnd = FindWindow(null,"窗口标题");
//或者用ParenthWnd = FindWindow("窗口类名",null);
//判断这个窗体是否有效
if (ParenthWnd != IntPtr.Zero)
{
MessageBox.Show("找到窗口");
}
else
{
MessageBox.Show("没有找到窗口");
}

可以使用工具AccExplorer32.exe来查找窗口所属的类和窗体的标题。

如果用VC开发平台,可以使用其中的Spy快速的找到窗口的类型,在Spy++中有一个FindWindow工具,它允许你使用鼠标选择窗口,然后Spy++会显示这个窗口的类。

同时在微软的帮助文档中也给出了对微软常用OFFICE工具窗体句柄查找的方法,同样是用FindWindow()方法,链接:http://support.microsoft.com/kb/302295/zh-cn

(4)查找子窗体的方法

[DllImport("user32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindowEx( IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow );

其中hwndParent是要查找子窗口的父窗口句柄,如果hwndParent为Null,则函数以桌面窗口为父窗口,查找桌面窗口的所有子窗口;如果hwndParent是HWND_MESSAGE,函数仅查找所有消息窗口;

hwndChildAfter :子窗口句柄。查找从在Z序中的下一个子窗口开始。子窗口必须为hwndPareRt窗口的直接子窗口而非后代窗口。如果HwndChildAfter为NULL,查找从hwndParent的第一个子窗口开始。如果hwndParent 和 hwndChildAfter同时为NULL,则函数查找所有的顶层窗口及消息窗口。

lpszClass:指向一个指定了类名的空结束字符串,或一个标识类名字符串的成员的指针。如果该参数为一个成员,则它必须为前次调用theGlobaIAddAtom函数产生的全局成员。该成员为16位,必须位于lpClassName的低16位,高位必须为0。

lpszWindow:指向一个指定了窗口名(窗口标题)的空结束字符串。如果该参数为 NULL,则为所有窗口全匹配。返回值:如果函数成功,返回值为具有指定类名和窗口名的窗口句柄。如果函数失败,返回值为NULL。总之,这个函数查找子窗口,从排在给定的子窗口后面的下一个子窗口开始。在查找时不区分大小写。

下面通过一个简单的例子来说明对子窗口的查找。相信大家都有QQ号,那么就写一个简单的外挂:通过查找QQ登陆窗口并模拟按键实现QQ的自动登陆,以下只是介绍其中如何通过父窗体查找子窗体

const int BM_CLICK = 0xF5;
IntPtr maindHwnd = FindWindow(null, "QQ用户登录"); //获得QQ登陆框的句柄
if (maindHwnd != IntPtr.Zero)
{
IntPtr childHwnd = FindWindowEx(maindHwnd, IntPtr.Zero, null, "登录"); //获得按钮的句柄
if (childHwnd != IntPtr.Zero)
{
SendMessage(childHwnd, BM_CLICK, , ); //发送点击按钮的消息
}
else
{
MessageBox.Show("没有找到子窗口");
}
}
else
{
MessageBox.Show("没有找到窗口");
}

(5)找到窗体后对其的简单处理,比如开关,隐藏

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);

其中ShowWindow(IntPtr hwnd, int nCmdShow);

nCmdShow的含义

0    隐藏窗口

1    正常大小显示窗口

2    最小化窗口

3    最大化窗口

(6)获取窗口大小及位置

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect); [StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; //最左坐标
public int Top; //最上坐标
public int Right; //最右坐标
public int Bottom; //最下坐标
} 示例:
InPtr awin = GetForegroundWindow(); //获取当前窗口句柄
RECT rect = new RECT();
GetWindowRect(awin, ref rect);
int width = rc.Right - rc.Left; //窗口的宽度
int height = rc.Bottom - rc.Top; //窗口的高度
int x = rc.Left;
int y = rc.Top;

(7)常用操作:

GetClassName(
hWnd: HWND; {指定窗口句柄}
lpClassName: PChar; {缓冲区}
nMaxCount: Integer {缓冲区大小}
): Integer; {返回类名大小; 失败返回 }获取指定窗口的类名
GetNextWindow(
hWnd: HWND; {指定的窗口句柄}
uCmd: UINT {指定的关系选项}
): HWND; {失败返回0; 成功返回符合的窗口句柄}
//uCmd 可选值:
GW_HWNDNEXT = ; {同级别 Z 序之下}
GW_HWNDPREV = ; {同级别 Z 序之上}获取指定窗口Z上或Z下的窗口的句柄
GetTopWindow(
hWnd: HWND; {指定的窗口句柄}
): HWND; {失败返回0; 成功返回最顶层的子窗口句柄}获取指定窗口的子窗口中最顶层的窗口句柄
GetWindow(
hWnd: HWND; {指定的窗口句柄}
uCmd: UINT {指定的关系选项}
): HWND; {失败返回0; 成功返回符合的窗口句柄}
//uCmd 可选值:
GW_HWNDFIRST = ; {同级别第一个}
GW_HWNDLAST = ; {同级别最后一个}
GW_HWNDNEXT = ; {同级别下一个}
GW_HWNDPREV = ; {同级别上一个}
GW_OWNER = ; {属主窗口}
GW_CHILD = ; {子窗口}获取与指定窗口具有指定关系的窗口的句柄
GetWindowTextLength(
hWnd: HWND {窗口句柄}
): Integer; {返回窗口标题长度} 获取窗口标题长度
SetWindowText(
hWnd: HWND; {窗口句柄}
lpString: PChar {新标题串指针}
): BOOL;设置窗口标题
GetDesktopWindow: HWND; {无参数; 返回桌面窗口的句柄}

前面我们提到找到目标句柄后通过SetForeGroudWindow(int hwnd)方法可以将其激活并设置为前台窗口,但是如果只是想将其激活而不设置为前台的话就要用到函数SetActiveWindow()

但是使用该方法要特别注意,当在其他线程中对当前线程窗体进行激活使用该方法是没有作用的。

想在找到目标窗体的前提下,让目标窗体和其它窗体同时出现在桌面上,同时要保证只有目标窗体是处于激活状态,也就是说只有目标窗体可以接受到模拟按键消息。终于找到了,可以通过SetForwardWindow(int handle)方法将目标窗体激活并处于最前窗体。同时利用另外一个API函数SetWindowPos来设置其他窗体,使其可以同处桌面。下面就简单介绍下这个方法:

static extern bool SetWindowPos(
  HWND hWnd, //窗口句柄
  HWND hWndInsertAfter, //排列顺序的句柄
  int X, //水平坐标
  int Y, //垂直坐标
  int cx, //宽
  int cy, //高
  UINT uFlags //窗口定位标识
  );

其中

返回值:

BOOL,如果返回值非零表示成功,返回零表示失败。错误信息请参看GetLastError函数。

参数表:

参数 类型及说明 
hwnd HWND,欲定位的窗口句柄 
hWndInsertAfter HWND,置于hwnd前面的窗口句柄。这个参数必须是窗口的句柄或是下面的值之一:  HWND_BOTTOM 将窗口置于其它所有窗口的底部 
HWND_NOTOPMOST 将窗口置于其它所有窗口的顶部,并位于任何最顶部窗口的后面。如果这个窗口非顶部窗口,这个标记对该窗口并不产生影响 
HWND_TOP 将窗口置于它所有窗口的顶部 
HWND_TOPMOST 将窗口置于其它所有窗口的顶部,并位于任何最顶部窗口的前面。即使这个窗口不是活动窗口,也维持最顶部状态

x:

int,指定窗口新的X坐标

Y:

int,指定窗口新的Y坐标

cx:

int,指定窗口新的宽度

cy:

int,指定窗口新的高度

wFlags:

UINT,指定窗口状态和位置的标记。这个参数使用下面值的组合: SWP_DRAWFRAME 围绕窗口画一个框 
SWP_FRAMECHANGED 发送一条WM_NCCALCSIZE消息进入窗口,即使窗口的大小没有发生改变。如果不指定这个参数,消息WM_NCCALCSIZE只有在窗口大小发生改变时才发送 
SWP_HIDEWINDOW 隐藏窗口 
SWP_NOACTIVATE 不激活窗口 
SWP_NOCOPYBITS 屏蔽客户区域 
SWP_NOMOVE 保持当前位置(X和Y参数将被忽略) 
SWP_NOOWNERZORDER 不改变所有窗口的位置和排列顺序 
SWP_NOREDRAW 窗口不自动重画 
SWP_NOREPOSITION 与SWP_NOOWNERZORDER标记相同 
SWP_NOSENDCHANGING 防止这个窗口接受WM_WINDOWPOSCHANGING消息 
SWP_NOSIZE 保持当前大小(cx和cy会被忽略) 
SWP_NOZORDER 保持窗口在列表的当前位置(hWndInsertAfter将被忽略) 
SWP_SHOWWINDOW 显示窗口 
备注:

如果设置了SWP_SHOWWINDOW或SWP_HIDEWINDOW标记,这个窗口不发生移动或改变大小。窗口成为最顶级窗口后,它的所有子窗口也会进入最顶级。一旦将其设为非最顶级,则它的所有子窗口也会转为非最顶级。

程序中引用如下:

[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
static extern bool SetWindowPos(
IntPtr hWnd,
IntPtr hWndInsertAfter,
int X,
int Y,
int cx,
int cy,
uint uFlags
);
static readonly IntPtr HWND_TOPMOST = new IntPtr(-);
static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-);
static readonly IntPtr HWND_TOP = new IntPtr();
const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 SWP_NOZORDER = 0x0004;
const UInt32 SWP_NOREDRAW = 0x0008;
const UInt32 SWP_NOACTIVATE = 0x0010;
const UInt32 SWP_FRAMECHANGED = 0x0020;
const UInt32 SWP_SHOWWINDOW = 0x0040;
const UInt32 SWP_HIDEWINDOW = 0x0080;
const UInt32 SWP_NOCOPYBITS = 0x0100;
const UInt32 SWP_NOOWNERZORDER = 0x0200;
const UInt32 SWP_NOSENDCHANGING = 0x0400;
const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;

C# 窗体常用API函数 应用程序窗体查找的更多相关文章

  1. C#通过WIN32 API实现嵌入程序窗体

    本文实例讲述了C#通过WIN32 API实现嵌入程序窗体的方法,分享给大家供大家参考.具体如下: 这是一个不使用COM,而是通过WIN32 API实现的示例, 它把写字板程序嵌在了自己的一个面板中. ...

  2. Delphi 常用API 函数

    Delphi 常用API 函数 AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小 AnyPopup 判断屏幕上是否存在任何弹出式窗口 ArrangeIconic ...

  3. Delphi 常用API 函数列表

    Delphi 常用API 函数 AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小AnyPopup 判断屏幕上是否存在任何弹出式窗口ArrangeIconicWi ...

  4. C语言实现单链表,并完成链表常用API函数

    C语言实现单链表,并完成链表常用API函数: 1.链表增.删.改.查. 2.打印链表.反转打印.打印环形链表. 3.链表排序.链表冒泡排序.链表快速排序. 4.求链表节点个数(普通方法.递归方法). ...

  5. 通过 WIN32 API 实现嵌入程序窗体

    写了一个不使用 COM, 而是通过 WIN32 API 实现的示例, 它把写字板程序嵌在了自己的一个面板中. 这么做可能没有实际意义, 因为两个程序之前没有进行有价值的交互, 这里仅仅是为了演示这么做 ...

  6. Delphi使用Windows API函数AnimateWindow实现窗体特效

    {**********************************************************************API函数 AnimateWindow 使用:函数功能:窗 ...

  7. C#常用 API函数大全

    常用Windows API1. API之网络函数WNetAddConnection 创建同一个网络资源的永久性连接WNetAddConnection2 创建同一个网络资源的连接WNetAddConne ...

  8. Delphi 常用API 函数(好多都没见过)

    AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小AnyPopup 判断屏幕上是否存在任何弹出式窗口ArrangeIconicWindows 排列一个父窗口的最小 ...

  9. Delphi实现窗体内嵌其他应用程序窗体

    实现原理是启动一个应用程序,通过ProcessID得到窗体句柄,然后对其设定父窗体句柄为本程序某控件句柄(本例是窗体内一个Panel的句柄),这样就达成了内嵌的效果. 本文实现的是内嵌一个记事本程序, ...

随机推荐

  1. <<网络是怎样连接的>>笔记第2章用电信号传输Tcp/ip数据

    创建套接字: 协议栈的内部结构.套接字的实体,以及创建套接字的操作过程 连接服务器: “连接”具体是进行怎样的操作,在这个过程中协议栈到底是如何工作的, 以及客户端和服务器是如何进行交互的. 收发数据 ...

  2. PHP------数组和对象相互转化,stdClass Object转array

    数组转JSON PHP json_encode() 用于对变量进行 JSON 编码,该函数如果执行成功返回 JSON 数据,否则返回 FALSE . JSON转数组 PHP json_decode() ...

  3. Android Studio 中删除项目和项目找回------ Project Structure的使用

    删除项目 点击File——Project Structure 在Project Structure页面,选中要删除的项目,点击上面的减号图标. 我把两个一起删除了,再次打开时,啥也没有 如果想要把不要 ...

  4. ultraedit开发使用技巧

    抛开Mybatis和Hibernate这些dao框架,如果维护老项目时或者不得不用sql拼接时,一个几百行的sql光是去掉navicat中查询的注释或者在sql前后加上双引号就已经很费劲,影响开发效率 ...

  5. Python 实现图片上表格的写入

    直接上代码:import matplotlib.pylab as pltimport numpy as npplt.figure()axes=plt.gca()y= np.random.randn(9 ...

  6. $'\r': command not found in Cygwin

    这是因为windows下的回车符改为Unix下的回车符,用以下命令可以批量修改. dos2unix ./*

  7. [转载]队列queue和双端Dequeue

    转载自:http://uule.iteye.com/blog/2095650?utm_source=tuicool 注意:这都只是接口而已 1.Queue API 在java5中新增加了java.ut ...

  8. MySQL 服务正在启动 .MySQL 服务无法启动。系统出错。发生系统错误 1067。进程意外终止。

    MySQL 服务正在启动 .MySQL 服务无法启动.系统出错.发生系统错误 1067.进程意外终止. 检查了一个晚上才发现是---配置问题 #Path to installation directo ...

  9. java第十次面试题

    一.给定一个字符串,把字符串内的字母转换成该字母的下一个字母,a换成b,z换成a,Z换成A,如aBf转换成bCg,字符串内的其他字符不改变,给定函数,编写函数. public static void ...

  10. fusionjs 学习一 基本试用

    参考demo 项目 https://github.com/rongfengliang/fusionjs-docker-demo 安装 create startkit yarn global add c ...