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

本文介绍了一种方法,利用Windows API和进程内存操作技术来读取指定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;
usingSystem.Runtime.InteropServices;

[DllImport(
"User32.DLL")]
publicstaticexternintSendMessage(IntPtrhWnd,uintMsg,intwParam,intlParam);

publicdelegateboolWNDENUMPROC(IntPtrhwnd,intlParam);

[DllImport(
"user32.dll")]
publicstaticexternintEnumWindows(WNDENUMPROClpEnumFunc,intlParam);
[DllImport(
"user32.dll")]
publicstaticexternintEnumChildWindows(IntPtrhWndParent,
WNDENUMPROClpEnumFunc,
intlParam);
[DllImport(
"user32.dll")]
publicstaticexternintGetWindowText(IntPtrhWnd,StringBuilderlpString,
intnMaxCount);
[DllImport(
"user32.dll")]
publicstaticexternintGetClassName(IntPtrhWnd,StringBuilderlpClassName,
intnMaxCount);
[DllImport(
"user32.dll")]
publicstaticexternboolIsWindow(IntPtrhWnd);
[DllImport(
"user32.dll")]
publicstaticexternboolIsWindowVisible(IntPtrhWnd);
[DllImport(
"user32.DLL")]
publicstaticexternIntPtrFindWindowEx(IntPtrhwndParent,
IntPtrhwndChildAfter,
stringlpszClass,stringlpszWindow);
[DllImport(
"user32.dll")]
publicstaticexternuintGetWindowThreadProcessId(IntPtrhWnd,
outuintdwProcessId);

[DllImport(
"psapi.dll")]
publicstaticexternuintGetModuleBaseName(IntPtrhProcess,IntPtrhModule,
StringBuilderlpBaseName,
uintnSize);

publicconstuintPROCESS_VM_OPERATION=0x0008;
publicconstuintPROCESS_VM_READ=0x0010;
publicconstuintPROCESS_VM_WRITE=0x0020;
publicconstuintPROCESS_QUERY_INFORMATION=0x0400;

[DllImport(
"kernel32.dll")]
publicstaticexternIntPtrOpenProcess(uintdwDesiredAccess,
boolbInheritHandle,uintdwProcessId);

[DllImport(
"kernel32.dll")]
publicstaticexternboolCloseHandle(IntPtrhandle);

[DllImport(
"user32.dll")]
publicstaticexternintGetWindowLong(IntPtrhWnd,intnIndex);
publicconstintGWL_STYLE=-16;
publicconstintES_READONLY=0x800;

publicconstuintMEM_COMMIT=0x1000;
publicconstuintMEM_RELEASE=0x8000;

publicconstuintMEM_RESERVE=0x2000;
publicconstuintPAGE_READWRITE=4;

[DllImport(
"kernel32.dll")]
publicstaticexternIntPtrVirtualAllocEx(IntPtrhProcess,IntPtrlpAddress,
uintdwSize,uintflAllocationType,uintflProtect);

[DllImport(
"kernel32.dll")]
publicstaticexternboolVirtualFreeEx(IntPtrhProcess,IntPtrlpAddress,
uintdwSize,uintdwFreeType);

[DllImport(
"kernel32.dll")]
publicstaticexternboolWriteProcessMemory(IntPtrhProcess,IntPtrlpBaseAddress,
IntPtrlpBuffer,
intnSize,refuintvNumberOfBytesRead);

[DllImport(
"kernel32.dll")]
publicstaticexternboolReadProcessMemory(IntPtrhProcess,IntPtrlpBaseAddress,
IntPtrlpBuffer,
intnSize,refuintvNumberOfBytesRead);

privateIntPtrrichHandle;

publicstringGetProcessName(uintAProcessId)
...{
StringBuildervBuffer
=newStringBuilder(256);
IntPtrvProcess
=OpenProcess(
PROCESS_QUERY_INFORMATION
|PROCESS_VM_READ,false,AProcessId);
try
...{
if(GetModuleBaseName(vProcess,IntPtr.Zero,vBuffer,
(
uint)vBuffer.Capacity)>0)
returnvBuffer.ToString();
elsereturnstring.Empty;
}

finally
...{
CloseHandle(vProcess);
}

}


