Шаг 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 автоматически не передается.

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

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


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Аванесов Самвел - 05.09.2002