Pull to refresh

Удобная навигация в Windows Explorer и Total Commander

.NET
Вы никогда не задумывались над тем, что навигация в Windows могла бы быть намного удобней? Почему бы не добавить возможность, аналогичную навигации по классам во многих современных IDE, когда в выпадающем списке, вызываемом сочетанием клавиш, отображаются папки с нужным именем, вот так:

image

Однажды задумавшись, я написал небольшое приложение под названием «Navigation Assistant», изображенное выше. Оно доступно здесь, исходный код открыт, само оно бесплатное, распространяется по лицензии MIT. Надеюсь, оно окажется кому-либо полезным.

Зачем это нужно?


Вот недостатки навигации в Windows Explorer и Total Commander, которые, уверен, у многих вызывают фрустрацию:
  1. при большой глубине вложенности искомой папки необходимо совершить множество кликов мышью
  2. поиск по умолчанию в Windows Explorer невероятно медленный. Кроме того, чтоб воспользоваться им, надо запустить сам explorer, кликнуть по полю поиска, набрать имя папки или файла целиком, и долго ждать
  3. В Total Commander имеются подсказки при наборе пути в адресной строке, однако набирать необходимо либо полный путь, либо относительный путь (по отношению к текущей папке), что неудобно

Поэтому я и написал «Navigation Assistant», работа которого аналогична навигации по классам или файлам многих современных IDE: сочетания Ctrl-N и Ctrl-Shift-N в продуктах JetBrains (ReSharper, IDEA, PhpStorm, WebStorm), Ctrl-Shift-T в Eclipse.

Бонусом, получаемым при использовании этой программы, является лучшая структура каталогов. Многие разработчики, особенно прочитавшие Code Complete, в курсе того, что мозг хорошо справляется с 7 ± 2 объектами в рабочей памяти; поэтому так же, как полезно ограничивать число полей и методов в классе, полезно ограничивать число подкаталогов в данном каталоге.

При текущем положении вещей этого можно достигнуть лишь ценой неудобной навигации. При использовании Navigation Assistant более не придется опасаться большой вложенности каталогов.

Как этим пользоваться?


Пока поддерживается лишь быстрая навигация по папкам, но не по файлам.

Чтобы быстро попасть в нужную вам папку, в окне Windows Explorer или Total Commander (либо в любом другом, но тогда для навигации будет инстанциирован новый Windows Explorer) нажмите специальное сочетание клавиш (по умолчанию Ctrl-Shift-M, но его можно изменить в настройках). Появится основное окошко приложения:



Начните набирать имя папки, до которой вы хотели бы добраться.

Killer feature: необязательно набирать имя папки целиком; например, чтоб попасть в Documents and Settings, можно набрать лишь «documents and». Более того, необязательно набирать слово «documents» целиком, хватит и «doc and» (привет, JetBrains!); также необязательно набирать имя папки с первого слова: подойдет и «and settings». Специально для разработчиков поддерживается pascal/camel case: к строке поиска «nav assist» будет отнесена и папка «NavigationAssistant».

В результате этих манипуляций на экране появится список подходящих каталогов:



Вам остается либо выбрать нужный элемент мышкой, либо воспользоваться клавишами вверх/вниз и кликнуть Enter (фокус ввода может оставаться в текстовом поле в это время).

Если окошко чем-либо не угодило, его можно быстро свернуть в трей клавишей Escape.

Если же вызвать программу не в Windows Explorer и не в Total Commander, то откроется новое окно Windows Explorer (с необходимой папкой); в настройках же можно изменить навигатор по умолчанию на Total Commander.

Что в нем есть еще?


Еще имеется окно настроек, в котором можно изменить
  1. список программ для поддержки улучшенной навигации (например, отключить Total Commander)
  2. программу для навигации по умолчанию
  3. сочетание клавиш для вызова окошка Navigation Assistant
  4. указать, в каких каталогах производить поиск (например, только в C:\Users\ или только в D:\)
  5. кроме того, можно исключить некоторые имена каталогов из результатов (например, bin, obj, .svn)
    (точнее, будет исключен любой путь, содержащий папку bin; замечу, что на самом деле это регулярные выражения, так что можно указать что-то типа bin\S*)
  6. настроить загрузку по умолчанию (рекомендуется, потому что это позволит не обновлять внутренний кэш каталогов при каждом запуске)

Для всех опций есть в наличии всплывающие подсказки. Чтоб добраться до настроек, просто кликните правой кнопкой по иконке в трее.

Как это сделано


Утилита написана на Microsoft .Net 3.5 с помощью технологии WPF, поэтому должна работать везде, где присутствует .Net 3.5.

Инсталлер написан с помощью Inno Setup, который я дико рекомендую всем, кто пишет инсталлеры: он намного лучше WiX, Install Shield, Visual Studio Installer, потому что он
  1. свободный и бесплатный
  2. модульный (не привязан к технологиям Microsoft)
  3. прозрачный (редактируется только текстовый скрипт, никакого визуального программирования, как, например, в Visual Studio Installer)
  4. как следствие, файлы инсталлера не пересоздаются при каждом изменении—нет проблем с системой контроля версий
  5. гибкий (поддерживает скриптование с помощью Pascal/Delphi). До этого Delphi я видел последний раз лет 7 назад, на первом курсе института, но преимущества InnoSetup этот недостаток с лихвой компенсируют
  6. ах да, он волшебным образом создает один файл установки для x32 и x64 версий

