Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 29.04.2009, 14:02
smart_man smart_man вне форума
Прохожий
 
Регистрация: 08.12.2008
Сообщения: 40
Репутация: 10
По умолчанию Select-диалог

Возможно ли, и если да то как, превратить стандартный OpenDialog или SaveDialog в Select-диалог, который должен только выбирать место, куда будут сохранены ранее выбранные файлы (то есть такое окно, в котором я могу выбрать путь, куда экспортировать файлы и чтобы больше ничего нельзя было менять, то есть строки с названием файла вообще не должно быть).
Ответить с цитированием
  #2  
Старый 29.04.2009, 16:06
Nyctos Kasignete Nyctos Kasignete вне форума
Активный
 
Регистрация: 29.03.2009
Сообщения: 300
Репутация: 94
По умолчанию

Есть специальная функция Win32 API, показвающая диалог выбора папки. Называется SHBrowseForFolder. Возвращает идентификатор, который можно преобразовать в путь с помощью функции SHGetPathFromIDList.
Вот например, готовая функция, отображающая диалог выбора пути и возвращающая строку с терминальным нулем, в которой записывается путь к выбранной папке.
Код:
function TFaceForm.ShowChooseDirDialog: PChar;
const
  TitleName = 'Укажите папку назначения'; // это подсказка, которая будет выведена в диалоге
var
  lpItemID: PItemIDList;
  BrowseInfo: TBrowseInfo;
  DisplayName: array[0..MAX_PATH] of Char;
  TempPath: array[0..MAX_PATH] of Char;
