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

时间:2023-03-09 17:07:36
获得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;
获得QQ聊天输入框中的内容using System.Runtime.InteropServices;
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容[DllImport("User32.DLL")]
获得QQ聊天输入框中的内容public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容public delegate bool WNDENUMPROC(IntPtr hwnd, int lParam);
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容[DllImport("user32.dll")]
获得QQ聊天输入框中的内容public static extern int EnumWindows(WNDENUMPROC lpEnumFunc, int lParam);
获得QQ聊天输入框中的内容[DllImport("user32.dll")]
获得QQ聊天输入框中的内容public static extern int EnumChildWindows(IntPtr hWndParent, 
获得QQ聊天输入框中的内容    WNDENUMPROC lpEnumFunc, int lParam);
获得QQ聊天输入框中的内容[DllImport("user32.dll")]
获得QQ聊天输入框中的内容public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString,
获得QQ聊天输入框中的内容    int nMaxCount);
获得QQ聊天输入框中的内容[DllImport("user32.dll")]
获得QQ聊天输入框中的内容public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName,
获得QQ聊天输入框中的内容    int nMaxCount);
获得QQ聊天输入框中的内容[DllImport("user32.dll")]
获得QQ聊天输入框中的内容public static extern bool IsWindow(IntPtr hWnd);
获得QQ聊天输入框中的内容[DllImport("user32.dll")]
获得QQ聊天输入框中的内容public static extern bool IsWindowVisible(IntPtr hWnd);
获得QQ聊天输入框中的内容[DllImport("user32.DLL")]
获得QQ聊天输入框中的内容public static extern IntPtr FindWindowEx(IntPtr hwndParent,
获得QQ聊天输入框中的内容    IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
获得QQ聊天输入框中的内容[DllImport("user32.dll")]
获得QQ聊天输入框中的内容public static extern uint GetWindowThreadProcessId(IntPtr hWnd,
获得QQ聊天输入框中的内容    out uint dwProcessId);
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容[DllImport("psapi.dll")]
获得QQ聊天输入框中的内容public static extern uint GetModuleBaseName(IntPtr hProcess, IntPtr hModule,
获得QQ聊天输入框中的内容    StringBuilder lpBaseName, uint nSize);
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容public const uint PROCESS_VM_OPERATION = 0x0008;
获得QQ聊天输入框中的内容public const uint PROCESS_VM_READ = 0x0010;
获得QQ聊天输入框中的内容public const uint PROCESS_VM_WRITE = 0x0020;
获得QQ聊天输入框中的内容public const uint PROCESS_QUERY_INFORMATION = 0x0400;
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容[DllImport("kernel32.dll")]
获得QQ聊天输入框中的内容public static extern IntPtr OpenProcess(uint dwDesiredAccess,
获得QQ聊天输入框中的内容    bool bInheritHandle, uint dwProcessId);
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容[DllImport("kernel32.dll")]
获得QQ聊天输入框中的内容public static extern bool CloseHandle(IntPtr handle);
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容[DllImport("user32.dll")]
获得QQ聊天输入框中的内容public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
获得QQ聊天输入框中的内容public const int GWL_STYLE = -16;
获得QQ聊天输入框中的内容public const int ES_READONLY = 0x800;
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容public const uint MEM_COMMIT = 0x1000;
获得QQ聊天输入框中的内容public const uint MEM_RELEASE = 0x8000;
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容public const uint MEM_RESERVE = 0x2000;
获得QQ聊天输入框中的内容public const uint PAGE_READWRITE = 4;
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容[DllImport("kernel32.dll")]
获得QQ聊天输入框中的内容public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
获得QQ聊天输入框中的内容    uint dwSize, uint flAllocationType, uint flProtect);
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容[DllImport("kernel32.dll")]
获得QQ聊天输入框中的内容public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
获得QQ聊天输入框中的内容   uint dwSize, uint dwFreeType);
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容[DllImport("kernel32.dll")]
获得QQ聊天输入框中的内容public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
获得QQ聊天输入框中的内容   IntPtr lpBuffer, int nSize, ref uint vNumberOfBytesRead);
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容[DllImport("kernel32.dll")]
获得QQ聊天输入框中的内容public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
获得QQ聊天输入框中的内容   IntPtr lpBuffer, int nSize, ref uint vNumberOfBytesRead); 
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容private IntPtr richHandle;
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容public string GetProcessName(uint AProcessId)
获得QQ聊天输入框中的内容{
获得QQ聊天输入框中的内容    StringBuilder vBuffer = new StringBuilder(256);
获得QQ聊天输入框中的内容    IntPtr vProcess = OpenProcess(
获得QQ聊天输入框中的内容        PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, AProcessId);
获得QQ聊天输入框中的内容    try
获得QQ聊天输入框中的内容    {
获得QQ聊天输入框中的内容        if (GetModuleBaseName(vProcess, IntPtr.Zero, vBuffer, 
获得QQ聊天输入框中的内容            (uint)vBuffer.Capacity) > 0)
获得QQ聊天输入框中的内容            return vBuffer.ToString();
获得QQ聊天输入框中的内容        else return string.Empty;
获得QQ聊天输入框中的内容    }
获得QQ聊天输入框中的内容    finally
获得QQ聊天输入框中的内容    {
获得QQ聊天输入框中的内容        CloseHandle(vProcess);
获得QQ聊天输入框中的内容    }
获得QQ聊天输入框中的内容}
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容public bool EnumChild(IntPtr hwnd, int lParam)
获得QQ聊天输入框中的内容{
获得QQ聊天输入框中的内容    if (!IsWindowVisible(hwnd)) return true; // 不可见
获得QQ聊天输入框中的内容    StringBuilder vBuffer = new StringBuilder(256);
获得QQ聊天输入框中的内容    GetClassName(hwnd, vBuffer, vBuffer.Capacity);
获得QQ聊天输入框中的内容    if (vBuffer.ToString().ToLower() == "richedit20a")
获得QQ聊天输入框中的内容    {
获得QQ聊天输入框中的内容        if ((GetWindowLong(hwnd, GWL_STYLE) & ES_READONLY) != ES_READONLY) // 非只读
获得QQ聊天输入框中的内容        {
获得QQ聊天输入框中的内容            richHandle = hwnd;
获得QQ聊天输入框中的内容            return false;
获得QQ聊天输入框中的内容        }
获得QQ聊天输入框中的内容    }
获得QQ聊天输入框中的内容    return true;
获得QQ聊天输入框中的内容}
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容public bool EnumFunc(IntPtr hwnd, int lParam)
获得QQ聊天输入框中的内容{
获得QQ聊天输入框中的内容    if (!IsWindowVisible(hwnd)) return true; // 不可见
获得QQ聊天输入框中的内容    StringBuilder vBuffer = new StringBuilder(256);
获得QQ聊天输入框中的内容    GetClassName(hwnd, vBuffer, vBuffer.Capacity);
获得QQ聊天输入框中的内容    if (vBuffer.ToString() == "#32770")
获得QQ聊天输入框中的内容    {
获得QQ聊天输入框中的内容        uint vProcessId;
获得QQ聊天输入框中的内容        GetWindowThreadProcessId(hwnd, out vProcessId);
获得QQ聊天输入框中的内容        if (GetProcessName(vProcessId).ToLower() == "qq.exe")
获得QQ聊天输入框中的内容        {
获得QQ聊天输入框中的内容            GetWindowText(hwnd, vBuffer, vBuffer.Capacity);
获得QQ聊天输入框中的内容            if (vBuffer.ToString().IndexOf("聊天中") >= 0) // 标题中含"聊天中"
获得QQ聊天输入框中的内容            {
获得QQ聊天输入框中的内容                EnumChildWindows(hwnd, @EnumChild, lParam);
获得QQ聊天输入框中的内容                return false;
获得QQ聊天输入框中的内容            }
获得QQ聊天输入框中的内容        }
获得QQ聊天输入框中的内容    }
获得QQ聊天输入框中的内容    return true;
获得QQ聊天输入框中的内容}
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容[StructLayout(LayoutKind.Sequential)]
获得QQ聊天输入框中的内容public struct GETTEXTLENGTHEX
获得QQ聊天输入框中的内容{
获得QQ聊天输入框中的内容    public uint flags;
获得QQ聊天输入框中的内容    public uint codepage;
获得QQ聊天输入框中的内容}
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容[StructLayout(LayoutKind.Sequential)]
获得QQ聊天输入框中的内容public struct GETTEXTEX
获得QQ聊天输入框中的内容{
获得QQ聊天输入框中的内容    public int cb;
获得QQ聊天输入框中的内容    public int flags;
获得QQ聊天输入框中的内容    public int codepage;
获得QQ聊天输入框中的内容    public IntPtr lpDefaultChar;
获得QQ聊天输入框中的内容    public IntPtr lpUsedDefChar;
获得QQ聊天输入框中的内容};
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容public const int GTL_DEFAULT = 0;
获得QQ聊天输入框中的内容public const int GT_DEFAULT = 0;
获得QQ聊天输入框中的内容public const int WM_USER = 0x0400;
获得QQ聊天输入框中的内容public const int EM_GETTEXTEX = WM_USER + 94; 
获得QQ聊天输入框中的内容public const int EM_GETTEXTLENGTHEX = WM_USER + 95;
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容public string Process_ReadRichEditText(IntPtr AHandle)
获得QQ聊天输入框中的内容{
获得QQ聊天输入框中的内容    if (!IsWindow(AHandle)) return string.Empty;
获得QQ聊天输入框中的内容    string vReturn = string.Empty;
获得QQ聊天输入框中的内容    uint vProcessId;
获得QQ聊天输入框中的内容    GetWindowThreadProcessId(AHandle, out vProcessId);
获得QQ聊天输入框中的内容    IntPtr vProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ |
获得QQ聊天输入框中的内容        PROCESS_VM_WRITE, false, vProcessId);
获得QQ聊天输入框中的内容    try
获得QQ聊天输入框中的内容    {
获得QQ聊天输入框中的内容        uint vNumberOfBytesRead = 0;
获得QQ聊天输入框中的内容        IntPtr vPointer = VirtualAllocEx(vProcess, IntPtr.Zero, 0x1000, 
获得QQ聊天输入框中的内容            MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
获得QQ聊天输入框中的内容        GETTEXTLENGTHEX vGetTextLengthEx = new GETTEXTLENGTHEX();
获得QQ聊天输入框中的内容        vGetTextLengthEx.flags = GTL_DEFAULT;
获得QQ聊天输入框中的内容        vGetTextLengthEx.codepage = 1200; // Unicode
获得QQ聊天输入框中的内容        IntPtr vAddress = Marshal.AllocCoTaskMem(Marshal.SizeOf(vGetTextLengthEx));
获得QQ聊天输入框中的内容        Marshal.StructureToPtr(vGetTextLengthEx, vAddress, false);
获得QQ聊天输入框中的内容        WriteProcessMemory(vProcess, vPointer, vAddress,
获得QQ聊天输入框中的内容            Marshal.SizeOf(vGetTextLengthEx), ref vNumberOfBytesRead);
获得QQ聊天输入框中的内容        Marshal.FreeCoTaskMem(vAddress);
获得QQ聊天输入框中的内容        int L = SendMessage(AHandle, EM_GETTEXTLENGTHEX, (int)vPointer, 0);
获得QQ聊天输入框中的内容        VirtualFreeEx(vProcess, vPointer, 0, MEM_RELEASE);
获得QQ聊天输入框中的内容        if (L <= 0) return vReturn;
获得QQ聊天输入框中的内容        GETTEXTEX vGetTextEx = new GETTEXTEX();
获得QQ聊天输入框中的内容        vGetTextEx.cb = L * 2 + 2;
获得QQ聊天输入框中的内容        vGetTextEx.flags = GT_DEFAULT;
获得QQ聊天输入框中的内容        vGetTextEx.codepage = 1200; // Unicode
获得QQ聊天输入框中的内容        vGetTextEx.lpDefaultChar = IntPtr.Zero;
获得QQ聊天输入框中的内容        vGetTextEx.lpUsedDefChar = IntPtr.Zero;
获得QQ聊天输入框中的内容        vPointer = VirtualAllocEx(vProcess, IntPtr.Zero,
获得QQ聊天输入框中的内容            (uint)(Marshal.SizeOf(vGetTextEx) + L * 2 + 2),
获得QQ聊天输入框中的内容            MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
获得QQ聊天输入框中的内容        vAddress = Marshal.AllocCoTaskMem(Marshal.SizeOf(vGetTextEx));
获得QQ聊天输入框中的内容        Marshal.StructureToPtr(vGetTextEx, vAddress, false);
获得QQ聊天输入框中的内容        WriteProcessMemory(vProcess, vPointer, vAddress,
获得QQ聊天输入框中的内容            Marshal.SizeOf(vGetTextEx), ref vNumberOfBytesRead);
获得QQ聊天输入框中的内容        Marshal.FreeCoTaskMem(vAddress);
获得QQ聊天输入框中的内容        SendMessage(AHandle, EM_GETTEXTEX, (int)vPointer,
获得QQ聊天输入框中的内容            (int)vPointer + Marshal.SizeOf(vGetTextEx));
获得QQ聊天输入框中的内容        vAddress = Marshal.AllocCoTaskMem(L * 2);
获得QQ聊天输入框中的内容        ReadProcessMemory(vProcess, 
获得QQ聊天输入框中的内容            (IntPtr)((int)vPointer + Marshal.SizeOf(vGetTextEx)),
获得QQ聊天输入框中的内容            vAddress, L * 2, ref vNumberOfBytesRead);
获得QQ聊天输入框中的内容        vReturn = Marshal.PtrToStringUni(vAddress, L * 2);
获得QQ聊天输入框中的内容        Marshal.FreeCoTaskMem(vAddress);
获得QQ聊天输入框中的内容        VirtualFreeEx(vProcess, vPointer, 0, MEM_RELEASE);
获得QQ聊天输入框中的内容    }
获得QQ聊天输入框中的内容    finally
获得QQ聊天输入框中的内容    {
获得QQ聊天输入框中的内容        CloseHandle(vProcess);
获得QQ聊天输入框中的内容    }
获得QQ聊天输入框中的内容    return vReturn;
获得QQ聊天输入框中的内容}
获得QQ聊天输入框中的内容
获得QQ聊天输入框中的内容private void button1_Click(object sender, EventArgs e)
获得QQ聊天输入框中的内容{
获得QQ聊天输入框中的内容    richHandle = IntPtr.Zero;
获得QQ聊天输入框中的内容    EnumWindows(EnumFunc, 0);
获得QQ聊天输入框中的内容    if (richHandle == IntPtr.Zero) return;
获得QQ聊天输入框中的内容    Console.WriteLine(Process_ReadRichEditText(richHandle));
获得QQ聊天输入框中的内容}
获得QQ聊天输入框中的内容
http://blog.csdn.net/zswang/article/details/2009868