如何通过C#程序控制另一个程序
涉及到的知识点
-
如何通过C#程序读取Excel中内容,并加载到DataGridView中
-
如何通过C#程序下载DataGridView中的内容并保存到Excel文件中
-
如何通过C#程序读取到另一个程序的句柄
-
如何通过C#程序向另一个程序发送指定的指令
需求:
向一个程序中指定的控制录入信息,点击指定的按钮则可以执行指定的操作,当程序处理完成后会弹出对应的对话框,接下来关闭弹出提示对话框,再进入下一次的操作,这个操作过程固定需要把这个操作过程自动化来释放人工操作产生的资源浪费。
需求拆解:
1.首选需要向程序中指定的控件录入相关的信息,录入什么信息需要人为的指定(比如:业务单据号),所以需要人为把待操作的数据先用批量录入好,然后程序去一次一次的遍历执行
2.人工录入的信息需要写入到对应程序的控件,那么需要得到那个被控制程序的指定控件的句柄信息,接下来通过发送消息的方式来向对应的控件中写入值
3.在录入信息后需要点击按钮以触发程序操作,那么需要得到那个被控制程序的指定控钮的控件句柄信息,接下来通过发送消息的方式来模拟按钮的点击动作
4.当程序处理完成后会弹出提示对话框,那么在完成第三步后需要等待程序返回对话框,并得到对话框的句柄并把提示的信息保存下来,并记录此次处理的结果
一、程序界面设计

上传文件:后的输入框可以处理双击消息,在双击后会弹出文件对话框在对话框中可以选择待处理数据的Excel文档
“上传”按钮:目的是把选择的Excel文件中的数据加载到下方的DataGridView控件中
“导出处理结果”按钮:目的是把DataGridView控件中数据导出到指定的Excel中,当DataGridView中存在数据中会弹出Excel文件保存的对话框,用于指定保存文件的位置
“DataGridView”列表:它用来展示导入的待处理Excel文档中的数据以及处理结果的回写,这里指定了列头[OMS单号、状态、处理状态、处理结果],前两列是上传待处理Excel中必须要有的,后面两列是程序在运行过程中回写回来的数据
OMS单号:后的输入框默认禁用的,当拿到了被控制程序的句柄的ID后把对应的值写入到这里面
状态:后的输入框默认禁用的,当拿到了被控制程序的句柄的ID后把对应的值写入到这里面
注意:在上面两个文本框后还有一个静态标签,用于存放被控制程序的按钮句柄ID后显示在这里,并且是不可以修改的,因为程序启动后句柄是不会变化的,但每一次重新打开程序句柄是会不一样的
处理进度:后面的静态文本是展示当前上传待处理的总记录数有多少,有多少已处理了,还有多少未处理
当前处理文件:这里展示了上传Excel文件的完整路径
“测试”按钮:在点击这个按钮前必须要打开被控制程序,它会把我们需要的句框ID全获取出来
“执行”按钮:根据OMS单号后的句柄ID把DataGridView列表中的OMS单号值写入,根据状态后的句柄ID把DataGridView列表中的状态值写入,写入两个值后再跟据被控制的程序的控钮控件模拟点击事件,等待被控制程序弹出执行结果提示对话框,获取对话框中的消息把DataGridView列表中的处理状态和处理结果值返写回去
“停止”按钮:当模拟执行完操作后可以点击“停止”让程序停止处理下面的数据(这里只是把一个公共的变量设置为false,这里程序在进入下一个循环时可以提出执行)
“关闭”按钮:整个界面把ControlBox设置为了false,所以需要关闭程序需要点击“关闭”按钮,目的是为了防止在程序执行过程中程序被关闭掉
说明:
下面是被控制应用的界面

当点击“测试”按钮后被控制程序对话框中各输入框控件会显示控件ID

