2007. december 11., kedd
Capture text from another non-Delphi application window
Problem/Question/Abstract:
I need to capture the text from a scrolling text window in another program that I don't have access to only through a window handle. Can I use SendMEssage or something to ge the text with WM_GETTEXT type message. I know there are programs like spell checkers that can do this. Any help would be appreciated.
Answer:
Solve 1:
The example runs 'chkdsk.exe c:\' and displays the output to Memo1. Put a TMemo (Memo1) and a TButton (Button1) on your form. Put this code in the OnCLick of Button1:
procedure TForm1.Button1Click(Sender: TObject);
procedure RunDosInMemo(DosApp: string; AMemo: TMemo);
const
ReadBuffer = 2400;
var
Security: TSecurityAttributes;
ReadPipe, WritePipe: THandle;
start: TStartUpInfo;
ProcessInfo: TProcessInformation;
Buffer: Pchar;
BytesRead: DWord;
Apprunning: DWord;
begin
with Security do
begin
nlength := SizeOf(TSecurityAttributes);
binherithandle := true;
lpsecuritydescriptor := nil;
end;
if Createpipe(ReadPipe, WritePipe, @Security, 0) then
begin
Buffer := AllocMem(ReadBuffer + 1);
FillChar(Start, Sizeof(Start), #0);
start.cb := SizeOf(start);
start.hStdOutput := WritePipe;
start.hStdInput := ReadPipe;
start.dwFlags := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW;
start.wShowWindow := SW_HIDE;
if CreateProcess(nil, PChar(DosApp), @Security, @Security, true,
NORMAL_PRIORITY_CLASS, nil, nil, start, ProcessInfo) then
begin
repeat
Apprunning := WaitForSingleObject(ProcessInfo.hProcess, 100);
Application.ProcessMessages;
until
(Apprunning <> WAIT_TIMEOUT);
repeat
BytesRead := 0;
ReadFile(ReadPipe, Buffer[0],
ReadBuffer, BytesRead, nil);
Buffer[BytesRead] := #0;
OemToAnsi(Buffer, Buffer);
AMemo.Text := AMemo.text + string(Buffer);
until
(BytesRead < ReadBuffer);
end;
FreeMem(Buffer);
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ReadPipe);
CloseHandle(WritePipe);
end;
end;
begin {Button1 code}
RunDosInMemo('chkdsk.exe c:\', Memo1);
end;
Unfortunaly that will only work with applications that send output to stdout. A Windows application usually doesn't do this.
Solve 2:
The usually use different techiques, like OCR on a screen bitmap. There is simply no generic method to get text from other windows. What you can try, however, is this:
function GetTextFromWindow(wnd: HWND): string;
var
count: Cardinal;
begin
result := '';
if SendMessageTimeout(wnd, WM_GETTEXTLENGTH, 0, 0,
SMTO_ABORTIFHUNG, 1000, count) <> 0 then
begin
if count = 0 then
Exit;
SetLength(result, count);
if SendMessageTimeout(wnd, WM_GETTEXT, count + 1, lparam(@result[1]),
SMTO_ABORTIFHUNG, 1000, count) = 0 then
result := '';
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
wnd: HWND;
begin
wnd := FindWindow('notepad', nil);
if wnd <> 0 then
begin
wnd := GetWindow(wnd, GW_CHILD);
if wnd <> 0 then
memo1.text := GetTextfromwindow(wnd);
end
else
memo1.text := 'Notepad not running.';
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése