1. // 首先得到输入框的句柄。通过spy++这类工具分析,聊天窗体的类名为“#32770”
    // 但当前系统里不只一个类名为“#32770”的窗体,这就需要全体遍历一次。
    // 类名为“#32770”标题含“聊天”基本能确定。为保险起见还判断一下所在进程是否为“qq.exe”
  1. uses PsAPI, RichEdit;
  1. function Process_ReadRichEditText(AHandle: THandle): WideString;
    var
      vGetTextEx: GETTEXTEX;
      vGetTextLengthEx: GETTEXTLENGTHEX;
      L: Integer;
  1.   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 }
  1. 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 }
  1. 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 }
  1. 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 }
  1. 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. Cryptographic method and system

    The present invention relates to the field of security of electronic data and/or communications. In ...

  2. java常用api2

    calendar calendar=calendar.getInstance(); StringBuilder和C#的用法一样 hashSet无序的,不可重复 LInkedHashSet有序的,不可重 ...

  3. Cordova各种事件

    原文:Cordova各种事件 Cordova事件 Cordova框架了一组事件,开发者用来对某些运行Cordova应用的设备上的事件作出反应.事件处理的一种情况是硬件相关活动,如电池状态变化或用户按了 ...

  4. 【26.87%】【codeforces 712D】Memory and Scores

    time limit per test2 seconds memory limit per test512 megabytes inputstandard input outputstandard o ...

  5. base64编码转图片

    protected void Button1_Click(object sender, EventArgs e) { //strImg为base64编码的图片字符串 string strImg = & ...

  6. Qt实用技巧:界面切换使用Dialog全屏切换

    需求 在做应用程序的过程中,需要使用界面切换,界面切换到下一个界面使用new一个界面并显示,如系统设置,相关信息展示等等. (注意:本技巧适用的条件是,主界面不需要相关的信号与槽做消息循环,因为主界面 ...

  7. java server wrapper 和 maven assembly 插件

    Java Service Wrapper工具YAJSW 简介信息 YAJSW是一个开源的Java服务包装(Java Service Wrapper)工具.YAJSW允许您把任何应用程序安装为windo ...

  8. javascript相框echarts插件实现酷立方效果图的人

    最近由于项目需求,我们需要做的一类似网络效应的人立方效果,很多文件中的查询之后.百度发现echarts开源组件非常适合,而加载速度是伟大的.echarts图形主要使用html5这些新功能做,使用can ...

  9. 简明Python3教程 18.下一步是什么

    如果你有认真通读本书之前的内容并且实践其中包含的大量例程,那么你现在一定可以熟练使用python了. 同时你可能也编写了一些程序用于验证python特性并提高你的python技能.如果还没有这样做的话 ...

  10. #747 –在WPF程序的触摸操作中使用惯性移动 (Implementing Inertia during Touch Manipulation)

    原文:#747 –在WPF程序的触摸操作中使用惯性移动 (Implementing Inertia during Touch Manipulation) 原文地址:https://wpf.2000th ...