Сравнение инсталлеров можно найти, например, здесь.

В коде присутствует несколько нетривиальных моментов:

Реакция на глобальные нажатие клавиш

Чтоб вовремя показать окно Navigation Assistant, необходимо слушать нажатие комбинации клавиш глобально (то есть во всех приложениях). .Net не позволяет этого «из коробки». Посему я воспользовался кодом отсюда (хотя есть несколько других решений, стоит лишь погуглить фразы global hooks/ global hotkeys).

Установка фокуса на неактивное приложение

После того, как мы обнаружили, что в каком-то окне была нажата заветная комбинация клавиш, необходимо показать Navigation Assistant, а также установить в него фокус (сделать активным, то бишь).

Да, в WPF имеется метод Window.Activate, который вызывает WinApi функцию SetForegroundWindow, и, следовательно, обладает всеми ее ограничениями. А именно, если ваше приложение неактивно при вызове метода, окно не будет сделано рабочим, то есть фокус останется в старом окне. Вообще-то, это правильно, чтоб не давать злонамеренным программам внезапно изменять текущий фокус и всячески препятствовать работе юзера. Но в нашем случае хочется обойти это ограничение.

Помогло решение вот отсюда, хотя есть несколько других (раз, два), но они работали не так хорошо.

Интеграция с Windows Explorer

Для того, чтоб получать список открытых окон Windows Explorer, был позаимствован вот этот код. Имея обертку над COM-объектом, можно легко менять текущий путь в данном окне explorera.

Интеграция с Total Commander

Интеграция с Total Commander осуществляется с помощью опций командной строки, в первую очередь /O, которая устанавливает передаваемый вместе с ней путь не в новом экземпляре Total Commander, а в уже открытом (если таковой имеется).

Архитектура


Используется стандартная многоуровневая архитектура (отличный обзор есть в "Domain Driven Design Quickly Online" за авторством Avram и Marinescu)
  1. UI Layer
    1. Views
  2. Presenters Layer
    1. Presenters
    2. Presentation Services
    3. View Models
    4. View Model Mappers
  3. Domain Model aka Business Layer
    1. Domain Services
    2. Domain Data Objects (plain Data Transfer Objects)
  4. Никакого Data Access Layer :-)

Вначале я пытался использовать шаблон Model-View-View Model, но потом перешел к
Model-View-Presenter по следующим причинам:
  1. MVP добавляет дополнительный уровень абстракции Presenters, а без него вся логика оказывается во View Models, и последние неоправданно разрастаются
  2. Эта логика семантически не должна принадлежать View Models (single responsibility, то-се)
  3. Невозможно использовать interface-driven development (для Views)
  4. Как следствие, UI layer превращается в кашу (в смысле, отсутствует разделение обязанностей, модульность, ясные интерфейсы)

Таким образом, сейчас используется Model-View-Presenter, а UI и данные связываются через View Models (WPF Binding), притом View Models
  1. либо передаются в методы интерфейсов представлений из презентеров
  2. либо инстанциируются самими представлениями

Основная функциональность покрыта тестами (используются nUnit и Moq).

Проблемы


Наверняка в приложении есть еще ненайденные баги.

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

При первом запуске какое-то время будет происходить поиск всех папок на пользовательском компьютере, поэтому придется подождать несколько минут.

Если Navigation Assistant был закрыт не при последнем выключении компьютера, или не был запущен автоматически при запуске системы, то невозможно сказать, актуален ли текущий кэш каталогов; поэтому этот кэш будет обновляться в дополнительном потоке, а до завершения этого процесса будет использоваться последний сохраненный кэш каталогов (который может не полностью соответствовать настоящей файловой системе).

Да, .Net вообще и WPF медленные и ресурсоемкие, но с этим приходится мириться.

Заключение


Итак, я поспешил поделиться с хабрасообществом небольшой утилитой для удобной навигации в Windows Explorer и Total Commander. Надеюсь, она окажется полезной кому-либо. Кроме того, возможно, окажется полезным краткий обзор технических решений.

Еще раз ссылки: на инсталлятор, на проект на google code (используется svn, как с высокой вероятностью известный большинству).

Исходный код открыт, приложение бесплатное, распространяется по лицензии MIT.

Всем спасибо!
Tags:WindowsNavigationAccessibilityWindows ExplorerTotal Commander.NetWPFInno Setup
Hubs: .NET
Total votes 72: ↑59 and ↓13 +46
Views7K

Popular right now

C# .Net Developer
from 1,200 to 3,500 $Profit CenterRemote job
.Net разработчик
from 150,000 ₽ArtezioСаратов
.Net разработчик
from 150,000 ₽ArtezioСанкт-Петербург
.NET WPF-разработчик
from 160,000 ₽Exquance SoftwareСанкт-ПетербургRemote job
.NET Core Engineer (Remote)
from 3,500 to 4,000 €Jimmy TechnologiesRemote job

Top of the last 24 hours