Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Активное окно (http://forum.oszone.net/showthread.php?t=347297)

beginer 10-12-2020 20:22 2942554

Активное окно
 
Здравствуйте.

Подскажите, пожалуйста как изменить следующую функцию, чтобы "захват" производился только с активного окна?
Мне это нужно для дела(вредительством не занимаюсь). Нужно как-бы "просеять" все открытые окна-проводники и отделить от них только активное.
Да, могу выделить нужное содержимое ориентируясь на путь, но проблемы начинаются тогда, когда открыто сразу ДВА! (и более) проводника с одинаковым путём.
Вот здесь-то и нужно определиться с какого из них "захватывать" выделенные объекты.

Вот код:
Код:

Function GetSelectedFiles() 'Returns paths as array of strings
  Dim FileList, Window, SelectedItem
  'avoid duplicates by storing paths in dictionary keys
  Set FileList = CreateObject("Scripting.Dictionary")

  With CreateObject("Shell.Application")
    For Each Window In .Windows
      ' Document type IShellFolderViewDual3
      If InStr(1, typename(Window.Document),"IShellFolderView", 1) > 0 Then
        For Each SelectedItem In Window.Document.SelectedItems
          FileList(SelectedItem.Path) = Null
        Next
      End If
    Next
  End With
   
  GetSelectedFiles = FileList.Keys 'array of paths
End Function

И ещё один вопрос, если позволите. Тоже по теме, но это скорее вопрос к ОС.
Есть такая замечательная комбинация клавиш как Alt+Esc (активация предыдущего приложения). К сожалению, такого же антипода не нашёл(альтернатива - только Alt+TAB). Хорошо, допустим. Но почему игнорируются окна c флагом "поверх остальных"? Например, я запустил "Диспетчер задач" и выставил ему(его окну) этот флаг. Далее переключился, например, на Total Commander. А вот теперь начинается самое интересное. Почему по нажатию вышеуказанной комбинации клавиш я не попадаю на окно "Диспетчера задач", а на какое-то др. окно?


Очень надеюсь на вашу помощь.
Скрытый текст
Данное сообщение было отредактировано в связи с замечанием администратора

Vadikan 12-12-2020 16:39 2942743

Цитата:

Цитата beginer
Тоже по теме, но это скорее вопрос к ОС. »

Не разводите оффтоп (ответы будут удалены). Одна проблема/вопрос - одна тема. Вопросы по ОС задавайте в осевых форумах.

beginer 15-12-2020 14:18 2943030

Vadikan, хорошо. Вас понял. Тогда может ли кто-нибудь помочь мне с первой частью?
Как в вышеприведённой функции отфильтровать все остальные окна, кроме целевого (если мне известен заголовок целевого окна) ?


Добавлено:
Дополнительное условие, типа:
Код:

If Window.Visible = True Then
не подходит, так как все открытые окна проводника являются видимыми. И те, которые нужно отсеять и целевое окно.

Iska 15-12-2020 16:27 2943044

beginer, в чём исполняется код?

beginer 15-12-2020 19:16 2943069

Iska, в том-то и дело, что не через w(с)script.
Код выполняется в PureBasic'е. Там через такие дебри производится пуск, что самое простое для меня это поправить сам скрипт (по-возможности).
Единственный вариант, который могу выполнить - это перед выполнением закрыть окно проводника с идентичным путём или временно скрыть его, чтобы сработало условие выше. Но это некрасиво. И хотелось более элегантного решения. Спрашивал здесь как читать заголовок каждого окна во время перебора(в уже существующем цикле) и соответственно сравнивать его с определённой строкой каждую итерацию. В этом и заключалась суть вопроса. Если из vbs можно вызывать API ОС, то это бы решило/существенно упростило задачу. "Я так думаю" (С). Не скрою, что пример скрипта взял уже готовый. Он потребовался дабы выяснить отмеченные объекты. Иных решений данного вопроса увы не встречал. Неудобство данного варианта заключается в том, что скрипт "хватает" всё что "видит". Повторюсь, что отсеять проводники с уникальными путями не составляет особого труда. НО с идентичным путём(ями) - это проблема!


Добавлено:
Пожалуйста не беспокойтесь о случаях, когда в настройках ОС (св-ва папки) не выставлено показывать полный путь. Сейчас говорю про вариации с одинаковыми папками на различных разделах и расположенных на одинаковых уровнях(к примеру, "C:\Test"; "D:\Test"; "E:\Test" и т.д.). Ну и соответственно про одинаковые для такого случая заголовки окон. Это проблема решаема.
В PB прочитать title совсем не сложно (неужели vbs'у это не под силу?). Категорически нужен этот скрипт (без него никак не обойтись).

Iska 15-12-2020 20:12 2943079

О, боже ж ты мой :( …


Iska 15-12-2020 21:22 2943085

Цитата:

Цитата beginer
Код выполняется в PureBasic'е. »

У меня в нём ошибка прямо на строке:
Код:

Function GetSelectedFiles() 'Returns paths as array of strings
Попробуйте это:
Цитата:

Остановлюсь на п.2. В документации говорится, что вызов ShellWindows.Item() без параметров возвращает то же, что и ShellWindows.Item(0). Однако, как я убедился, это не соответствует действительности: стабильно возвращается последнее активное окно в коллекции ShellWindows. Хотя, может быть, это верно не на всех системах…
Отсюда: WSH(+ Реестр): «Найти объект...» в контекстном меню ярлыков (Страница 1) — Windows Script Host, HTA (VBScript, JScript) — Общение — Серый форум.

Iska 15-12-2020 21:54 2943086

У меня, увы, не сработало — под Windows 7 SP1 x64:
Код:

CreateObject("Shell.Application").Windows().Item(3).document.Folder.self.Path
стабильно возвращает не последнее активное окно, а тупо Desktop текущего пользователя.

beginer 15-12-2020 21:58 2943087

Iska, спасибо за желание помочь. Но этот код не запустить "напрямую"(с ходу/в лоб). Нужна ещё довольно весомая и мудрёная обвёртка. Так что тот кусочек кода, что выше - это только вершина айсберга. Однако сделана обвёртка достойно/добротно. По всем канонам(всё по-взрослому). Очень много работы с памятью(указателями). Немец постарался и поделился своим титаническим трудом с остальными/общественностью.
К тому же в модуле используются вызовы API-функций. Смотрю, что Вы "качаете" демо-версию, а в ней для вызова API нужно действовать немного по-другому. То есть сначала нужно открыть библиотеку и т.д. В полной же версии эти функции являются как бы "нативные" и не требуют дополнительных телодвижений для их вызова. Работать намного проще и удобней.
Не знаю запрещены ли здесь ссылки на сторонние сайты, но если что поправьте (по крайней мере это точно не варез, а вполне себе open source).
Вот сам модуль-обвёртка, если интересно посмотреть. Но я бы туда без поллитры не лез :)
Шутка.

Вот чувствую, что не в то русло опять зашёл разговор. Заругают админы(наверное нужно завязывать). Поэтому и просил подправить непосредственно vbscript.


P.S. Когда-то начинал знакомство со скриптами, но это было недолго(довольно быстро перешёл на PB). Поэтому и задаю здесь возможно детский вопрос. + знаю, что на этом форуме обитает/прописано много профессионалов, причём русскоговорящих.

Iska 15-12-2020 22:43 2943091

Цитата:

Цитата beginer
К тому же в модуле используются вызовы API-функций. »

beginer, в приведённом Вами коде нет вызовов WinAPI. Чистый COM/Automation.

Цитата:

Цитата beginer
Поэтому и просил подправить непосредственно vbscript. »

Так нечего поправлять. Я не вижу способов найти средствами Automation «активное окно Проводника». Как бы мы их не тасовали — они возвращаются в порядке создания окон, а не в порядке Z-order. А вот Вы можете, взяв WinAPI наперевес, попробовать пройтись по списку полученных окон.

beginer 16-12-2020 21:43 2943190

Iska, говорил про модуль(вызовы WinAPI).
Ну нет, так нет. Видимо прийдётся закрывать одинаковые. Получить Z-Order - не проблема. Недопонял только что это даст? Хэндл активного окна мне и так известен(причём заранее и достоверно). То есть его не нужно искать непосредственно в скрипте. Если бы его теперь сравнивать с каждым найденным окном(цикл скрипта), тогда да. Будет толк. Или даже не хэндл, а заголовок окна. Повторюсь, что мне не нужно искать активное окно проводника! Я спрашивал совсем не об этом. А о возможности добавить в скрипт дополнительное условие(в момент перебора окон). Представьте, что у Вас есть ещё одна переменная(естественно в поле зрения скрипта), в которой находится хэндл или заголовок активного окна проводника(как угодно). Как эту переменную сделать видимой самим скриптом - тоже не есть вопрос данной темы.

Iska 16-12-2020 22:15 2943193

Цитата:

Цитата beginer
Хэндл активного окна мне и так известен

Если бы его теперь сравнивать с каждым найденным окном(цикл скрипта), тогда да. Будет толк. Или даже не хэндл, а заголовок окна. »

Именно хэндл. Заголовок не годится — он не уникален.

WSH:
Код:

Option Explicit

Dim objWebBrowser

For Each objWebBrowser In WScript.CreateObject("Shell.Application").Windows()
        With objWebBrowser
                If InStr(1, TypeName(.document), "ShellFolderViewDual", vbTextCompare) > 0 Then
                        WScript.Echo .hwnd, vbTab, .document.Folder.self.Path
                End If
        End With
Next

WScript.Quit 0

Сравнивайте:
Код:

                If InStr(1, TypeName(.document), "ShellFolderViewDual", vbTextCompare) > 0 Then
                        WScript.Echo .hwnd, vbTab, .document.Folder.self.Path
                       
                        If .hwnd = ... Then
                                ...
                        End If
                End If


Serguei Kouzmine 19-12-2020 03:57 2943448

@beginer VB языку трудно с получением

поэтому часто советуют запустить повершелл обертку win32 API которая даст вам
ответ
например
Код:

param(
  [int]$sleep = 10
)
start-sleep -second $sleep
# based on https://social.technet.microsoft.com/Forums/en-US/4d257c80-557a-4625-aad3-f2aac6e9a1bd/get-active-window-info?forum=winserverpowershell
add-type -name Utils -namespace Win32 -memberdefinition @'
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
'@
$windowHandle = [Win32.Utils]::GetForegroundWindow()
Get-Process | where-Object { $_.mainWindowHandle -eq $windowHandle } |
  select-Object -property processName, MainWindowTItle, MainWindowHandle

Код:

PS C:\Users\Serguei> . .\get_window_has_focus.ps1 -sleep 4

ProcessName MainWindowTitle                  MainWindowHandle
----------- ---------------                  ----------------
vivaldi    Get Active Window Info - Vivaldi            67038

в вашем скрипте эту информацию прочитаете и найдете которое активное

кстати если будете гуглить то ищите по английски это назваетется
Window has Focus

напр

find which window has focus

https://social.technet.microsoft.com...rverpowershell - то что я привел выше (добавил задержку чтобы тестировать было время поднять другое окно

beginer 19-12-2020 10:54 2943457

Serguei Kouzmine, спасибо большое за желание помочь, но PS не подходит. Да и запускается он откровенно/неприлично долго. Хотел только подстроиться под уже готовый vbscript, так как он благополучно "прикручен" к основной программе. И в принципе, работа скрипта вполне устраивает, за исключением этой небольшой оказии. И, да, конечная цель заключалась совсем не в поиске активного окна. Почему изначально сделал акцент на это и тему так назвал, так это для того, чтобы задавая вопрос объяснить/сразу дать понять, что ищу способ сепарации/разделения. Скрипт этот захватывает выделенные объекты из открытых окон-проводников. Если у Вас на ПК, допустим, открыты проводники с путями "С:\TEST" и "D:\TEST" + в обоих что-то выбрано, то этот случай просто решается. А вот если открыто два окна(две копии проводника) с "С:\TEST"(сейчас не важно что там покажет title, полный путь или нет) и допустим, что у вас в этом каталоге есть след. файлы: "1.txt", "2.txt", "3.txt", "4.txt" и "5.txt". Допустим в одном окне вы выбрали файлы 1, 3, 5, а во втором 2 и 4. Так вот в этом случае в результат будут включены все пять файлов. И это есть нехорошо и неправильно. И обойти это не представляется возможным, кроме как закрыть или временно скрыть идентичный проводник(и). Надеюсь, что доходчиво объяснил суть задачи. Естественно, случай с двумя идентичными проводниками, но когда объекты выделены только в одном из них - тоже не представляет опасности.

Iska, Вам тоже спасибо за участие.

Как уже говорил выше, тут мне видится разве что вариант с закрытием окон проводников с идентичными путями(не трогая при этом уникальные, если таковые имеются/открыты). Правда это может раздражать пользователя (мелькающие окна). Будем считать этот случай большой редкостью и что нужно очень постараться/сделать это умышленно, чтобы его достичь.

Всем спасибо!

Iska 19-12-2020 20:21 2943507

beginer, да зачем закрывать-то? Получили хэндл «верхнего» окна Проводника — WinAPI. Перечислили все окна Проводника, отобрали из них только то, которое имеет ранее полученный хэндл, получили из этого окна перечень выделенных объектов Проводника (необязательно файлов или папок) — COM/Automation.


Время: 05:06.

Время: 05:06.
© OSzone.net 2001-