Semua string yang dilewatkan ke dan menerima dari 32-bit OLE api dan
antarmuka metode menggunakan Unicode. Ini memerlukan aplikasi yang menggunakan ANSI
string untuk mengkonversikannya ke Unicode sebelum melewati mereka untuk OLE dan untuk
mengkonversi string Unicode yang diterima dari OLE ANSI. Ini
Artikel menunjukkan bagaimana konversi ini dapat dilakukan.
Windows NT mengimplementasikan Unicode (atau karakter lebar) dan versi ANSI
Win32 fungsi yang mengambil parameter string. Namun Windows 95 tidak
menerapkan versi Unicode Win32 sebagian besar fungsi-fungsi yang mengambil string
parameter. Alih-alih menerapkan hanya ANSI versi ini
fungsi.
Besar pengecualian aturan ini adalah OLE 32-bit. 32-bit OLE api dan
antarmuka metode pada Windows NT dan Windows 95 menggunakan Unicode secara eksklusif.
ANSI versi fungsi-fungsi ini tidak dilaksanakan baik pada Windows
NT atau Windows 95.
Ini berarti bahwa aplikasi 32-bit yang perlu berjalan di kedua Windows
95 dan Windows NT harus menggunakan versi ANSI dari non - OLE Win32
fungsi dan harus mengubah ANSI string untuk Unicode sebelum mereka
dilewatkan ke OLE.
Tidak perlu menggunakan 32-bit Unicode aplikasi yang berjalan pada Windows NT
setiap ANSI/Unicode konversi fungsi.
Win32 menyediakan MultiByteToWideChar dan WideCharToMultiByte untuk mengkonversi
ANSI string untuk Unicode dan Unicode string untuk ANSI. Artikel ini
menyediakan AnsiToUnicode dan UnicodeToAnsi, yang menggunakan fungsi-fungsi ini untuk
ANSI/Unicode konversi.
/*
* 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;
}
Contoh penggunaan fungsi-fungsi ini adalah sebagai berikut. CoTaskMemFree digunakan untuk
gratis string dikonversi jika CoTaskMemAlloc digunakan untuk mengalokasikan
string. String dikonversi harus tidak dibebaskan jika kembali melalui
yang keluar-parameter lain OLE komponen, karena komponen
bertanggung jawab untuk membebaskan string. LPOLESTR adalah sebuah pointer ke Unicode
string.
// 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);
}
CATATAN: Komentar di AnsiToUnicode dan UnicodeToAnsi mengenai
pengalokasi yang digunakan untuk mengalokasikan string dikonversi. CoTaskMemAlloc
(OLE pengalokasi) diperlukan untuk hanya dapat digunakan jika string resultan
akan dilewatkan ke komponen OLE lain dan jika komponen tersebut dapat bebas
string. Ini berarti bahwa string yang berlalu sebagai dalam parameter untuk
OLE antarmuka metode perlu menggunakan OLE pengalokasi. String yang
berlalu sebagai di-out-parameter atau kembali melalui keluar-parameter atau di-
keluar-parameter harus dialokasikan menggunakan OLE pengalokasi.
Konstanta string dapat dikonversi ke Unicode pada waktu kompilasi dengan menggunakan
makro OLESTR. Misalnya:
CreateFileMoniker(OLESTR("c:\\boo\\har.doc"), &pmk);
Contoh lain dari ANSI/Unicode konversi rutinitas dapat ditemukan di
Microsoft Foundation Classes (MFC) kode sumber yang kapal dengan
Visual C++ 4.0 kompilator. Rutinitas ini dijelaskan dalam MFC Technote
59: 'Menggunakan MFC MBCS/Unicode konversi macro'. Definisi ini
makro OLE2T, T2OLE, OLE2CT, T2COLE, A2W, W2A, A2CW, W2CA dan
USES_CONVERSION berada di \msdev\mfc\include\afxpriv.h. Juga melihat
AfxA2WHelper dan AfxW2AHelper di kode sumber MFC di \msdev\mfc\src
dan penggunaan OLE2T, T2OLE, OLE2CT dan T2COLE di kode sumber MFC di
\msdev\mfc\src. Fungsi-fungsi ini memungkinkan kode untuk menyusun baik untuk
Unicode atau ANSI tergantung pada apakah _UNICODE preprocessor
definisi yang telah dibuat. Sebagai contoh, CreateFileMoniker panggilan
contoh di atas dapat dilakukan sebagai berikut dengan macro MFC:
USES_CONVERSION;
GetOpenFileName(&ofn);
CreateFileMoniker(T2OLE(ofn.lpstrFile), &pmk);
Jika _UNICODE didefinisikan, T2OLE didefinisikan sebagai berikut:
inline LPOLESTR T2OLE(LPTSTR lp) { return lp; }
Jika _UNICODE tidak ditentukan, T2OLE didefinisikan sebagai berikut:
#define T2OLE(lpa) A2W(lpa)
T di T2OLE menunjukkan bahwa jenis yang dikonversi ke OLE string
(Unicode string) adalah serangkaian Unicode ketika _UNICODE didefinisikan dan sebuah
ANSI string ketika _UNICODE tidak didefinisikan. Demikian pula LPTSTR didefinisikan sebagai
pointer ke string Unicode ketika _UNICODE didefinisikan dan sebagai pointer
ke ANSI string ketika _UNICODE tidak didefinisikan. T2OLE tidak melakukan apapun
konversi ketika _UNICODE didefinisikan (LPTSTR == LPOLESTR). Ketika Unicode
adalah tidak didefinisikan, disebut A2W. A2W mengkonversi string ANSI-untuk Unicode sebagai
berikut:
#define A2W(lpa) (\
((LPCSTR)lpa == NULL) ? NULL : (\
_convert = (strlen(lpa)+1),\
AfxA2WHelper((LPWSTR) alloca(_convert*2), lpa, _convert)\
)\
)
AfxA2WHelper menggunakan MultiByteToWideChar untuk melakukan konversi.
Macro konversi MFC menggunakan _alloca untuk mengalokasikan ruang dari program
tumpukan untuk string dikonversi. Ruang ini secara otomatis deallocated
ketika panggilan prosedur telah selesai. OLE memerlukan OLE pengalokasi untuk
digunakan untuk semua string (data) yang akan dialokasikan oleh satu komponen
dan dibebaskan oleh orang lain. Ini berarti bahwa string melewati keluar-
parameter dan di-out-parameter OLE antarmuka harus dialokasikan
dengan OLE pengalokasi. Dalam parameter tidak perlu dialokasikan dengan OLE
pengalokasi karena penelpon bertanggung jawab untuk membebaskan mereka. Sebagian besar
Menghubungkan/Embedding OLE antarmuka dan API lulus string sebagai dalam parameter.
Akibatnya MFC konversi macro dapat digunakan dalam banyak kasus. The
MFC konversi makro tidak dapat digunakan untuk parameter dalam keluar atau untuk
kembali nilai-nilai melalui parameter keluar karena mereka tidak mengalokasikan
ruang menggunakan OLE pengalokasi. AnsiToUnicode dan UnicodeToAnsi dapat
digunakan dalam kasus ini.
Namun serangkaian Unicode/ANSI konversi rutinitas dapat ditemukan di Don
Kolom kotak pada OLE di Microsoft sistem Journal, Agustus 1995, Vol. 10
No. 8, halaman 86. Don kotak mendefinisikan kelas C++ dengan operator pemain yang
akan kembali string Unicode/ANSI dikonversi. Ruang yang dialokasikan
secara otomatis dibebaskan ketika objek berjalan keluar dari lingkup. Kelas ini dapat
dimodifikasi untuk mengalokasikan menggunakan OLE pengalokasi dan tidak gratis
mengalokasikan ruang untuk string yang melewati dalam keluar atau keluar-
parameter.
Salah satu kelas, String16, dari kolom Don kotak yang mengubah
ANSI string untuk Unicode, berikut. Kelas lain, String8, yang mirip
satu ini digunakan untuk ANSI untuk Unicode konversi. The
CreateFileMoniker panggilan dari contoh sebelumnya dapat dibuat sebagai berikut
dengan kelas ini:
GetOpenFileName(&ofn);
CreateFileMoniker(String16(ofn.lpstrFile), &pmk);
Pada kode diatas, contoh String16 dibuat. Konstruktor
kelas akan mengkonversi ANSI string untuk Unicode. Bahasa
implementasi akan memanggil pemain operator, operator const wchar_t *,
untuk pemain parameter ini jenis CreateFileMoniker's pertama
parameter. Operator pemain akan kembali string Unicode yang
berlalu untuk CreateFileMoniker. Objek akan merusak ketika di keluar
lingkup.
// 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;
}