// 首先得到输入框的句柄。通过spy++这类工具分析,聊天窗体的类名为“#32770” // 但当前系统里不只一个类名为“#32770”的窗体,这就需要全体遍历一次。 // 类名为“#32770”标题含“聊天”基本能确定。为保险起见还判断一下所在进程是否为“qq.exe”
C#获取QQ聊天输入框中的内容代码如下:
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)); }