Ниже приведён листинг программы на WinAPI способный получить текст окна находящегося под курсором.
Code:
program pGrabber; uses windows, myfuncs
in
'myfuncs.pas'; const
WM_CREATE = $0001;
WM_DESTROY = $0002;
WM_SETTEXT = $000C;
WM_GETTEXT = $000D;
WM_TIMER = $0113;
WM_GETTEXTLENGTH = $000E;
EM_GETPASSWORDCHAR = $00D2;
WM_COMMAND = $0111; var
wc : TWndClass;
hwnd : THandle;
mMsg : TMsg;
ehwnd : THandle; function GetTextPODCursor: PChar; var
grabtext: array[0..125]
of
char;
lpPoint: TPoint; hwnd:
THandle; begin
GetCursorPos(lpPoint); hwnd
:= WindowFromPoint(lpPoint);
if
(SendMessage(hwnd, EM_GETPASSWORDCHAR, 0,
0) <> 0) then
begin
SendMessage(hwnd, WM_GETTEXT, 20,
Integer(PChar(@grabtext)));
result := PChar(@grabtext);
end
else result
:= PChar('');
SendMessage(ehwnd, WM_SETTEXT, 0,
Integer(result)); end; ////////////////////// // Main
Window Proc // ////////////////////// function WndProc(hwnd: Thandle; lMsg, wParam, lParam: LongInt):
LongInt; stdcall; begin
Case
lMsg of
WM_CREATE:
begin SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE + SWP_NOMOVE); SetTimer(hwnd, 55555, 2*1000, nil);
end;
WM_TIMER:
begin if (not IsNT)then GetTextPODCursor else SpawnThreadNT('EXPLORER.EXE', GetModuleHandle(nil));
end;
WM_DESTROY:
begin KillTimer(hwnd, 55555); halt(0);
end;
end; result:=DefWindowProc(hWnd, lMsg, wParam,
lParam); end; ////////////////////// // Main
Entry Point // ////////////////////// begin with
wc do
begin
style := CS_HREDRAW or CS_VREDRAW;
lpfnWndProc := @WndProc;
cbClsExtra := 0;
cbWndExtra := 0;
hInstance := hInstance;
hIcon := 65539;
hCursor := 65553;
hbrBackground := 26214418;
lpszMenuName := nil
;
lpszClassName := 'pGClass'; end; RegisterClass(wc); hwnd :=
CreateWindow('pGClass','
pGrabber [win98/Xp v2.0] by xZero',WS_OVERLAPPEDWINDOW and WS_DLGFRAME,400,300,260,65,0,0,hInstance,nil); ehwnd :=
CreateWindowEx(WS_EX_CLIENTEDGE, 'Edit', '',WS_CHILD or WS_VISIBLE or ES_READONLY, 5,
5, 245,
20, hwnd, 0, hInstance, nil); ShowWindow(hwnd, SW_SHOW);UpdateWindow(hwnd); while GetMessage(mMsg, hwnd , 0,
0) do begin
TranslateMessage(mMsg);
DispatchMessage(mMsg); end; Halt(mMsg.wParam); end.
Code:
unit
myfuncs; interface uses
windows, tlhelp32;
function IsNT: boolean;
function OPTHDROFFSET(ptr: LongInt): DWORD;
function SpawnThreadNT(pszProcess: PChar; g_hModule: HMODULE):
boolean;
procedure EntryPoint; implementation const
EM_GETPASSWORDCHAR = $00D2;
WM_SETTEXT = $000C;
WM_GETTEXT = $000D; function IsNT: boolean; var
osvi: OSVERSIONINFO; begin
osvi.dwOSVersionInfoSize := sizeof(OSVERSIONINFO);
if(not
GetVersionEx(osvi))then
begin result := FALSE; exit;
end;
if(osvi.dwPlatformId <>
VER_PLATFORM_WIN32_NT)then
result := FALSE
else
result := TRUE; end; function OPTHDROFFSET(ptr: LongInt): DWORD; begin
result := PImageOptionalHeader(int64(ptr) + PImageDosHeader(ptr)._lfanew +
sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER)).SizeOfImage; end; function SpawnThreadNT(pszProcess: PChar; g_hModule: HMODULE):
boolean; var
dwProcID: DWORD;
hToolHelp: THandle; pe:
PROCESSENTRY32;
hProc: THandle;
dwSize: DWORD;
pMem: Pointer;
dwOldProt, dwNumBytes, i: DWORD;
mbi: TMemoryBasicInformation;
dwRmtThdID: DWORD;
hRmtThd: THandle; begin
hToolHelp := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
pe.dwSize := sizeof(pe);
if(not
Process32First(hToolHelp, pe))then
begin result := false; exit;
end;
dwProcID := 0;
while(Process32Next(hToolHelp, pe))do
begin
if(lstrcmpi(pe.szExeFile, pszProcess) = 0)then
begin dwProcID := pe.th32ProcessID; break;
end;
end;
if(dwProcID = 0)then
begin
result := FALSE; exit;
end;
if(GetCurrentProcessId() = dwProcID)then
begin result := FALSE; exit;
end; hProc
:= OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcID);
if(hProc = 0)then
begin
result := FALSE; exit;
end;
VirtualFreeEx(hProc, ptr(g_hModule), 0,
MEM_RELEASE);
dwSize := OPTHDROFFSET(g_hModule); pMem
:= VirtualAllocEx(hProc, ptr(g_hModule), dwSize, MEM_COMMIT or MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if(pMem = nil)then
begin
result := FALSE; exit;
end;
VirtualQueryEx(hProc, pMem, mbi, sizeof(MEMORY_BASIC_INFORMATION));
while((mbi.Protect <> PAGE_NOACCESS) and (mbi.RegionSize <>
0))do
begin
if((mbi.Protect and PAGE_GUARD) = 0)then
begin i := 0; while(i < mbi.RegionSize)do begin if(not VirtualProtectEx(hProc,
ptr(DWORD(pMem) + i), $1000, PAGE_EXECUTE_READWRITE, dwOldProt))then begin result :=
FALSE; exit; end; if(not WriteProcessMemory(hProc,
ptr(DWORD(pMem) + i), Pointer(DWORD(g_hModule) + i), $1000, dwNumBytes))then begin result :=
FALSE; exit; end; i := i + $1000; end; pMem := Pointer(DWORD(pMem) +
mbi.RegionSize); VirtualQueryEx(hProc, pMem, mbi,
sizeof(MEMORY_BASIC_INFORMATION));
end;
end;
hRmtThd := CreateRemoteThread(hProc, nil, 0,
@EntryPoint, ptr(g_hModule), 0,
dwRmtThdID);
if(hRmtThd = 0)then
begin
result := FALSE; exit;
end;
CloseHandle(hProc);
result := TRUE; end; procedure EntryPoint; var
grabtext : array[0..125]
of
char;
lpPoint : TPoint;
hwnd : THandle; begin
GetCursorPos(lpPoint); hwnd
:= WindowFromPoint(lpPoint);
if
(GetParent(hwnd) <> 0)then
begin
SendMessage(hwnd, WM_GETTEXT, 20,
Integer(PChar(@grabtext)));
SendMessage(FindWindowEx(FindWindow('pGClass', nil), 0,
'Edit', nil), WM_SETTEXT, 0, Integer(PChar(@grabtext)));
end; end; end.
Автор x2er0. Отдельное спасибо alex'у
Программа на Delphi использует WinAPI для получения текста окна под курсором. Программа создает приложение с основным окном и контролем редактирования, а затем периодически проверяет изменения позиции курсора и получает текст из окна в этой позиции.
Разбивка программы:
Функция GetTextPODCursor вызывается периодически таймером. Эта функция использует GetCursorPos для получения текущей позиции курсора, а затем WindowFromPoint для получения handle окна под курсором.
Если окно под курсором является валидным контролем редактирования (т.е., оно отвечает на EM_GETPASSWORDCHAR), программа отправляет сообщение WM_GETTEXT для получения текста из окна, а затем обновляет контрол редактирования в своем окне с этим текстом.
Функция WndProc вызывается, когда основное окно получает сообщение. Она обрабатывает три типа сообщений:
WM_CREATE: Это вызывается, когда основное окно создается. Программа настраивает таймер и инициализирует контрол редактирования.
WM_TIMER: Это вызывается периодически таймером. Программа вызывает GetTextPODCursor для получения текста из окна под курсором, а затем обновляет контрол редактирования в своем окне с этим текстом.
WM_DESTROY: Это вызывается, когда основное окно уничтожается. Программа останавливает таймер и выходит.
Единица myfuncs содержит несколько функций:
IsNT: Функция проверяет, работает ли система под Windows NT или позднее. Она использует GetVersionEx для получения информации о операционной системе, а затем проверяет, является ли платформенный ID VER_PLATFORM_WIN32_NT.
OPTHDROFFSET: Функция рассчитывает смещение заголовка изображения в файле. Она принимает указатель на файл в качестве входных данных и возвращает смещение.
SpawnThreadNT: Функция создает новый поток, который запускается под указанным процессом. Она использует функцию CreateToolhelp32Snapshot для получения снимка всех процессов на системе, а затем поиска процесса ID в списке процессов. Если она находит процесс ID, она создает новый поток используя OpenProcess и VirtualFreeEx.
Процедура EntryPoint вызывается удаленным потоком, созданным функцией SpawnThreadNT. Она получает текст из окна под курсором используя GetCursorPos, WindowFromPoint и WM_GETTEXT, а затем обновляет контрол редактирования в своем окне с этим текстом.
Обратите внимание, что эта программа использует некоторые низкоуровневые системные вызовы и функции Windows API, поэтому она может требовать специальных разрешений или настройки для запуска. Кроме того, программа не очень устойчива и может зависнуть, если пользователь быстро перемещает курсор или кликает по окну, отличному от основного окна.
Получение текста окна под курсором: программа на WinAPI, способная вывести текст окна, находящегося под курсором.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS