Описание этой структуры выглядит очень по-спартански:
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 автоматически не передается.
Ну значит, как описать (декларировать то есть, а то мало ли тут кто что подумает) ясно. Теперь посмотрим, что эта функция может и что ей передается...
Пфуххх. Много я написал... А может и не очень. Но чуть устал... Так что пора мне выпить кофе...