Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π‘ΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ БОМ. Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 21

Автор Π”ΠΎΠ½Π°Π»ΡŒΠ΄ Бокс

Одним ΠΈΠ· ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΎΠ² ΠΊ ΡƒΠΏΡ€ΠΎΡ‰Π΅Π½ΠΈΡŽ прСобразования тСкста являСтся ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ систСмы Ρ‚ΠΈΠΏΠΎΠ² C++ ΠΈ использованиС ΠΏΠ΅Ρ€Π΅Π³Ρ€ΡƒΠ·ΠΊΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ для Π²Ρ‹Π±ΠΎΡ€Π° Π½ΡƒΠΆΠ½ΠΎΠΉ строковой ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹, построСнной Π½Π° Ρ‚ΠΈΠΏΠ°Ρ… ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ². Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡ‡Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» ustring.h ΠΈΠ· прилоТСния ΠΊ этой ΠΊΠ½ΠΈΠ³Π΅ содСрТит сСмСйство Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅Ρ‡Π½Ρ‹Ρ… строковых ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€, Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½Ρ‹Ρ… стандартным Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅Ρ‡Π½Ρ‹ΠΌ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π°ΠΌ Π‘, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ находятся Π² Ρ„Π°ΠΉΠ»Π΅ string.h. НапримСр, функция strncpy ΠΈΠΌΠ΅Π΅Ρ‚ Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹, зависящиС ΠΎΡ‚ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΈΠ· ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· Π΄Π²ΡƒΡ… ΡΠΈΠΌΠ²ΠΎΠ»ΡŒΠ½Ρ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ² (wchar_t ΠΈΠ»ΠΈ char):


// from ustring.h (book-specific header)

// ΠΈΠ· ustring.h (Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ, спСцифичСский для Π΄Π°Π½Π½ΠΎΠΉ ΠΊΠ½ΠΈΠ³ΠΈ)

inline bool ustrncpy(char *p1, const wchar_t *p2, size_t c)

{

size_t cb = wcstombs(p1, p2, c);

return cb != c && cb != (size_t)-1;

};

inline bool ustrncpy(wchar_t *p1, const wchar_t *p2, size_t c)

{

wcsncpy(p1, p2, c);

return p1[c – 1] == 0;

};

inline bool ustrncpy(char *p1, const char *p2, size_t c)

{

strncpy(p1, p2, c);

return p1[c – 1] == 0;

};

inline bool ustrncpy(wchar_t *p1, const char *p2, size_t c)

{

size_t cch = mbstowcs(p1, p2, c);

return cch != c && cch != (size_t)-1;

}


ΠžΡ‚ΠΌΠ΅Ρ‚ΠΈΠΌ, Ρ‡Ρ‚ΠΎ для любого сочСтания Ρ‚ΠΈΠΏΠΎΠ² ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠ² ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π½Π°ΠΉΠ΄Π΅Π½Π° ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ пСрСгруТСнная функция ustrncpy, ΠΏΡ€ΠΈΡ‡Π΅ΠΌ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, Π±Ρ‹Π»Π° ΠΈΠ»ΠΈ Π½Π΅Ρ‚ вся строка Ρ†Π΅Π»ΠΈΠΊΠΎΠΌ скопирована ΠΈΠ»ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½Π°. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ эти ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹ ΠΊΠ°ΠΊ встраиваСмыС (inline) Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΈΡ… использованиС Π½Π΅ внСсСт Π½ΠΈΠΊΠ°ΠΊΠΈΡ… Π·Π°Ρ‚Ρ€Π°Ρ‚ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ. Π‘ этими ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π°ΠΌΠΈ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ ΠΊΠΎΠ΄Π° станСт Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΡ€ΠΎΡ‰Π΅ ΠΈ Π½Π΅ ΠΏΠΎΡ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ условной компиляции:


class BigDog : public ILabrador

