Преобразование из ANSI в Юникод & Юникод в ANSI для OLE

Переводы статьи Переводы статьи
Код статьи: 138813
Развернуть все | Свернуть все

Аннотация

Все строки, передаваемых и получаемых из 32-разрядными интерфейсами OLE API и методы интерфейса используется Юникод. Для этого приложения, использующие ANSI строки перед их передачей OLE и преобразовать их в кодировке Юникод Преобразование строки Юникода, полученных из OLE в ANSI. Это в статье показано, как эти преобразования могут быть выполнены.

Дополнительная информация

Windows NT использует Юникод (либо двухбайтовых знаков) и в формате ANSI Функции Win32, которые принимают строковых параметров. Тем не менее не поддерживает Windows 95 реализации Юникода версии большинства функций Win32, принимающих строки параметры. Вместо этого он реализует только ANSI версии функции.

Основные исключения для данного правила является 32-разрядной OLE. OLE 32-разрядных интерфейсов API и методы интерфейса в Windows NT и Windows 95 монопольно использовать Юникод. ANSI версии этих функций, не реализуется на Windows NT или Windows 95.

Это означает, что 32-разрядного приложения, который должен выполняться на обоих окнах 95 и Windows NT необходимо использовать версий ANSI из не - OLE Win32 функции и необходимо преобразовать строки ANSI в Юникод, прежде чем они будут передано OLE.

32-Разрядное приложение Юникод, которое будет выполняться только в Windows NT не требуется использовать все функции преобразования ANSI и Юникода.

Win32 предоставляет MultiByteToWideChar и WideCharToMultiByte преобразования Строки ANSI в Юникод и строки Юникода в ANSI. В данной статье AnsiToUnicode и UnicodeToAnsi, в которой используются эти функции для Преобразование ANSI и Юникода.
/*
 * AnsiToUnicode converts the ANSI string pszA to a Unicode string
 * and returns the Unicode string through ppszW. Space for the
 * the converted string is allocated by AnsiToUnicode.
 */ 

