鼠标取词相关

来源:互联网 发布:ipad上软件hd 编辑:程序博客网 时间:2024/04/28 01:48

1撷取自WinObject.cs,针对部份输入文字型的控件,可使用WM_SETTEXT指定文字内容

//由类别名称识别是否为特定的文字输入控件对象
public bool IsEditControl
{
        get 
        {
               string cn=ClassName.ToUpper();
               return (cn=="EDIT" || cn=="THUNDERRT5TEXTBOX" || cn=="RICHCNTL" || cn=="RICHEDIT");
        }
}
 
const uint WM_GETTEXTLENGTH=0x0e;
const uint WM_GETTEXT=0x0d;
const uint WM_SETTEXT=0x0c;
 
//窗口对象的标题或控件的文字内容
public string Text
{
 
        get
        {
               if (IsEditControl) 
               {
                       int l=(int) SendMessage(hWnd,WM_GETTEXTLENGTH,0,0);
                       StringBuilder sb=new StringBuilder(l+1);
                       l=(int) SendMessage(hWnd,WM_GETTEXT,sb.Capacity,sb);
                       return sb.ToString();
               }
               else 
               {
                       int length = GetWindowTextLength(hWnd);
                       StringBuilder sb = new StringBuilder(length + 1);
                       GetWindowText(hWnd, sb, sb.Capacity);
                       return sb.ToString();                         
               }
        }
        set
        {
               if (IsEditControl) 
                       SendMessage(hWnd,WM_SETTEXT,0,value);
               else 
                       SetWindowText(hWnd, value);
        }
}
-----end-----
 
 
-----box-----
#程序2 与下拉选单互动的范例
[DllImport("USER32.DLL", SetLastError=true)]
public static extern long SendMessage(IntPtr hWnd, uint msg, int wparam, StringBuilder sb);
private void button2_Click(object sender, System.EventArgs e)
{
//Spy++观察该下拉选单控件的从属关系,以FindChild方式锁定之。
//由于同一层有多个TadvCityCbBox控件,因此使用FindChildren再由数组中取出第2(户籍地)
//原理及细节说明请参见前期文章。
WinObject cb = (WinObject)
        WinObject.FindWindow("TBasicForm","财政部九十二年度综合所得税二维条形码结算申报系统")
        .FindChild("TNotebook","").FindChild("TPage","Basic").FindChild("TPanel","Panel2")
        .FindChild("TPanel","").FindChildren("TadvCityCbBox",null)[1];
 
int itemCount = (int) cb.SendMessage(0x0146,0,0); //CB_GETCOUNT=0x146
string[] itemValues=new string[itemCount];
Debug.Write("共有"+itemCount.ToString()+"个选项,包含有:");
int idxTaipei=-1;
for (int i=0; i<itemCount; i++) 
{
        //先取得字符串长度 CB_GETLBTEXTLEN 0x0149
        int len=(int) cb.SendMessage(0x0149,(uint) i,0);
        //取回字符串 CB_GETLBTEXT 0x0148
        StringBuilder sb=new StringBuilder(len);
        SendMessage(cb.Handle,0x0148, i, sb);
        itemValues[i]=sb.ToString();
        if (itemValues[i]=="台北市") idxTaipei=i;
        if (i % 10==0) Debug.WriteLine("");
        Debug.Write(itemValues[i]+" ");
}
Debug.WriteLine("");
//取得目前的选取索引值 CB_GETCURSEL 0x0147
int idxNow=(int) cb.SendMessage(0x0147,0,0);
Debug.WriteLine("目前的选取值="+idxNow.ToString()+"."+itemValues[idxNow]);
//改变选取索引值至台北市的选项,CB_SETCURSEL 0x014E
cb.SendMessage(0x014E,(uint) idxTaipei,0);
Debug.WriteLine("已设定为"+idxTaipei.ToString()+"."+itemValues[idxTaipei]);
}
-----end-----
 
 
-----box-----
#程序3 跨程序远程记忆体操作 RemoteMemory.cs
public class RemoteMemory
{
        private uint lpMem=0;
        private int size=0;
        private IntPtr hProcess;
        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
 
        uint PROCESS_VM_OPERATION  = (0x0008);  
        uint PROCESS_VM_READ       = (0x0010);  
        uint PROCESS_VM_WRITE      = (0x0020);
        uint MEM_COMMIT           = 0x1000;
        uint MEM_RESERVE          = 0x2000;
        uint MEM_RELEASE          = 0x8000;
        uint PAGE_READWRITE       = 0x04;
 
