Диалог открытия файлов и юзабилити Windows
При всех удобствах Windows некоторые моменты меня очень сильно раздражают. Особенно поведение системы при вызове диалогов открытия файлов. Сперва немного предыстории. При работе с файлами через функцию GetOpenFileName или GetSaveFileName в структуре OPENFILENAME есть возможность указать путь, который должен открыться по умолчанию. Если это значение не задано, то система сама где-то запоминает папку, в которой последний раз был удачно открыт файл (то есть окно выбора файла было закрыто через кнопку "Ok"). Где именно хранится эта информация - я пока не выяснил, да и не особо надо. Второй вариант. Предположим, что некоторая программа самостоятельно запоминает путь к папке, в которой последний раз ею выполнялись какие-то действия с файлами. Это может быть, например, текстовый редактор, просмотрщик графики и т.п., не суть. Главное, что задумка очень хорошая и правильная. При следующем запуске или вызове диалога выбора файла в соответствующее поле OPENFILENAME будет подставлен сохраненный путь и пользователь продолжит работу с того места, где он в прошлый раз остановился. Что-то типа такого:Code (Assembler) : Убрать нумерацию
- ...
- invoke GetModuleHandle,0
- mov [ofn.hInstance],eax
- mov [ofn.lStructSize], sizeof.OPENFILENAME
- mov [ofn.hwndOwner],0
- mov [ofn.nMaxFile],MAX_PATH
- mov [ofn.lpstrFile],buff
- ; Открывать с последней сохраненной папки
- mov [ofn.lpstrInitialDir],saved_dir
- mov [ofn.Flags],OFN_EXPLORER+OFN_FILEMUSTEXIST
- invoke GetOpenFileName,ofn
- ...
После очередной серии чудесатых чудес я решил сделать для себя небольшую вспомогательную функцию. Она проверяет сохраненный путь и возвращает последнюю папку максимального уровня вложенности, которая существует на диске в текущий момент. Например, если ваша программа в последнем сеансе работы сохранила, а затем пытается открыть путь
D:\PICTURES\Путешествия\2011\Разобрать\Китай\NIKOND90\001
но при этом папки "\Китай" и, соответственно, вложенных в нее папок уже не существует, то должна открываться папка
D:\PICTURES\Путешествия\2011\Разобрать
и никак иначе! По-моему, это единственно правильное поведение системы. Почему разработчики Windows до сих пор открывают непонятно что вместо ПОСЛЕДНЕЙ ДОСТУПНОЙ папки из запрошенного пути - непонятно. Какая-то дефолтная папка может открываться только в одном единственном случае - когда ВЕСЬ запрошенный путь, включая букву диска, недоступен.
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------------------
- ; Функция проверки доступности пути в файловой системе
- ; (C) ManHunter / PCL
- ; http://www.manhunter.ru
- ;------------------------------------------------------------
- ; Параметры:
- ; lpRaw - указатель на буфер размером MAX_PATH, в который
- ; записан проверяемый путь
- ; lpGood - указатель на буфер размером MAX_PATH, в который
- ; будет записан максимально доступный путь
- ;
- ; На выходе:
- ; EAX=0 - ни один из составляющих пути, включая носитель, не
- ; доступен
- ; EAX=1 - по крайней мере один из составляющих пути доступен,
- ; результат без финального слеша записан в буфер lpGood
- ;------------------------------------------------------------
- proc GetLastValidFolder lpRaw:DWORD, lpGood:DWORD
- locals
- result dd ?
- old_dir rb MAX_PATH
- new_dir rb MAX_PATH
- endl
- pusha
- ; Сохранить текущую директорию
- lea eax,[old_dir]
- invoke GetCurrentDirectory,MAX_PATH,eax
- ; Скопировать поверяемый путь
- lea esi,[new_dir]
- invoke lstrcpy,esi,[lpRaw]
- mov edi,esi
- invoke lstrlen,esi
- or eax,eax
- jz .loc_bad
- dec eax
- add edi,eax
- ; Исправить слеши
- .loc_fix_slash:
- cmp byte [esi+eax],'/'
- jne @f
- mov byte [esi+eax],'\'
- @@:
- dec eax
- or eax,eax
- jnz .loc_fix_slash
- .loc_chk:
- ; Попробовать установить текущую директорию
- invoke SetCurrentDirectory,esi
- or eax,eax
- jne .loc_ok
- .loc_scan:
- mov byte [edi],0
- dec edi
- ; Сканируем с конца до ближайшего слеша
- cmp byte [edi],'\'
- je .loc_chk
- ; Добрались до начала строки?
- cmp edi,esi
- jne .loc_scan
- .loc_bad:
- ; Результат - ошибка
- mov [result],0
- ; Обнулить строку
- mov eax,[lpGood]
- mov byte [eax],0
- jmp .loc_ret
- .loc_ok:
- ; Убрать финальный слеш
- cmp byte [edi],'\'
- jne @f
- mov byte [edi],0
- @@:
- ; Скопировать последний правильный путь
- invoke lstrcpy,[lpGood],esi
- ; Результат - успешно
- mov [result],1
- .loc_ret:
- ; Вернуть на место текущую директорию
- lea eax,[old_dir]
- invoke SetCurrentDirectory,eax
- popa
- ; Записать результат в EAX
- mov eax,[result]
- ret
- endp
Я прекрасно понимаю, что ждать подобной милости от разработчиков Windows бесполезно, поэтому предлагаю программистам взять на себя заботу об удобстве пользователей. Ведь именно из таких, казалось бы, незначительных мелочей складывается впечатление о программном продукте и разработчике в целом.
В приложении пример программы с исходным текстом, в которой используется описанная выше функция для проверки доступности пути.
Просмотров: 7230 | Комментариев: 6
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(08.11.2011 в 10:55):
Matsist, ну для правильных пацанов могли бы где-нибудь сделать секретную галочку, чтобы эта опция работала как надо :)
Matsist
(06.11.2011 в 22:53):
Думаю, Microsoft сознательно сбрасывает несуществующий путь в МоиДокументы и т.п., чтобы сделать систему дуракозащищенной в этой части. Средняя секретарша испугается, если ей внезапно откроется папка сокрытая где-нибудь в недрах системы, а средняя школота еще и попробует навести в ней порядок.
Но вот реализовать твой алгоритм хотя бы в рамках папок типа "Мои документы" с их стороны было бы просто отлично!
Но вот реализовать твой алгоритм хотя бы в рамках папок типа "Мои документы" с их стороны было бы просто отлично!
ManHunter
(03.11.2011 в 11:20):
Compiller, спасибо, буду знать.
Compiller
(03.11.2011 в 10:06):
Windows хранит данные последних папок и много чего ещё в реестре в разделах со словом MRU в названии (Most Recently Used).
ManHunter
(01.11.2011 в 14:41):
Тут все на чистом WinAPI, так что можно портировать куда угодно.
Dimas
(01.11.2011 в 14:39):
Согласен, как меня вымораживал microangelo explorer когда не находил последний открытый файл - выдавал веселое сообщение, что файл не найден и выпинывал в мой компьютер...
На ассемблере не пишу, но саму идею возьму на вооружение, спасибо
На ассемблере не пишу, но саму идею возьму на вооружение, спасибо
Добавить комментарий
Заполните форму для добавления комментария