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:

    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

Comments

  • update for multiplefont charcters display

    Posted by ArtiGujare on 04/12/2006 07:15am

    Hi, A very nice article. I was actually looking out for similar CEdit class but which supports multiple fonts. Something like MS Word Symbol table. CEdit should support this test case. Select font Lucida ...Unicode -> choose subset - latin extended -> dbl clk to display this character (call it C1F1)-> choose another font say (Tunga -> Kannada) -> dbl clk to display this character (call it C2F2). Result: CEdit should display both the characters C1F1 C2F2 Is this possible? I did have a look in the net but havent got any success in this regards, Any help would be great. Cheers! -rt

    • Re: update for multiplefont charcters display

      Posted by Alin on 06/02/2006 12:43pm

      i don't know if that's possible, but as soon as i have some time i will look into it.

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: September 19, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT In response to the rising number of data breaches and the regulatory and legal impact that can occur as a result of these incidents, leading analysts at Forrester Research have developed five important design principles that will help security professionals reduce their attack surface and mitigate vulnerabilities. Check out this upcoming eSeminar and join Chris Sherman of Forrester Research to learn how to deal with the influx of new device …

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds