CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15
  1. #1
    Join Date
    Apr 2009
    Posts
    21

    ComboBox + LPWSTR

    Hi,

    I have MFC project, with character set is Multibyte. I want to put Unicode string into CComboBox.
    I have done follow code.


    CStringW strWText = L"Quảng Trị";
    nIndex = (int)::SendMessageW(m_cboCustomer.GetSafeHwnd(), CB_ADDSTRING, 0, (LPARAM)((LPCWSTR)strWText));


    But, ComboBox display "Qu?ng Tr?". What wrong with my code ?
    (My project setting must be Multibyte character set)

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: ComboBox + LPWSTR

    Since your project is MBCS the text you send with the CB_ADDSTRING message is also assumed to be MBCS, so it is interpreted as MBCS.
    To put a UNICODE text you have to build your project as UNICODE.

    // Edit:
    Sorry, it was not correct... (I wrote this post too fast to understand the problem....)
    The problem is, however, that in MBCS build controls cannot display symbols not belonging to the currently used code page.
    Last edited by VictorN; January 18th, 2012 at 01:09 PM.
    Victor Nijegorodov

  3. #3
    Join Date
    Oct 2005
    Location
    Minnesota, U.S.A.
    Posts
    680

    Re: ComboBox + LPWSTR

    Convert the UNICODE string to MBCS, then insert it.

    Code:
    size_t size;
    CHAR szString[256];
    wcstombs_s(&size, szString, _countof(szString), (LPCWSTR)strWText, strWText.GetLength());
    //nIndex = (int)::SendMessage(m_cboCustomer.GetSafeHwnd(), CB_ADDSTRING, 0, (LPARAM)szString);
    nIndex = m_cboCustomer.AddString(szString);

  4. #4
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: ComboBox + LPWSTR

    (My project setting must be Multibyte character set)
    No it's not. Your project setting must comply with the project high level design. Accepting characters not fitting in current code page naturally makes a part of HLD and implies a requirement to deal with some sort of Unicode instead. Windows controls are aware of only one flavor, UCS-2. So you either have your whole project Unicode aware, or otherwise, create the particular control by means of CreateWindowW call and never let your MBCS dialog do this for you.
    Best regards,
    Igor

  5. #5
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: ComboBox + LPWSTR

    Once the program has to deal with UNICODE, it's usually much easier to set the project to build for UNICODE.

    Then convert any ANSI data that comes into or goes out of the program (like reading and/or saving a file).

    If you take the straightforward approach of doing the data conversion all in one spot, then you avoid the nightmare of handling conversions all over the place, of using a mix of A and W controls and so on.

    I almost want to take a he!! program that has ANSI/UNICODE conversions throughout, convert it into the approach I've outlined above and write an article about it to show folks how easy it can be.

    I haven't done this because I don't have any he!! programs to use as a starting point.

    If anyone would like to give me a he!! program to use as the starting point for the article, I would be sure to give them full credit as the original author of the program.

  6. #6
    Join Date
    Oct 2005
    Location
    Minnesota, U.S.A.
    Posts
    680

    Re: ComboBox + LPWSTR

    I have written several whitepapers on "Rootbeer" functions (A&W functions) for my work. If anyone is interested, I can dig them up and repost.

    -Erik

  7. #7
    Join Date
    Apr 2009
    Posts
    21

    Re: ComboBox + LPWSTR

    Thank you all,

    My project is extend from old project that set MBCS. If i change it to MBCS then i have to change thousand line codes too.

    [egawtry]
    Code:
    size_t size;
    CHAR szString[256];
    wcstombs_s(&size, szString, _countof(szString), (LPCWSTR)strWText, strWText.GetLength());
    //nIndex = (int)::SendMessage(m_cboCustomer.GetSafeHwnd(), CB_ADDSTRING, 0, (LPARAM)szString);
    nIndex = m_cboCustomer.AddString(szString);

    I tried your code, but szString = "" if strWText = L"Quảng Trị" after use wcstombs_s to convert.

    I have read on MDSN http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx , it said
    Use CBEM_SETUNICODEFORMAT message to sets the UNICODE character format flag for the control. This message enables you to change the character set used by the control at run time rather than having to re-create the control.
    I have change m_cboCustomer to CComboxEx. and use follow line code

    Code:
    ::SendMessage(m_cboCustomer.GetSafeHwnd(), CBEM_SETUNICODEFORMAT, (WPARAM)1L, 0L);
    before

    Code:
    CStringW strWText = L"Quảng Trị";
    nIndex = (int)::SendMessageW(m_cboCustomer.GetSafeHwnd(), CB_ADDSTRING, 0, (LPARAM)((LPCWSTR)strWText));
    but the result is same. ComboBox still display "Qu?ng Tr?"

  8. #8
    Join Date
    Apr 1999
    Posts
    27,449

    Re: ComboBox + LPWSTR

    Quote Originally Posted by pcuong1983 View Post
    Code:
    size_t size;
    CHAR szString[256];
    wcstombs_s(&size, szString, _countof(szString), (LPCWSTR)strWText, strWText.GetLength());
    //nIndex = (int)::SendMessage(m_cboCustomer.GetSafeHwnd(), CB_ADDSTRING, 0, (LPARAM)szString);
    nIndex = m_cboCustomer.AddString(szString);
    I tried your code, but szString = "" if strWText = L"Quảng Trị" after use wcstombs_s to convert.
    Functions that are used by thousands of programmers every day just don't fail for no reason.

    Did you check the return value of wcstombs_s? Please read the "Return Value" section:

    http://msdn.microsoft.com/en-us/libr...=vs.80%29.aspx

    Regards,

    Paul McKenzie

  9. #9
    Join Date
    Apr 2009
    Posts
    21

    Re: ComboBox + LPWSTR

    Quote Originally Posted by Paul McKenzie View Post
    Functions that are used by thousands of programmers every day just don't fail for no reason.

    Did you check the return value of wcstombs_s? Please read the "Return Value" section:

    http://msdn.microsoft.com/en-us/libr...=vs.80%29.aspx

    Regards,

    Paul McKenzie
    wcstombs_s return EILSEQ
    If wcstombs_s encounters a wide character it cannot convert to a multibyte character, it puts 0 in *pReturnValue, sets the destination buffer to an empty string, sets errno to EILSEQ, and returns EILSEQ.
    Here i got from step by step debug:
    /* Actually, there are such wchar_t characters which are > 255,
    * but they can be transformed to a valid single byte char
    * (i.e. a char in the C locale case). Like, for example,
    * alternative digits in unicode like Arabic-Indic U+0660..U+0669.
    * The problem is that WideCharToMultiByte() does not translate those
    * wchar_t unless we pass the correct codepage (1256, Arabic).
    * See bug VSW:192653.
    */
    Thank you!

  10. #10
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: ComboBox + LPWSTR

    Quote Originally Posted by pcuong1983 View Post
    Here i got from step by step debug:
    /* Actually, there are such wchar_t characters which are > 255,
    * but they can be transformed to a valid single byte char
    * (i.e. a char in the C locale case). Like, for example,
    * alternative digits in unicode like Arabic-Indic U+0660..U+0669.
    * The problem is that WideCharToMultiByte() does not translate those
    * wchar_t unless we pass the correct codepage (1256, Arabic).
    * See bug VSW:192653.
    */
    Well, it is exactly what I wrote in my edited post#2 yesterday.
    Victor Nijegorodov

  11. #11
    Join Date
    Apr 2009
    Posts
    21

    Re: ComboBox + LPWSTR

    VictorN

    What about
    Use CBEM_SETUNICODEFORMAT message to sets the UNICODE character format flag for the control. This message enables you to change the character set used by the control at run time rather than having to re-create the control.
    how to use CBEM_SETUNICODEFORMAT and When to use CBEM_SETUNICODEFORMAT ?

  12. #12
    Join Date
    Apr 1999
    Posts
    27,449

    Re: ComboBox + LPWSTR

    Quote Originally Posted by pcuong1983 View Post
    VictorN

    What about


    how to use CBEM_SETUNICODEFORMAT and When to use CBEM_SETUNICODEFORMAT ?
    You have to set the code page correctly. Did you do that, and if so, did that solve the problem?

    Regards,

    Paul McKenzie

  13. #13
    Join Date
    Nov 2003
    Posts
    1,902

    Re: ComboBox + LPWSTR

    >> wcstombs_s return EILSEQ
    For wcstombs() to work on anything other than "C" locale characters (A-Z, a-z, 0-9, etc...), you must call setlocale(LC_CTYPE, "") so that the CRT will convert using the system ANSI codepage (ACP).

    Even then, wcstombs() will fail if it encounters any characters that aren't in the ACP. I don't think that "ả" (U+1EA3) or "ị" (U+1ECB) are in any of the Windows codepages, so wcstombs() will never work on windows for those characters.

    >> strWText = L"Quảng Trị";
    Putting extended characters directly into your source can be dangerous. Anyone who edits/saves that source file will have to save it with a Unicode encoding.

    Code:
    #include <windows.h>
    #include <stdio.h>
    
    HFONT CreateFont(HDC hdc, int pitch, const wchar_t *facename);
    
    const wchar_t *g_wide_string = L"Qu\u1EA3ng Tr\u1ECB";
    
    //------------------------------------------------------------------------------
    
    int main()
    {
        const char *className = "ANSI_MsgLoop_Test";
        WNDCLASSA wincl = {0};
        wincl.hInstance = GetModuleHandle(0);
        wincl.lpszClassName = className;
        wincl.lpfnWndProc = DefWindowProcA;
        wincl.style = CS_DBLCLKS;
        wincl.hIcon = LoadIcon(0, IDI_APPLICATION);
        wincl.hCursor = LoadCursor(0, IDC_ARROW);
        wincl.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
    
        if (!RegisterClassA(&wincl))
            return 0;
    
        HWND parent;
        parent = CreateWindowA(className, "ANSI Msg Loop", 
                               WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                               CW_USEDEFAULT, CW_USEDEFAULT,
                               300, 100, HWND_DESKTOP, 0, 
                               GetModuleHandle(0), 0);
        if (!parent)
            return 0;
    
        HWND combo;
        combo = CreateWindowW(L"ComboBox", L"", 
                              WS_CHILD | WS_VISIBLE | WS_DISABLED | CBS_DROPDOWNLIST,
                              10, 10,  260, 30,
                              parent, (HMENU)1, 
                              GetModuleHandle(0), 0);
        if (!combo)
            return 0;
    
        // give it a nice font
        HDC hdc = GetDC(combo);
        HFONT hfont = CreateFont(hdc, 12, L"Times New Roman");
        ReleaseDC(combo, hdc);
        SendMessageA(combo, WM_SETFONT, (WPARAM)hfont, 0); 
    
        // add string and select it
        SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)g_wide_string);
        SendMessageA(combo, CB_SETCURSEL, 0, 0);
        
        MSG msg;
        BOOL bRet;
        for (;;)
        {
            bRet = GetMessageA(&msg, parent, 0, 0);
            if ((bRet == 0) || (bRet == -1))
                break;
    
            if (!IsWindow(parent) || !IsDialogMessageA(parent, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }//if
        }//while
    
        DeleteObject(hfont);
        return 0;
    }//main
    
    //------------------------------------------------------------------------------
    
    HFONT CreateFont(HDC hdc, int pitch, const wchar_t *facename)
    {
        LOGFONTW lf = {0};
        wcscpy_s(lf.lfFaceName, sizeof(lf.lfFaceName)/sizeof(*lf.lfFaceName), 
                 facename);
        lf.lfHeight = -MulDiv(pitch, GetDeviceCaps(hdc, LOGPIXELSY), 72);
        lf.lfWeight = FW_NORMAL;
        lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
        lf.lfClipPrecision = CLIP_STROKE_PRECIS;
        lf.lfQuality = CLEARTYPE_QUALITY;
    
        return CreateFontIndirectW(&lf);
    }//CreateFont
    Notes:
    - No extended characters in source (save source as Unicode otherwise)
    - ComboBox created with CreateWindowW()
    - Created a nice font that should have support for those Unicode characters (was getting "best fit" characters without it)

    gg

  14. #14
    Join Date
    Apr 1999
    Posts
    27,449

    Re: ComboBox + LPWSTR

    Very good points, Codeplug. Especially the point of not having strings with embedded foreign characters in the source, and instead use the escape sequences in the string.

    Regards,

    Paul McKenzie

  15. #15
    Join Date
    Apr 2009
    Posts
    21

    Re: ComboBox + LPWSTR

    I got it, Thank you CodePlug. I also thank Paul McKenzie

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured