2007-06-28

文字列操作(続き)

今日も文字列操作で引っ張ります。
 
「文字列操作は ATL::CStringが良さそう」という結論になったのですが、よく考えると標準関数の多くは文字列といえばchar *を期待しているわけです。
取得したデータもANSIコードページだったりするので、UNICODEに変換してやらないとまともに表示することはできません。
 
で、文字列の変換にはMultiByteToWideChar()を使用する必要があるようです。
void ShowMessage(HWND hWnd)
{
    WSADATA     wsaData;
    CString     msg = _T("");

    char        hostname[256];
    _TCHAR *    buf;
    int         len;

    WSAStartup(MAKEWORD(2,2), &wsaData);
    gethostname(hostname, 256);
    WSACleanup();

    len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, hostname, -1, NULL, 0);
    if (len > 0) {
        buf = (_TCHAR *)calloc( len, sizeof(_TCHAR));
        if (buf != NULL) {
            MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, hostname, -1, buf, len);
            
            msg.Format(_T("host=%s"), buf);
            free(buf);
        }
    }
    MessageBox(hWnd, msg, _T("ホスト名"), MB_OK);
}
 
面度くせぇ(笑
 
せっかくATL::CStringで行こうと思ってるのに、char *やら _TCHAR *やらの方が目立ってます。
 
その後 ATL::CStringのヘルプを見ていると CSimpleStringT::GetBufferなるものを発見。
void ShowMessage(HWND hWnd)
{
    WSADATA     wsaData;
    CString     msg = _T("");

    char        hostname[256];
    CString     buf;
    int         len;

    WSAStartup(MAKEWORD(2,2), &wsaData);
    gethostname(hostname, 256);
    WSACleanup();

    len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, hostname, -1, NULL, 0);
    if (len > 0) {
        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, hostname, -1, buf.GetBuffer(len) , len);
        msg.Format(_T("host=%s"), buf);
        buf.ReleaseBuffer();
    }
    MessageBox(hWnd, msg, _T("ホスト名"), MB_OK);
}
 
ちょっとだけスッキリしましたね。
gethostname()に渡す部分もATL::CStringにしてみます。
void ShowMessage(HWND hWnd)
{
    WSADATA     wsaData;
    CString     msg = _T("");

    CString     hostname;
    CString     buf;
    int         len;
    char *      pszHostname;

    WSAStartup(MAKEWORD(2,2), &wsaData);
    pszHostname = (char *)hostname.GetBuffer(256);
    gethostname(pszHostname, 256);
    WSACleanup();

    len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszHostname, -1, NULL, 0);
    if (len > 0) {
        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszHostname, -1, buf.GetBuffer(len) , len);
        msg.Format(_T("host=%s"), buf);
        buf.ReleaseBuffer();
    }
    pszHostname = NULL;
    hostname.ReleaseBuffer();
    MessageBox(hWnd, msg, _T("ホスト名"), MB_OK);
}
 
冗長になっただけのような気もしますが、ANSI->UNICODE変換部分を別関数に持っていけばこれでもいいのかな?
 

0 件のコメント: