Тема: AHK: Переход на уровень вверх по double click
Здравствуйте. Как можно, или вообще возможно ли реализовать переход на уровень вверх в проводнике Windows по двойному клику в любом пустом месте папки?
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Здравствуйте. Как можно, или вообще возможно ли реализовать переход на уровень вверх в проводнике Windows по двойному клику в любом пустом месте папки?
~LButton::
if (A_PriorHotkey <> "~LButton" or A_TimeSincePriorHotkey > 400)
{
;Слишком большой промежуток между нажатиями, так что это не двойное нажатие.
KeyWait, LButton
return
}
Send !{sc148} ;Alt + стрелка вверх
return
Из справки по KeyWait.
isxodnik, а как ваш скрипт узнает, что место, по которому кликнули, действительно пустое, и под ним не было иконки?
Никак. Самому интересно, как это возможно.
Acc можно использовать думаю для этого. Главное чтобы скрипт не заблочил антивир.
__Михаил__ Что за асс?
Нужно ahk именно?
svoboden Да нет, не обязательно ahk. Нужно для личных нужд. Пользовался разными файловыми менеджерами, и там привык к этому действию.
Для проводника есть QTTabBar там есть такая функция.
svoboden Я знаю про эту утилиту, пользовался какое то время (окна по типу вкладок, слишком много настроек). Но не зашла эта утилита, со временем вернулся на проводник Windows. Не хватает для полного счастья, только этой функции.
Вижу, без поллитра не разберётесь.
#If hWnd := WinActive("ahk_class CabinetWClass")
~LButton::
if (A_PriorHotkey = A_ThisHotkey && A_TimeSincePriorHotkey < 400 && IsEmptySpaceUnderCusor())
NavigateToParentDir(hWnd)
Return
#If
IsEmptySpaceUnderCusor() {
static ROLE_SYSTEM_WINDOW := 0x00000009
AccObj := AccObjectFromPoint(childId)
Return (childId ? AccObj : AccObj.accParent).accRole(0) = ROLE_SYSTEM_WINDOW
}
AccObjectFromPoint(ByRef childId = "", x = "", y = "") {
static VT_DISPATCH := 9, F_OWNVALUE := 1, h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
AccObject := 0
(x = "" || y = "") ? DllCall("GetCursorPos", "Int64P", pt) : pt := x & 0xFFFFFFFF | y << 32
VarSetCapacity(varChild, 8 + A_PtrSize*2, 0)
if DllCall("oleacc\AccessibleObjectFromPoint", "Int64", pt, "PtrP", pAcc, "Ptr", &varChild) = 0
childId := NumGet(varChild, 8, "UInt"), AccObject := ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
Return AccObject
}
NavigateToParentDir(hWnd) {
static comType := (VT_ARRAY := 0x2000) | (VT_UI1 := 0x11)
Shell := ComObjCreate("Shell.Application")
for Window in Shell.Windows {
if (hWnd = Window.hwnd) {
Folder := Window.Document.Folder
parentDirPath := Folder.ParentFolder.Self.Path
break
}
}
if parentDirPath {
DllCall("shell32\SHParseDisplayName", "WStr", parentDirPath, "Ptr", 0, "PtrP", PIDL, "UInt", 0, "Ptr", 0)
ilSize := DllCall("shell32\ILGetSize", "Ptr", PIDL, "UInt")
VarSetCapacity(SAFEARRAY, 16 + A_PtrSize*2, 0)
NumPut(1 , SAFEARRAY)
NumPut(1 , SAFEARRAY, 4)
NumPut(PIDL , SAFEARRAY, 8 + A_PtrSize)
NumPut(ilSize, SAFEARRAY, 8 + A_PtrSize*2)
try Window.Navigate2( ComObject(comType, &SAFEARRAY), 0 )
DllCall("shell32\ILFree", "Ptr", PIDL)
}
}
teadrinker Даже не думал что будет решение. Опробовал скрипт, работает, но к сожалению с ошибками. После открытия нескольких папок выходит ошибка на 11 строке, где нужно вернуть значение из функции. Появляется в момент double клика по папке.
Сделайте скриншот сообщения об ошибке.
Чтобы отобразить картинку, пользуйтесь сервисами, где можно получить прямую ссылку на изображение, эту ссылку оборачиваете тегами img. Я отредактировал ваш пост, можете посмотреть, как это сделано, нажав кнопку «Изменить».
работает, но к сожалению с ошибками
Попробуйте так:
#If hWnd := WinActive("ahk_class CabinetWClass")
~LButton::
if (A_PriorHotkey = A_ThisHotkey && A_TimeSincePriorHotkey < 400 && IsEmptySpaceUnderCusor())
NavigateToParentDir(hWnd)
Return
#If
IsEmptySpaceUnderCusor() {
Return AccObjectFromPoint().accRole(0) = (ROLE_SYSTEM_LIST := 0x21)
}
AccObjectFromPoint(ByRef childId = "", x = "", y = "") {
static VT_DISPATCH := 9, F_OWNVALUE := 1, h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
AccObject := 0
(x = "" || y = "") ? DllCall("GetCursorPos", "Int64P", pt) : pt := x & 0xFFFFFFFF | y << 32
VarSetCapacity(varChild, 8 + A_PtrSize*2, 0)
if DllCall("oleacc\AccessibleObjectFromPoint", "Int64", pt, "PtrP", pAcc, "Ptr", &varChild) = 0
childId := NumGet(varChild, 8, "UInt"), AccObject := ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
Return AccObject
}
NavigateToParentDir(hWnd) {
static comType := (VT_ARRAY := 0x2000) | (VT_UI1 := 0x11)
Shell := ComObjCreate("Shell.Application")
for Window in Shell.Windows {
if (hWnd = Window.hwnd) {
Folder := Window.Document.Folder
parentDirPath := Folder.ParentFolder.Self.Path
break
}
}
if parentDirPath {
DllCall("shell32\SHParseDisplayName", "WStr", parentDirPath, "Ptr", 0, "PtrP", PIDL, "UInt", 0, "Ptr", 0)
ilSize := DllCall("shell32\ILGetSize", "Ptr", PIDL, "UInt")
VarSetCapacity(SAFEARRAY, 16 + A_PtrSize*2, 0)
NumPut(1 , SAFEARRAY)
NumPut(1 , SAFEARRAY, 4)
NumPut(PIDL , SAFEARRAY, 8 + A_PtrSize)
NumPut(ilSize, SAFEARRAY, 8 + A_PtrSize*2)
try Window.Navigate2( ComObject(comType, &SAFEARRAY), 0 )
DllCall("shell32\ILFree", "Ptr", PIDL)
}
}
teadrinker теперь понял как выкладывать на i.imgur. По скрипту: ошибки не выдает, но изредка имеют место ложные срабатывания. При открытие папки, она открывается на сотые доли секунды, и тут же возвращается на уровень вверх (то есть на исходную директорию где был сделан клик)
P.s. Если бы не этот небольшой недочет, то наверное ему место в коллекции. Уж очень удобный в повседневном использовании.
теперь понял как выкладывать на i.imgur.
Ваш сервис тоже даёт прямую ссылку, вот она:
изредка имеют место ложные срабатывания
Скорее всего, с этим ничего не сделаешь, просто основная функция двойного клика успевает сработать раньше, чем код скрипта. Потестировал, у меня такое происходит очень редко, но случалось.
teadrinker Понимаю, изначально считал что невозможно это сделать средствами ahk. Спасибо вам большое за реализацию скрипта.
Вот так должно быть надёжнее:
#If !res && hWnd := WinActive("ahk_class CabinetWClass")
~LButton::
if !res := IsEmptySpaceUnderCusor()
Return
KeyWait, LButton
KeyWait, LButton, D T.4
(!ErrorLevel && NavigateToParentDir(hWnd))
res := ""
Return
#If
IsEmptySpaceUnderCusor() {
Return AccObjectFromPoint().accRole(0) = (ROLE_SYSTEM_LIST := 0x21)
}
AccObjectFromPoint(ByRef childId = "", x = "", y = "") {
static VT_DISPATCH := 9, F_OWNVALUE := 1, h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
AccObject := 0
(x = "" || y = "") ? DllCall("GetCursorPos", "Int64P", pt) : pt := x & 0xFFFFFFFF | y << 32
VarSetCapacity(varChild, 8 + A_PtrSize*2, 0)
if DllCall("oleacc\AccessibleObjectFromPoint", "Int64", pt, "PtrP", pAcc, "Ptr", &varChild) = 0
childId := NumGet(varChild, 8, "UInt"), AccObject := ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
Return AccObject
}
NavigateToParentDir(hWnd) {
static comType := (VT_ARRAY := 0x2000) | (VT_UI1 := 0x11)
Shell := ComObjCreate("Shell.Application")
for Window in Shell.Windows {
if (hWnd = Window.hwnd) {
Folder := Window.Document.Folder
parentDirPath := Folder.ParentFolder.Self.Path
break
}
}
if parentDirPath {
DllCall("shell32\SHParseDisplayName", "WStr", parentDirPath, "Ptr", 0, "PtrP", PIDL, "UInt", 0, "Ptr", 0)
ilSize := DllCall("shell32\ILGetSize", "Ptr", PIDL, "UInt")
VarSetCapacity(SAFEARRAY, 16 + A_PtrSize*2, 0)
NumPut(1 , SAFEARRAY)
NumPut(1 , SAFEARRAY, 4)
NumPut(PIDL , SAFEARRAY, 8 + A_PtrSize)
NumPut(ilSize, SAFEARRAY, 8 + A_PtrSize*2)
try Window.Navigate2( ComObject(comType, &SAFEARRAY), 0 )
DllCall("shell32\ILFree", "Ptr", PIDL)
}
}
Сейчас только проверил, по мне этот вариант идеальный! Ни одного ложного срабатывания. 100% отработал как надо. Большое вам спасибо уважаемый teadrinker за такой замечательный скрипт. Скрипту точно место в коллекции.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться