PDA

Просмотр полной версии : Диалоговое окно "Выбор папки" ???



sand
03.10.2004, 02:51
Есть ли проще реализация диалогового окна "Выбор папки", чем через Shell ?????

Andy
04.10.2004, 11:36
SHBrowseForFolder самый простой способ.

sand
04.10.2004, 14:05
Ну это да...
А без Шелла есть????????

Romeo
04.10.2004, 14:40
Проще, чем через Shell не получится :)

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

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

Romeo
04.10.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
05.10.2004, 00:45
F:\Work\dialog1\dialog1Dlg.cpp(175) : error C2065: 'IMallocPtr' : undeclared identifier

Romeo
05.10.2004, 12:02
#include <comdef.h>

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

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

Romeo
07.10.2004, 12:04
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\Include\ComDef.h

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

sand
07.10.2004, 12:39
понял
спасибо

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

Romeo
07.10.2004, 12:50
в файле:
C:\Program Files\Microsoft Visual Studio\VC98\Include\COMDEF.H

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

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

Hup
07.10.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.