// 首先得到输入框的句柄。通过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 <= 0) return 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 * 2, ref 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));
}

 
http://blog.csdn.net/zswang/article/details/2009868

获得QQ聊天输入框中的内容的更多相关文章

  1. 屏蔽QQ聊天对话框中的广告

    原文地址: 怎么在QQ聊天对话框中屏蔽广告_百度经验 http://jingyan.baidu.com/article/48a42057ca12c1a924250402.html     QQ已经成为 ...

  2. Javascript 对输入框中的内容进行 “全选/反选”

    <</span>script> document.write("<</span>ul>"); for(var i=0;i<&l ...

  3. vue时时监听input输入框中 输入内容 写法

    Vue input 监听 使用 v-on:input="change" 实现即可 App.vue <template> <div> <md-field ...

  4. JS简单仿QQ聊天工具的制作

    刚接触JS,对其充满了好奇,利用刚学到的一点知识,写了一个简单的仿QQ聊天的东西,其中还有很多的不足之处,有待慢慢提高. 功能:1.在输入框中输入内容,点击发送,即可在上方显示所输入内容. 2.点击‘ ...

  5. Web聊天应用中的表情插件

    聊天应用中的表情插件 用于即时聊天应用的图片表情插件,具有展示表情.插入表情和表情编解码的功能 项目地址 看代码 看demo 原理介绍 web端的即时聊天中看到的表情,其实就是一张张表情图片,通过im ...

  6. 输入框中的空"",0,null的判断

    改了一个小项目,里面有一个小的问题他们是这样提需求的.两个输入框,第一个输入框里面,输入的内容会对第二个输入框中的内容产生影响.具体是这样的:如果第一个输入框中的值不是“0”,那么第二个输入框就不能填 ...

  7. 八、Uniapp+vue+腾讯IM+腾讯音视频开发仿微信的IM聊天APP,支持各类消息收发,音视频通话,附vue实现源码(已开源)-聊天输入框扩展面板的实现

    聊天输入框扩展面板的实现 1.项目引言 2.腾讯云后台配置TXIM 3.配置项目并实现IM登录 4.会话好友列表的实现 5.聊天输入框的实现 6.聊天界面容器的实现 7.聊天消息项的实现 8.聊天输入 ...

  8. 在WEB项目中调用QQ通讯组件打开QQ聊天界面

    在很多WEB项目中,需要提供在线服务的功能,加上自己的联系方式,例如:QQ,不用添加QQ好友也可以交谈,那这到底是怎么实现的呢? 对于这个功能,需要提到一个组件,即“QQ通讯组件”.QQ通讯组件是一种 ...

  9. QQ聊天气泡(图片拉伸不变样)、内容尺寸定制(高度随字数、字体而变)

    - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; /** QQ聊 ...

随机推荐

  1. 一种基于uCos-II操作系统和lwIP协议栈的IEEE-1588主站以及基于该主站的报文处理方法

    主站以及应用于电力系统的支持IEEE‐1588协议的主时钟(IEEE‐1588主站)的实现方法.该方法是在一个低成本的硬件平台上,借助uCos‐II操作系统和TCP/IP的协议栈,对以太网数据进行了分 ...

  2. Mina、Netty、Twisted一起学习(三):TCP前缀固定大小的消息(Header)

    于以前的博文于,有介绍切割消息换行的方法. 但是有一个小问题,这样的方法,设消息中本身就包括换行符,那将会将这条消息切割成两条.结果就不正确了. 本文介绍第二种消息切割方式,即上一篇博文中讲的第2条: ...

  3. VS版本 与 .NET版本以及C#版本之间的关系

    版本 .NET Framework版本 Visual Studio版本 发布日期 特性 C# 1.0 .NET Framework 1.0 Visual Studio .NET 2002 2002.1 ...

  4. myeclipse 8.6 software and workspace center is currently not available

    Myeclipse安装EGit插件的时候偏偏遇到software and workspace center is currently not available 不用打开myeclipse  conf ...

  5. java构造器的作用

    通常通过在构造器中传入参数,对字段进行初始化,以达到初始化所创建的对象实例的目的.

  6. WPF-WPF BitmapEffect (按钮凹凸效果)

    原文:WPF-WPF BitmapEffect (按钮凹凸效果) BitmapEffect位图效果是简单的像素处理操作.它可以呈现下面几种特殊效果.              BevelBitmapE ...

  7. WPF 4 日历控件(Calendar)

    原文:WPF 4 日历控件(Calendar)      在之前我已经写过两篇关于WPF 4 任务栏(Taskbar)相关的特性.相信自从VS2010 Beta 版放出后,WPF 的粉丝们肯定在第一时 ...

  8. Java Policy

    # What The policy for a Java™ programming language application environment (specifying which permiss ...

  9. 【转】Powerdesigner逆向工程从sql server数据库生成pdm

    第一步:打开"控制面板"中的"管理工具" 第二步:点击"管理工具"然后双击"数据源(odbc)" 第三步:打开之后,点击 ...

  10. Simple BeamSearch Codes for Python

    Code from: https://github.com/SeitaroShinagawa/simple_beamsearch probs = [[[],[0.3,0.7]], [[0],[0.1, ...