C#中用WinAPI调用外部程序

    在使用别人的程序时,我们常发现一些好的功能,想通过自己的程序来重复调用。可偏偏这个程序没有留可编程接口,无法通过API、DLL、COM等方式实现调用。早些年与同仁们讨论时,常对此深表遗憾。最近,通过研究Windows API的使用方法,终于从理论上解决了这一问题,即可通WinAPI中SendMessage、EnumChildWindows等,从模拟操作的角度来调用指定程序的指定功能。
    我们知道,Windows是消息驱动的,即Windows窗口、控件的任何操作,都是通过消息事件来完成的。从理论上讲,在我们自己的程序中,只要能准确地找到相应功能所在的窗口或控件的句柄Handle,发出相应的消息,即可完成相应任务。从这个层面上,这种技术可以应用在所有windows程序上。只是这种技术的处理,需要非常细心。因为在实际应用中,从某一个程序中找到相应的控件(包括Parent/Child/Next等)还是比较麻琐的,一不小心,调用的功能就实法实现,还有可能导致程序甚至系统的崩溃。所以,这种技术的关键在于两个地方:一是找准句柄,二是找对消息。
    推荐分析一个窗体(控件)的句柄或消息的工具:SPY++,这在Visual Studio Tools中有,操作起来很简单。

    C#中实现外部程序调用,可以通过封装User32.dll中sendmessage等函数来实现。我已将常用的功能封装成一个类:
using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Runtime.InteropServices;


namespace  MuliCall
{
    
class  WinApi
    {
        
#region   宏定义

        
public   const   int  WM_KEYDOWN  =   0x100 ;
        
public   const   int  WM_KEYUP  =   0x101 ;
        
public   const   int  VK_CONTROL  =   0x11 ;
        
public   const   int  VK_F5  =   0x74 ;
        
public   const   int  KEYEVENTF_KEYUP  =   0x2 ;
        
public   const   int  VK_MENU  =   0x12 ;
        
public   const   int  WM_SETTEXT  =   0xC ;
        
public   const   int  WM_CLEAR  =   0x303 ;
        
public   const   int  BN_CLICKED  =   0 ;
        
public   const   int  WM_LBUTTONDOWN  =   0x201 ;
        
public   const   int  WM_LBUTTONUP  =   0x202 ;
        
public   const   int  WM_CLOSE  =   0x10 ;
        
public   const   int  WM_COMMAND  =   0x111 ;
        
public   const   int  WM_SYSKEYDOWN  =   0x104 ;

        
#endregion

        
public   delegate   bool  EnumChildWindowsProc(IntPtr hwnd,  int  lParam);         

        
#region   WinAPI定义

        [DllImport(
" User32.dll " , EntryPoint  =   " SendMessage " )]
        
public   static   extern   int  SendMessage(
            
int  hWnd,  //  handle to destination window 
             int  Msg,  //  message 
             int  wParam,  //  first message parameter 
              int  lParam  //  second message parameter 
        );
        [DllImport(
" User32.dll " , EntryPoint  =   " SendMessage " )]
        
public   static   extern   int  SendTxtMessage(
            
int  hWnd,  //  handle to destination window 
             int  Msg,  //  message 
             int  wParam,  //  first message parameter 
             char [] lParam
            
//  int  lParam  //  second message parameter 
        );
        [DllImport(
" user32.dll " , EntryPoint  =   " PostMessage " )]
        
public   static   extern   int  PostMessage(
            
int  hwnd,
            
int  wMsg,
            
int  wParam,
            
int  lParam
        );

        [DllImport(
" user32.dll " , EntryPoint  =   " FindWindow " )]
        
public   static   extern   int  FindWindow(
            
string  lpClassName,
            
string  lpWindowName
        );
        [DllImport(
" user32.dll " , EntryPoint  =   " FindWindowEx " )]
        
public   static   extern   int  FindWindowEx(
            
int  hwndParent,
            
int  hwndChildAfter,
            
string  lpszClass,
            
string  lpszWindow
        );
        [DllImport(
" user32.dll " , EntryPoint  =   " EnumChildWindows " )]
        
public   static   extern   int  EnumChildWindows(
            
int  hWndParent,
            
int  lpEnumFunc,
            
int  lParam
        );

        [DllImport(
" user32.dll " , EntryPoint  =   " EnumChildWindows " )]
        
public   static   extern   int  EnumChildWindows(
            
int  hWndParent,
            EnumChildWindowsProc lpEnumFunc,
            
int  lParam
        );

        [DllImport(
" user32.dll " , EntryPoint  =   " SetFocus " )]
        
public   static   extern   int  SetFocus(
            
int  hWnd
        );

        [DllImport(
" user32.dll " , EntryPoint  =   " SetWindowText " )]
        
public   static   extern   int  SetWindowText(
            
int  hwnd,
            
string  lpString
        );

        [DllImport(
" user32.dll " , EntryPoint  =   " keybd_event " )]
        
public   static   extern   void  keybd_event(
            
byte  bVk,
            
byte  bScan,
            
int  dwFlags,
            
int  dwExtraInfo
        );

        [DllImport(
" user32.dll " , EntryPoint  =   " SetForegroundWindow " )]
        
public   static   extern   int  SetForegroundWindow(
            
int  hwnd
        );