{

TCHAR m_szName[1024];

// note TCHAR-based string

// ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΠΌ строку Ρ‚ΠΈΠΏΠ° TCHAR

public:

STDMETHODIMP SetName(/* [in,string] */ const OLECHAR *pwsz)

{

HRESULT hr = S_OK;

// use book-specific overloaded ustrncpy to copy or convert

// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ для копирования ΠΈ прСобразования

// ΠΏΠ΅Ρ€Π΅Π³Ρ€ΡƒΠΆΠ΅Π½Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ustrncpy, ΡΠΏΠ΅Ρ†ΠΈΡ„ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ для Π΄Π°Π½Π½ΠΎΠΉ ΠΊΠ½ΠΈΠ³ΠΈ

if (!ustrncpy(m_szName, pwsz, 1024))

{

m_szName[0] = 0;

hr = E_INVALIDARG;

} return hr;

}

};


Π‘ΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅Π³Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ для ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€ strlen, strcpy ΠΈ strcat Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡ‡Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» ustring.h.

ИспользованиС ΠΏΠ΅Ρ€Π΅Π³Ρ€ΡƒΠ·ΠΊΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅Ρ‡Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ для копирования строк ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π±ΡƒΡ„Π΅Ρ€Π° Π² Π΄Ρ€ΡƒΠ³ΠΎΠΉ, ΠΊΠ°ΠΊ это ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π²Ρ‹ΡˆΠ΅, обСспСчиваСт Π»ΡƒΡ‡ΡˆΠ΅Π΅ качСство исполнСния, ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΊΠΎΠ΄Π° ΠΈ Π½Π΅ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΈΠ·Π΄Π΅Ρ€ΠΆΠΊΠΈ программиста. Однако часто Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ ситуация, ΠΊΠΎΠ³Π΄Π° ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ БОМ ΠΈ API-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Win32, Ρ‡Ρ‚ΠΎ Π½Π΅ Π΄Π°Π΅Ρ‚ возмоТности ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ эту Ρ‚Π΅Ρ…Π½ΠΈΠΊΡƒ. Рассмотрим ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ ΠΊΠΎΠ΄Π°, Ρ‡ΠΈΡ‚Π°ΡŽΡ‰ΠΈΠΉ строку ΠΈΠ· элСмСнта рСдактирования ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΡŽΡ‰ΠΈΠΉ Π΅Π΅ Π² IID:


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);

}


Π—Π°ΠΌΠ΅Ρ‚ΠΈΠΌ, Ρ‡Ρ‚ΠΎ Π½Π΅ трСбуСтся Π½ΠΈΠΊΠ°ΠΊΠΎΠΉ условной компиляции. Если ΠΊΠΎΠ΄ скомпилирован с вСрсиСй Win32 с ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΎΠΉ Unicode, Ρ‚ΠΎ класс _UNCC просто пропустит исходный Π±ΡƒΡ„Π΅Ρ€ Ρ‡Π΅Ρ€Π΅Π· свой ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ привСдСния Ρ‚ΠΈΠΏΠ°. Если ΠΆΠ΅ ΠΊΠΎΠ΄ компилируСтся с вСрсиСй Win32, Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‰Π΅ΠΉ Unicode, Ρ‚ΠΎ класс _UNCC Π²Ρ‹Π΄Π΅Π»ΠΈΡ‚ Π±ΡƒΡ„Π΅Ρ€ ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ строку Π² Unicode. Π—Π°Ρ‚Π΅ΠΌ дСструктор _UNCC освободит Π±ΡƒΡ„Π΅Ρ€, ΠΊΠΎΠ³Π΄Π° опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ[3].

