获得QQ聊天输入框中的内容

// 首先得到输入框的句柄。通过spy++这类工具分析,聊天窗体的类名为“#32770”
// 但当前系统里不只一个类名为“#32770”的窗体,这就需要全体遍历一次。
// 类名为“#32770”标题含“聊天”基本能确定。为保险起见还判断一下所在进程是否为“qq.exe”
uses PsAPI, RichEdit;
function Process_ReadRichEditText(AHandle: THandle): WideString;
var
  vGetTextEx: GETTEXTEX;
  vGetTextLengthEx: GETTEXTLENGTHEX;
  L: Integer;
  vProcessId: DWORD;
  vProcess: THandle;
  vPointer: Pointer;
  vNumberOfBytesRead: Cardinal;
begin
  Result := '';
  if not IsWindow(AHandle) then Exit;
  GetWindowThreadProcessId(AHandle, @vProcessId);
  vProcess := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or
    PROCESS_VM_WRITE, False, vProcessId);
  try
    vPointer := VirtualAllocEx(vProcess, nil, 4096, MEM_RESERVE or MEM_COMMIT,
      PAGE_READWRITE);
    vGetTextLengthEx.flags := GTL_DEFAULT;
    vGetTextLengthEx.codepage := 1200; // Unicode
    WriteProcessMemory(vProcess, vPointer, @vGetTextLengthEx,
      SizeOf(vGetTextLengthEx), vNumberOfBytesRead);
    L := SendMessage(AHandle, EM_GETTEXTLENGTHEX, Integer(vPointer), 0);
    VirtualFreeEx(vProcess, vPointer, 0, MEM_RELEASE);
    if L <= 0 then Exit;
    vPointer := VirtualAllocEx(vProcess, nil, SizeOf(vGetTextEx) + L * 2 + 2,
      MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
    SetLength(Result, L);
    vGetTextEx.cb := L * 2 + 2;
    vGetTextEx.flags := GT_DEFAULT;
    vGetTextEx.codepage := 1200; // Unicode
    vGetTextEx.lpDefaultChar := nil;
    vGetTextEx.lpUsedDefChar := nil;
    WriteProcessMemory(vProcess, vPointer, @vGetTextEx,
      SizeOf(vGetTextEx), vNumberOfBytesRead);
    SendMessage(AHandle, EM_GETTEXTEX, Integer(vPointer),
      Integer(vPointer) + SizeOf(vGetTextEx));
    ReadProcessMemory(vProcess, Pointer(Integer(vPointer) + SizeOf(vGetTextEx)),
      @Result[1], L * 2, vNumberOfBytesRead);
    VirtualFreeEx(vProcess, vPointer, 0, MEM_RELEASE);
  finally
    CloseHandle(vProcess);
  end;
end; { Process_ReadRichEditText }
function GetProcessName(AProcessID: THandle): string;
var
  vBuffer: array[0..MAX_PATH] of Char;
  vProcess: THandle;
begin
  vProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False,
    AProcessID);
  try
    if GetModuleBaseName(vProcess, 0, vBuffer, SizeOf(vBuffer)) > 0 then
      Result := vBuffer
    else Result := '';
  finally
    CloseHandle(vProcess);
  end;
end; { GetProcessName }
function EnumChild(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
var
  vBuffer: array[0..255] of Char;
begin
  Result := True;
  if not IsWindowVisible(hwnd) then Exit; // 不可见
  GetClassName(hwnd, vBuffer, SizeOf(vBuffer));
  if SameText(vBuffer, 'RichEdit20A') then
  begin
    if GetWindowLong(hwnd, GWL_STYLE) and ES_READONLY <> ES_READONLY then // 非只读
    begin
      PInteger(lParam)^ := hwnd;
      Result := False;
    end;
  end;
end; { EnumChild }
function EnumFunc(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
var
  vBuffer: array[0..255] of Char;
  vProcessId: THandle;
begin
  Result := True;
  if not IsWindowVisible(hwnd) then Exit; // 不可见
  GetClassName(hwnd, vBuffer, SizeOf(vBuffer));
  if SameText(vBuffer, '#32770') then
  begin
    GetWindowThreadProcessId(hwnd, vProcessId);
    if SameText(GetProcessName(vProcessId), 'qq.exe') then
    begin
      GetWindowText(hwnd, vBuffer, SizeOf(vBuffer));
      if Pos('聊天中', vBuffer) > 0 then // 标题中含"聊天中"
      begin
        EnumChildWindows(hwnd, @EnumChild, lParam);
        Result := False;
      end;
    end;
  end;
end; { EnumFunc }
procedure TForm1.Button1Click(Sender: TObject);
var
  vHandle: THandle;
begin
  vHandle := 0;
  EnumWindows(@EnumFunc, Integer(@vHandle));
  if vHandle = 0 then Exit;
  Memo1.Text := Process_ReadRichEditText(vHandle);
end;
 
  
using  System.Runtime.InteropServices;

[DllImport(
" User32.DLL " )]
public   static   extern   int  SendMessage(IntPtr hWnd,  uint  Msg,  int  wParam,  int  lParam);

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

[DllImport(
" user32.dll " )]
public   static   extern   int  EnumWindows(WNDENUMPROC lpEnumFunc,  int  lParam);
[DllImport(
" user32.dll " )]
public   static   extern   int  EnumChildWindows(IntPtr hWndParent, 
    WNDENUMPROC lpEnumFunc, 
int  lParam);
[DllImport(
" user32.dll " )]
public   static   extern   int  GetWindowText(IntPtr hWnd, StringBuilder lpString,
    
int  nMaxCount);
[DllImport(
" user32.dll " )]
public   static   extern   int  GetClassName(IntPtr hWnd, StringBuilder lpClassName,
    
int  nMaxCount);
[DllImport(
" user32.dll " )]
public   static   extern   bool  IsWindow(IntPtr hWnd);
[DllImport(
" user32.dll " )]
public   static   extern   bool  IsWindowVisible(IntPtr hWnd);
[DllImport(
" user32.DLL " )]
public   static   extern  IntPtr FindWindowEx(IntPtr hwndParent,
    IntPtr hwndChildAfter, 
string  lpszClass,  string  lpszWindow);
[DllImport(
" user32.dll " )]
public   static   extern   uint  GetWindowThreadProcessId(IntPtr hWnd,
    
out   uint  dwProcessId);

[DllImport(
" psapi.dll " )]
public   static   extern   uint  GetModuleBaseName(IntPtr hProcess, IntPtr hModule,
    StringBuilder lpBaseName, 
uint  nSize);

public   const   uint  PROCESS_VM_OPERATION  =   0x0008 ;
public   const   uint  PROCESS_VM_READ  =   0x0010 ;
public   const   uint  PROCESS_VM_WRITE  =   0x0020 ;
public   const   uint  PROCESS_QUERY_INFORMATION  =   0x0400 ;

[DllImport(
" kernel32.dll " )]
public   static   extern  IntPtr OpenProcess( uint  dwDesiredAccess,
    
bool  bInheritHandle,  uint  dwProcessId);

[DllImport(
" kernel32.dll " )]
public   static   extern   bool  CloseHandle(IntPtr handle);

[DllImport(
" user32.dll " )]
public   static   extern   int  GetWindowLong(IntPtr hWnd,  int  nIndex);
public   const   int  GWL_STYLE  =   - 16 ;
public   const   int  ES_READONLY  =   0x800 ;

public   const   uint  MEM_COMMIT  =   0x1000 ;
public   const   uint  MEM_RELEASE  =   0x8000 ;

public   const   uint  MEM_RESERVE  =   0x2000 ;
public   const   uint  PAGE_READWRITE  =   4 ;

[DllImport(
" kernel32.dll " )]
public   static   extern  IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
    
uint  dwSize,  uint  flAllocationType,  uint  flProtect);

[DllImport(
" kernel32.dll " )]
public   static   extern   bool  VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
   
uint  dwSize,  uint  dwFreeType);

[DllImport(
" kernel32.dll " )]
public   static   extern   bool  WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
   IntPtr lpBuffer, 
int  nSize,  ref   uint  vNumberOfBytesRead);

[DllImport(
" kernel32.dll " )]
public   static   extern   bool  ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
   IntPtr lpBuffer, 
int  nSize,  ref   uint  vNumberOfBytesRead); 

private  IntPtr richHandle;

public   string  GetProcessName( uint  AProcessId)
{
    StringBuilder vBuffer 
= new StringBuilder(256);
    IntPtr vProcess 
= OpenProcess(
        PROCESS_QUERY_INFORMATION 
| PROCESS_VM_READ, false, AProcessId);
    
try
    
{
        
if (GetModuleBaseName(vProcess, IntPtr.Zero, vBuffer, 
            (
uint)vBuffer.Capacity) > 0)
            
return vBuffer.ToString();
        
else return string.Empty;
    }

    
finally
    
{
        CloseHandle(vProcess);
    }

}


public   bool  EnumChild(IntPtr hwnd,  int  lParam)
{
    
if (!IsWindowVisible(hwnd)) return true// 不可见
    StringBuilder vBuffer = new StringBuilder(256);
    GetClassName(hwnd, vBuffer, vBuffer.Capacity);
    
if (vBuffer.ToString().ToLower() == "richedit20a")
    
{
        
if ((GetWindowLong(hwnd, GWL_STYLE) & ES_READONLY) != ES_READONLY) // 非只读
        {
            richHandle 
= hwnd;
            
return false;
        }

    }

    
return true;
}


public   bool  EnumFunc(IntPtr hwnd,  int  lParam)
{
    
if (!IsWindowVisible(hwnd)) return true// 不可见
    StringBuilder vBuffer = new StringBuilder(256);
    GetClassName(hwnd, vBuffer, vBuffer.Capacity);
    
if (vBuffer.ToString() == "#32770")
    
{
        
uint vProcessId;
        GetWindowThreadProcessId(hwnd, 
out vProcessId);
        
if (GetProcessName(vProcessId).ToLower() == "qq.exe")
        
{
            GetWindowText(hwnd, vBuffer, vBuffer.Capacity);
            
if (vBuffer.ToString().IndexOf("聊天中">= 0// 标题中含"聊天中"
            {
                EnumChildWindows(hwnd, @EnumChild, lParam);
                
return false;
            }

        }

    }

    
return true;
}


[StructLayout(LayoutKind.Sequential)]
public   struct  GETTEXTLENGTHEX
{
    
public uint flags;
    
public uint codepage;
}


[StructLayout(LayoutKind.Sequential)]
public   struct  GETTEXTEX
{
    
public int cb;
    
public int flags;
    
public int codepage;
    
public IntPtr lpDefaultChar;
    
public IntPtr lpUsedDefChar;
}
;

public   const   int  GTL_DEFAULT  =   0 ;
public   const   int  GT_DEFAULT  =   0 ;
public   const   int  WM_USER  =   0x0400 ;
public   const   int  EM_GETTEXTEX  =  WM_USER  +   94
public   const   int  EM_GETTEXTLENGTHEX  =  WM_USER  +   95 ;

public   string  Process_ReadRichEditText(IntPtr AHandle)
{
    
if (!IsWindow(AHandle)) return string.Empty;
    
string vReturn = string.Empty;
    
uint vProcessId;
    GetWindowThreadProcessId(AHandle, 
out vProcessId);
    IntPtr vProcess 
= OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ |
        PROCESS_VM_WRITE, 
false, vProcessId);
    
try
    
{
        
uint vNumberOfBytesRead = 0;
        IntPtr vPointer 
= VirtualAllocEx(vProcess, IntPtr.Zero, 0x1000
            MEM_RESERVE 
| MEM_COMMIT, PAGE_READWRITE);
        GETTEXTLENGTHEX vGetTextLengthEx 
= new GETTEXTLENGTHEX();
        vGetTextLengthEx.flags 
= GTL_DEFAULT;
        vGetTextLengthEx.codepage 
= 1200// Unicode
        IntPtr vAddress = Marshal.AllocCoTaskMem(Marshal.SizeOf(vGetTextLengthEx));
        Marshal.StructureToPtr(vGetTextLengthEx, vAddress, 
false);
        WriteProcessMemory(vProcess, vPointer, vAddress,
            Marshal.SizeOf(vGetTextLengthEx), 
ref vNumberOfBytesRead);
        Marshal.FreeCoTaskMem(vAddress);
        
int L = SendMessage(AHandle, EM_GETTEXTLENGTHEX, (int)vPointer, 0);
        VirtualFreeEx(vProcess, vPointer, 
0, MEM_RELEASE);
        
if (L <= 0return vReturn;
        GETTEXTEX vGetTextEx 
= new GETTEXTEX();
        vGetTextEx.cb 
= L * 2 + 2;
        vGetTextEx.flags 
= GT_DEFAULT;
        vGetTextEx.codepage 
= 1200// Unicode
        vGetTextEx.lpDefaultChar = IntPtr.Zero;
        vGetTextEx.lpUsedDefChar 
= IntPtr.Zero;
        vPointer 
= VirtualAllocEx(vProcess, IntPtr.Zero,
            (
uint)(Marshal.SizeOf(vGetTextEx) + L * 2 + 2),
            MEM_RESERVE 
| MEM_COMMIT, PAGE_READWRITE);
        vAddress 
= Marshal.AllocCoTaskMem(Marshal.SizeOf(vGetTextEx));
        Marshal.StructureToPtr(vGetTextEx, vAddress, 
false);
        WriteProcessMemory(vProcess, vPointer, vAddress,
            Marshal.SizeOf(vGetTextEx), 
ref vNumberOfBytesRead);
        Marshal.FreeCoTaskMem(vAddress);
        SendMessage(AHandle, EM_GETTEXTEX, (
int)vPointer,
            (
int)vPointer + Marshal.SizeOf(vGetTextEx));
        vAddress 
= Marshal.AllocCoTaskMem(L * 2);
        ReadProcessMemory(vProcess, 
            (IntPtr)((
int)vPointer + Marshal.SizeOf(vGetTextEx)),
            vAddress, L 
* 2ref vNumberOfBytesRead);
        vReturn 
= Marshal.PtrToStringUni(vAddress, L * 2);
        Marshal.FreeCoTaskMem(vAddress);
        VirtualFreeEx(vProcess, vPointer, 
0, MEM_RELEASE);
    }

    
finally
    
{
        CloseHandle(vProcess);
    }

    
return vReturn;
}


private   void  button1_Click( object  sender, EventArgs e)
{
    richHandle 
= IntPtr.Zero;
    EnumWindows(EnumFunc, 
0);
    
if (richHandle == IntPtr.Zero) return;
    Console.WriteLine(Process_ReadRichEditText(richHandle));
}



你可能感兴趣的:(获得QQ聊天输入框中的内容)