分享

C# API 的一些用法,API控制另一个程序,API控制另一个窗体,触发另一个窗体按钮事件,设置文本

 长江黄鹤 2016-09-07

由于项目要用到文件的转换(word,excel,txt,图片等等转换成ceb 格式),思来想去,不知道用哪种方法来做,网上也没有一些关于 用程序来转换ceb的资料,于是就联系官网,看看他们有没有提供一些借口或者类库给我们这些程序员调用,联系了一位李经理,人蛮好的,很耐心跟我交流的一会,也发了服务版(测试)的提供我参考,看了参考资料,发现是用Java来做的,他的资料说,里面MakerSDKJNI2.dll 有提供接口,也是唯一一个接口public native int SyncConvert2(StringpszSrcFileUrl, String pszDstFileUrl);我在调用的时候,无法进入接口,于是决定放弃调用它的接口,直接在它的转换器上,用程序直接操作。我用的版本是Apabi Maker 5.1。

看看效果图吧

点击button1的时候,程序去做批量转换的工作



现在我们来看下代码吧

[csharp] view plain copy
  1. using System.Runtime.InteropServices;  
  2. //查找主窗体  
  3. [DllImport("user32.dll", EntryPoint = "FindWindow")]  
  4.         public static extern int FindWindow(string lpClassName, string lpWindowName);  
  5.   
  6. // Find Window Ex  
  7.         // 查找窗体的子窗体  
  8.         // @para1: 父窗体的句柄 如果为null,则函数以桌面窗口为父窗口,查找桌面窗口的所有子窗口  
  9.         // @para2: 子窗体的句柄 如果为null,从@para1的直接子窗口的第一个开始查找  
  10.         // @para3: 子窗体的类名 为""表示所有类  
  11.         // @para4: 子窗体的标题 为""表示要查找的窗体无标题 如空白的textBox控件  
  12.         // return: 子窗体的句柄  
  13.         [DllImport("user32.dll", EntryPoint = "FindWindowEx")]  
  14.         private static extern IntPtr FindWindowEx( IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);  
  15.   
  16.  // SendMessage  
  17.   
  18.         // 向窗体发送消息  
  19.   
  20.         // @para1: 窗体句柄  
  21.   
  22.         // @para2: 消息类型  
  23.   
  24.         // @para3: 附加的消息信息  
  25.   
  26.         // @para4: 附加的消息信息  
  27.   
  28.         [DllImport("User32.dll", EntryPoint = "SendMessage")]  
  29.         private static extern int SendMessage(  
  30.             IntPtr hWnd,  
  31.             int Msg,  
  32.             IntPtr wParam,  
  33.             string lParam);  
  34.         const int WM_CLICK = 0x00F5;  // 发送点击消息如调用该窗体(按钮)的"button1_Click();"  
  35.         const int WM_SETTEXT = 0x000C;  // 设置窗体文本 如设置文本框内容  
  36. <pre name="code" class="csharp">        const int WM_GETTEXT = 0x000D;  //获取文本 即一般是获取textbox.text和label.text  

        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(
            IntPtr hWnd,
            uint Msg,
            int wParam,
            int lParam);

/// <summary>
        /// 向控件发送消息(异步,进入消息队列)
        /// </summary>
        /// <param name="hWnd">需要发送消息到的控件句柄</param>
        /// <param name="Msg">消息</param>
        /// <param name="wParam">附加的消息指定信息(当发送键盘消息时此值为键盘按键的十六进制虚拟键盘)</param>
        /// <param name="lParam">附加的消息指定信息(当发送鼠标消息时此值为点击客户区逻辑坐标值,为x+(y<<16))</param>
        /// <returns></returns>
        [DllImport("user32", SetLastError = true)]
        private static extern bool PostMessage(
            int hWnd,
            int Msg,
            int wParam,
            int lParam
            );

