c#获取当前活动窗⼝句柄,获取窗⼝⼤⼩及位置需调⽤API函数
需在开头引⼊命名空间
using System.Runtime.InteropServices;
获取当前窗⼝句柄:GetForegroundWindow()
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetForegroundWindow();
返回值类型是IntPtr,即为当前获得焦点窗⼝的句柄
使⽤⽅法 :  IntPtr myPtr=GetForegroundWindow();
获取到该窗⼝句柄后,可以对该窗⼝进⾏操作.⽐如,关闭该窗⼝或在该窗⼝隐藏后,使其显⽰
[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    最⼤化窗⼝
使⽤实例:    ShowWindow(myPtr, 0);
获取窗⼝⼤⼩及位置:需要调⽤⽅法GetWindowRect(IntPtr hWnd, ref RECT lpRect)
[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;
------------------------------------------------------------------------
C#中的FindWindow
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint="FindWindow")]
public static extern int FindWindow (
string lpClassName,
string lpWindowName
)
;
已知窗⼝标题"abc",怎么得到窗⼝句柄?
IntPtr hWnd = FindWindow(null, "abc");
-------------------------------------------------------
C#使⽤FindWindow()函数:
[DllImport("coredll.dll", EntryPoint = "FindWindow")]
private extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
这个函数有两个参数,第⼀个是要的窗⼝的类,第⼆个是要的窗⼝的标题。在搜索的时候不⼀定两者都知道,但⾄少要知道其中的⼀个。有的窗⼝的标题是⽐较容易得到的,如"计算器",所以搜索时应使⽤标题进⾏搜索。但有的软件的标题不是固定的,如"记事本",如果打开的⽂件不同,窗⼝标题也不同,这时使⽤窗⼝类搜索就⽐较⽅便。如果到了满⾜条件的窗⼝,这个函数返回该窗⼝的句柄,否则返回0。看例⼦
IntPtr ParenthWnd = new IntPtr(0);
ParenthWnd = FindWindow(null,"Word Mobile");
//判断这个窗体是否有效
if (ParenthWnd != IntPtr.Zero)
{
MessageBox.Show("到窗⼝");
}
else
MessageBox.Show("没有到窗⼝");
从上⾯的讨论中可以看出,如果要搜索的外部程序的窗⼝标题⽐较容易得到,问题是⽐较简单的。可如果窗⼝的标题不固定或者根本就没有标题,怎么得到窗⼝的类呢?如果你安装了Visual C++,你可以使⽤其中的Spy,在Spy++中有⼀个FindWindow⼯具,它允许你使⽤⿏标选择窗⼝,然后Spy++会显⽰这个窗⼝的类。
在Win32 API中还有⼀个FindWindowEx,它⾮常适合寻⼦窗⼝。
FindWindowEx⽤法
函数功能:该函数获得⼀个窗⼝的句柄,该窗⼝的类名和窗⼝名与给定的字符串相匹配。这个函数查⼦窗⼝,从排在给定的⼦窗⼝后⾯的下⼀个⼦窗⼝开始。在查时不区分⼤⼩写。函数原型:HWND FindWindowEx(HWND hwndParent,HWND hwndChildAfter,LPCTSTR lpszClass,LPCTSTR lpszWindow);
参数:
hwndParent:要查⼦窗⼝的⽗窗⼝句柄。
如果hwnjParent为NULL,则函数以桌⾯窗⼝为⽗窗⼝,查桌⾯窗⼝的所有⼦窗⼝。
Windows NT5.0 and later:如果hwndParent是HWND_MESSAGE,函数仅查所有消息窗⼝。
hwndChildAfter :⼦窗⼝句柄。查从在Z序中的下⼀个⼦窗⼝开始。⼦窗⼝必须为hwndPareRt窗⼝的直接⼦窗⼝⽽⾮后代窗⼝。如果HwndChildAfter为NULL,查从hwndParent 的第⼀个⼦窗⼝开始。如果hwndParent 和 hwndChildAfter同时为NULL,则函数查所有的顶层窗⼝及消息窗⼝。
lpszClass:指向⼀个指定了类名的空结束字符串,或⼀个标识类名字符串的成员的指针。如果该参数为⼀个成员,则它必须为前次调⽤theGlobaIAddAtom函数产⽣的全局成员。该成员为16位,必须位于lpClassName的低16位,⾼位必须为0。
lpszWindow:指向⼀个指定了窗⼝名(窗⼝标题)的空结束字符串。如果该参数为 NULL,则为所有窗⼝全匹配。返回值:如果函数成功,返回值为具有指定类名和窗⼝名的窗⼝句柄。如果函数失败,返回值为NULL。
C#中使⽤该函数⾸先导⼊命名空间:
01.using System.Runtime.InteropServices;
然后写API引⽤部分的代码,放⼊ class 内部
01.[DllImport("user32.dll", EntryPoint = "FindWindow")]
02.private static extern IntPtr FindWindowEx( IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow )
例如:
02.IntPtr maindHwnd = FindWindow(null, "QQ⽤户登录"); //获得QQ登陆框的句柄
03.if (maindHwnd != IntPtr.Zero)
04.{
05.    IntPtr childHwnd = FindWindowEx(maindHwnd, IntPtr.Zero, null, "登录");  //获得按钮的句柄
06.    if (childHwnd != IntPtr.Zero)
07.    {
08.        SendMessage(childHwnd, BM_CLICK, 0, 0);    //发送点击按钮的消息
09.    }
10.    else
11.    {
12.        MessageBox.Show("没有到⼦窗⼝");
13.    }
14.}
15.else
16.{
17.    MessageBox.Show("没有到窗⼝");
18.}
---------------------------------------------------------------------------------------
DllImport("user32", SetLastError = true)]
public static extern int GetWindowText(
IntPtr hWnd,//窗⼝句柄
StringBuilder lpString,//标题
int nMaxCount //最⼤值
);
//获取类的名字
[DllImport("user32.dll")]
private static extern int GetClassName(
IntPtr hWnd,//句柄
StringBuilder lpString, //类名
int nMaxCount //最⼤值
);
//根据坐标获取窗⼝句柄
[DllImport("user32")]
private static extern IntPtr WindowFromPoint(
Point Point  //坐标
);
private void timer1_Tick(object sender, EventArgs e)
{
int x = Cursor.Position.X;
int y = Cursor.Position.Y;
Point p = new Point(x, y);
IntPtr formHandle = WindowFromPoint(p);//得到窗⼝句柄
StringBuilder title = new StringBuilder(256);
GetWindowText(formHandle, title, title.Capacity);//得到窗⼝的标题
StringBuilder className = new StringBuilder(256);
GetClassName(formHandle, className, className.Capacity);//得到窗⼝的句柄
}
--------------------------------------
⽂章不错,收藏备⽤。
设计初衷:
  公司为了安全性考虑,不让密码被太多⼈知道,所以想实现⼀个⾃动登录的模块。
