Запрос каталога “почти по взрослому”
Иногда хочется запросить у пользователя не файл, а именно каталог. И сделать это хочется красиво, без использования getfiled или сторонних приложений, чистым лиспом. Попробуем?
Вообще говоря, решение существует уже давно. Один из вариантов показал Владимир Азарко здесь. На всякий случай (caduser уже столько раз падал, что не помешает и страховая копия) приведу здесь ключевой код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | (vl-load-com) (defun directory-dia (message / sh folder folderobject result) ;; By Tony Tanzillo ;; Modified by Tim Willey ;; 16 Will let you type in the path ;; 64 Will let you create a new folder ;; Use ;; (Directory-Dia "Create Sheet Index \nSelect directory to grab Drawings \nBy Tim Willey 09/13/07") (vl-load-com) (setq sh (vla-getinterfaceobject (vlax-get-acad-object) "Shell.Application" ) ;_ end of vla-getInterfaceObject ) ;_ end of setq (setq folder (vlax-invoke-method sh 'browseforfolder (vla-get-hwnd (vlax-get-acad-object)) message 0 ;;; This is the bit number to change. ;;; (+ 16 64) ) ;_ end of vlax-invoke-method ) ;_ end of setq (vlax-release-object sh) (if folder (progn (setq folderobject (vlax-get-property folder 'self) ) ;_ end of setq (setq result (vlax-get-property folderobject 'path) ) ;_ end of setq (vlax-release-object folder) (vlax-release-object folderobject) (strcat (vl-string-right-trim "\\" result) "\\") ) ;_ end of progn ) ;_ end of if ) ;_ end of defun |
Поискав в MSDN, можно обнаружить, что у метода BrowseForFolder несколько параметров:
1 | oFolder = Shell.BrowseForFolder(Hwnd, sTitle, iOptions [, vRootFolder]) |
Hwnd | Required. The handle to the parent window of the dialog box. This value can be zero. |
sTitle | Required. A String value that represents the title displayed inside the Browse dialog box. |
iOptions | Required. An Integer value that contains the options for the method. This can be zero or a combination of the values listed under the ulFlags member of the BROWSEINFO structure. |
vRootFolder | Optional. The root folder to use in the dialog box. The user cannot browse higher in the tree than this folder. If this value is not specified, the root folder used in the dialog box is the desktop. This value can be a string that specifies the path of the folder or one of the ShellSpecialFolderConstants values. Note that the constant names found in ShellSpecialFolderConstants are available in Microsoft Visual Basic, but not in Visual Basic Scripting Edition (VBScript) or Microsoft JScript. In those cases, the numeric values must be used in their place. |
В общем-то все понятно, кроме самого интересного - iOptions. Если заняться несложным поиском, очень быстро будет обнаружено, что это перечисление, значения которого хранятся в одном из заголовочных файлов, входящих в поставку VisualStudio. Поскольку значения изначально представлены в шестнадцатиричной системе, понимать и запоминать их не очень удобно. В таблице показаны и шестнадцатиричная, и десятичная формы записи
Символьное представление | Оригинальный текст | Попытка перевода | Значение [16] | Значение[10] |
BIF_RETURNONLYFSDIRS |
Only return file system directories. If the user selects folders that are not part of the file system, the OK button is grayed. |
Возвращает только системные каталоги. Попытка выбора несистемного каталога блокирует кнопку ОК |
0x0001 | 1 |
BIF_DONTGOBELOWDOMAIN |
Do not include network folders below the domain level in the dialog box's tree view control. |
Исключает сетевые папки ниже уровня домена при представлении в виде дерева | 0x0002 | 2 |
BIF_STATUSTEXT |
Include a status area in the dialog box. The callback function can set the status text by sending messages to the dialog box. This flag is not supported when BIF_NEWDIALOGSTYLE is specified. |
Включает показ статусной строки в окне. теоретически можно установить новые значения статусной строки через специальную callback-функцию (сам не пробовал, не до того было). Значение блокируется, если установлен флаг BIF_NEWDIALOGSTYLE |
0x0004 | 4 |
BIF_RETURNFSANCESTORS |
Only return file system ancestors. An ancestor is a subfolder that is beneath the root folder in the namespace hierarchy. If the user selects an ancestor of the root folder that is not part of the file system, the OK button is grayed. |
Как-то с переводом у меня не задалось | 0x0008 | 8 |
BIF_EDITBOX |
Include an edit control in the browse dialog box that allows the user to type the name of an item. |
Включает текстовое поле, позволяющее вручную ввести путь к каталогу. | 0x0010 | 16 |
BIF_VALIDATE |
If the user types an invalid name into the edit box, the browse dialog box will call the application's BrowseCallbackProc with the BFFM_VALIDATEFAILED message. This flag is ignored if BIF_EDITBOX is not specified. |
Если пользователь вводит в текстовое поле некорректный путь, диалоговое окно будет вызывать специальную функцию BrowseCallbackProc с сообщением BFFM_VALIDATEFAILED. Флаг игнорируется, если BIF_EDITBOX не установлен |
0x0020 | 32 |
BIF_NEWDIALOGSTYLE |
Use the new user interface. Setting this flag provides the user with a larger dialog box that can be resized. The dialog box has several new capabilities, including: drag-and-drop capability within the dialog box, reordering, shortcut menus, new folders, delete, and other shortcut menu commands. To use this flag, you must call OleInitialize or CoInitialize before calling SHBrowseForFolder. |
Использует новый пользовательский интерфейс. Установка этого флага позволяет использовать диалоговое окно большего размера, да еще и с изменяемыми границами. Также предоставляется несколько новых возможностей: drag-n-drop, изменение порядка следования каталогов, контекстные меню, создание новых каталогов, удаление каталогов, и т.п. Использование этого флага в lisp'е затруднено, т.к. требуется дополнительно вызывать специальные функции OleInitialize и CoInitialize |
0x0040 | 64 |
BIF_USENEWUI | Является комбинацией флагов BIF_NEWDIALOGSTYLE и BIF_EDITBOX | 0x0050 | 80 | |
BIF_BROWSEINCLUDEURLS | The browse dialog box can display URLs. The BIF_USENEWUI and BIF_BROWSEINCLUDEFILES flags must also be set. If these three flags are not set, the browser dialog box will reject URLs. Even when these flags are set, the browse dialog box will only display URLs if the folder that contains the selected item supports them. When the folder's IShellFolder::GetAttributesOf method is called to request the selected item's attributes, the folder must set the SFGAO_FOLDER attribute flag. Otherwise, the browse dialog box will not display the URL. | Допускается показ и выбор URL. Требует обязательной установки флагов BIF_USENEWUI и BIF_BROWSEINCLUDEFILES. | 0x0080 | 128 |
BIF_UAHINT | When combined with BIF_NEWDIALOGSTYLE, adds a usage hint to the dialog box in place of the edit box. BIF_EDITBOX overrides this flag. | 0x0100 | 256 | |
BIF_NONEWFOLDERBUTTON | Do not include the New Folder button in the browse dialog box. | Исключает кнопку [Создать новую папку] из диалога | 0x0200 | 512 |
BIF_NOTRANSLATETARGETS | When the selected item is a shortcut, return the PIDL of the shortcut itself rather than its target. | (насколько я понял) Если выбирается ярлык, то возвращается именно он, а не тот каталог, на который он указывает. Если будет время, проверю и отпишусь. | 0x0400 | 1024 |
BIF_BROWSEFORCOMPUTER | Only return computers. If the user selects anything other than a computer, the OK button is grayed. | Ну, и по названию уже все понятно | 0x1000 | 4096 |
BIF_BROWSEFORPRINTER | Only allow the selection of printers. If the user selects anything other than a printer, the OK button is grayed. In Microsoft Windows XP, the best practice is to use an XP-style dialog, setting the root of the dialog to the Printers and Faxes folder (CSIDL_PRINTERS). |
Позволяет выбирать только принтеры. | 0x2000 | 8192 |
BIF_BROWSEINCLUDEFILES | The browse dialog box will display files as well as folders. | Показывает файлы как каталоги. Удобно не всегда | 0x4000 | 16384 |
В общем-то, комбинируя разные флаги простым сложением, можно поиграться с видом окна.
Остается только один, последний параметр. Необязательный - vRootFolder. Указывает родительский каталог, с которого пользователь сможет выбирать подкаталоги. Вроде бы и удобно, да вот проблема - подняться "выше" этого каталога невозможно.
Понятно, что диалоги, разработанные с использованием C++ или .NET, будут намного более интересны и многофункциональны. Но зато это решение практически не зависит от версии и разрядности как AutoCAD, так и Windows.
Что называется, "стоило написать" Тут же всплыли темы http://www.caduser.ru/forum/index.php?PAGE_NAME=read&FID=23&TID=34695&PAGEN_1=2 и http://cadtips.cadalyst.com/programmers-tools/select-multiple-files . Куда катится этот мир!
В заголовке окна, кстати, можно указывать до 3 строк текста, разделенного символом "\n"