HRESULT __fastcall AnsiToUnicode(LPCSTR pszA, LPOLESTR* ppszW)
{

    ULONG cCharacters;
    DWORD dwError;

    // If input is null then just return the same.
    if (NULL == pszA)
    {
        *ppszW = NULL;
        return NOERROR;
    }

    // Determine number of wide characters to be allocated for the
    // Unicode string.
    cCharacters =  strlen(pszA)+1;

    // Use of the OLE allocator is required if the resultant Unicode
    // string will be passed to another COM component and if that
    // component will free it. Otherwise you can use your own allocator.
    *ppszW = (LPOLESTR) CoTaskMemAlloc(cCharacters*2);
    if (NULL == *ppszW)
        return E_OUTOFMEMORY;

    // Covert to Unicode.
    if (0 == MultiByteToWideChar(CP_ACP, 0, pszA, cCharacters,
                  *ppszW, cCharacters))
    {
        dwError = GetLastError();
        CoTaskMemFree(*ppszW);
        *ppszW = NULL;
        return HRESULT_FROM_WIN32(dwError);
    }

    return NOERROR;
/*
 * UnicodeToAnsi converts the Unicode string pszW to an ANSI string
 * and returns the ANSI string through ppszA. Space for the
 * the converted string is allocated by UnicodeToAnsi.
 */ 

HRESULT __fastcall UnicodeToAnsi(LPCOLESTR pszW, LPSTR* ppszA)
{

    ULONG cbAnsi, cCharacters;
    DWORD dwError;

    // If input is null then just return the same.
    if (pszW == NULL)
    {
        *ppszA = NULL;
        return NOERROR;
    }

    cCharacters = wcslen(pszW)+1;
    // Determine number of bytes to be allocated for ANSI string. An
    // ANSI string can have at most 2 bytes per character (for Double
    // Byte Character Strings.)
    cbAnsi = cCharacters*2;

    // Use of the OLE allocator is not required because the resultant
    // ANSI  string will never be passed to another COM component. You
    // can use your own allocator.
    *ppszA = (LPSTR) CoTaskMemAlloc(cbAnsi);
    if (NULL == *ppszA)
        return E_OUTOFMEMORY;

    // Convert to ANSI.
    if (0 == WideCharToMultiByte(CP_ACP, 0, pszW, cCharacters, *ppszA,
                  cbAnsi, NULL, NULL))
    {
        dwError = GetLastError();
        CoTaskMemFree(*ppszA);
        *ppszA = NULL;
        return HRESULT_FROM_WIN32(dwError);
    }
    return NOERROR;

}
				
Далее представлен пример использования этих функций. CoTaskMemFree используется для Освободите преобразованная строка в случае CoTaskMemAlloc выделить Строка. Преобразованная строка не должны быть освобождены, если возвращается через любой параметр out в другой компонент OLE поскольку это ответственность за освобождение строки. LPOLESTR является указателем Юникода Строка.
// The following code gets an ANSI filename that is specified by the
// user in the OpenFile common dialog. This file name is converted into
// a Unicode string and is passed to the OLE API CreateFileMoniker. The
// Unicode string is then freed.

OPENFILENAME ofn;
LPOLESTR pszFileNameW;
LPMONIKER pmk;
:

// Get file name from OpenFile Common Dialog. The ANSI file name will
// be placed in ofn.lpstrFile

GetOpenFileName(&ofn);
:
AnsiToUnicode(ofn.lpstrFile, &pszFileNameW);
CreateFileMoniker(pszFileNameW, &pmk);
CoTaskMemFree(pszFileNameW);

// The following code implements IOleInPlaceFrame::SetStatusText.
// The lpszStatusText string, that is received from another OLE
// component, uses Unicode. The string is converted to ANSI before it is
// passed to the ANSI version of SetWindowText. Windows 95 supports only
// the ANSI version of SetWindowText.

COleInPlaceFrame::SetStatusText(LPCOLESTR pszStatusTextW)
{

    LPSTR pszStatusTextA;
    UnicodeToAnsi(pszStatusTextW, &pszStatusTextA);
    SetWindowText(m_hwndStatus, pszStatusTextA);
    CoTaskMemFree(pszStatusTextA);

}
				
ПРИМЕЧАНИЕ: Комментарии в AnsiToUnicode и UnicodeToAnsi относительно распределитель, который используется для выделения преобразованная строка. CoTaskMemAlloc (распределитель OLE) необходим, только если результирующая строка будут передаваться на другой компонент OLE, и если этот компонент можно освободить Строка. Это значит, строки, которые передаются как в параметры для Методы интерфейса OLE не требуется использовать распределителя OLE. Строки, которые являются передаются как в параметры out или возвращаются через выходные параметры или в- выходные параметры должны выделяться с помощью распределителя OLE.

Строковые константы можно преобразовать в Юникод во время компиляции с помощью макрос OLESTR. Например:
CreateFileMoniker(OLESTR("c:\\boo\\har.doc"), &pmk);
				
Еще одним примером процедуры преобразования ANSI и Юникода можно найти в Исходный код Microsoft Foundation Classes (MFC), который поставляется в комплекте с Компилятор Visual C++ 4.0. Эти процедуры описаны в MFC Technote 59: «Использование MFC многобайтовых Кодировок и Юникода преобразование макросов». Определение этих макрос OLE2T, T2OLE, OLE2CT, T2COLE, A2W, W2A, A2CW, W2CA и USES_CONVERSION, \msdev\mfc\include\afxpriv.h. Также см. AfxA2WHelper и AfxW2AHelper в MFC исходный код в \msdev\mfc\src и использование исходного кода MFC в OLE2T, T2OLE, OLE2CT и T2COLE \msdev\mfc\src. Эти функции позволяют код будет скомпилирован для Юникод или ANSI в зависимости от того, нужно ли _UNICODE препроцессора Определение были сделаны. Например, вызов CreateFileMoniker в выше примере можно сделать следующим образом с макросами MFC:
USES_CONVERSION;
GetOpenFileName(&ofn);
CreateFileMoniker(T2OLE(ofn.lpstrFile), &pmk);
				
Если определяется _UNICODE, T2OLE определяется следующим образом:
inline LPOLESTR T2OLE(LPTSTR lp) { return lp; }
				
Если не определяется _UNICODE, T2OLE определяется следующим образом:
#define T2OLE(lpa) A2W(lpa)
				
T в T2OLE указывает, что тип, оно преобразуется в строку OLE (Строка Юникод) является строкой Юникода, если определяется _UNICODE и Строка ANSI при _UNICODE не определен. Аналогичным образом LPTSTR определяется как курсор в строку Юникода при определяется _UNICODE и как указатель Строка ANSI при _UNICODE не определен. Не выполнять T2OLE Если определяется _UNICODE преобразования (LPTSTR == LPOLESTR). Когда Юникод Это не определен, называется A2W. A2W преобразует строки ANSI в Юникод как выглядит следующим образом:
#define A2W(lpa) (\ 
        ((LPCSTR)lpa == NULL) ? NULL : (\ 
            _convert = (strlen(lpa)+1),\ 
            AfxA2WHelper((LPWSTR) alloca(_convert*2), lpa, _convert)\ 
        )\ 

)
				
AfxA2WHelper использует MultiByteToWideChar для этого преобразования.