设计思想:
  主要是通过调⽤Windows API中的⼀些⽅法,到⽬标窗⼝和进程之后把保存在数据库中的⽤户名密码⾃动填⼊输⼊框中,并登录。
设计步骤:
⼀、调⽤Windows API。
 C#下调⽤Windows API⽅法如下:
 1、引⼊命名空间:using System.Runtime.InteropServices;
 2、引⽤需要使⽤的⽅法,格式:[DllImport("DLL⽂件")]⽅法的声明;
 [DllImport("user32.dll")]private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
 [DllImport("user32.dll")]private static extern bool SetForegroundWindow(IntPtr hWnd);
 [DllImport("user32.dll")]private static extern IntPtr FindWindow(string lpClassName,string lpWindowName);
 [DllImport("user32.dll")]private static extern int SendMessage(IntPtr hWnd,int Msg,int wParam,int lParam);
 [DllImport("user32.dll")]private static extern bool SetCursorPos(int X, int Y);
 [DllImport("user32.dll")]private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
 [DllImport("user32.dll")]private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
  [DllImport("user32.dll")]private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndlnsertAfter, int X, int Y, int cx, int cy, uint Flags);  //ShowWindow参数
 private const int SW_SHOWNORMAL = 1;
 private const int SW_RESTORE = 9;
 private const int SW_SHOWNOACTIVATE = 4;
 //SendMessage参数
 private const int WM_KEYDOWN = 0X100;
 private const int WM_KEYUP = 0X101;
 private const int WM_SYSCHAR = 0X106;
 private const int WM_SYSKEYUP = 0X105;
 private const int WM_SYSKEYDOWN = 0X104;
 private const int WM_CHAR = 0X102;