publicboolEnumChild(IntPtrhwnd,intlParam)
...{
if(!IsWindowVisible(hwnd))returntrue;//不可见
StringBuildervBuffer=newStringBuilder(256);
GetClassName(hwnd,vBuffer,vBuffer.Capacity);
if(vBuffer.ToString().ToLower()=="richedit20a")
...{
if((GetWindowLong(hwnd,GWL_STYLE)&ES_READONLY)!=ES_READONLY)//非只读
...{
richHandle
=hwnd;
returnfalse;
}

}

returntrue;
}


publicboolEnumFunc(IntPtrhwnd,intlParam)
...{
if(!IsWindowVisible(hwnd))returntrue;//不可见
StringBuildervBuffer=newStringBuilder(256);
GetClassName(hwnd,vBuffer,vBuffer.Capacity);
if(vBuffer.ToString()=="#32770")
...{
uintvProcessId;
GetWindowThreadProcessId(hwnd,
outvProcessId);
if(GetProcessName(vProcessId).ToLower()=="qq.exe")
...{
GetWindowText(hwnd,vBuffer,vBuffer.Capacity);
if(vBuffer.ToString().IndexOf("聊天中")>=0)//标题中含"聊天中"
...{
EnumChildWindows(hwnd,@EnumChild,lParam);
returnfalse;
}

}

}

returntrue;
}


[StructLayout(LayoutKind.Sequential)]
publicstructGETTEXTLENGTHEX
...{
publicuintflags;
publicuintcodepage;
}


[StructLayout(LayoutKind.Sequential)]
publicstructGETTEXTEX
...{
publicintcb;
publicintflags;
publicintcodepage;
publicIntPtrlpDefaultChar;
publicIntPtrlpUsedDefChar;
}
;

publicconstintGTL_DEFAULT=0;
publicconstintGT_DEFAULT=0;
publicconstintWM_USER=0x0400;
publicconstintEM_GETTEXTEX=WM_USER+94;
publicconstintEM_GETTEXTLENGTHEX=WM_USER+95;

publicstringProcess_ReadRichEditText(IntPtrAHandle)
...{
if(!IsWindow(AHandle))returnstring.Empty;
stringvReturn=string.Empty;
uintvProcessId;
GetWindowThreadProcessId(AHandle,
outvProcessId);
IntPtrvProcess
=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE,
false,vProcessId);
try
...{
uintvNumberOfBytesRead=0;
IntPtrvPointer
=VirtualAllocEx(vProcess,IntPtr.Zero,0x1000,
MEM_RESERVE
|MEM_COMMIT,PAGE_READWRITE);
GETTEXTLENGTHEXvGetTextLengthEx
=newGETTEXTLENGTHEX();
vGetTextLengthEx.flags
=GTL_DEFAULT;
vGetTextLengthEx.codepage
=1200;//Unicode
IntPtrvAddress=Marshal.AllocCoTaskMem(Marshal.SizeOf(vGetTextLengthEx));
Marshal.StructureToPtr(vGetTextLengthEx,vAddress,
false);
WriteProcessMemory(vProcess,vPointer,vAddress,
Marshal.SizeOf(vGetTextLengthEx),
refvNumberOfBytesRead);
Marshal.FreeCoTaskMem(vAddress);
intL=SendMessage(AHandle,EM_GETTEXTLENGTHEX,(int)vPointer,0);
VirtualFreeEx(vProcess,vPointer,
0,MEM_RELEASE);
if(L<=0)returnvReturn;
GETTEXTEXvGetTextEx
=newGETTEXTEX();
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),
refvNumberOfBytesRead);
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,refvNumberOfBytesRead);
vReturn
=Marshal.PtrToStringUni(vAddress,L*2);
Marshal.FreeCoTaskMem(vAddress);
VirtualFreeEx(vProcess,vPointer,
0,MEM_RELEASE);
}

finally
...{
CloseHandle(vProcess);
}

returnvReturn;
}


privatevoidbutton1_Click(objectsender,EventArgse)
...{
richHandle
=IntPtr.Zero;
EnumWindows(EnumFunc,
0);
if(richHandle==IntPtr.Zero)return;
Console.WriteLine(Process_ReadRichEditText(richHandle));
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值