Диалоговое окно "Выбор папки" ???

Ответить

Код подтверждения
Введите код в точности так, как вы его видите. Регистр символов не имеет значения.

BBCode ВКЛЮЧЁН
[img] ВКЛЮЧЁН
[flash] ОТКЛЮЧЕН
[url] ВКЛЮЧЁН
Смайлики ОТКЛЮЧЕНЫ

Обзор темы
   

Развернуть Обзор темы: Диалоговое окно "Выбор папки" ???

Hup » 07 окт 2004, 13:33

Случайно напоролся...
Вот одна статейка в тему :wink:

Как выдать окно выбора каталога?
Автор: Игорь Ткачёв

Windows Shell API включает функцию SHBrowseForFolder, которая отображает стандартный диалог, с помощью которого пользователь может выбрать нужный каталог. На самом деле, выбрать можно не только каталог, а любой объект Shell namespace, в том числе принтеры и компьютеры. Ниже приведён пример использования этой функции:


#include <windows.h>
#include <shlobj.h>
#pragma comment(lib,"shell32")

bool GetFolder (LPTSTR szPath)
{
szPath[0] = 0;
bool result = false;

LPMALLOC pMalloc;
if (::SHGetMalloc(&pMalloc) == NOERROR) {
BROWSEINFO bi;
::ZeroMemory(&bi,sizeof bi);
bi.ulFlags = BIF_RETURNONLYFSDIRS;
LPITEMIDLIST pidl = ::SHBrowseForFolder(&bi);
if (pidl != NULL) {
if (::SHGetPathFromIDList(pidl,szPath))
result = true;
pMalloc->Free(pidl);
}
pMalloc->Release();
}
return result;
}

Хотя наша функция и делает то, что нам нужно, но, скорее всего, вы найдёте её возможности слишком скромными. С другой стороны возможности функции ::SHBrowseForFolder позволяют добавить следующую функциональность:

* Установка дескриптора окна-владельца диалога.
* Добавление заголовка к диалогу.
* Отображение текущего каталога.
* Установка каталога по умолчанию.
* Установка корневого каталога.

Я не вижу причин не использовать эти возможности. Изменим нашу функцию.


#include <windows.h>
#include <atlbase.h>
#include <shlobj.h>
#pragma comment(lib,"shell32")

static int CALLBACK
BrowseCallbackProc (HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
TCHAR szPath[_MAX_PATH];
switch (uMsg) {
case BFFM_INITIALIZED:
if (lpData)
SendMessage(hWnd,BFFM_SETSELECTION,TRUE,lpData);
break;
case BFFM_SELCHANGED:
SHGetPathFromIDList(LPITEMIDLIST(lParam),szPath);
SendMessage(hWnd, BFFM_SETSTATUSTEXT, NULL, LPARAM(szPath));
break;
}
return ;
}

BOOL GetFolder (LPCTSTR szTitle, LPTSTR szPath, LPCTSTR szRoot, HWND hWndOwner)
{
if (szPath == NULL)
return false;

bool result = false;

LPMALLOC pMalloc;
if (::SHGetMalloc(&pMalloc) == NOERROR) {
BROWSEINFO bi;
::ZeroMemory(&bi,sizeof bi);
bi.ulFlags = BIF_RETURNONLYFSDIRS;


bi.hwndOwner = hWndOwner;


bi.lpszTitle = szTitle;


bi.lpfn = BrowseCallbackProc;
bi.ulFlags |= BIF_STATUSTEXT;


bi.lParam = LPARAM(szPath);


if (szRoot != NULL) {
IShellFolder *pDF;
if (SHGetDesktopFolder(&pDF) == NOERROR) {
LPITEMIDLIST pIdl = NULL;
ULONG chEaten;
ULONG dwAttributes;

USES_CONVERSION;
LPOLESTR oleStr = T2OLE(szRoot);

pDF->ParseDisplayName(NULL,NULL,oleStr,&chEaten,&pIdl,&dwAttributes);
pDF->Release();

bi.pidlRoot = pIdl;
}
}

LPITEMIDLIST pidl = ::SHBrowseForFolder(&bi);
if (pidl != NULL) {
if (::SHGetPathFromIDList(pidl,szPath))
result = true;
pMalloc->Free(pidl);
}
if (bi.pidlRoot != NULL)
pMalloc->Free(bi.pidlRoot);
pMalloc->Release();
}
return result;
}

Прототип нашей функции может выглядеть следующим образом:


BOOL GetFolder(LPCTSTR szTitle,LPTSTR szPath,LPCTSTR szRoot=NULL,HWND hWndOwner=NULL);

При успешном выполнении функция возвращает TRUE и возвращает выбранный каталог по указателю szPath, Вы должны сами позаботиться о выделении необходимой памяти. Этот же параметр используется для задания каталога по умолчанию.

Это все на сегодня. Пока!

Алекс Jenter jenter@rsdn.ru
Duisburg, 2001. Публикуемые в рассылке материалы принадлежат сайту RSDN.

Romeo » 07 окт 2004, 12:50

в файле:
C:\Program Files\Microsoft Visual Studio\VC98\Include\COMDEF.H

есть строка:
_COM_SMARTPTR_TYPEDEF(IMalloc, __uuidof(IMalloc));

Посмотри как этот define раскрывается (в этом же фале) и всё поймёшь.

sand » 07 окт 2004, 12:46

А что мне делать, если у меня шестой VC++? там такого нет.
(если не ставить .NET)...

sand » 07 окт 2004, 12:39

понял
спасибо

Romeo » 07 окт 2004, 12:04

C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\Include\ComDef.h

P.S. IMallocPtr - это не зверь. Это враппер IMalloc интерфейса, который является шеловским интерфейсом, предназначенным для менеджмента памяти при работе с шеловскими объектами. В данном случае он нужен для того, чтобы очистить память, выделенную шеловской функцией SHBrowseForFolder под pidl, соответствующий выбранной папке.

sand » 07 окт 2004, 00:28

А что это за IMallocPtr такой?
Где достать такую зверюгу? (уж явно не в comdef.h)

Romeo » 05 окт 2004, 12:02

#include <comdef.h>

Господи, ну подправь уже сам. Это не работающий код, я его писал прямо в окошко Oper'ы, естественно в последней встроенного С++ компилятора нет :)

sand » 05 окт 2004, 00:45

F:\Work\dialog1\dialog1Dlg.cpp(175) : error C2065: 'IMallocPtr' : undeclared identifier

Romeo » 04 окт 2004, 21:33

Код: Выделить всё

#include <shlobj.h>

...

BROWSEINFO br;
TCHAR strDisplayName[MAX_PATH];

ZeroMemory(&br, sizeof(br));

br.pszDisplayName = strDisplayName;
br.lpszTitle = _T("Please select some file system folder. It is very needed for me");
br.ulFlags = BIF_RETURNONLYFSDIRS;

LPITEMIDLIST lpItemIDList = SHBrowseForFolder(&br);

if (lpItemIDList != NULL)
{
      TCHAR strResultPath[MAX_PATH];
      SHGetPathFromIDList(lpItemIDList, strResultPath);

      IMallocPtr spMalloc;
      SHGetMalloc(&spMalloc);
      spMalloc->Free(lpItemIDList);

      // В этом месте мы имеем в strResultPath выбранный путь
}

sand » 04 окт 2004, 17:41

У меня программа с MFC.
Я так понимаю, что код типа
LPBROWSEINFO br;
SHBrowseForFolder(br);

Ничего путного не сделает...
Примерчик можно махнуть?

Вернуться к началу