Преобразование макросов с помощью функции _alloca выделить пространство в программе стек для преобразованная строка. Пространство автоматически выделяемой Завершение вызова процедуры. OLE требуется распределителя OLE для для всех строк (данные), которые будут выделяться один компонент и освобожденные, другим. Это означает, что строки передаются out- должно быть выделено и в out параметры интерфейсов OLE с помощью распределителя OLE. Не нужно выделить в параметры с помощью OLE распределитель потому, что вызывающий объект отвечает за их освобождение. Большинство Связывание и внедрение OLE интерфейсов и API-Интерфейса передачи строк как в параметры. Таким образом в большинстве случаев можно использовать преобразование макросов. В Преобразование макросов нельзя использовать для параметров-исходящий или Возврат значений через выходные параметры, так как они сами не выделяют пространство, распределитель OLE. Может быть AnsiToUnicode и UnicodeToAnsi используемые в этих случаях.

Еще можно найти другой набор процедуры преобразования Юникода или ANSI в Дон Поля столбцов на OLE в Microsoft Systems Journal, август 1995 Vol. 10 Номер 8, 86 страницы. Дон Бокс определяет класс C++ с помощью оператора приведения которого Возвращает строку Юникода или ANSI преобразуется. Выделенные места автоматически освобождается, когда объект выходит из области. Этот класс может быть измененный выделить с помощью распределителя OLE и освобождает пространство, выделенное для строк, которые передаются через-выход или выход- параметры.

Один из классов, String16, Дон Бокс столбце, который преобразует Строка ANSI, Юникод, выглядит следующим образом. Другой класс, String8, вида для этого используются для ANSI для преобразования в формат Юникод. В Вызов CreateFileMoniker из предыдущего примера может быть выполнен следующим образом с помощью этого класса:
GetOpenFileName(&ofn);
CreateFileMoniker(String16(ofn.lpstrFile), &pmk);
				
В приведенном выше коде создается экземпляр класса String16. Конструктор класса преобразует строки ANSI в Юникод. Язык реализация будет вызывать оператор приведения, оператор const wchar_t *, для приведения этого параметра типа из CreateFileMoniker первый параметр. Возвращает строку Юникода, которая является оператор приведения передано CreateFileMoniker. Объект будет destruct в случае выходит за пределы из области видимости.
// String16 //////////////////////////////////////////////////////// 
// Shim class that converts both 8-bit (foreign) and
// 16-bit (native) strings to 16-bit wideness

class String16 {
public:

// native and foreign constructors
    String16(const char *p8);
    String16(const wchar_t *p16);

// non-virtual destructor (this class is concrete)

  ~String16(void);

// native conversion operator

  operator const wchar_t * (void) const;
private:

// native wideness string
    wchar_t *m_sz;
// is foreign??
    BOOL m_bIsForeign;

// protect against assignment!

  String16(const String16&);

    String16& operator=(const String16&);
};

// native constructor is a pass-through

inline String16::String16(const wchar_t *p16)
: m_sz((wchar_t *)p16), m_bIsForeign(FALSE)
{
}

// simply give out the native wideness string

inline String16::operator const wchar_t * (void) const
{
  return m_sz;
}

// foreign constructor requires allocation of a native
// string and conversion

inline String16::String16(const char *p8)
: m_bIsForeign(TRUE)
{

// calculate string length

  size_t len = strlen(p8);

// calculate required buffer size (some characters may
// already occupy 16-bits under DBCS)

  size_t size = mbstowcs(0, p8, len) + 1;

// alloc native string and convert

  if (m_sz = new wchar_t[size])

    mbstowcs(m_sz, p8, size);

}

// delete native string only if synthesized in foreign constructor

inline String16::~String16(void) {
  if (m_bIsForeign)

    delete[] m_sz;

}
				

Свойства

Код статьи: 138813 - Последний отзыв: 2 июня 2011 г. - Revision: 4.0
Ключевые слова: 
kbcode kbhowto kbprogramming kbmt KB138813 KbMtru
Переведено с помощью машинного перевода
ВНИМАНИЕ! Перевод данной статьи был выполнен не человеком, а с помощью программы машинного перевода, разработанной корпорацией Майкрософт. Корпорация Майкрософт предлагает вам статьи, переведенные как людьми, так и средствами машинного перевода, чтобы у вас была возможность ознакомиться со статьями базы знаний KB на родном языке. Однако машинный перевод не всегда идеален. Он может содержать смысловые, синтаксические и грамматические ошибки, подобно тому как иностранец делает ошибки, пытаясь говорить на вашем языке. Корпорация Майкрософт не несет ответственности за неточности, ошибки и возможный ущерб, причиненный в результате неправильного перевода или его использования. Корпорация Майкрософт также часто обновляет средства машинного перевода.
Эта статья на английском языке:138813

Отправить отзыв

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com