Чтение онлайн

на главную - закладки

Жанры

Применение Windows API

Легалов А. И.

Шрифт:

Обратите также внимание, что я не уверен, может ли _shellMalloc быть статическим элементом SShellPtr. Проблема состоит в том, что статические элементы инициализируются перед WinMain. Из-за этого вся COM система может оказаться неустойчивой. С другой стороны, документация говорит, что Вы можете безопасно вызывать из другой API функции CoGetMalloc перед обращением к CoInitialize. Это не говорит о том, может ли SHGetMalloc, который делает почти то же самое, также вызываться в любое время в вашей программе. Подобно многим других случаям, когда система ужасно разработана или задокументирована, только эксперимент может ответить на такие вопросы. Добро пожаловать к нам с такими ответами.

Между

прочим, если Вы нуждаетесь в интеллектуальном указателе, который использует специфическое распределение памяти для COM, то получите его, вызывая CoGetMalloc. Вы можете без опаски сделать этот _malloc статическим элементом и инициализировать его только один раз в вашей программе (ниже SComMalloc::GetMalloc тоже статический):

IMalloc* SComMalloc::_malloc = SComMalloc::GetMalloc;

IMalloc* SComMalloc::GetMalloc {

 IMalloc* malloc = 0;

 if (CoGetMalloc(1, &malloc) == S_OK) return malloc;

 else return 0;

}