begin
  Result := nil;
  FillChar(BrowseInfo, sizeof(TBrowseInfo), #0);
  BrowseInfo.hwndOwner := FaceForm.Handle;
  BrowseInfo.pszDisplayName := @DisplayName;
  BrowseInfo.lpszTitle := @TitleName[1];
  BrowseInfo.ulFlags := BIF_RETURNONLYFSDIRS;
  lpItemID := SHBrowseForFolder(BrowseInfo);
  if lpItemID <> nil then
  begin
    SHGetPathFromIDList(lpItemID, TempPath);
    Result := TempPath;
    GlobalFreePtr(lpItemID);
  end;
end;
Для использования нужно подключить модуль ShlObj.pas.
Не подойдет?
Ответить с цитированием
  #3  
Старый 29.04.2009, 16:20
Аватар для Rokuell
Rokuell Rokuell вне форума
Активный
 
Регистрация: 27.12.2006
Адрес: Псков
Сообщения: 274
Версия Delphi: Delphi 7
Репутация: 497
По умолчанию

Можно использовать стандартую функцию SelectDirectory из модуля FileCtrl , которая делает то же самое. Не приходиться писать то, что уже написано
__________________
Велик и могуч наш Object Pascal !
ICQ: 357-591-887
Ответить с цитированием
  #4  
Старый 29.04.2009, 16:36
smart_man smart_man вне форума
Прохожий
 
Регистрация: 08.12.2008
Сообщения: 40
Репутация: 10
По умолчанию

Видимо у нас разные версии delphi (у меня 7), потому как не могу найти ни SHBrowseForFolder ни SelectDirectory.
Ответить с цитированием
  #5  
Старый 29.04.2009, 16:48
Аватар для Rokuell
Rokuell Rokuell вне форума
Активный
 
Регистрация: 27.12.2006
Адрес: Псков
Сообщения: 274
Версия Delphi: Delphi 7
Репутация: 497
По умолчанию

У меня тоже 7 версия.
Добавить необходимые модули не забыл ?
Для использования функции SelectDirectory нужен модуль FileCtrl
Для SHBrowseForFolder - ShlObj
__________________
Велик и могуч наш Object Pascal !
ICQ: 357-591-887
Ответить с цитированием
  #6  
Старый 29.04.2009, 16:57
smart_man smart_man вне форума
Прохожий
 
Регистрация: 08.12.2008
Сообщения: 40
Репутация: 10
По умолчанию

Это те которые лежат в ...\Borland\Delphi7\Source\Vcl\ ?
или в ...\Borland\Delphi7\Lib\Debug\ ?
Ответить с цитированием
  #7  
Старый 29.04.2009, 17:02
Аватар для Rokuell
Rokuell Rokuell вне форума
Активный
 
Регистрация: 27.12.2006
Адрес: Псков
Сообщения: 274
Версия Delphi: Delphi 7
Репутация: 497
По умолчанию

В начале кода можно увидеть такую строку(или что-то похожее):
Код:
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;
Это стандартные модули, которые используются в твоем приложении.
Если надо использовать функции из модуля, не указанного в этом списке, просто добавь его туда через запятую, например чтобы стало так:
Код:
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, FileCtrl;
__________________
Велик и могуч наш Object Pascal !
ICQ: 357-591-887
Ответить с цитированием
  #8  
Старый 29.04.2009, 17:13
smart_man smart_man вне форума
Прохожий
 
Регистрация: 08.12.2008
Сообщения: 40
Репутация: 10
По умолчанию

Теперь понял. Я просто перепутал слово "модуль" со словом "компонент"
Ответить с цитированием
  #9  
Старый 04.05.2009, 10:28
smart_man smart_man вне форума
Прохожий
 
Регистрация: 08.12.2008
Сообщения: 40
Репутация: 10
По умолчанию

Проверил оба варианта. По удобству для пользователя более приемлемым показался графический интерфейс, основанный на модуле ShlObj.pas (минимум лишней информации на экране, текст на кнопках на русском языке). Из недостатков — отсутствует кнопка создания новой директории. Если как-то добавить в окно диалога эту кнопку, то оно стало бы идеальным.
Ответить с цитированием
  #10  
Старый 04.05.2009, 16:22
Аватар для Rokuell
Rokuell Rokuell вне форума
Активный
 
Регистрация: 27.12.2006
Адрес: Псков
Сообщения: 274
Версия Delphi: Delphi 7
Репутация: 497
Сообщение

Есть два варианта процедуры SelectDirectory, в зависимости какой используешь, будут разные графические интерфейсы, да и код у них разный, можешь посмотреть исходник FileCtrl. Но вот кнопку создания новой папки туда не добавить. Поэтому процедуру вызова диалога надо писать самому, добавив необходимый флаг:
Код:
function ShowChooseDirDialog: String;
const
  TitleName = 'Укажите папку назначения'; // это подсказка
var
  lpItemID: PItemIDList;
  BrowseInfo: TBrowseInfo;
  DisplayName: array[0..MAX_PATH] of Char;
  TempPath: array[0..MAX_PATH] of Char;
begin
  Result := '';
  FillChar(BrowseInfo, sizeof(TBrowseInfo), 0);
  //Здесь нужно использовать именно Application.Handle
  BrowseInfo.hwndOwner := Application.Handle;
  BrowseInfo.pszDisplayName := @DisplayName;
  BrowseInfo.lpszTitle := @TitleName[1];
  // NEWDIALOGSTYLE - будет добавлена кнопка "Создать папку"
  BrowseInfo.ulFlags := BIF_RETURNONLYFSDIRS or BIF_NEWDIALOGSTYLE;
  lpItemID := SHBrowseForFolder(BrowseInfo);
  if lpItemID <> nil then
  begin
    SHGetPathFromIDList(lpItemID, TempPath);
    Result := String(TempPath);
    GlobalFreePtr(lpItemID);
  end;
end;
__________________
Велик и могуч наш Object Pascal !
ICQ: 357-591-887
Ответить с цитированием
  #11  
Старый 05.05.2009, 13:39
smart_man smart_man вне форума
Прохожий
 
Регистрация: 08.12.2008
Сообщения: 40
Репутация: 10
По умолчанию

Rokuell, диалог стал таким как надо!

Но есть проблема: после того как я выполняю хотя бы один раз ShowChooseDirDialog приложение неправильно закрывается (то есть программа визуально закрывается, но в процессах виндов остается висеть EXE прграммы). Думаю это связано со строкой:
BrowseInfo.hwndOwner := Application.Handle;
Ответить с цитированием
  #12  
Старый 05.05.2009, 17:31
Аватар для Rokuell
Rokuell Rokuell вне форума
Активный
 
Регистрация: 27.12.2006
Адрес: Псков
Сообщения: 274
Версия Delphi: Delphi 7
Репутация: 497
Радость

Я думаю это связано с глюками в твоей программе, а не в функции:

Во-первых: Поле hwndOwner определяет окно-владельца данного диалога, и никак на закрытие программы оно не влияет.

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

В-третьих: можешь создать новый проект и добавть туда только эту функцию, и убедишься, что всё работает нормально.

В-четвёртых: Даже в исходниках Delphi ты можешь посмотреть, что владельцем делается именно всё приложение ( файл FileCtrl.pas строка 1998 )
__________________
Велик и могуч наш Object Pascal !
ICQ: 357-591-887
Ответить с цитированием
  #13  
Старый 05.05.2009, 21:39
smart_man smart_man вне форума
Прохожий
 
Регистрация: 08.12.2008
Сообщения: 40
Репутация: 10
По умолчанию

Сделал чистый проект с этой функцией, но та же проблема (после хотя бы одного запуска функции выбора пути, выход по кнопке "Exit" из главной формы уже не работает, точнее exe-файл программы остается в процессах виндов). Вот исходники тестового проекта:
test.rar
Ответить с цитированием
  #14  
Старый 05.05.2009, 23:42
Аватар для Rokuell
Rokuell Rokuell вне форума
Активный
 
Регистрация: 27.12.2006
Адрес: Псков
Сообщения: 274
Версия Delphi: Delphi 7
Репутация: 497
По умолчанию

Странно, у меня всё нормально работает. Попробуй проверить на другой винде (кстати, у тебя какая версия?).
Или изменить строки:
Код:
procedure TForm2.Button2Click(Sender: TObject);
begin
  Form1.Show;
  //Form2.Hide;
  Form2.Close;
end;
__________________
Велик и могуч наш Object Pascal !
ICQ: 357-591-887
Ответить с цитированием
  #15  
Старый 06.05.2009, 00:16
smart_man smart_man вне форума
Прохожий
 
Регистрация: 08.12.2008
Сообщения: 40
Репутация: 10
По умолчанию

Win XP Pro SP3, Delphi7. Изменил строки - тот же глюк. Другой винды не стоит.

Возможно проблема действительно в моем компе. Но все равно спасибо за коды и участие в теме.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 20:25.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025