Сущность технологии СОМ. Библиотека программиста | страница 67
HRESULT IIDFromHWND(HWND hwnd, IID& riid)
{
TCHAR szEditText[1024];
// call a TCHAR-based Win32 routine
// вызываем TCHAR-процедуру Win32
GetWindowText(hwnd, szEditText, 1024);
// call an OLECHAR-based СОМ routine
// вызываем OLECHAR-процедуру СОМ
return IIDFromString(szEditText, &riid);
}
Допуская, что этот код скомпилирован с указанным символом С-препроцессора UNICODE; он работает безупречно, так как TCHAR и OLECHAR являются просто псевдонимами wchar_t и никакого преобразования не требуется. Если же функция скомпилирована с версией Win32 API, не поддерживающей Unicode, то TCHAR является псевдонимом для char, и первый параметр для IIDFromString имеет неправильный тип. Чтобы решить эту проблему, нужно провести условную компиляцию:
HRESULT IIDFromHWND(HWND hwnd, IID& riid)
{
TCHAR szEditText[1024];
GetWindowText(hwnd, szEditText, 1024);
#ifdef UNICODE return IIDFromString(szEditText, &riid);
#else OLECHAR wszEditText[l024];
ustrncpy(wszEditText, szEditText, 1024);
return IIDFromString(wszEditText, &riid);
#endif
}
Хотя этот фрагмент и генерирует оптимальный код, очень утомительно применять эту технику всякий раз, когда символьный параметр имеет неверный тип. Можно справиться с этой проблемой, если использовать промежуточный (shim) класс с конструктором, принимающим в качестве параметра любой тип символьной строки. Этот промежуточный класс должен также содержать в себе операторы приведения типа, что позволит использовать его в обоих случаях: когда ожидается const char * или const wchar_t *. В этих операциях приведения промежуточный класс либо выделяет резервный буфер и производит необходимое преобразование, либо просто возвращает исходную строку, если преобразования не требовалось. Деструктор промежуточного класса может затем освободить все выделенные буферы. Заголовочный файл ustring.h содержит два таких промежуточных класса: _U и _UNCC. Первый предназначен для нормального использования; второй используется с функциями и методами, тип аргументов которых не включает спецификатора const[2] (таких как IIDFromString). При возможности применения двух промежуточных классов предыдущий фрагмент кода может быть значительно упрощен:
HRESULT IIDFromHWND(HWND hwnd, IID& riid)
{
TCHAR szEditText[1024];
GetWindowText(hwnd, szEditText, 1024);
// use _UNCC shim class to convert if necessary
// используем для преобразования промежуточный класс _UNCC,
// если необходимо
return IIDFromString(_UNCC(szEditText), &riid);