利用API函數向外部應用程序發送消息收藏

//爲了使用Win32 API,需要先引入下面這個命名空間
using System.Runtime.InteropServices;

namespace k8
{
    public partial class _3k8Frm : Form
    {
        #region Dll Import 添加對API的引用

            //獲取主窗口句柄的API函數
            [DllImport("User32.dll", EntryPoint = "FindWindow")]
            private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
           
            //獲取子窗口句柄的API函數
            [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 int SendMessage(IntPtr hWnd,int Msg,IntPtr wParam,string lParam);

            const int WM_GETTEXT = 0x000D;
            const int WM_SETTEXT = 0x000C;
            const int WM_CLICK = 0x00F5;

        #endregion

        #region 聲明字段 用Spy++查到的
            //下面的這些參數都可以用Spy++查到
            string lpszParentClass = "TForm1"; //整個窗口的類名
            string lpszParentWindow = "Form1"; //窗口標題
            string lpszClass = "TEdit"; //需要查找的子窗口的類名,也就是輸入框
            string lpszClass_Submit = "TBitBtn"; //需要查找的Button的類名
            string lpszName_Submit = "確定"; //需要查找的Button的標題
            string text = "";

            string lpszClass1 = "TPanel";//多了一個類,輸入框和按鈕都放在這個類上的!

            IntPtr ParenthWnd = new IntPtr(0);
            IntPtr ParenthWnd_sub = new IntPtr(0);
            IntPtr EdithWnd = new IntPtr(0);

            //下面的參數設定登陸用戶名及密碼
            string UserID_3k8 = "4898";
            string Pwd_3k8="2";

        #endregion

        #region 構造函數
       
        public _3k8Frm()
        {
            InitializeComponent();
        }
        #endregion
        
        #region SearchWindow 核心部分,查找窗體並對它進行登陸操作

        private int SearchWindow()
        {
            int retval = 0; //增加一個返回值用來判斷操作是否成功

            //查到窗體,得到整個窗體
            ParenthWnd = FindWindow(lpszParentClass, lpszParentWindow);
            ParenthWnd_sub = FindWindowEx(ParenthWnd, EdithWnd, lpszClass1, "");


             //判斷這個窗體是否有效
            if (!ParenthWnd_sub.Equals(IntPtr.Zero))
            {
                //得到User Name這個子窗體,並設置其內容
                EdithWnd = FindWindowEx(ParenthWnd_sub, EdithWnd, lpszClass, "");
                if (!EdithWnd.Equals(IntPtr.Zero))
                {
                    text = Pwd_3k8.Trim(); //this.tbUserName.Text.Trim();
                    //調用SendMessage方法設置其內容
                    SendMessage(EdithWnd, WM_SETTEXT, (IntPtr)0, text);
                    retval++;
                }

                //得到Password這個子窗體,並設置其內容
                EdithWnd = FindWindowEx(ParenthWnd_sub, EdithWnd, lpszClass, "");
                if (!EdithWnd.Equals(IntPtr.Zero))
                {
                    text = UserID_3k8; //this.tbPassword.Text.Trim();
                    SendMessage(EdithWnd, WM_SETTEXT, (IntPtr)0, text);
                    retval++;
                }

                 //得到Button這個子窗體,並觸發它的Click事件
                EdithWnd = (IntPtr)0;
                EdithWnd = FindWindowEx(ParenthWnd_sub, EdithWnd, lpszClass_Submit, lpszName_Submit);
                if (!EdithWnd.Equals(IntPtr.Zero))
                {
                    SendMessage(EdithWnd, WM_CLICK, (IntPtr)0, "0");
                    retval++;
                }

                return retval;
        }

        #endregion

    }
}

在win2003ser+vs2005下測試通過,交流QQ:69524898

2007.10.10補充如入:

在後面的測試中出現一個問題,當SendMessage當擊確定按鈕後,如果外部應用程序彈出對話框(比如提示你用戶名或密碼錯誤),這時你的程序將暫停運行,必須等待點擊彈出的對話框你的程序才恢復正常!但我希望外部應用程序彈出的對話框並不影響我的程序的運行,於是想到了新開線程來解決,代碼如下:
       private void a()
        {
            SendMessage(EdithWnd, WM_CLICK, (IntPtr)0, "0");
        }

                 //得到Button這個子窗體,並觸發它的Click事件
                EdithWnd = (IntPtr)0;
                EdithWnd = FindWindowEx(ParenthWnd_sub, EdithWnd, lpszClass_Submit, lpszName_Submit);
                if (!EdithWnd.Equals(IntPtr.Zero))
                {
                    //SendMessage(EdithWnd, WM_CLICK, (IntPtr)0, "0");
                        Thread t = new Thread(new ThreadStart(a)); //新建一個運行a方法的線程
                        t.Start();//線程開始
                        t.Join(3000);//暫停3秒
                        t.Abort();//結束線程
                        retval++;
                }

   這樣修改代碼後,實現了想要的效果!但是很麻煩!後來進一步查找資料,原來SendMessage發送消息後要等待返回數據,所以纔會出現程序無反應的問題,而另一個API函數PostMessage發送消息後不等待返回數據,於是又將代碼更改如下:

//首先添加對PostMessage函數的引用
        [DllImport("User32.dll", EntryPoint = "PostMessage")]
        private static extern int PostMessage(IntPtr hwnd,int Msg,IntPtr wParam,string lParam);

//修改代碼
                EdithWnd = (IntPtr)0;
                EdithWnd = FindWindowEx(ParenthWnd_sub, EdithWnd, lpszClass_Submit, lpszName_Submit);
                if (!EdithWnd.Equals(IntPtr.Zero))
                {
                    PostMessage(EdithWnd, WM_CLICK, (IntPtr)0, "0");
                    retval++;
                }

問題圓滿解決,又簡單方便!

順便說一下SendMessage和PostMessage如果是點擊彈出對話框的確定,代碼要如下:
PostMessage(EdithWnd, WM_CLICK, (IntPtr)0, "2");
SendMessage(EdithWnd, WM_CLICK, (IntPtr)0, "2");

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章