        [DllImport("kernel32.dll")]
        public static extern uint VirtualAllocEx(IntPtr hProcess, uint lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
        [DllImport("kernel32.dll")]
        public static extern int WriteProcessMemory(IntPtr hProcess, uint lpBaseAddress, uint lpObject, uint nSize, ref uint lpNumberOfBytesWritten);
        [DllImport("kernel32.dll")]
        public static extern int ReadProcessMemory(IntPtr hProccess, uint lpBaseAddress, uint lpObject, uint nSize, ref uint lpNumberOfBytesRead);
        [DllImport("kernel32.dll")]
        public static extern int ReadProcessMemory(IntPtr hProcess, uint lpBaseAddress,[In, Out] byte[] buffer, uint nSize, ref uint lpNumberOfBytesRead);
        [DllImport("kernel32.dll")]
        public static extern int VirtualFreeEx(IntPtr hProcess, uint lpAddress, int dwSize, uint dwFreeType);
        [DllImport("USER32.DLL", SetLastError=true)]
        public static extern uint SendMessage(IntPtr hWnd, uint Msg, uint wParam, uint lParam);
        [DllImport("user32.dll")]
        static extern uint GetWindowThreadProcessId(IntPtr hWnd, ref uint processId);
        //在指定的Process,取得一段指定大小的内存
        public RemoteMemory(IntPtr hWnd, int size)
        {
               uint dwProcessId=0;
               GetWindowThreadProcessId(hWnd,ref dwProcessId);
               hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, 0, dwProcessId);
               lpMem=VirtualAllocEx(hProcess, 0, (uint) size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
               this.size=size;
        }
        //释放原先取得的内存
        public void Unallocate() 
        {
               VirtualFreeEx(hProcess, lpMem, 0, MEM_RELEASE);
        }
        //将对象的内容抄写到先前取得的内存中
        public void Write(object o) 
        {
               if (Marshal.SizeOf(o)>size) 
                       throw new ApplicationException("RemoteMemory.Write method error: allocated memory size is not enough!");
               GCHandle gc=GCHandle.Alloc(o,GCHandleType.Pinned);
               uint bytesWritten=0;
               int ret=WriteProcessMemory(hProcess, lpMem, (uint) gc.AddrOfPinnedObject(), (uint) Marshal.SizeOf(o), ref bytesWritten);
        }
        //将内存中的内容还原至对象
        public void Read(ref object o)  
        {
               GCHandle gc=GCHandle.Alloc(o,GCHandleType.Pinned);
               uint bytesRead=0;
              int ret=ReadProcessMemory(hProcess, lpMem, (uint) gc.AddrOfPinnedObject(), (uint) Marshal.SizeOf(o), ref bytesRead);
        }
        //将内存中的某一段解析成为字符串
        public string ReadCString(uint offset, int stringLen) 
        {
               uint bytesRead=0;
               byte[] buffer=new byte[stringLen];
               int ret=ReadProcessMemory(hProcess, lpMem+offset, buffer, (uint) stringLen, ref bytesRead);
               return szToString(buffer);
        }
        //将整块内存解析成为字符串
        public string ReadCString() 
        {
               return ReadCString(0,size);           
        }
        //将字节转成字符串
        private string szToString(byte[] byteArray) 
        {
               int length=0;
               for (int i=0; i<byteArray.Length; i++) 
               {
                       if (byteArray[i]==0) 
                       {
                               length=i;
                               break;
                       }
               }
               return System.Text.Encoding.GetEncoding("big5").GetString(byteArray,0,length);
        }
        //传回内存地址
        public uint MemoryAddress 
        {
               get { return lpMem; }
        }
}-----end-----
 
-----box-----
#程序4 List ViewGrid内容,转为DataTable: ListViewSpy.cs
 
public class ListViewSpy
{
        [StructLayout(LayoutKind.Sequential)]
               public struct LVITEM //List ViewItem数据结构
        {
               public uint mask;
               public int iItem;
               public int iSubItem;
               public uint state;
               public uint stateMask;
               public IntPtr pszText; //struct中不可使用StringBuilder
               public int cchTextMax;
               public int iImage;
               public IntPtr lParam;
        }
 
