C++ C++ C# C# ASP.NET Security ASP.NET Security ASM ASM Скачать Скачать Поиск Поиск Хостинг Хостинг  
  Программа для работы с LPT портом...
Язык: .NET — ©Alexey...
  "ASP.NET Atlas" – AJAX в исполнении Micro...
Язык: .NET — ©legigor@mail.ru...
  "Невытесняющая" Многопоточность...
Язык: C/C++ — ©...
  01.05.2010 — Update World C++: Сборник GPL QT исходников
  15.12.2007 — Весь сайт целиком можно загрузить по ссылкам из раздела Скачать
Хостинг:
Windows 2003, ASP.NET 2.0
бесплатный и от 80 руб./мес


   Отправить письмо
Кулабухов Артем, Беларусь




 80 - Shell списки идентификаторов / С++ Builder 5 / Borland C++

Шаг 80 - Shell списки идентификаторов

Описание этой структуры выглядит очень по-спартански:

typedef struct _ITEMIDLIST {	// idl
	SHITEMID mkid;  // list of item identifers
} ITEMIDLIST, * LPITEMIDLIST;
typedef const ITEMIDLIST * LPCITEMIDLIST;

Хм... Можно предположить, что взглянув на это, Вы все уже поняли? В справке ничего больше нет... Ну, на то я и нужен, чтоб подобные вещи объяснять. Дело в том, что структура SHITEMID представляет собой комбинацию массива произвольной длины с данными об этом массиве. Еще хочу обрадовать, что нормальным способом (представив массив как NULL-terminated строку) данные вытянуть из него не получится. Для этого существуют... Нет, не функции! Для этого оказывается, существует COM... Ну как? А Вы что думали, будет легко... Цитата - "сложнее и непонятнее COM люди ничего пока не смогли придумать". Особенно, если работать с COM через VCL или даже MFC. А оказывается, можно проще... Вобщем при наличии фантазии можно построить примитивную модель, предоставляющий к COM функциям произвольный доступ...

Но! Сейчас мы этим заниматься не будем. Сейчас я просто приведу пару своих функций, которые обеспечивают перевод обычной строки в список идентификаторов и обратно.

bool __fastcall ConvertPathToIdList(String Path,LPITEMIDLIST *pidl)
{
	if (Path.Length()==0) return false;
	LPSHELLFOLDER folder;
	SHGetDesktopFolder(&folder);
	unsigned long parsed;
	folder->ParseDisplayName(NULL,0,WideString(Path).c_bstr(),
		&parsed,pidl,NULL);
	delete folder;
	return true;
}

String __fastcall ConvertIdToPath(LPITEMIDLIST pidl)
{
	char buf[MAX_PATH];
	int i=SHGetPathFromIDList(pidl,buf);
	return String(buf);
}

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

Кроме того, чтобы расширить функциональность компонента до максимума, нужно же еще обеспечить корректную обработку событий. Статусный текст... И так далее. Поэтому дозарезу необходима BrowseCallbackProc.

Мы же говорили про __closure несколько шагов назад? Так вот. Это аналог в стиле старого C. Так вот, не знаю, что там написано в справке, но для того, чтобы все работало, необходимо описать функцию вида:

static int __stdcall BrowseProc(HWND hwnd,
	UINT uMsg, LPARAM lParam, LPARAM lpData);

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

BROWSEINFO bi;
setmem (&bi, sizeof(bi), 0);
bi.lpfn = (BFFCALLBACK)BrowseProc;
(void*)bi.lParam = (void*)this;

Теперь, во-первых, компилятор не будет ругаться на то, что присваивание сделано не так, во-вторых, в качестве lParam процедура BrowseProc получит указатель на вызвавший его объект. Что очень удобно, поскольку в отличие от __closure, здесь неявный указатель this автоматически не передается.

Ну значит, как описать (декларировать то есть, а то мало ли тут кто что подумает) ясно. Теперь посмотрим, что эта функция может и что ей передается...

  • hwnd - Содержит указатель на окно диалога. Этому окну можно посылать разные сообщения... Надеюсь, Вы не забыли, что есть такая функция SendMessage? Варианты вызова могут быть такими:
    • ::SendMessage(hwnd,BFFM_ENABLEOK,enable,NULL); - Соответственно включает (enable = true) и отключает enable = false (делает серой) кнопку ok в диалоге. Полезно, если пользователь при выборе каталога для удаления дает скажем C:\Winnt.
    • ::SendMessage(hwnd,BFFM_SETSELECTION,wParam,lParam); - Меняет выделенную папку на папку. Если wParam = false, то lParam - список идентификаторов, на которые нужно заменить текущую папку, иначе это просто путь к нужной папке. pidl.
    • ::SendMessage(hwnd,BFFM_SETSTATUSTEXT,NULL,text); - Меняет статусный текст на Null-terminated строку text.

  • uMsg - Определяет, по какому поводу вообще обработчик вызвали... Может быть BFFM_INITIALIZED и BFFM_SELCHANGED. Во втором случае lParam - указатель на ITEMIDLIST с новой папкой.

  • lParam - Зависит от uMsg

  • lpData - То, что мы определили автоматически передавать нашей функции при каждом вызове.

Пфуххх. Много я написал... А может и не очень. Но чуть устал... Так что пора мне выпить кофе...


| |
Автор Аванесов Самвел.
[AD]