无忧编程_ASP.NET  / C# / PHP 程序员的软件世界

?找回密码
?立即注册

QQ登录

只需一步,快速开始

查看: 7366|回复: 0
打印 上一主题 下一主题

C#+Win32 API实现指定窗体激活并前置

[复制链接]

423

主题

456

帖子

1899

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1899
跳转到指定楼层
楼主
发表于 2016-2-16 21:36:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
C#+Win32 API实现指定窗体激活并前置:
不熟悉API使得我为了实现一个简单的功能浪费了很长的时间,下面就把自己查阅的相关东西做个总结:

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

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

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

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

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

使用博彩bet356在线投注_bet356登录不了_bet356 怎么样 :? ?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)

下面用一个例子对该博彩bet356在线投注_bet356登录不了_bet356 怎么样说明
程序中要实现一个功能:可以在当前打开的窗体中找到目标窗体,并在需要时将其激活,置为前台窗体
复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;//调用DLLIMPORT

namespace EmuWindowInfor
{
? ? ///
? ? /// 调用API的EnumWindows来枚举窗口
? ? ///

? ? 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, 0);
? ?? ?? ?? ?Console.ReadKey();
? ?? ???}

? ?? ???//实例化回调函数(可以在回调函数中根据窗体名称找到目标窗体句柄)
? ?? ???public static bool Report(int hwnd,int lparm)
? ?? ???{
? ?? ?? ?? ?//分配空间
? ?? ?? ?? ?var sb = new StringBuilder(50);
? ?? ?? ?? ?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);

其中lpClassName是要找的窗口的类

lpWindowName是要找的窗口的标题,当然在搜索的时候不一定两者都要知道,但至少要知道一个。根据窗口标题查找的一般多用在多窗口的应用程序中,因为程序中的窗体标题固定,方便搜索。但要是对于系统中

的一些窗体,例如记事本窗体,PPT等,窗体的标题是不定的,所以用窗口类搜索更方便。当然有关常见的窗口类可以很方便找到,下面是一个搜索当前打开文本文档的窗口句柄的代码



复制代码
? ?? ?? ???IntPtr ParenthWnd = new IntPtr(0);

? ?? ?? ?? ?ParenthWnd = FindWindow(null,"Word Mobile");
? ?? ?? ?? ?//判断这个窗体是否有效
? ?? ?? ?? ?if (ParenthWnd != IntPtr.Zero)
? ?? ?? ?? ?{
? ?? ?? ?? ?? ? MessageBox.Show("找到窗口");
? ?? ?? ?? ?}

? ?? ?? ?? ?else

? ?? ?? ?? ?? ? MessageBox.Show("没有找到窗口");
复制代码


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

同时在微软的帮助文档中也给出了对微软常用OFFICE工具窗体句柄查找的博彩bet356在线投注_bet356登录不了_bet356 怎么样,同样是用FindWindow()博彩bet356在线投注_bet356登录不了_bet356 怎么样,链接:http://support.microsoft.com/kb/302295/zh-cn

(4)查找子窗体的博彩bet356在线投注_bet356登录不了_bet356 怎么样

[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, 0, 0);? ???//发送点击按钮的消息??
? ? }??
? ? 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;? ?? ?? ???{返回类名大小; 失败返回 0}获取指定窗口的类名

GetNextWindow(
??hWnd: HWND; {指定的窗口句柄}
??uCmd: UINT??{指定的关系选项}
): HWND;? ?? ?{失败返回0; 成功返回符合的窗口句柄}
//uCmd 可选值:
GW_HWNDNEXT??= 2; {同级别 Z 序之下}
GW_HWNDPREV??= 3; {同级别 Z 序之上}获取指定窗口Z上或Z下的窗口的句柄

GetTopWindow(
??hWnd: HWND; {指定的窗口句柄}
): HWND;? ?? ?{失败返回0; 成功返回最顶层的子窗口句柄}获取指定窗口的子窗口中最顶层的窗口句柄

GetWindow(
??hWnd: HWND; {指定的窗口句柄}
??uCmd: UINT??{指定的关系选项}
): HWND;? ?? ?{失败返回0; 成功返回符合的窗口句柄}

//uCmd 可选值:
GW_HWNDFIRST = 0; {同级别第一个}
GW_HWNDLAST??= 1; {同级别最后一个}
GW_HWNDNEXT??= 2; {同级别下一个}
GW_HWNDPREV??= 3; {同级别上一个}
GW_OWNER? ???= 4; {属主窗口}
GW_CHILD? ???= 5; {子窗口}获取与指定窗口具有指定关系的窗口的句柄

GetWindowTextLength(
??hWnd: HWND {窗口句柄}
): Integer;??{返回窗口标题长度} 获取窗口标题长度

SetWindowText(
??hWnd: HWND;? ???{窗口句柄}
??lpString: PChar {新标题串指针}
): BOOL;设置窗口标题

GetDesktopWindow: HWND; {无参数; 返回桌面窗口的句柄}

(8)还有个问题尚待解决

前面我们提到找到目标句柄后通过SetForeGroudWindow(int hwnd)博彩bet356在线投注_bet356登录不了_bet356 怎么样可以将其激活并设置为前台窗口,但是如果只是想将其激活而不设置为前台的话就要用到函数SetActiveWindow()

但是使用该博彩bet356在线投注_bet356登录不了_bet356 怎么样要特别注意,当在其他线程中对当前线程窗体进行激活使用该博彩bet356在线投注_bet356登录不了_bet356 怎么样是没有作用的。具体解决以后再给出......

分享到:? QQ好友和群QQ好友和群
收藏收藏
windows .net(C#+MSSQL) linux(php+mysql)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|软件编程 ( 鄂ICP备11006601号 )鄂公网安备 42011102001337号 |

GMT+8, 2019-9-26 16:06 , Processed in 0.054754 second(s), 19 queries .

Powered by Discuz! X3.4

? 2001-2017 Comsenz Inc.

快速回复 返回顶部 365体育投注提款短信