const int WM_GETTEXT = 0x000D;
const int WM_SETTEXT = 0x000C;
const int WM_CLICK = 0x00F5;
从名称上应该就可以了解这些参数具体的含义是什么了,而且这些参数都可以通过VS附带的工具Spy ++查到。
下面是整个程序的核心部分,查找窗体并对它进行操作:
![](/bbs/images/1c53668bcee393edac0d7b3b3daff1ae.png)
SearchWindow#region SearchWindow
private int SearchWindow()
![](/bbs/images/2887d91d0594ef8793c1db92b8a1d545.png)
{
int retval = 0; //增加一个返回值用来判断操作是否成功
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
//下面的这些参数都可以用Spy++查到
string lpszParentClass = "#32770"; //整个窗口的类名
string lpszParentWindow = "本地连接"; //窗口标题
string lpszClass = "Edit"; //需要查找的子窗口的类名,也就是输入框
string lpszClass_Submit = "Button"; //需要查找的Button的类名
string lpszName_Submit = "确定"; //需要查找的Button的标题
string text = "";
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
IntPtr ParenthWnd = new IntPtr(0);
IntPtr EdithWnd = new IntPtr(0);
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
//查到窗体,得到整个窗体
ParenthWnd = FindWindow(lpszParentClass,lpszParentWindow);
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
//判断这个窗体是否有效
if (!ParenthWnd.Equals(IntPtr.Zero))
![](/bbs/images/2887d91d0594ef8793c1db92b8a1d545.png)
{
//得到User Name这个子窗体,并设置其内容
EdithWnd = FindWindowEx(ParenthWnd,EdithWnd,lpszClass,"");
if (!EdithWnd.Equals(IntPtr.Zero))
![](/bbs/images/2887d91d0594ef8793c1db92b8a1d545.png)
{
text = this.tbUserName.Text.Trim();
//调用SendMessage方法设置其内容
SendMessage(EdithWnd, WM_SETTEXT, (IntPtr)0, text);
retval ++;
}
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
//得到Password这个子窗体,并设置其内容
EdithWnd = FindWindowEx(ParenthWnd,EdithWnd,lpszClass,"");
if (!EdithWnd.Equals(IntPtr.Zero))
![](/bbs/images/2887d91d0594ef8793c1db92b8a1d545.png)
{
text = this.tbPassword.Text.Trim();
SendMessage(EdithWnd, WM_SETTEXT, (IntPtr)0, text);
retval ++;
}
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
//得到Domain这个子窗体,并设置其内容
EdithWnd = FindWindowEx(ParenthWnd,EdithWnd,lpszClass,"");
if (!EdithWnd.Equals(IntPtr.Zero))
![](/bbs/images/2887d91d0594ef8793c1db92b8a1d545.png)
{
text = this.tbDomain.Text.Trim();
SendMessage(EdithWnd, WM_SETTEXT, (IntPtr)0, text);
retval ++;
}
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
//得到Button这个子窗体,并触发它的Click事件
EdithWnd = FindWindowEx(ParenthWnd,
EdithWnd,lpszClass_Submit,lpszName_Submit);
if (!EdithWnd.Equals(IntPtr.Zero))
![](/bbs/images/2887d91d0594ef8793c1db92b8a1d545.png)
{
SendMessage(EdithWnd,WM_CLICK,(IntPtr)0,"0");
retval ++;
}
}
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
return retval;
}
#endregion
这里有一点需要说明的是,当一个窗体下面有几个类名相同的子窗体时,也就是说如果有三个输入框,这三个输入框的类名都是Edit,查找结果是依次从上往下的,最开始我不知道该怎么办才能分出具体的每个不同的输入框,后来只能这样一个一个来查找来试一下,没想到居然是对的。(有别的办法么?)
上面的这段代码也只适用于中文版的操作系统,因为不同的操作系统下同一个窗体的名称都是不一样的,我这里也没有英文版的系统,所以也没办法进行测试。
为了免去每次都让用户手动输入的烦恼,我需要把这些信息都保存到一个特定的文件里面去,当用户在第一次运行这个程序的时候,只需要输入一次,点下Save,先把这些信息保存到一个文件中,然后再把程序本身加载到系统启动项里去,这样下次开机的时候程序就可以自启动,然后从文件中读取信息完成以下的操作。
选择存放文件的路径:
private string UserPro =
System.Environment.GetEnvironmentVariable("USERPROFILE");
private string PATH = System.Environment.GetEnvironmentVariable("USERPROFILE") + @"\Local Settings\AutoLog.ini";
当用户点下Save按钮所触发的事件:
![](/bbs/images/1c53668bcee393edac0d7b3b3daff1ae.png)
Button Submit Click#region Button Submit Click
private void btSubmit_Click(object sender, System.EventArgs e)
![](/bbs/images/2887d91d0594ef8793c1db92b8a1d545.png)
{
SaveData();
}
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
private void SaveData()
![](/bbs/images/2887d91d0594ef8793c1db92b8a1d545.png)
{
try
![](/bbs/images/2887d91d0594ef8793c1db92b8a1d545.png)
{
//Save Data
FileInfo obj = new FileInfo(PATH);
if(obj.Exists)
obj.Delete();
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
FileStream ofile = new FileStream(PATH,FileMode.Create);
//Hidden the file
File.SetAttributes(PATH,FileAttributes.Hidden);
StreamWriter sw = new StreamWriter(ofile);
//把用户名密码和域信息写入文件
sw.WriteLine(this.tbUserName.Text);
sw.WriteLine(this.tbPassword.Text);
sw.WriteLine(this.tbDomain.Text);
sw.Flush();
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
sw.Close();
ofile.Close();
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
//把当前文件拷贝到指定位置,然后再添加到注册表的启动项里
string opath = Application.StartupPath + @"\Login.exe";
string tpath = UserPro + @"\Local Settings\Login.exe";
if(File.Exists(tpath))
File.Delete(tpath);
File.Copy(opath,tpath);
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
RegistryKey hklm = Registry.CurrentUser;
RegistryKey run =
hklm.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
run.SetValue("AutoLogin",tpath);
![](/bbs/images/33d02437d135341f0800e3d415312ae8.png)
//最后程序退出
MessageBox.Show("OK","Information",
MessageBoxButtons.OK,MessageBoxIcon.Information);
Application.Exit();
}
catch(Exception ex)
![](/bbs/images/2887d91d0594ef8793c1db92b8a1d545.png)
{
MessageBox.Show(ex.ToString(),"Error",
MessageBoxButtons.OK,MessageBoxIcon.Error);
}
}
#endregion
这样的话,程序就可以从文件中读取已经存放好的信息来进行验证了。最后要做的就是,需要单独开一个进程来循环执行上面的SearchWindow这个方法,直到找到符合条件的窗口并成功验证为止,并且这个进程需要随程序的启动而启动。
我们可以在构造函数中添加一个名为LoadData的方法,然后在这个方法中进行具体的读文件信息和启动进程的操作。
当然,先定义好这个进程:
private Thread thread;
然后是LoadData这个方法:
辰域智控app
系统工具 下载
网医联盟app
运动健身 下载
汇丰汇选App
金融理财 下载