September 21, 2009
Hi,

I wrote a header file to resolve wide string literal issue.
Previously, when UNICODE is defined, wide string literals like L"foo" or
_T("foo") doesn't work correctly (garbled).   In this case, programmers must
write wide string literals in character codes by using \u.

e.g.)

// Garbled
::MessgaeBoxW(NULL, _T("Hello"), _T("Title"), MB_OK);


This header file resolve the problem (this requires STLPort).

// dmctchar.h

#ifndef DMCTCHAR_H
#define DMCTCHAR_H

#include <windows.h>
#include <tchar.h>
#include <string>

using namespace std;

namespace {     // nameless namespace
    // MBCS->UNICODE converting function
    wstring MultiByteToWstr(const char* mbChar, UINT cp)
    {
        // Get buffer size
        int numChars = ::MultiByteToWideChar(cp, 0, mbChar, -1, NULL, 0);
        wchar_t* pWst = new wchar_t[numChars];

        // Conversion
        numChars = ::MultiByteToWideChar(cp, 0, mbChar, -1, pWst, numChars);
        wstring result = wstring(pWst);
        delete[] pWst;
        return result;
    }
}

#ifdef UNICODE
    #undef _T
    #define _T(str) MultiByteToWstr(str, ::GetACP()).c_str()
#endif // UNICODE

#endif // DMCTCHAR_H


When UNICODE is defined, Include above header file after tchar.h in your program, and you can write wide string literals directly as _T("foo").

Please feel free to use it if you faced with this problem. Your bug reports are appreciated.


hirofield
November 20, 2009
> Your bug reports are appreciated.

Haven't compiled it, but I can tell you that it's got issues wrt exception-safety and error-conditions.

First, you don't check the return value of MultiByteToWideChar(). If it returns 0, you may want to just return wstring().

Second, if the expression

  wstring result = wstring(pWst);

throws an exception, then the memory in the wide-char array will be leaked.

(btw, you can just write

  wstring result(pWst);

or, even better,

  wstring result(pWst, static_cast<size_t>(numChars));
)

Third, you might consider avoiding the (potentially unnecessary) explicit memory allocation, and use an auto_buffer instead; see
www.ddj.com/cpp/184401740 and http://www.stlsoft.org/doc-1.9/classstlsoft_1_1auto__buffer.html

    wstring MultiByteToWstr(const char* mbChar, UINT cp)
    {
        // Get buffer size
        int numChars = ::MultiByteToWideChar(cp, 0, mbChar, -1, NULL, 0);
       stlsoft::auto_buffer<wchar_t> buff(numChars);

        // Conversion
        numChars = ::MultiByteToWideChar(cp, 0, mbChar, -1, &buff[0], numChars);
        wstring(&buff[0], numChars);
        return result;
    } // if any memory allocated in buff, will be freed here automatically

btw, the second problem now disappears as well.

Four, I'm not sure what you're doing with redefining _T(), but it looks suspicious. I'd need to hear more from you before
commenting, but I think you're doing something that might screw up other code.

HTH

Matt

"hirofield" <hi_ohta@nifty.com> wrote in message news:h9810v$3bi$1@digitalmars.com...
> Hi,
>
> I wrote a header file to resolve wide string literal issue.
> Previously, when UNICODE is defined, wide string literals like L"foo" or
> _T("foo") doesn't work correctly (garbled).   In this case, programmers must
> write wide string literals in character codes by using \u.
>
> e.g.)
>
> // Garbled
> ::MessgaeBoxW(NULL, _T("Hello"), _T("Title"), MB_OK);
>
>
> This header file resolve the problem (this requires STLPort).
>
> // dmctchar.h
>
> #ifndef DMCTCHAR_H
> #define DMCTCHAR_H
>
> #include <windows.h>
> #include <tchar.h>
> #include <string>
>
> using namespace std;
>
> namespace {     // nameless namespace
>     // MBCS->UNICODE converting function
>     wstring MultiByteToWstr(const char* mbChar, UINT cp)
>     {
>         // Get buffer size
>         int numChars = ::MultiByteToWideChar(cp, 0, mbChar, -1, NULL, 0);
>         wchar_t* pWst = new wchar_t[numChars];
>
>         // Conversion
>         numChars = ::MultiByteToWideChar(cp, 0, mbChar, -1, pWst, numChars);
>         wstring result = wstring(pWst);
>         delete[] pWst;
>         return result;
>     }
> }
>
> #ifdef UNICODE
>     #undef _T
>     #define _T(str) MultiByteToWstr(str, ::GetACP()).c_str()
> #endif // UNICODE
>
> #endif // DMCTCHAR_H
>
>
> When UNICODE is defined, Include above header file after tchar.h in your program, and you can write wide string literals directly as _T("foo").
>
> Please feel free to use it if you faced with this problem. Your bug reports are appreciated.
>
>
> hirofield