        [StructLayout(LayoutKind.Sequential)]
               public struct HDITEM //List ViewHeader数据结构
        {
               public uint mask; 
               public int cxy; 
               public IntPtr pszText; 
               public uint hbm; 
               public int cchTextMax; 
               public int fmt; 
               public IntPtr lParam;
        }
 
        [DllImport("USER32.DLL", SetLastError=true)]
        public static extern uint SendMessage(IntPtr hWnd, uint msg, uint wparam, uint lparam);
 
        private IntPtr hWnd;
        private int columnCount,rowCount;
        private const int MAX_STR_SIZE=256;
        private DataTable table=new DataTable();
 
        public ListViewSpy(IntPtr hWnd)
        {
               this.hWnd=hWnd;
               //取得Header(SysHeader32)
               uint LVM_GETHEADER=0x1000+31;
               IntPtr header=new IntPtr(SendMessage(hWnd,LVM_GETHEADER,0,0));
               if (header==IntPtr.Zero) return;
               //取得Column
               uint HDM_GETITEMCOUNT=0x1200+0;
               columnCount=(int) SendMessage(header,HDM_GETITEMCOUNT,0,0);
               //取得Column Header Text
               HDITEM hdi=new HDITEM();
               uint HDI_TEXT=0x0002;
               hdi.mask=HDI_TEXT;
               hdi.cchTextMax=MAX_STR_SIZE;
               int iStructSize=Marshal.SizeOf(hdi);
               //在目的地Process取得一块用来存放HDITEM的内存空间
               //并额外多要一些用来放字符串
               RemoteMemory rm=new RemoteMemory(hWnd,iStructSize+MAX_STR_SIZE);
               //指向额外的空间
               hdi.pszText=new IntPtr(rm.MemoryAddress+iStructSize);
               //hdi的内容复制到目的地Process的内存上
               rm.Write(hdi);
 
               //SendMessage
               uint HDM_GETITEMA=0x1200+3;
               byte[] buffer=new byte[MAX_STR_SIZE];
               table=new DataTable();
               for (int i=0; i<columnCount; i++) 
               {
                       int r=(int) SendMessage(header,HDM_GETITEMA, (uint) i,rm.MemoryAddress);
                       //以字段名称建立DataTable的字段
                       table.Columns.Add(rm.ReadCString((uint) iStructSize,MAX_STR_SIZE),Type.GetType("System.String"));
               }
               rm.Unallocate();
 
               //取得ListView资料笔数
               uint LVM_GETITEMCOUNT=0x1000+4;
               rowCount=(int) SendMessage(hWnd,LVM_GETITEMCOUNT,0,0);
               LVITEM lvi=new LVITEM();
               uint LVIF_TEXT = 0x0001;
               lvi.mask=LVIF_TEXT;
               lvi.cchTextMax=MAX_STR_SIZE;
               //在目的地Process建立LVITEM,原理同HDITEM
               iStructSize=Marshal.SizeOf(lvi);
               rm=new RemoteMemory(hWnd,(int) iStructSize+MAX_STR_SIZE);
               lvi.pszText=new IntPtr(rm.MemoryAddress+iStructSize);
 
               //SendMessage
               uint LVM_GETITEMTEXTA=0x1000+45;
               for (int i=0; i<rowCount; i++) 
               {
                       lvi.iItem=i;
                       DataRow row=table.NewRow();
                       for (int j=0; j<columnCount; j++) 
                       {
                               lvi.iSubItem=j;
                               rm.Write(lvi);
                               int ret=(int) SendMessage(hWnd,LVM_GETITEMTEXTA, (uint) i,rm.MemoryAddress);
                               row[j]=rm.ReadCString((uint) iStructSize,MAX_STR_SIZE);
                       }
                       table.Rows.Add(row);
               }
               rm.Unallocate();
        }
 
        public DataTable Data 
        {
               get {   return table;}
        }
}
-----end-----
 
-----box-----
程序5 Task Manager Processes List View的数据在DataGrid还原, 结果如图3
private void button1_Click(object sender, System.EventArgs e)
{
        //使用SPY++时,看到Task ManagerClass Name#32770 (Dialog)
        //寻找时记得只要指定#32770即可,加上(Dialog)后会找不到
        WinObject lvProcesses=WinObject.FindWindow("#32770","Windows Task Manager")
               .FindChild("#32770","").FindChild("SysListView32","Processes");
        ListViewSpy lvs=new ListViewSpy(lvProcesses.Handle);
        dataGrid1.DataSource=lvs.Data;
        dataGrid1.Refresh();                          
}