Π‘Π»Π΅Π΄ΡƒΠ΅Ρ‚ ΠΎΠ±ΡΡƒΠ΄ΠΈΡ‚ΡŒ Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Ρ‚ΠΈΠΏ Π΄Π°Π½Π½Ρ‹Ρ…, связанный с тСкстом, β€“ BSTR. Π‘Ρ‚Ρ€ΠΎΠΊΠΎΠ²Ρ‹ΠΉ Ρ‚ΠΈΠΏ BSTR Π½ΡƒΠΆΠ½ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ Π²ΠΎ всСх интСрфСйсах, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ прСдполагаСтся ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΠ· языков Visual Basic ΠΈΠ»ΠΈ Java. Π‘Ρ‚Ρ€ΠΎΠΊΠΈ BSTR ΡΠ²Π»ΡΡŽΡ‚ΡΡ OLECHAR-строками с прСфиксом Π΄Π»ΠΈΠ½Ρ‹ (length-prefix) Π² Π½Π°Ρ‡Π°Π»Π΅ строки ΠΈ Π½ΡƒΠ»Π΅ΠΌ Π² Π΅Π΅ ΠΊΠΎΠ½Ρ†Π΅. ΠŸΡ€Π΅Ρ„ΠΈΠΊΡ Π΄Π»ΠΈΠ½Ρ‹ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ число Π±Π°ΠΉΡ‚, содСрТащихся Π² строкС (ΠΈΡΠΊΠ»ΡŽΡ‡Π°Ρ Π·Π°Π²Π΅Ρ€ΡˆΠ°ΡŽΡ‰ΠΈΠΉ Π½ΡƒΠ»ΡŒ) ΠΈ записан Π² Ρ„ΠΎΡ€ΠΌΠ΅ Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅Ρ…Π±Π°ΠΉΡ‚ΠΎΠ²ΠΎΠ³ΠΎ Ρ†Π΅Π»ΠΎΠ³ΠΎ числа, нСпосрСдствСнно ΠΏΡ€Π΅Π΄ΡˆΠ΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ ΠΏΠ΅Ρ€Π²ΠΎΠΌΡƒ символу строки. Рисунок 2.7 дСмонстрируСт BSTR Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ строки Β«HiΒ». Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌ свободно Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ строки BSTR Π±Π΅Π· Π·Π°Π±ΠΎΡ‚Ρ‹ ΠΎ Π²Ρ‹Π΄Π΅Π»Π΅Π½ΠΈΠΈ памяти, всС BSTR Ρ€Π°Π·ΠΌΠ΅Ρ‰Π΅Π½Ρ‹ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ распрСдСлитСля памяти, управляСмого БОМ. Π’ БОМ прСдусмотрСно нСсколько API-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ для управлСния BSTR:



// from oleauto.h

// allocate and initialize a BSTR

// выдСляСм ΠΏΠ°ΠΌΡΡ‚ΡŒ ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ строку BSTR

BSTR SysAllocString(const OLECHAR *psz);

BSTR SysAllocStringLen(const OLECHAR *psz, UINT cch);

// reallocate and initialize a BSTR

// ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ выдСляСм ΠΏΠ°ΠΌΡΡ‚ΡŒ ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ BSTR

INT SysReAllocString(BSTR *pbstr, const OLECHAR *psz);

INT SysReAllocStringLen(BSTR *pbstr, const OLECHAR * psz, UINT cch);

// free a BSTR

// освобоТдаСм BSTR void SysFreeString(BSTR bstr);

// peek at length-prefix as characters or bytes

// считываСм прСфикс Π΄Π»ΠΈΠ½Ρ‹ ΠΊΠ°ΠΊ число символов ΠΈΠ»ΠΈ Π±Π°ΠΉΡ‚

UINT SysStringLen(BSTR bstr);

UINT SysStringByteLen(BSTR bstr);


ΠŸΡ€ΠΈ пСрСсылкС строк ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π² качСствС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Ρ‚ΠΈΠΏΠ° [in] Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π·Π°Π±ΠΎΡ‚ΠΈΡ‚ΡŒΡΡ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ SysAllocString ΠΏΡ€Π΅ΠΆΠ΄Π΅, Ρ‡Π΅ΠΌ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ сам ΠΌΠ΅Ρ‚ΠΎΠ΄, ΠΈ Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ SysFreeString послС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π·Π°ΠΊΠΎΠ½Ρ‡ΠΈΠ» Ρ€Π°Π±ΠΎΡ‚Ρƒ. Рассмотрим ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°:


HRESULT SetString([in] BSTR bstr);


ΠŸΡƒΡΡ‚ΡŒ Π² Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ ΡƒΠΆΠ΅ имССтся строка, совмСстимая с OLECHAR, Ρ‚ΠΎΠ³Π΄Π° для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ строку Π² BSTR Π΄ΠΎ Π²Ρ‹Π·ΠΎΠ²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π°, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅:


// convert raw OLECHAR string to a BSTR

// ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Π΅ΠΌ Β«ΡΡ‹Ρ€ΡƒΡŽΒ» строку OLECHAR Π² строку BSTR