IntPtr wdn;//获取主窗体句柄
IntPtr pn ;//转换窗体句柄
IntPtr pn2;
IntPtr pn3;
IntPtr pn4;
IntPtr pn5;

 Process process = new Process();//在定义一个进程来启动ceb转换器


    private void Form3_Load(object sender, EventArgs e)
        {
            process.StartInfo = new ProcessStartInfo(@"C:\Program Files\Founder\Apabi Maker 5.0\Bin\ApaMaker.exe");
            process.Start();
            Thread.Sleep(3000);//停顿3秒钟,等待加载完成到主窗体
            int hDesktop = FindWindow("Progman", null);//获取系统句柄
            hDesktop = GetWindow(hDesktop, GW_CHILD);//获取其子窗口句柄,就是桌面的句柄
            //SetParent((int)this.Handle, hDesktop);//设置父窗体,第一个为要被设置的窗口,第二个参数为指定其父窗口句柄
            //SendMessage((IntPtr)329266, WM_SETTEXT, (IntPtr)0, @"12345678955");
            wdn = (IntPtr)FindWindow(null, "Apabi Maker");//找到主窗体
            pn = FindWindowEx(wdn, IntPtr.Zero, "wxWindowClassNR", null); //找到第一个panel。转换
            pn2 = FindWindowEx(wdn, pn, "wxWindowClassNR", null); //找到第二个panel。批量转换
            pn3 = FindWindowEx(wdn, pn2, "wxWindowClassNR", null); //找到合并
            pn4 = FindWindowEx(wdn, pn3, "wxWindowClassNR", null); //找到拆分
            pn5 = FindWindowEx(wdn, pn4, "wxWindowClassNR", null); //找到结果


        }

 private void button1_Click(object sender, EventArgs e)
        {
            //给批量转换文本框赋值
            IntPtr txt = FindWindowEx(pn2, IntPtr.Zero, "Edit", null);
            IntPtr txt2 = FindWindowEx(pn2, txt, "Edit", null);
            SendMessage(txt, WM_SETTEXT, (IntPtr)0, @"C:\Users\Administrator\Desktop\新建文件夹 (3)");
            SendMessage(txt2, WM_SETTEXT, (IntPtr)0, @"C:\Users\Administrator\Desktop\新建文件夹 (4)");

            //在批量转换查找相应按钮
            IntPtr btn = FindWindowEx(pn2, IntPtr.Zero, "Static", null);
            IntPtr btn2 = FindWindowEx(pn2, btn, "Static", null);
            IntPtr btn3 = FindWindowEx(pn2, btn2, "Static", null);
            IntPtr btn4 = FindWindowEx(pn2, btn3, "Static", null);//添加到列表
            IntPtr btn5 = FindWindowEx(pn2, btn4, "Static", null);//删除
            IntPtr btn6 = FindWindowEx(pn2, btn5, "Static", null);//清空
            IntPtr btn7 = FindWindowEx(pn2, btn6, "Static", null);//开始转换

            Thread.Sleep(500);

            SendBtn((int)btn4);//添加到列表

            Thread.Sleep(1000);

            SendBtn((int)btn7);//开始转换
            ti = new System.Windows.Forms.Timer();
            ti.Interval = 300;
            ti.Enabled = true;
            ti.Tick += new EventHandler(ti_Tick);
            Thread.Sleep(1000);
            SendBtn((int)btn6);//清空

           

        }

void ti_Tick(object sender, EventArgs e)
        {
            IntPtr lb = FindWindowEx(pn5, IntPtr.Zero, "Static", null);
            IntPtr lb2 = FindWindowEx(pn5, lb, "Static", null);
            const int buffer_size = 1024;
            StringBuilder buffer = new StringBuilder(buffer_size);
            SendMessage(lb2, WM_GETTEXT, buffer_size, buffer);
            //任务列表(3成功,0失败,0跳过,0等待)
            string strRet = buffer.ToString().Replace("任务列表(", "").Replace(")", "");//3成功,0失败,0跳过,0等待

            string[] arrstr = strRet.Split(',');
            string strR = arrstr[arrstr.Length - 1];
            if (strR == "0等待")
            {
                ti.Dispose();
                MessageBox.Show("转换已完成");
            }
        }

 public void SendBtn(int wn)
        {
            const int WM_LBUTTONDOWN = 0x201;
            int WM_LBUTTONUP = 0x202;
            PostMessage(wn, WM_LBUTTONDOWN, 0, 20);
            Thread.Sleep(200);
            PostMessage(wn, WM_LBUTTONUP, 0, 20);
        }



大致的代码如上。

不过在做的过程遇到了一些问题,在发送消息的时候,赋值给文本,是没有问题的,但是要触发按钮事件,貌似不行,即

[csharp] view plain copy
  1. SendMessage(btn, WM_CLICK, 0, 0);  

是没有效果的,然后就郁闷了很久,上午找资料,无果,只能用

[csharp] view plain copy
  1. PostMessage  
来模拟鼠标点击事件,值得注意的是最后的那个参数,我在这里给的参数的20,为什么呢,因为在我给0的时候,无法触发事件,即:

[csharp] view plain copy
  1.   PostMessage(wn, WM_LBUTTONDOWN, 0, 0);  

我又郁闷了,就用Microsoft Spy++
来看看发送的消息是怎么样的,然后发现有个坐标,如果按钮的句柄的point(0,0)的话点击是没有效果的,就好像你在桌面的坐标(0,0)点击的效果是一样

所以最后的参数我给了20,因为,按钮的大小应该也是有20的。

好了今天就说到这里吧





    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多