Тема: AHK: Получение имени файла под курсором в Проводнике
Скрипт определяет содержание первой колонки (имя файла/папки) той строки контрола SysListView32 проводника Windows, над которой находится курсор. При небольшой задержке курсора над строкой появляется ToolTip с именем файла.
Принцип работы скрипта. При остановке курсора над контролом SysListView32 определяются координаты курсора, затем определяются координаты всех видимых строк, а также считывается текст из их первых колонок. При пересечении координат курсора и какой-либо из строк содержание её первой колонки показывается в ToolTip'е.
Координаты строк считываются с помощью посылки контролу SysListView32 сообщения LVM_GETITEMRECT. Некоторая сложность в том, что информацию это сообщение может записать только в буфер, находящийся в виртуальном адресном пространстве процесса, которому принадлежит контрол. Поэтому перед использованием сообщения нужно зарезервировать место в виртуальной памяти процесса под буфер (это делает ф-ция VirtualAllocEx()), а затем уже скопировать информацию из него в буфер, принадлежащий процессу скрипта (ReadProcessMemory()).
LVM_FIRST := 0x1000
LVM_GETITEMCOUNT := (LVM_FIRST + 4)
LVM_GETTOPINDEX := (LVM_FIRST + 39)
LVM_GETITEMRECT := (LVM_FIRST + 14)
PROCESS_VM_OPERATION := 0x8
PROCESS_VM_READ := 0x10
MEM_COMMIT := 0x1000
PAGE_READWRITE := 0x4
MEM_RELEASE := 0x8000
#Persistent
Process, Priority,, H
CoordMode, Mouse
CoordMode, ToolTip
VarSetCapacity(RECT, 16) ; буфер в адресном пространстве скрипта
SetTimer, MouseGetPos, 50
Return
MouseGetPos:
MouseGetPos,,,, Control
if !InStr(Control, "SysListView")
{
ToolTip
Return
}
MouseGetPos, XM, YM, Win_ID, LV_ID, 2
if (XM != XM_Prev || YM != YM_Prev)
{
ToolTip
SetTimer, GetItem, -100
}
XM_Prev := XM, YM_Prev := YM
Return
GetItem:
WinGetPos, X_LV, Y_LW,,, ahk_id %LV_ID%
WinGet, PID, PID, ahk_id %Win_ID%
SendMessage, LVM_GETITEMCOUNT,,,, ahk_id %LV_ID%
Rows := ErrorLevel
SendMessage, LVM_GETTOPINDEX,,,, ahk_id %LV_ID%
TopIndex := ErrorLevel
ControlGet, Text, List, Col1,, ahk_id %LV_ID%
Stop =
While !Stop && (A_Index <= Rows - TopIndex)
{
CurrentItem := TopIndex + A_Index - 1
hProcess := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ
, UInt, 0
, UInt, PID)
; буфер в адресном пространстве окна проводника:
pBuffer := DllCall("VirtualAllocEx", UInt, hProcess
, UInt, 0
, UInt, 16
, UInt, MEM_COMMIT
, UInt, PAGE_READWRITE)
SendMessage, LVM_GETITEMRECT, CurrentItem, pBuffer,, ahk_id %LV_ID%
DllCall("ReadProcessMemory", UInt, hProcess
, UInt, pBuffer
, UInt, &RECT
, UInt, 16
, UInt, 0)
Left := NumGet(RECT), Right := NumGet(RECT, 8)
Top := NumGet(RECT, 4), Bottom := NumGet(RECT, 12)
DllCall("VirtualFreeEx", UInt, hProcess
, UInt, pBuffer
, UInt, 0
, UInt, MEM_RELEASE)
DllCall("CloseHandle", UInt, hProcess)
if (XM >= X_LV + Left && XM <= X_LV + Right && YM >= Y_LW + Top && YM <= Y_LW + Bottom)
{
Loop, parse, Text, `n
{
if (A_Index = CurrentItem + 1)
{
ToolTip, %A_LoopField%, XM+20, YM-5 ; в переменной A_LoopField имя файла под курсором
Stop = 1
Break
}
}
}
}
Return
Тема для обсуждения на форуме.