c# 编程实现对WINDOWS自带计算器进行操作

来源:互联网 发布:php reflection 意义 编辑:程序博客网 时间:2024/05/20 18:41

在windows平台句柄是共享资源,也就是一个进程可以拿到另外一个进程的句柄,当然包括那个进程创建的窗体句柄,甚至是控件的句柄(除非拿不到该句柄)
方法是:
1.FindWindow 拿到目标窗体的句柄,当然也可其他方式拿到窗体句柄
2.FindwindowEx拿到1上面的控件(应当先知道该控件的名字,俺用spy++探测)
3.SendMessage发送消息给2返回的句柄
下面用windows自带的计算器(calc)进行简单的操作,将两个uint进行运算


//////////////////////////Feng's//////////////////////////////////
/*作为测试仅使用十进制的无符号int进行计算,浮点数,负数不在此列,当然,如果想要仍可算到。
GETControlTEXT 类是对描述的实现进行包装,调用Count方法得到计算结果,调用GetText获取输出
* Count的第一个参数输入第一个操作数,例如123456789;第二个参数输入操作的符号,例如
+ - * / ,获取其他操作符号;第三个参数输入 第二个操作数,例如9876。调用成功后,在计算器上显示计算结果,这时可以调用GetText在Console上输入结果。*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using System.Diagnostics;
public class GETControlTEXT {

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string ClassName, string windowName);

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindowEx(IntPtr hwndPareent,
        IntPtr hwndChildAfter,
        string ClassName,
        string windowName);

    [DllImport("user32.dll", SetLastError = true)]
    static extern int SendMessage(IntPtr hwnd, int msg, IntPtr  wParam, IntPtr  lParam);

  
    //WM_GETTEXT 消息用于获取其他应用程序的标题获取控件的标题
    //0x000D
    //用SendMessage获取
    static int WM_GETTEXT = 0x000D;
    public static void GetText() {
     

        IntPtr jsq = FindWindow(null, "计算器");
        IntPtr ctext = FindWindowEx(jsq, IntPtr.Zero, "Edit", null);


        IntPtr wp = Marshal.AllocHGlobal(4);
        Marshal.WriteInt32(wp, 260);
        IntPtr lp = Marshal.AllocHGlobal(wp);
        SendMessage(ctext, WM_GETTEXT, wp, lp);

        string s = Marshal.PtrToStringAnsi(lp);
    Console.WriteLine(s);


        if(wp != IntPtr.Zero)
            Marshal.FreeHGlobal(wp);
        if(lp != IntPtr.Zero)
            Marshal.FreeHGlobal(lp);
    }

 

    static int BM_CLICK = 0x00F5;
  
    static string button="Button";
    /// <summary>
    /// 用这个函数可以用来编程实现对计算器的操作,仅可用来做十进制计算
    /// </summary>
    /// <param name="firstOperand">第一个操作数</param>
    /// <param name="Operate">操作符号,例如"+","-","*","-","x^y"等等,在CALC上的操作符</param>
    /// <param name="secondOperand"></param>
    public static void Count(uint firstOperand,string Operate,uint secondOperand ) {
        //十进制计算


        //1+1=2
       // BM_CLICK Button被点击
        //WM_SETTEXT 设置文本
        IntPtr jsq = FindWindow(null, "计算器");
        if(jsq == IntPtr.Zero)
            Process.Start("calc");
         jsq = FindWindow(null, "计算器");
        //CE被点击
         IntPtr buttonHandle = FindWindowEx(jsq, IntPtr.Zero, button, "CE");//无法解释为什么点击C只有一声响,却没有任何作用
    
     int rv=   SendMessage(buttonHandle, BM_CLICK, IntPtr.Zero, IntPtr.Zero);//清空原有的数据


     string[] fsary = setUinttoStringAry( firstOperand);
     string[] ssary = setUinttoStringAry( secondOperand);

     foreach(string t in fsary)
         Operator(jsq, t);

     Operator(jsq, Operate);

     foreach(string t in ssary)
         Operator(jsq, t);
        //结果
     Operator(jsq, "=");

    }

    static string[] setUinttoStringAry(uint value) {
        List<string> temp = new List<string>();
        uint c = _Count(value);

       for(uint i = 0; i < c; i++)
        temp.Add(   getValuefromLeftDigit(value, i).ToString());

       return temp.ToArray();
    }


    static void Operator(IntPtr jsq, string oprand) {

      IntPtr  buttonHandle = FindWindowEx(jsq, IntPtr.Zero, button, oprand);
      SendMessage(buttonHandle, BM_CLICK, IntPtr.Zero, IntPtr.Zero);

    }

    internal static uint getValuefromLeftDigit(uint specValue, uint LeftDigit) {

        uint count = 1;
        uint t = specValue;
        while((t /= 10) > 0)
            count++;
        if(count < LeftDigit)

            throw new ArgumentOutOfRangeException
                ("参数LeftDigit指定的位数范围大于specValue参数的位数");

        LeftDigit++;
        uint tempValue = specValue / (uint)Math.Pow(10, count - LeftDigit);
     
        return tempValue % 10;


    }

    public static uint _Count(uint specValue) {
        uint count = 1;
        uint t = specValue;
        while((t /= 10) > 0)
            count++;
        return count;
    }
};