public class CloseForm

     {          [DllImport( "user32" , EntryPoint =  "FindWindow" )]          private  static  extern  IntPtr FindWindow( string  lpClassName,  string  lpWindowName);            [DllImport( "user32.dll" , EntryPoint =  "FindWindowEx" )]          private  static  extern  IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,  string  lpszClass,  string  lpszWindow);            [DllImport( "User32.dll" , EntryPoint =  "SendMessage" )]          private  static  extern  void  SendMessage(IntPtr hWnd,  int  Msg, IntPtr wParam,  int  lParam);            private  const  int  WM_CLOSE = 0x10; //关闭          private  const  int  BM_CLICK = 0xF5; //点击            private  DateTime dt = DateTime.Now; //当前时间            private  string  MsgTitle {  get set ; }            public  void  CloseTitleForm( string  title)          {              this .MsgTitle = title;              System.Windows.Forms.Timer timer1 =  new  System.Windows.Forms.Timer();              timer1.Tick +=  new  EventHandler(timer1_Tick);              timer1.Interval = 1000;              timer1.Enabled =  true ;              //MessageBox.Show("若不回應的話,X秒後此 MsgBox 會自動關閉", MsgTitle);              //timer1.Enabled = false;          }            private  void  timer1_Tick( object  sender, EventArgs e)          {              IntPtr hWnd = FindWindow( null , MsgTitle);              //窗体按钮              IntPtr childHwnd = FindWindowEx(hWnd, IntPtr.Zero,  null "是(&Y)" );              if  (childHwnd != IntPtr.Zero)              {                  //模拟点击 是(&Y)                  SendMessage(childHwnd, BM_CLICK, IntPtr.Zero, 0);              }              else              {                  //没有找到按钮则关闭                  SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, 0);              }              if  (DateTime.Now.Subtract(dt).TotalSeconds > 10)              {                  //10秒后停止执行                  ((System.Windows.Forms.Timer)sender).Stop();              }          }      }  

2:难点:如何获取指定的控件句柄
   细心的人可能已经发现,上文中,给文本框赋值的地方,使用了如下代码:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

 
foreach (IntPtr item in listWnd)
{
if (item != hwnd_button)
{
char[] UserChar = "luminji".ToCharArray();
foreach (char ch in UserChar)
{
SendChar(item, ch, 100);
}
}
}

   假设我们的窗体上有多个文本框,那么事实上,这段代码会给所有的文本框输入"luminji”字样。这在多数应用程序中都是不允许的,我们需要精确定位需要控制的控件。
   我们在得到OK按钮的句柄的时候,使用了函数:

IntPtr hwnd_button = FindWindowEx(mainWnd, new IntPtr(0), null, "OK");
   而想要获取文本框句柄的时候,这个函数却不能使用,因为,所有文本框都是没有标题的,也就是类似"OK"这个值。有人说,那就使用控件ID吧。且看:

2.1:获取控件ID
   非.NET程序,一旦程序被生成,控件ID就是固定的,所以这一招,用在非.NET程序中,那是再好也不过了。


根据ID来得到控件句柄的函数声明如下:

[DllImport("user32.dll ", EntryPoint = "GetDlgItem")] public static extern IntPtr GetDlgItem( IntPtr hParent, int nIDParentItem);
   其中,第一个参数就是窗体的句柄,第二个参数就是控件ID。

   但是,显然,这种方法不适用于我们的.NET程序,因为我们会发现,我们的.NET程序没运行一次,这个ID是变化的。

2.2:获取控件位置
   所以,最终的一个方案是:根据控件位置,人工比对后得到我们想要的控件句柄。该函数的声明如下:

   好了,现在的关键就是怎么取得这个控件的位置。我们在VS中查看,某个控件有X坐标和Y坐标,以上面程序的这个TextBox来说,其在VS中显示的位置是“70,83”,但是而VS中显示的,是不包含标题和边框的坐标值。但是这个坐标值可以作为我们人工比对的参考。 

   更精确的坐标值,我们写代码来实现,如下:


EnumChildWindows(mainWnd, new CallBack(delegate(IntPtr hwnd, int lParam)
{
listWnd.Add(hwnd);
StringBuilder className = new StringBuilder(126);
StringBuilder title = new StringBuilder(200);
GetWindowText(hwnd, title, 200);
RECT clientRect;
GetClientRect(hwnd, out clientRect);
int controlWidth = clientRect.Width;
int controlHeight = clientRect.Height;
int x = 0, y = 0;
IntPtr parerntHandle = GetParent(hwnd);
if (parerntHandle != IntPtr.Zero)
{
GetWindowRect(hwnd, out clientRect);
RECT rect;
GetWindowRect(parerntHandle, out rect);
x = clientRect.X - rect.X;
y = clientRect.Y - rect.Y;
Debug.Print(x.ToString());
Debug.Print(y.ToString());
}
return true;
}), 0);

    注意,上面代码中的X和Y就是某个控件的精确的X和Y值,记录下来,比对一下,我们就能得到精确的坐标值了。在上文的例子中,我们的文本框的坐标最终得到为“78,113”。
    有了这个坐标值,我们便知道这个控件的句柄,也就是hwnd是属于哪个控件的了。
 
2.3:根据EnumChildWindows枚举次序得到句柄
    如果你不想这么麻烦,还有一种简单的方案,那就是利用EnumChildWindows的枚举顺序。要知道,在不同的机器上,EnumChildWindows枚举一个窗体上子控件的顺序是相同的,也就是说,如果有两个文本框,它们在这台机器上被枚举的顺序一个是2,一个是3,那么,它们在其它机器上被枚举的顺序,也是这个固定次序。通过比对,我们也能得到它们各自的句柄。当然,如果我们有了这些句柄,还有什么是不能做到的呢?
2.4:使用SPY++
    SPY++是微软的一个工具,用户获取窗体上的ID或者类型或者句柄等信息。因为在我们的这个例子里,ID和句柄在每台机器上都是不变的,所以这个工具对于我们来说,没有多大的用处。但是,当你HACK别人的程序的时候,它会发挥一定作用。
---------------------
作者:亿洋
来源:CSDN
原文:https://blog.csdn.net/m0_37283423/article/details/74910283
版权声明:本文为博主原创文章,转载请附上博文链接!

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