Using MFC MBCS/Unicode Conversion Macros

来源:互联网 发布:睡眠记录的软件 编辑:程序博客网 时间:2024/05/21 17:32

TN059: Using MFC MBCS/Unicode Conversion Macros

The following technical note has not been updated since it was first included in the online documentation. As a result, some procedures and topics might be out of date or incorrect. For the latest information, it is recommended that you search for the topic of interest in the online documentation index.

This note describes how to use the macros for MBCS/Unicode conversion, which are defined in AFXPRIV.H. These macros are most useful if your application deals directly with the OLE API or for some reason, often needs to convert between Unicode and MBCS.

  Overview

  Generic Conversion Macros

The generic conversion macros form the underlying mechanism. The macro example and implementation shown in the previous section, A2W, is one such "generic" macro. It is not related to OLE specifically. The set of generic macros is listed below:

A2CW      (LPCSTR) -> (LPCWSTR)A2W      (LPCSTR) -> (LPWSTR)W2CA      (LPCWSTR) -> (LPCSTR)W2A      (LPCWSTR) -> (LPSTR)

Besides doing text conversions, there are also macros and helper functions for converting TEXTMETRIC, DEVMODE, BSTR, and OLE allocated strings. These macros are beyond the scope of this discussion – refer to AFXPRIV.H for more information on those macros.

  OLE Conversion Macros

The OLE conversion macros are designed specifically for handling functions that expect OLESTR characters. If you examine the OLE headers, you will see many references to LPCOLESTR and OLECHAR. These types are used to refer to the type of characters used in OLE interfaces in a way that is not specific to the platform. OLECHAR maps to char in Win16 and Macintosh platforms and WCHAR in Win32.

In order to keep the number of #ifdef directives in the MFC code to a minimum we have a similar macro for each conversion that where OLE strings are involved. The following macros are the most commonly used:

T2COLE   (LPCTSTR) -> (LPCOLESTR)T2OLE   (LPCTSTR) -> (LPOLESTR)OLE2CT   (LPCOLESTR) -> (LPCTSTR)OLE2T   (LPCOLESTR) -> (LPCSTR)

Again, there are similar macros for doing TEXTMETRIC, DEVMODE, BSTR, and OLE allocated strings. Refer to AFXPRIV.H for more information.

  Other Considerations

Do not use the macros in a tight loop. For example, you do not want to write the following kind of code:

void BadIterateCode(LPCTSTR lpsz){   USES_CONVERSION;   for (int ii = 0; ii < 10000; ii++)      pI->SomeMethod(ii, T2COLE(lpsz));}

The code above could result in allocating megabytes of memory on the stack depending on what the contents of the stringlpszis! It also takes time to convert the string for each iteration of the loop. Instead, move such constant conversions out of the loop:

void MuchBetterIterateCode(LPCTSTR lpsz){   USES_CONVERSION;   LPCOLESTR lpszT = T2COLE(lpsz);   for (int ii = 0; ii < 10000; ii++)      pI->SomeMethod(ii, lpszT);}

If the string is not constant, then encapsulate the method call into a function. This will allow the conversion buffer to be freed each time. For example:

void CallSomeMethod(int ii, LPCTSTR lpsz){   USES_CONVERSION;   pI->SomeMethod(ii, T2COLE(lpsz));}void MuchBetterIterateCode2(LPCTSTR* lpszArray){   for (int ii = 0; ii < 10000; ii++)      CallSomeMethod(ii, lpszArray[ii]);}

Never return the result of one of the macros, unless the return value implies making a copy of the data before the return. For example, this code is bad:

LPTSTR BadConvert(ISomeInterface* pI){   USES_CONVERSION;   LPOLESTR lpsz = NULL;   pI->GetFileName(&lpsz);   LPTSTR lpszT = OLE2T(lpsz);   CoMemFree(lpsz);   return lpszT; // bad!  returning alloca memory}  

The code above could be fixed by changing the return value to something that copies the value:

CString BetterConvert(ISomeInterface* pI){   USES_CONVERSION;   LPOLESTR lpsz = NULL;   pI->GetFileName(&lpsz);   LPTSTR lpszT = OLE2T(lpsz);   CoMemFree(lpsz);   return lpszT; // CString makes copy}

The macros are easy to use and easy to insert into your code, but as you can tell from the caveats above, you need to be careful when using them.