1

Тема: AHK: Переход на уровень вверх по double click

Здравствуйте. Как можно, или вообще возможно ли реализовать переход на уровень вверх в проводнике Windows по двойному клику в любом пустом месте папки?

2 (изменено: isxodnik, 2022-05-18 17:20:17)

Re: AHK: Переход на уровень вверх по double click

~LButton::
if (A_PriorHotkey <> "~LButton" or A_TimeSincePriorHotkey > 400)
{
;Слишком большой промежуток между нажатиями, так что это не двойное нажатие.
    KeyWait, LButton
    return
}
Send !{sc148}	;Alt + стрелка вверх
return

Из справки по KeyWait.

3

Re: AHK: Переход на уровень вверх по double click

isxodnik, а как ваш скрипт узнает, что место, по которому кликнули, действительно пустое, и под ним не было иконки?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

4

Re: AHK: Переход на уровень вверх по double click

Никак. Самому интересно, как это возможно.

5

Re: AHK: Переход на уровень вверх по double click

Acc можно использовать думаю для этого. Главное чтобы скрипт не заблочил антивир.

Win10x64, AHK v1.1.37.01 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101

6

Re: AHK: Переход на уровень вверх по double click

__Михаил__ Что за асс?

7

Re: AHK: Переход на уровень вверх по double click

Библеотека такая.

Win10x64, AHK v1.1.37.01 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101

8 (изменено: svoboden, 2022-05-18 20:28:18)

Re: AHK: Переход на уровень вверх по double click

Нужно ahk именно?

9

Re: AHK: Переход на уровень вверх по double click

svoboden Да нет, не обязательно ahk. Нужно для личных нужд. Пользовался разными файловыми менеджерами, и там привык к этому действию.

10 (изменено: svoboden, 2022-05-18 20:47:21)

Re: AHK: Переход на уровень вверх по double click

Для проводника есть QTTabBar там есть такая функция.

11

Re: AHK: Переход на уровень вверх по double click

svoboden Я знаю про эту утилиту, пользовался какое то время (окна по типу вкладок, слишком много настроек). Но не зашла эта утилита, со временем вернулся на проводник Windows. Не хватает для полного счастья, только этой функции.

12

Re: AHK: Переход на уровень вверх по double click

Вижу, без поллитра не разберётесь.

#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)
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

13

Re: AHK: Переход на уровень вверх по double click

teadrinker Даже не думал что будет решение. Опробовал скрипт, работает, но  к сожалению с ошибками. После открытия нескольких папок выходит ошибка на 11 строке, где нужно вернуть значение из функции. Появляется в момент double клика по папке.

14

Re: AHK: Переход на уровень вверх по double click

Сделайте скриншот сообщения об ошибке.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

15

Re: AHK: Переход на уровень вверх по double click

https://i.imgur.com/Kv9hY09.png

16

Re: AHK: Переход на уровень вверх по double click

Чтобы отобразить картинку, пользуйтесь сервисами, где можно получить прямую ссылку на изображение, эту ссылку оборачиваете тегами img. Я отредактировал ваш пост, можете посмотреть, как это сделано, нажав кнопку «Изменить».

ppss42 пишет:

работает, но  к сожалению с ошибками

Попробуйте так:

#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)
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

17

Re: AHK: Переход на уровень вверх по double click

teadrinker теперь понял как выкладывать на i.imgur. По скрипту: ошибки не выдает, но изредка имеют место ложные срабатывания. При открытие папки, она открывается на сотые доли секунды, и тут же возвращается на уровень вверх (то есть на исходную директорию где был сделан клик)
P.s. Если бы не этот небольшой недочет, то наверное ему место в коллекции. Уж очень удобный в повседневном использовании.

18

Re: AHK: Переход на уровень вверх по double click

ppss42 пишет:

теперь понял как выкладывать на i.imgur.

Ваш сервис тоже даёт прямую ссылку, вот она:

+ открыть спойлер

https://i.imgur.com/UyEQLHg.png

ppss42 пишет:

изредка имеют место ложные срабатывания

Скорее всего, с этим ничего не сделаешь, просто основная функция двойного клика успевает сработать раньше, чем код скрипта. Потестировал, у меня такое происходит очень редко, но случалось.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

19 (изменено: ppss42, 2022-05-19 15:24:54)

Re: AHK: Переход на уровень вверх по double click

teadrinker Понимаю, изначально считал что невозможно это сделать средствами ahk. Спасибо вам большое за реализацию скрипта.

20

Re: AHK: Переход на уровень вверх по double click

Вот так должно быть надёжнее:

#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)
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

21

Re: AHK: Переход на уровень вверх по double click

Сейчас только проверил, по мне этот вариант идеальный! Ни одного ложного срабатывания. 100% отработал как надо. Большое вам спасибо уважаемый teadrinker за такой замечательный скрипт. Скрипту точно место в коллекции.