⼆、到⽬标窗⼝
1)、根据窗⼝的标题得到句柄
 IntPtr myIntPtr = FindWindow(null,"窗⼝名"); //null为类名,可以⽤Spy++得到,也可以为空
 ShowWindow(myIntPtr, SW_RESTORE); //将窗⼝还原
 SetForegroundWindow(myIntPtr); //如果没有ShowWindow,此⽅法不能设置最⼩化的窗⼝
2)、遍历所有窗⼝得到句柄
1 定义委托⽅法CallBack,枚举窗⼝API(EnumWindows),得到窗⼝名API(GetWindowTextW)和得到窗⼝类名API(GetClassNameW)
 public delegate bool CallBack(int hwnd, int lParam);
 [DllImport("user32")]public static extern int EnumWindows(CallBack x, int y);
  [DllImport("user32.dll")]private static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);
 [DllImport("user32.dll")]private static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);
2 调⽤EnumWindows遍历窗⼝
 CallBack myCallBack = new CallBack(Recall);
 EnumWindows(myCallBack, 0);
3 回调⽅法Recall
 public bool Recall(int hwnd, int lParam)
 {
  StringBuilder sb = new StringBuilder(256);
  IntPtr PW = new IntPtr(hwnd);
  GetWindowTextW(PW,sb,sb.Capacity); //得到窗⼝名并保存在strName中
  string strName = sb.ToString();
  GetClassNameW(PW,sb,sb.Capacity); //得到窗⼝类名并保存在strClass中
  string strClass = sb.ToString();
  if (strName.IndexOf("窗⼝名关键字") >= 0 && strClass.IndexOf("类名关键字") >= 0)
  {
   return false; //返回false中⽌EnumWindows遍历
  }
  else
  {
   return true; //返回true继续EnumWindows遍历
  }
 }
3)、打开窗⼝得到句柄
1 定义设置活动窗⼝API(SetActiveWindow),设置前台窗⼝API(SetForegroundWindow)
 [DllImport("user32.dll")]static extern IntPtr SetActiveWindow(IntPtr hWnd);
 [DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)]static extern bool SetForegroundWindow(IntPtr hWnd);
2 打开窗⼝
 Process proc = Process.Start(@"⽬标程序路径");
 SetActiveWindow(proc.MainWindowHandle);
 SetForegroundWindow(proc.MainWindowHandle);
三、向指定的窗⼝输⼊数据
1 利⽤发送消息API(SendMessage)向窗⼝发送数据
 InputStr(myIntPtr, _GameID); //输⼊游戏ID
 SendMessage(myIntPtr, WM_SYSKEYDOWN, 0X09, 0); //输⼊TAB(0x09)
 SendMessage(myIntPtr, WM_SYSKEYUP, 0X09, 0);
 InputStr(myIntPtr, _GamePass); //输⼊游戏密码
 SendMessage(myIntPtr, WM_SYSKEYDOWN, 0X0D, 0); //输⼊ENTER(0x0d)
 SendMessage(myIntPtr, WM_SYSKEYUP, 0X0D, 0);
 /// <summary>
 /// 发送⼀个字符串
 /// </summary>
 /// <param name="myIntPtr">窗⼝句柄</param>
 /// <param name="Input">字符串</param>
 public void InputStr(IntPtr myIntPtr, string Input)
 {
  byte[] ch = (ASCIIEncoding.ASCII.GetBytes(Input));
  for (int i = 0; i < ch.Length; i++)
  {
   SendMessage(PW, WM_CHAR, ch, 0);
  }
 }
2 利⽤⿏标和键盘模拟向窗⼝发送数据
 SetWindowPos(PW, (IntPtr)(-1), 0, 0, 0, 0, 0x0040 | 0x0001); //设置窗⼝位置
 SetCursorPos(476, 177); //设置⿏标位置
 mouse_event(0x0002, 0, 0, 0, 0); //模拟⿏标按下操作
 mouse_event(0x0004, 0, 0, 0, 0); //模拟⿏标放开操作
 SendKeys.Send(_GameID);  //模拟键盘输⼊游戏ID
 SendKeys.Send("{TAB}"); //模拟键盘输⼊TAB
 SendKeys.Send(_GamePass); //模拟键盘输⼊游戏密码
 SendKeys.Send("{ENTER}"); //模拟键盘输⼊ENTER
另:上⾯还提到了keybd_event⽅法,⽤法和mouse_event⽅法类似,作⽤和SendKeys.Send⼀样。
C# 别⼈软件⾥边做好的⽂本框,我如何给他赋值并且提交,最好有源码可供参考,如有合适的,将⾼额追加分
可以⽤WINDOWS api函数实现。
下⾯的WINDIWS API引⽤部分的代码,放⼊ class 内部
[DllImport ( "user32.dll", EntryPoint = "FindWindow", SetLastError = true )]
private static extern IntPtr FindWindow( string lpClassName, string lpWindowName );//查窗⼝句柄
[DllImport ( "user32.dll", EntryPoint = "FindWindowEx", SetLastError = true )]
private static extern IntPtr FindWindowEx( IntPtr hwndParent, uint hwndChildAfter, string lpszClass, string lpszWindow );//查窗⼝内控件句柄
[DllImport ( "user32.dll", EntryPoint = "SendMessage", SetLastError = true, CharSet = CharSet.Auto )]
private static extern int SendMessage( IntPtr hwnd, uint wMsg, int wParam, int lParam );//发送消息
[DllImport ( "user32.dll", EntryPoint = "SetForegroundWindow", SetLastError = true )]
private static extern void SetForegroundWindow( IntPtr hwnd );// 设置窗⼝为激活状态
哈哈,现在可以开⼯了。我就⽤QQ的⾃动登录为列⼦
下⾯是你winfrom窗⼝的按钮事件:
private void button1_Click( object sender, EventArgs e )
{
const uint WM_SETTEXT = 0x000C;//设置⽂本框内容的消息
const uint BM_CLICK = 0xF5; //⿏标点击的消息,对于各种消息的数值,你还是得去查查API⼿册
IntPtr hwndCalc = FindWindow ( null, "QQ2011" ); //查QQ2011的窗⼝句柄
if ( hwndCalc != IntPtr.Zero )//到啦
{
IntPtr hwndLogin= FindWindowEx ( hwndCalc, 0, null, "安全登录" ); //获取登陆按钮的句柄
IntPtr hwndQ = FindWindowEx ( hwndCalc, 0, “ComboBox”, "" );  //获取QQ号码输⼊框的控件句柄
IntPtr hwndP = FindWindowEx ( hwndCalc, 0,"Edit", “” );  //获取密码输⼊框的控件句柄 SetForegroundWindow ( hwndCalc );    //将QQ窗⼝设置为激活
System.Threading.Thread.Sleep ( 1000 );  //暂停1秒让你看到效果
SendMessage ( hwndQ, WM_SETTEXT, TextBox1.Text, 0 );//发送⽂本框1⾥⾯的内容(QQ号啦)
System.Threading.Thread.Sleep ( 1000 );  //暂停1秒让你看到效果
SendMessage( hwndP, WM_SETTEXT, TextBox2.Text, 0 );//发送⽂本框2⾥⾯的内容(QQpassword)
System.Threading.Thread.Sleep ( 1000);  //暂停1秒让你看到效果
SendMessage ( hwndLogin, BM_CLICK, 0, 0 );//点击登录
}
else
{
MessageBox.Show ("没有启动 [QQ2011]");
}
}
---------------------------------------------------
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;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。