BSTR bstr = SysAllocString(OLESTR(Β«HelloΒ»));

// invoke method

// Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ ΠΌΠ΅Ρ‚ΠΎΠ΄ HRESULT hr = p->SetString(bstr);

// free BSTR

// освобоТдаСм BSTR SysFreeString(bstr);


ΠŸΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹ΠΉ класс для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с BSTR, _UBSTR, Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡ‡Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» ustring.h:


// from ustring.h (book-specific header file)

// ΠΈΠ· ustring.h (спСцифичСский для Π΄Π°Π½Π½ΠΎΠΉ ΠΊΠ½ΠΈΠ³ΠΈ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΡ‡Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ»)

class _UBSTR

{

BSTR m_bstr;

public:

_UBSTR(const char *psz) : m_bstr(SysAllocStringLen(0, strlen(psz)))

{

mbstowcs(m_bstr, psz, INT_MAX);

}

_UBSTR(const wchar_t *pwsz) : m_bstr(SysAllocString(pwsz))

{

}

operator BSTR (void) const

{ return m_bstr; }

~_UBSTR(void)

{ SysFreeString(m_bstr); }

};


ΠŸΡ€ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠΈ Ρ‚Π°ΠΊΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ класса ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ ΠΊΠΎΠ΄Π° Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ упростится:


// invoke method

// Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ ΠΌΠ΅Ρ‚ΠΎΠ΄

HRESULT hr = p->SetString(_UBSTR(OLESTR(Β«HelloΒ»)));


Π—Π°ΠΌΠ΅Ρ‚ΠΈΠΌ, Ρ‡Ρ‚ΠΎ Π² ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠΌ классС UBSTR ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π² Ρ€Π°Π²Π½ΠΎΠΉ стСпСни ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½Ρ‹ строки Ρ‚ΠΈΠΏΠΎΠ² char ΠΈ wchar_t.

ΠŸΡ€ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ ΠΈΠ· ΠΌΠ΅Ρ‚ΠΎΠ΄Π° строк Ρ‡Π΅Ρ€Π΅Π· ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ Ρ‚ΠΈΠΏΠ° [out] ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ обязан Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ SysAllocString, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰ΡƒΡŽ строку Π² Π±ΡƒΡ„Π΅Ρ€. Π—Π°Ρ‚Π΅ΠΌ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΡΠ²ΠΎΠ±ΠΎΠ΄ΠΈΡ‚ΡŒ Π±ΡƒΡ„Π΅Ρ€ ΠΏΡƒΡ‚Π΅ΠΌ Π²Ρ‹Π·ΠΎΠ²Π° SysFreeString. Рассмотрим ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°:


HRESULT GetString([out, retval] BSTR *pbstr);


ΠŸΡ€ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° потрСбуСтся ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π½ΠΎΠ²ΡƒΡŽ BSTR-строку для Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π° Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΌΡƒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ:


STDMETHODIMP MyClass::GetString(BSTR *pbstr)

{

*pbstr = SysAllocString(OLESTR(Β«Coodbye!Β»)) ;

return S_OK;

}


Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΡΠ²ΠΎΠ±ΠΎΠ΄ΠΈΡ‚ΡŒ строку сразу послС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΎΠ½Π° скопирована Π² управляСмый ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ строковый Π±ΡƒΡ„Π΅Ρ€:


extern OLECHAR g_wsz[];

BSTR bstr = 0;

HRESULT hr = p->GetString(&bstr);

if (SUCCEEDED(hr))

{

wcscpy(g_wsz, bstr); SysFreeString(bstr);

}


Π’ΡƒΡ‚ Π½ΡƒΠΆΠ½ΠΎ Ρ€Π°ΡΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ Π²Π°ΠΆΠ½Ρ‹ΠΉ аспСкт BSTR. Π’ качСствС BSTR ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Π½ΡƒΠ»Π΅Π²ΠΎΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ Π½Π° ΠΏΡƒΡΡ‚ΡƒΡŽ строку. Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ ΠΊΠΎΠ΄Π° Π½Π΅ совсСм ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π΅Π½. Π’Ρ‹Π·ΠΎΠ² wcscpy:


wcscpy(g_wsz, bstr);