Это – все, что надо знать, чтобы начать использовать оболочку Windows и ее COM интерфейсы. Ниже приводится пример. Оболочка Windows имеет понятие Рабочего стола, являющегося корнем «файловой» системы. Вы обращали внимание, как Windows приложения допускают пользователя, просматривают файловую систему, начинающуюся на рабочем столе? Этим способом Вы можете, например, создавать файлы непосредственно на вашем рабочем столе, двигаться между дисководами, просматривать сетевой дисковод, и т.д. Это, в действительности, Распределенная Файловая система (PMDFS — poor man's Distributed File System) ограниченного человека (?). Как ваше приложение может получить доступ к PMDFS? Просто. В качестве примера напишем код, который позволит пользователю, выбирать папку, просматривая PMDFS. Все, что мы должны сделать — это овладеть рабочим столом, позиционироваться относительно его, запустить встроенное окно просмотра и сформировать путь, который выбрал пользователь.

char path [MAX_PATH];

path [0] = '\0';

Desktop desktop;

ShPath browseRoot(desktop, unicodePath);

if (browseRoot.IsOK) {

 FolderBrowser browser(hwnd, browseRoot, BIF_RETURNONLYFSDIRS, "Select folder of your choice");

 if (folder.IsOK) {

strcpy (path, browser.GetPath);

 }

}

Давайте, запустим объект desktop. Он использует интерфейс по имени IShellFolder. Обратите внимание, как мы приходим к Первому Правилу Захвата. Мы распределяем ресурсы в конструкторе, вызывая функцию API SHGetDesktopFolder. Интеллектуальный указатель интерфейса будет заботиться об управлении ресурсами (подсчет ссылок).

class Desktop: public SIfacePtr<IShellFolder> {

public:

 Desktop {

if (SHGetDesktopFolder(&_p) != NOERROR) throw "SHGetDesktopFolder failed";

 }

};

Как только мы получили рабочий стол, мы должны создать специальный вид пути, который используется PMDFS. Класс ShPath инкапсулирует этот «путь». Он создан из правильного Unicode пути (используйте mbstowcs,

чтобы преобразовать путь ASCII в Unicode: int mbstowcs(wchar_t *wchar, const char *mbchar, size_t count)). Результат преобразования — обобщенный путь относительно рабочего стола. Обратите внимание, что память для нового пути распределена оболочкой – мы инкапсулируем это в SShellPtr, чтобы быть уверенными в правильном освобождении.

class ShPath: public SShellPtr<ITEMIDLIST> {

public:

 ShPath (SIfacePtr<IShellFolder>& folder, wchar_t* path) {

ULONG lenParsed = 0;

_hresult = folder->ParseDisplayName(0, 0, path, &lenParsed, &_p, 0);

 }

 bool IsOK const {

return SUCCEEDED(_hresult);

 }

private:

 HRESULT _hresult;

};

Этот путь оболочки станет корнем, из которого окно просмотра начнет его взаимодействие с пользователем.

С точки зрения клиентского кода, окно просмотра — путь, выбранный пользователем. Именно поэтому он наследуется от SShellPtr<ITEMIDLIST>.

Между прочим, ITEMIDLIST — официальное имя для этого обобщенного пути. Это — список, и я не назвал его SHITEMID'ом. Впредь я буду воздерживаться от любых дальнейших комментариев или шуток относительно соглашений, связанных с именами, используемыми в оболочке.

class FolderBrowser: public SShellPtr<ITEMIDLIST> {

public:

 FolderBrowser(HWND hwndOwner, SShellPtr<ITEMIDLIST>& root, UINT browseForWhat, char const *title);

 char const* GetDisplayName { return _displayName; }

 char const* GetPath { return _fullPath; }

 bool IsOKconst { return _p != 0; };

private:

 char _displayName[MAX_PATH];

 char _fullPath[MAX_PATH];

 BROWSEINFO _browseInfo;

};

FolderBrowser::FolderBrowser(HWND hwndOwner, SShellPtr<ITEMIDLIST>& root, UINT browseForWhat, char const *title) {

 _displayName [0] = '\0';

 _fullPath [0] = '\0';

 _browseInfo.hwndOwner = hwndOwner;

 _browseInfo.pidlRoot = root;

 _browseInfo.pszDisplayName = _displayName;

 _browseInfo.lpszTitle = title;

 _browseInfo.ulFlags = browseForWhat;

 _browseInfo.lpfn = 0;

 _browseInfo.lParam = 0;

 _browseInfo.iImage = 0;

 // Let the user do the browsing

 _p = SHBrowseForFolder(&_browseInfo);

 if (_p != 0) SHGetPathFromIDList(_p, _fullPath);

}

Вот так! Разве это не просто?

Поделиться:
Популярные книги

Газлайтер. Том 3

Володин Григорий
3. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 3

Геном хищника. Книга шестая

Гарцевич Евгений Александрович
6. Я - Легенда!
Старинная литература:
прочая старинная литература
5.00
рейтинг книги
Геном хищника. Книга шестая

Двойник короля 17

Скабер Артемий
17. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 17

Законы Рода. Том 9

Мельник Андрей
9. Граф Берестьев
Фантастика:
городское фэнтези
попаданцы
аниме
дорама
фэнтези
фантастика: прочее
5.00
рейтинг книги
Законы Рода. Том 9

Последний Паладин. Том 14

Саваровский Роман
14. Путь Паладина
Фантастика:
аниме
фэнтези
попаданцы
5.75
рейтинг книги
Последний Паладин. Том 14

Наследие Маозари 7

Панежин Евгений
7. Наследие Маозари
Фантастика:
боевая фантастика
юмористическое фэнтези
постапокалипсис
рпг
фэнтези
эпическая фантастика
5.00
рейтинг книги
Наследие Маозари 7

Пламя

Сокол Лена
3. ПОЖАРНАЯ ЧАСТЬ 17
Любовные романы:
современные любовные романы
прочие любовные романы
остросюжетные любовные романы
5.00
рейтинг книги
Пламя

Революция

Валериев Игорь
9. Ермак
Фантастика:
боевая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Революция

Газлайтер. Том 22

Володин Григорий Григорьевич
22. История Телепата
Фантастика:
боевая фантастика
попаданцы
фэнтези
5.00
рейтинг книги
Газлайтер. Том 22

Двойник Короля

Скабер Артемий
1. Двойник Короля
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Двойник Короля

Солнечный флот

Вайс Александр
4. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Солнечный флот

На границе империй. Том 7. Часть 5

INDIGO
11. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 7. Часть 5

Дважды одаренный. Том VII

Тарс Элиан
7. Дважды одаренный
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Дважды одаренный. Том VII

Бастард Императора. Том 4

Орлов Андрей Юрьевич
4. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Бастард Императора. Том 4