二、功能开发
1.Excel文件的上传与Excel文件的下载保存相对说比较独立,单独设计了一个Utils类进行处理(注意:需要引用Mircrosoft.Office.Interop.Excel)
/*
* Created by SharpDevelop.
* User: adven
* Date: 2021/1/29
* Time: 20:47
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Windows.Forms;
using System.Data;
using System.Data.OleDb;
using System.IO;
using Microsoft.Office.Interop;
namespace BD
{
///
<
summary
>
///
Description of Utils.
///
<
/
summary
>
public
class
Utils
{
public
Utils()
{
}
/**
上传文件并写入到DataGridView
**/
public
static
Boolean
exceToDataGrid(
String path,
DataGridView dataTable) {
Boolean flag =
false;
try{
String strCon =
"provider=microsoft.jet.oledb.4.0;data source=" + path +
";extended properties=excel 8.0";
//建立连接
OleDbConnection Con =
new
OleDbConnection(strCon);
//从sheet1中读取数据
String strSql =
"select * from [Sheet1$]";
OleDbCommand Cmd =
new
OleDbCommand(strSql, Con);
OleDbDataAdapter da =
new
OleDbDataAdapter(Cmd);
//新建数据集
DataSet ds =
new
DataSet();
da.
Fill(ds,
"bd");
dataTable.DataSource = ds.Tables[
0];
//dataTable.Rows.RemoveAt(0);
flag =
true;
}
catch (
Exception ex){
MessageBox.
Show(ex.Message);
//错误信息弹框
}
return flag;
}
/**
* 文件导出到Excel
**/
public
static
void
DataGridToExcel(
DataGridView dataTable){
//先做一个判断
if(dataTable.Rows.Count==
1){
MessageBox.
Show(
"大兄弟,没有数据就不要导出了吧!");
return;
}
string saveFileName =
"";
//bool fileSaved = false;
SaveFileDialog saveDialog =
new
SaveFileDialog();
saveDialog.DefaultExt =
"xls";
saveDialog.Filter =
"Excel文件|*.xls";
saveDialog.FileName = saveDialog.FileName;
saveDialog.
ShowDialog();
saveFileName = saveDialog.FileName;
if (saveFileName.
IndexOf(
":") <
0)
return;
//被点了取消
Microsoft.Office.Interop.Excel.
Application xlApp =
new Microsoft.Office.Interop.Excel.
Application();
if (xlApp ==
null)
{
MessageBox.
Show(
"无法创建Excel对象,可能您的机子未安装Excel");
return;
}
Microsoft.Office.Interop.Excel.
Workbooks workbooks = xlApp.Workbooks;
Microsoft.Office.Interop.Excel.
Workbook workbook = workbooks.
Add(Microsoft.Office.Interop.Excel.
XlWBATemplate.
xlWBATWorksheet);
Microsoft.Office.Interop.Excel.
Worksheet worksheet = (Microsoft.Office.Interop.Excel.
Worksheet)workbook.Worksheets[
1];
//取得sheet1
string[] array =
new
string[dataTable.Columns.Count];
//获取Visble =true 的列
foreach (
DataGridViewColumn column
in dataTable.Columns)
{
if (column.Visible ==
true)
{
array[column.DisplayIndex] = column.HeaderText +
'|' + column.Name; ;
}
}
int RowsCount = dataTable.Rows.Count;
int ColumnsCount = array.Length;
int mm =
1;
for (
int i =
0; i < ColumnsCount; i++)
{
string[] str =
new
string[
2];
string ColumnName;
try
{
str = array.
GetValue(i).
ToString().
Split(
'|');
ColumnName = str[
0];
}
catch
{
continue;
}
//导出列名
worksheet.Cells[
1, mm] = ColumnName;
//导出列内容
for (
int m =
0; m < RowsCount; m++)
{
try
{
worksheet.Cells[m +
2, mm] = dataTable.Rows[m].Cells[str[
1]].FormattedValue.
ToString();
}
catch
{ }
}
//执行完一列 mm++
mm++;
}
worksheet.Columns.EntireColumn.
AutoFit();
if (saveFileName !=
"")
{
try
{
workbook.Saved =
true;
workbook.
SaveCopyAs(saveFileName);
}
catch (
Exception ex)
{
MessageBox.
Show(
"导出文件时出错,文件可能正被打开!\n" + ex.Message);
}
}
xlApp.
Quit();
GC.
Collect();
//强行销毁
MessageBox.
Show(saveFileName +
"的表格资料保存成功",
"提示",
MessageBoxButtons.
OK);
}
}
}
2.核心功能代码
双击上传文件的输入框,弹出文件打开对话框,目的是得到文件的完整理路径
/**
* 输入待处理Excel文件的地址,双击可以打开文件选择对话框,选择的文件全路径会显示在文本输入框中
**/
void
TEXT_PATHDoubleClick(
object sender,
EventArgs e)
{
//打开读取文件的对话框,并且把读到的文件路径显示在控件
OpenFileDialog fd =
new
OpenFileDialog();
//指定可以打开文件的类型
fd.Filter =
"Excel(*.xls)|*.xls|Excel(*.xlsx)|*.xlsx";
if(fd.
ShowDialog() ==
DialogResult.
OK){
//得到完整的路径,并把这个路径绑定到TEXT_PATH控件
TEXT_PATH.Text = fd.FileName;
}
}
上传按钮,把Excel数据写入到DataGridView列表中
/**
* 上传按钮,把Excel的数据写入到DataGridView的列表中
**/
void
UplodaClick(
object sender,
EventArgs e)
{
if(
TEXT_PATH.Text.
Equals(
"双击选择文件,文 件类型为Excel,文件格式要求为两列“OMS单号”、“状态”")){
MessageBox.
Show(
"大兄弟,似乎没有选择要上传文件Excel文件!");
return;
}
Boolean result =
Utils.
exceToDataGrid(
TEXT_PATH.Text,
dataTable);
if(result){
MessageBox.
Show(
"成功加载数据!");
}
prcessFileName.Text =
"当前处理文件:" +
TEXT_PATH.Text;
TEXT_PATH.Text =
"";
totalRowCount =
dataTable.Rows.Count-
1;
processedCount =
0;
//重置已处理的数量
process.Text =
getProcessedTips();
OrderId.Text =
"";
StatusId.Text =
"";
}
注意:这里有一个getProcessedTips()方法,它的目的是把处理进度的提示信息做更新
/**
*这里提供一个提示信息的展示区
格式:总记录数:{0} 已处理记录数:{1} 待处理记录数:{2}
**/
private
String
getProcessedTips(){
return
String.
Format(
"总记录数:{0} 已处理记录数:{1} 待处理记录数:{2} ",
totalRowCount,
processedCount,
totalRowCount-
processedCount);
}
把DataGridView中的内容导出Excel
/**
* 导出处理结果为Excel表格
**/
void
DownloadClick(
object sender,
EventArgs e)
{
Utils.
DataGridToExcel(
dataTable);
}
测试按钮,目的是把被控制应用的所有控件ID显示在它对应的文本输入框中,因为我们主要需要对方的文本输入框的控件ID,所以直接把ID写到它的控件中
/**
* 点击测试是为了拿到所有输入框的句柄,并显示在对方应用的控件中
**/
void
TestClick(
object sender,
EventArgs e)
{
//获取oms补单工具的窗口句柄
IntPtr hwnd =
MainForm.
FindWindow(
null,
"OMS补单工具");
omsHwnd = hwnd;
getControlhwndId(
omsHwnd);
getButtonControl(
omsHwnd,
3);
buttonID.Text =
"查询订单管理按钮:" +
searchHwnd.
ToString();
OrderId.Enabled =
true;
StatusId.Enabled =
true;
}
获取对方应用的句柄使用方法FindWindow,这里需要提前引入user32.dll中的FindWindow方法
[
DllImport(
"user32.dll")]
public
static
extern
IntPtr
FindWindow(
string lpClassName,
string lpWindowName);
获取被控制程序的各个控件的ID,并把这些个ID写入到它对应的文件框入框中
/**
* 封装一个方法用来获取“oms补单工具”中的各个控件的ID值并写入到oms补单工具的输入框中
**/
private
void
getControlhwndId(
IntPtr hParent){
IntPtr res =
IntPtr.
Zero;
StringBuilder sb1 =
new
StringBuilder(
256);
do{
res =
FindWindowEx(hParent,res,
null,
null);
GetClassName(res,sb1,
256);
if(sb1.
ToString().
Equals(
"WindowsForms10.EDIT.app.0.34f5582_r8_ad1"))
MainForm.
SendMessage(res,
WM_SETTEXT,
IntPtr.
Zero, res.
ToString());
//MessageBox.Show(res.ToString() + "-" + sb1.ToString());
}
while (res !=
IntPtr.
Zero);
}
这里使用到了FindWindowEx、GetClassName、SendMessage、FindWindowEx,需要提前做引入
[
DllImport(
"User32.dll", EntryPoint =
"SendMessage")]
private
static
extern
int
SendMessage(
IntPtr hWnd,
int Msg,
IntPtr wParam,
string lParam);
[
DllImport(
"User32.dll",EntryPoint=
"GetClassName")]
public
static
extern
int
GetClassName
(
IntPtr
hWnd,
StringBuilder
lpString,
int
nMaxCont);
[
DllImport(
"User32.dll",EntryPoint=
"FindWindowEx",CharSet=
CharSet.
Auto)]
public
static
extern
IntPtr
FindWindowEx(
IntPtr parent,
IntPtr childe,
string strclass,
string FrmText);
[
DllImport(
"user32.dll", EntryPoint =
"FindWindowEx", SetLastError =
true)]
public
static
extern
IntPtr
FindWindowEx(
IntPtr hwndParent,
uint hwndChildAfter,
string lpszClass,
string lpszWindow);
获取被控制应用的查询订单管理按钮
/**
* 获取按钮:"查询订单管理"
**/
private
void
getButtonControl(
IntPtr hParent,
int index){
IntPtr res =
IntPtr.
Zero;
StringBuilder sb =
new
StringBuilder(
256);
int num =
0;
//
do{
res=
FindWindowEx(hParent,res,
null,
null);
GetClassName(res,sb,
256);
if(sb.
ToString().
Equals(
"WindowsForms10.BUTTON.app.0.34f5582_r8_ad1")){
num +=
1;
//MessageBox.Show(res.ToString());
}
if(num == index)
searchHwnd = res;
}
while(num!=index);
}
注意:这里有一个index值设置为3,这里的3是我们在对方程序中一个一个尝试出来的,暂时没有去深究好的办法
在“测试”的按钮点击方法中最后两个语句
OrderId.Enabled =
true;
StatusId.Enabled =
true;
表示把“OMS单号”、“状态”后的文件输入框设置为可用
“执行”按钮的处理方法
/**
* 开始执行处理
**/
void
StartClick(
object sender,
EventArgs e)
{
//判断一下是否有数据
if(
dataTable.Rows.Count ==
1){
MessageBox.
Show(
"大兄弟,还没有上传要处理的数据!");
return;
}
if(
totalRowCount ==
processedCount){
MessageBox.
Show(
"大兄弟,都处理完成,要处理赶下一把吧!");
return;
}
//
TODO
:判断本应用的控件ID写入的值是否存在,不存在则提示不可以执行
strOrderId =
OrderId.Text;
strStatusId =
StatusId.Text;
if(
strOrderId.
Equals(
"") ||
strStatusId.
Equals(
"")){
MessageBox.
Show(
"大兄弟,控件ID值还没有维护上去,不知道怎么处理呢!");
return;
}
//
TODO
:把写入控件值的控件设置为不可用,以防止被修改
OrderId.Enabled =
false;
StatusId.Enabled =
false;
//process.Text = getProcessedTips();
//
TODO
:把另一个应用中的控件中写入的值先清空
clearControlhwndInfo(
omsHwnd);
//禁用关闭按钮
closeWindow.Enabled =
false;
//点击开始按钮后,先设置为需要执行
Ex =
true;
//
TODO
:开始做处理
while(
Ex){
//遍历每一行取出对应的数据
for(
int i=
0;i<
dataTable.Rows.Count-
1;i++){
//ToDo:这里需要把列表中的值写入到另一个窗口中
String order =
dataTable.Rows[i].Cells[
"Order"].Value.
ToString();
String status =
dataTable.Rows[i].Cells[
"status"].Value.
ToString();
//MessageBox.Show(String.Format("单号:{0},状态:{1}",order,status));
//
TODO
:需要把拿到的列表中的值写入到另一个控件中去
setInfoToControl(
omsHwnd,
strOrderId,order);
setInfoToControl(
omsHwnd,
strStatusId,status);
//
TODO
:向“查询订单管理”铵钮发送点击命令(模拟点击按钮操作)
PostMessage(
MainForm.
searchHwnd,
BM_CLICK,
IntPtr.
Zero,
null);
//查找tip
while(
true){
Thread.
Sleep(
1000);
tip =
FindWindow(
null,
"提示");
if(
tip !=
IntPtr.
Zero)
break;
}
//MessageBox.Show(tip.ToString());
getTipsInfo(
tip);
//关闭OMS提示框
MainForm.
SendMessage(
tip,
WM_CLOSE,
IntPtr.
Zero,
null);
if(
process_code ==
1){
//oms补单工具自己处理失败了
MessageBox.
Show(
process_result);
//报错后保证程序可以点击关闭
Ex =
false;
closeWindow.Enabled =
true;
return;
}
else {
//
TODO
:根据执行的结查来判断需要向DataGridView中指定列写入值,同时需要关闭另一个程序的提示框
String process_status =
process_code+
"";
//处理状态
dataTable.Rows[i].Cells[
"process_status"].Value=process_status;
String result =
process_result;
dataTable.Rows[i].Cells[
"result"].Value=result;
//每次成功处理需要修改处理的记录数
processedCount +=
1;
//更新处理进度显示
process.Text =
getProcessedTips();
}
}
//处理完成后需要把关闭按钮置为可用,且设置不需要再处理数据
if(
totalRowCount-
processedCount ==
0){
Ex =
false;
closeWindow.Enabled =
true;
}
}
}
这里有一个点要注意:当我们把模拟了点击被控制程序的“查询订单管理”按钮,在获取到对应弹出提示框后需要Sleep一下,这里的目的是有了提示框但是windows要把这个提示框刷新显示出来需要一定的时间,否则我们程序向下去操作时会读到不提示框中我们想要提信息
这里我们使用了PostMessage,需要提前引入
[
DllImport(
"user32.dll",EntryPoint=
"PostMessage")]
public
static
extern
bool
PostMessage(
IntPtr hwnd,
int msg,
IntPtr wParam,
string lParam);
在处理前需要做好基础的判断
1,是否上传了待处理的数据,或者全部数据都处理完成了
2,在我们程序“OMS单号”、“状态”后的文件输入框中是否录入了被控制应用的输入框的控件ID,以便于后续在读取数据时让程序知道把我们待处理的数据写入到被控制应用的哪个控件上去
3,如果1,2都通过校验则把“OMS单号”、“状态”后的文件输入框禁用防止数据被无意修改掉,同时执行后面的操作
在读取待处理数据前需要把被控制的应用程序中控件中的ID值清空一下,因为接下来我们的程序要向指定的控制写入要处理的值了
/**
* 封装一个方法把oms补单工具中的各个控件ID中的值清空
**/
private
void
clearControlhwndInfo(
IntPtr hParent){
IntPtr res =
IntPtr.
Zero;
StringBuilder sb1 =
new
StringBuilder(
256);
do{
res =
FindWindowEx(hParent,res,
null,
null);
GetClassName(res,sb1,
256);
if(sb1.
ToString().
Equals(
"WindowsForms10.EDIT.app.0.34f5582_r8_ad1"))
MainForm.
SendMessage(res,
WM_SETTEXT,
IntPtr.
Zero,
"");
}
while (res !=
IntPtr.
Zero);
}
程序一开始执行则把“关闭”按钮禁用掉,并设置执行标记为可执行
接下来使用一个while循环去一行一行读取我们待处理的数据,同时在每一次的while中再嵌套一个while来让程序一直去判断被控制程序的提示框弹出,只有在弹出提示框则表示这个一行数据处理过了,则进行下面的操作,获取提示框中的信息
/**
* 获取提示框中的信息
**/
private
void
getTipsInfo(
IntPtr tip){
IntPtr res =
IntPtr.
Zero;
String str_tips =
"";
do{
StringBuilder sb1 =
new
StringBuilder(
256);
StringBuilder sb =
new
StringBuilder(
256);
res =
FindWindowEx(tip,res,
null,
null);
GetClassName(res,sb1,
256);
GetWindowText(res,sb,
256);
if(sb1.
ToString().
Equals(
"Static") && sb.
ToString().Length>
0){
//找到提示信息
str_tips = sb.
ToString();
if(!str_tips.
Contains(
"执行完毕")){
process_code =
1;
process_result = str_tips +
",请检查oms补单工具!";
}
else
if(str_tips.
Contains(
"1条保存失败")){
process_code =
2;
process_result = str_tips;
}
else
if(str_tips.
Contains(
"1条保存成功")){
process_code =
3;
process_result = str_tips;
}
else {
process_code =
4;
process_result = str_tips;
}
}
}
while(res!=
IntPtr.
Zero);
}
接下来根据弹出对话框中的内容做程序内容的判断同时把DataGridView中需要数据做绑定
当处理完所有的数据后激法“关闭”按钮的可用
“停止”按钮的方法
/**
* 停止按钮
**/
void
StopClick(
object sender,
EventArgs e)
{
//ToDo:要等待另一个系统返回了处理完成提示框
Ex =
false;
closeWindow.Enabled =
true;
}
“关闭”按钮的方法
/**
* 关闭程序,关闭铵钮
**/
void
CloseClick(
object sender,
EventArgs e)
{
this.
Close();
}
整个核心程序的代码如下:
/*
* Created by SharpDevelop.
* User: adven
* Date: 2021/1/29
* Time: 20:19
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace BD
{
///
<
summary
>
///
Description of MainForm.
///
<
/
summary
>
public
partial
class
MainForm :
Form
{
const
int
WM_SETTEXT =
0x000C;
const
int
WM_LBUTTONDOWN =
0x0201;
const
int
WM_LBUTTONUP =
0x0202;
const
int
WM_CLOSE =
0x0010;
const
int
BM_CLICK =
0xF5;
[
DllImport(
"user32.dll")]
public
static
extern
IntPtr
FindWindow(
string lpClassName,
string lpWindowName);
[
DllImport(
"User32.dll", EntryPoint =
"SendMessage")]
private
static
extern
int
SendMessage(
IntPtr hWnd,
int Msg,
IntPtr wParam,
string lParam);
[
DllImport(
"User32.dll",EntryPoint=
"FindWindowEx",CharSet=
CharSet.
Auto)]
public
static
extern
IntPtr
FindWindowEx(
IntPtr parent,
IntPtr childe,
string strclass,
string FrmText);
[
DllImport(
"user32.dll", EntryPoint =
"FindWindowEx", SetLastError =
true)]
public
static
extern
IntPtr
FindWindowEx(
IntPtr hwndParent,
uint hwndChildAfter,
string lpszClass,
string lpszWindow);
[
DllImport(
"User32.dll",EntryPoint=
"GetWindowText")]
public
static
extern
int
GetWindowText(
IntPtr hWnd,
StringBuilder lpString,
int nMaxCont);
[
DllImport(
"User32.dll",EntryPoint=
"GetClassName")]
public
static
extern
int
GetClassName(
IntPtr hWnd,
StringBuilder lpString,
int nMaxCont);
[
DllImport(
"user32.dll",EntryPoint=
"PostMessage")]
public
static
extern
bool
PostMessage(
IntPtr hwnd,
int msg,
IntPtr wParam,
string lParam);
//另外一个程序的hwnd
private
static
IntPtr
omsHwnd =
IntPtr.
Zero;
private
static
IntPtr
searchHwnd =
IntPtr.
Zero;
//查询订单管理按钮
private
static
IntPtr
tip =
IntPtr.
Zero;
//弹出的提示框
//列表中数据处理进度
private
static
int
totalRowCount =
0;
//总共要处理的数据记录条数
private
static
int
processedCount =
0;
//已经处理的记录条数
//是否可以循环执行的标记
private
static
Boolean
Ex =
false;
//判断是否要执行
//对应要写入应用中的控件ID值
private
String
strOrderId =
"";
private
String
strStatusId =
"";
//定时器内方法执行的判断标记
private
Boolean
timerEx =
false;
//定时器是执行内部方法,默认为false
//oms补单工具的处理结果
private
static
int
process_code;
//1:程序错误了走不过去了,2:处理完了但是未成功,3:且已成功
private
static
String
process_result;
//提示信息
public
MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//
//
TODO
: Add constructor code after the InitializeComponent() call.
//
}
/**
*这里提供一个提示信息的展示区
格式:总记录数:{0} 已处理记录数:{1} 待处理记录数:{2}
**/
private
String
getProcessedTips(){
return
String.
Format(
"总记录数:{0} 已处理记录数:{1} 待处理记录数:{2} ",
totalRowCount,
processedCount,
totalRowCount-
processedCount);
}
/**
* 输入待处理Excel文件的地址,双击可以打开文件选择对话框,选择的文件全路径会显示在文本输入框中
**/
void
TEXT_PATHDoubleClick(
object sender,
EventArgs e)
{
//打开读取文件的对话框,并且把读到的文件路径显示在控件
OpenFileDialog fd =
new
OpenFileDialog();
//指定可以打开文件的类型
fd.Filter =
"Excel(*.xls)|*.xls|Excel(*.xlsx)|*.xlsx";
if(fd.
ShowDialog() ==
DialogResult.
OK){
//得到完整的路径,并把这个路径绑定到TEXT_PATH控件
TEXT_PATH.Text = fd.FileName;
}
}
/**
* 上传按钮,把Excel的数据写入到DataGridView的列表中
**/
void
UplodaClick(
object sender,
EventArgs e)
{
if(
TEXT_PATH.Text.
Equals(
"双击选择文件,文 件类型为Excel,文件格式要求为两列“OMS单号”、“状态”")){
MessageBox.
Show(
"大兄弟,似乎没有选择要上传文件Excel文件!");
return;
}
Boolean result =
Utils.
exceToDataGrid(
TEXT_PATH.Text,
dataTable);
if(result){
MessageBox.
Show(
"成功加载数据!");
}
prcessFileName.Text =
"当前处理文件:" +
TEXT_PATH.Text;
TEXT_PATH.Text =
"";
totalRowCount =
dataTable.Rows.Count-
1;
processedCount =
0;
//重置已处理的数量
process.Text =
getProcessedTips();
OrderId.Text =
"";
StatusId.Text =
"";
}
/**
* 导出处理结果为Excel表格
**/
void
DownloadClick(
object sender,
EventArgs e)
{
Utils.
DataGridToExcel(
dataTable);
}
/**
* 开始执行处理
**/
void
StartClick(
object sender,
EventArgs e)
{
//判断一下是否有数据
if(
dataTable.Rows.Count ==
1){
MessageBox.
Show(
"大兄弟,还没有上传要处理的数据!");
return;
}
if(
totalRowCount ==
processedCount){
MessageBox.
Show(
"大兄弟,都处理完成,要处理赶下一把吧!");
return;
}
//
TODO
:判断本应用的控件ID写入的值是否存在,不存在则提示不可以执行
strOrderId =
OrderId.Text;
strStatusId =
StatusId.Text;
if(
strOrderId.
Equals(
"") ||
strStatusId.
Equals(
"")){
MessageBox.
Show(
"大兄弟,控件ID值还没有维护上去,不知道怎么处理呢!");
return;
}
//
TODO
:把写入控件值的控件设置为不可用,以防止被修改
OrderId.Enabled =
false;
StatusId.Enabled =
false;
//process.Text = getProcessedTips();
//
TODO
:把另一个应用中的控件中写入的值先清空
clearControlhwndInfo(
omsHwnd);
//禁用关闭按钮
closeWindow.Enabled =
false;
//点击开始按钮后,先设置为需要执行
Ex =
true;
//
TODO
:开始做处理
while(
Ex){
//遍历每一行取出对应的数据
for(
int i=
0;i<
dataTable.Rows.Count-
1;i++){
//ToDo:这里需要把列表中的值写入到另一个窗口中
String order =
dataTable.Rows[i].Cells[
"Order"].Value.
ToString();
String status =
dataTable.Rows[i].Cells[
"status"].Value.
ToString();
//MessageBox.Show(String.Format("单号:{0},状态:{1}",order,status));
//
TODO
:需要把拿到的列表中的值写入到另一个控件中去
setInfoToControl(
omsHwnd,
strOrderId,order);
setInfoToControl(
omsHwnd,
strStatusId,status);
//
TODO
:向“查询订单管理”铵钮发送点击命令(模拟点击按钮操作)
PostMessage(
MainForm.
searchHwnd,
BM_CLICK,
IntPtr.
Zero,
null);
//查找tip
while(
true){
Thread.
Sleep(
1000);
tip =
FindWindow(
null,
"提示");
if(
tip !=
IntPtr.
Zero)
break;
}
//MessageBox.Show(tip.ToString());
getTipsInfo(
tip);
//关闭OMS提示框
MainForm.
SendMessage(
tip,
WM_CLOSE,
IntPtr.
Zero,
null);
if(
process_code ==
1){
//oms补单工具自己处理失败了
MessageBox.
Show(
process_result);
//报错后保证程序可以点击关闭
Ex =
false;
closeWindow.Enabled =
true;
return;
}
else {
//
TODO
:根据执行的结查来判断需要向DataGridView中指定列写入值,同时需要关闭另一个程序的提示框
String process_status =
process_code+
"";
//处理状态
dataTable.Rows[i].Cells[
"process_status"].Value=process_status;
String result =
process_result;
dataTable.Rows[i].Cells[
"result"].Value=result;
//每次成功处理需要修改处理的记录数
processedCount +=
1;
//更新处理进度显示
process.Text =
getProcessedTips();
}
}
//处理完成后需要把关闭按钮置为可用,且设置不需要再处理数据
if(
totalRowCount-
processedCount ==
0){
Ex =
false;
closeWindow.Enabled =
true;
}
}
}
/**
* 停止按钮
**/
void
StopClick(
object sender,
EventArgs e)
{
//ToDo:要等待另一个系统返回了处理完成提示框
Ex =
false;
closeWindow.Enabled =
true;
}
/**
* 关闭程序,关闭铵钮
**/
void
CloseClick(
object sender,
EventArgs e)
{
this.
Close();
}
/**
* 点击测试是为了拿到所有输入框的句柄,并显示在对方应用的控件中
**/
void
TestClick(
object sender,
EventArgs e)
{
//获取oms补单工具的窗口句柄
IntPtr hwnd =
MainForm.
FindWindow(
null,
"OMS补单工具");
omsHwnd = hwnd;
getControlhwndId(
omsHwnd);
getButtonControl(
omsHwnd,
3);
buttonID.Text =
"查询订单管理按钮:" +
searchHwnd.
ToString();
OrderId.Enabled =
true;
StatusId.Enabled =
true;
}
/**
* 封装一个方法用来获取“oms补单工具”中的各个控件的ID值并写入到oms补单工具的输入框中
**/
private
void
getControlhwndId(
IntPtr hParent){
IntPtr res =
IntPtr.
Zero;
StringBuilder sb1 =
new
StringBuilder(
256);
do{
res =
FindWindowEx(hParent,res,
null,
null);
GetClassName(res,sb1,
256);
if(sb1.
ToString().
Equals(
"WindowsForms10.EDIT.app.0.34f5582_r8_ad1"))
MainForm.
SendMessage(res,
WM_SETTEXT,
IntPtr.
Zero, res.
ToString());
//MessageBox.Show(res.ToString() + "-" + sb1.ToString());
}
while (res !=
IntPtr.
Zero);
}
/**
* 获取提示框中的信息
**/
private
void
getTipsInfo(
IntPtr tip){
IntPtr res =
IntPtr.
Zero;
String str_tips =
"";
do{
StringBuilder sb1 =
new
StringBuilder(
256);
StringBuilder sb =
new
StringBuilder(
256);
res =
FindWindowEx(tip,res,
null,
null);
GetClassName(res,sb1,
256);
GetWindowText(res,sb,
256);
if(sb1.
ToString().
Equals(
"Static") && sb.
ToString().Length>
0){
//找到提示信息
str_tips = sb.
ToString();
if(!str_tips.
Contains(
"执行完毕")){
process_code =
1;
process_result = str_tips +
",请检查oms补单工具!";
}
else
if(str_tips.
Contains(
"1条保存失败")){
process_code =
2;
process_result = str_tips;
}
else
if(str_tips.
Contains(
"1条保存成功")){
process_code =
3;
process_result = str_tips;
}
else {
process_code =
4;
process_result = str_tips;
}
}
}
while(res!=
IntPtr.
Zero);
}
/**
* 封装一个方法把oms补单工具中的各个控件ID中的值清空
**/
private
void
clearControlhwndInfo(
IntPtr hParent){
IntPtr res =
IntPtr.
Zero;
StringBuilder sb1 =
new
StringBuilder(
256);
do{
res =
FindWindowEx(hParent,res,
null,
null);
GetClassName(res,sb1,
256);
if(sb1.
ToString().
Equals(
"WindowsForms10.EDIT.app.0.34f5582_r8_ad1"))
MainForm.
SendMessage(res,
WM_SETTEXT,
IntPtr.
Zero,
"");
}
while (res !=
IntPtr.
Zero);
}
/**
* 封装方法向控件中写入信息
**/
private
void
setInfoToControl(
IntPtr hParent,
String strControlId,
String info){
IntPtr res =
IntPtr.
Zero;
do{
res =
FindWindowEx(hParent,res,
null,
null);
if(res.
ToString().
Equals(strControlId)){
MainForm.
SendMessage(res,
WM_SETTEXT,
IntPtr.
Zero, info);
}
}
while(res !=
IntPtr.
Zero);
}
/**
* 获取按钮:"查询订单管理"
**/
private
void
getButtonControl(
IntPtr hParent,
int index){
IntPtr res =
IntPtr.
Zero;
StringBuilder sb =
new
StringBuilder(
256);
int num =
0;
//
do{
res=
FindWindowEx(hParent,res,
null,
null);
GetClassName(res,sb,
256);
if(sb.
ToString().
Equals(
"WindowsForms10.BUTTON.app.0.34f5582_r8_ad1")){
num +=
1;
//MessageBox.Show(res.ToString());
}
if(num == index)
searchHwnd = res;
}
while(num!=index);
}
}
}