        [DllImport(
" user32.dll " , EntryPoint  =   " GetClassName " )]
        
public   static   extern   int  GetClassName(
            IntPtr hwnd,
            StringBuilder lpClassName,
            
int  nMaxCount
        );
        [DllImport(
" user32.dll " , EntryPoint  =   " GetWindowText " )]
        
public   static   extern   int  GetWindowText(
            IntPtr hwnd,
            StringBuilder lpString,
            
int  cch
        ); 

        
#endregion
 
         // 综合处理全局HWD
         private   static   int  CurrnetFormHandle  =   0 ;
        
// 综合处理函数

        
public   static   void  SetCurrnetFormHandle( string  strWindow)
        {
            SetCurrnetFormHandle(
null , strWindow,  false );
        }
        
public   static   void  SetCurrnetFormHandle( string  strClass,  string  strWindow,  bool  beForeground)
        {
            CurrnetFormHandle 
=  FindWindow(strClass, strWindow);
            
if  (beForeground)
                SetForegroundWindow(CurrnetFormHandle);
        }
        
public   static   void  SetCurrnetFormHandle( int  hwd,  bool  beForeground)
        {
            CurrnetFormHandle 
=  hwd;
            
if  (beForeground)
                SetForegroundWindow(CurrnetFormHandle);
        }

        
public   static   void  SetCurrnetFormHandle( int  hwd)
        {
            CurrnetFormHandle
= hwd;
        }
        
public   static   int  GetCurrentFormHandle()
        {
            
return  CurrnetFormHandle;
        }

        
// 模拟单击按钮
         public   static   void  ClickButton( string  strWindow)
        {
            ClickButton(
" Button " , strWindow);
        }

        
public   static   void  ClickButton( string  strClass,  string  strWindow)
        {
            ClickButton(CurrnetFormHandle, 
0 , strClass, strWindow);
        }

        
public   static   void  ClickButton( int  hwdParent,  int  hwndChildAfter,  string  strClass,  string  strWindow)
        {
            
int  hwdButton  =  FindWindowEx(hwdParent, hwndChildAfter, strClass, strWindow);
            SendMessage(hwdButton, WM_LBUTTONDOWN, 
0 0 );
            SendMessage(hwdButton, WM_LBUTTONUP, 
0 0 );
        }

        
// 修改文本框内容
         public   static   void  SetWindowsText( string  Parnet_strClass,  string  Parnet_strText,  string  strClass,  string  strText)
        {
            
int  hwdParent  =  FindWindowEx(CurrnetFormHandle,  0 , Parnet_strClass, Parnet_strText);

            
// 停止 ThunderRT6OptionButton
             int  bntHwd  =  FindWindowEx(hwdParent,  0 " ThunderRT6OptionButton " " 停止 " );

            
int  hwdText  =  FindWindowEx(hwdParent, bntHwd, strClass,  null );   // ThunderRT6TextBox
            SendTxtMessage(hwdText, WM_SETTEXT,  0 , strText.ToCharArray());
        }
        
public   static   void  SetWindowsText( string  strClass, string  strText)
        {
            SetWindowsText( strClass, 
null , strText);
        }
        
public   static   void  SetWindowsText(  string  strClass,  string  strWindow,  string  strText)
        {
            SetWindowsText(CurrnetFormHandle, 
0 , strClass, strWindow, strText);
        }
        
public   static   void  SetWindowsText( int  hwdParent,  int  hwndChildAfter,  string  strClass,  string  strWindow,  string  strText)
        {
            
int  hwdText  =  FindWindowEx(hwdParent, hwndChildAfter, strClass, strText);
            SendTxtMessage(hwdText, WM_SETTEXT, 
0 , strText.ToCharArray());
        }

        
// 搜索子窗体
         public   static   void  SearchChild( string  strWindow)
        {
            EnumChildWindowsProc myEnumChild 
=   new  EnumChildWindowsProc(EumWinChiPro);
            
try
            {
                EnumChildWindows(CurrnetFormHandle, myEnumChild, 
0 );
            }
            
catch  (Exception ex)
            {
                ;   
//  MessageBox.Show(ex.Message + "\r\n" + ex.Source + "\r\n\r\n" + ex.StackTrace.ToString());
            }

        }

        
public   static   bool  EumWinChiPro(IntPtr hWnd,  int  lParam)
        {
            StringBuilder s 
=   new  StringBuilder( 1256 );
            GetClassName(hWnd, s, 
1257 );
            
string  ss  =  s.ToString();
            
if  (ss  ==   null )
                ss 
=   "" ;
            ss 
=  ss.Trim();
    
//         MessageBox.Show(ss);
            
//  ThunderRT6TextBox

            StringBuilder s2 
=   new  StringBuilder( 1256 );
            GetWindowText(hWnd, s2, 
1257 );
            ss 
=  s2.ToString(); 
            
return   true ;
        }
    }
}
    使用这个类,在自己的程序中,比较方便地实现外部程序的调用。
  int  hwnd  =  ( int )MainHandlArray[i];
 WinApi.SetCurrnetFormHandle(hwnd);
 WinApi.SetWindowsText(textBox_Class_EditPanel.Text, textBox_Title_EditPanel.ToString(), textBox_Class_Edit.Text, textBoxWorkID.Text);
    使用这种方法,我写个程序多开器,主要实现启动多个实例,能给EDIT框付值,能定时调用其中按钮。  

    多开程序下载



转载于:https://www.cnblogs.com/yuanbao/archive/2007/10/31/944086.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值