User ID:
Password:
Remember Me:
Forgot Password?
Not a member?
Click here for more information and to register.

    How to Display UNICODE Characters in a CListCtrl or a CEdit



    The question: How can I display special characters (such as ∞ and Φ ...) in a list control/edit box has come up a few times in the Codeguru Visual C++ Programming forum. There was a particular post that made me think of a simple way to display those characters. That being said I, built a small, dialog-based application that illustrates this in a very simple manner (or this is what I like to think).

    These are the steps to follow to have the same behavior reproduced in your projects:

    1. Create a file (using Notepad) with all the special characters you need to display. For the character ∞, for example, just press "Alt" and 236 on the numpad. For the character Φ, press "Alt" and 237, and so on. For a list of all the special characters, please see an ASCII table. All of them are listed under the "Extended ASCII Codes" section. Give this file a name (I named it Unicode.txt, but it can be whatever you think is suitable) and save it with "Unicode" encoding (File, Save As.). See the screenshot below for the encoding type:
    2. Create a dialog-based application with the following remarks:
      1. Make sure you have added _UNICODE in: Project->Settings->C/C++->General->Preprocessor definitions.
      2. Add wWinMainCRTStartup in: Project->Settings->Link->Category: Output->Entry-point symbol.
      3. Make sure that these settings are in the "Release" version as well. The pictures below show only the "Debug" build settings!
      4. For both these options, please see the following screenshots:


        (Full Size Image)


        (Full Size Image)

      5. Add a CListCtrl REPORT style and a CEdit box to your dialog using resource editor and, with the help of the class wizard, add member variables of type CListCtrl/CEdit to the newly added controls. Name the variable for the CListCtrl m_list and the variable for the CEdit m_edit. Add a protected member variable of type CFont to your dialog. Name this variable CFont m_font.
      6. Now, create two protected functions, one called SetControlsFont (to create and apply the UNICODE font to the controls) and another one called SetControlsText (to read the UNICODE characters from the file and display these characters into the created controls).
      7. The function SetControlsFont creates and applies the UNICODE font to the controls.
      8. void CUnicodeDlg::SetControlsFont()
        {
           // create UNICODE Font and apply it to the controls.
           CDC *pDC = GetDC();
        
           // create UNICODE font
           LOGFONT lf;
           memset(&lf, 0, sizeof(lf));
           lf.lfHeight =
              MulDiv(20, ::GetDeviceCaps(pDC->m_hDC,
                     LOGPIXELSY), 72);
           lf.lfWeight = FW_NORMAL;
           lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
           wcscpy(lf.lfFaceName, _T("Lucida Sans Unicode"));
           m_font.CreateFontIndirect(&lf);
        
           // apply the font to the controls
           m_list.SetFont(&m_font);
           m_edit.SetFont(&m_font);
        
           // release the device context.
           ReleaseDC(pDC);
        }
        
      9. The function SetControlsText reads the characters from the file and sets the text into the controls. The usage of the function is pretty basic: the first argument is the filename, the second and the third are the controls where to display the text. In your case, m_list and m_edit. For the usage of this function, please see the example shown below in OnInitDialog.
      10. void CUnicodeDlg::SetControlsText(LPCTSTR lpszFileName,
             CListCtrl &list, CEdit &edit)
        {
        
           CFile file;
        
           // open the file and read the Unicode characters
           // input file has to be encoded with UTF-16 little
           // endian
           // if the file was saved as described above this
           // condition is already fulfilled
           TRY
           {
              file.Open(lpszFileName, CFile::modeRead);
              CString strText;
              UINT nRes = file.Read(strText.GetBuffer(1024),
                                    1024);
              strText.ReleaseBuffer(nRes / 2);
        
              // test to see whether the file is UNICODE
              if(strText.GetAt(0) == 0xFEFF)
              {
                 // insert a column in the list control
                 list.InsertColumn(0, _T("Unicode characters"),
                                   LVCFMT_LEFT, 300);
        
                 // display characters in the list control
                 list.InsertItem(0, strText);
        
                 // display characters in the edit control
                 edit.SetWindowText(strText); 
        
                 // close file
                 file.Close();
              }
              else
                 AfxMessageBox(_T("The file is not UNICODE."));
           }
           CATCH(CFileException, e)
           {
              e->ReportError();
           }
           END_CATCH
        }
        
      11. All you have to do now is call these two functions from your CDialog's OnInitDialog and you're all set:
      12. BOOL CUnicodeDlg::OnInitDialog()
        {
           CDialog::OnInitDialog();
        
           // Add "About..." menu item to system menu.
        
           // IDM_ABOUTBOX must be in the system command range.
           ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
           ASSERT(IDM_ABOUTBOX < 0xF000);
        
           CMenu* pSysMenu = GetSystemMenu(FALSE);
           if (pSysMenu != NULL)
           {
              CString strAboutMenu;
              strAboutMenu.LoadString(IDS_ABOUTBOX);
              if (!strAboutMenu.IsEmpty())
              {
                 pSysMenu->AppendMenu(MF_SEPARATOR);
                 pSysMenu->AppendMenu(MF_STRING,
                    IDM_ABOUTBOX, strAboutMenu);
              }
           }
        
           // Set the icon for this dialog. The framework does
           // this automatically when the application's main
           // window is not a dialog.
           SetIcon(m_hIcon, TRUE);     // Set big icon
           SetIcon(m_hIcon, FALSE);    // Set small icon
        
           // TODO: Add extra initialization here
        
           // set controls font
           SetControlsFont();
        
           // fill the controls
           SetControlsText(_T("unicode.txt"), m_list, m_edit);
        
           return TRUE;    // return TRUE unless you set the
                           // focus to a control
        }
        

    This is an article where you can find a more detailed discussion about UTF-16 and UNICODE. The article also shows a class that deals with reading/writing from/to a UNICODE file. The credits for this article go to Jeffrey Walton.

    That's it. Pretty easy, right? Compile and run it. Enjoy!

    Downloads

  • unicode.zip

  • IT Offers


    Top Authors