How to Enumerate Code Pages and Locales

MLang provides two enumeration objects that can be used to retrieve the code pages and locales that are recognized by the system from the MIME database.

To use this functionality to enable end users to invoke their preference:

  1. Make sure the Component Object Library has been initialized.

    Before you can use any of the functionality provided by MLang, you must first initialize the Component Object Library through a call to CoInitialize. Every call to CoInitialize must be accompanied by a call to CoUninitialize when the application terminates. CoUninitialize ensures that the application does not quit until it has received all of its pending messages.

  2. Obtain a pointer to an IMultiLanguage interface.

    If no MultiLanguage object exists, this can be accomplished through a call to CoCreateInstance, using CLSID_CMultiLanguage and IID_IMultiLanguage for the first and fourth parameters, respectively. If a MultiLanguage object already exists, this can be accomplished by calling QueryInterface through the current MultiLanguage object interface.

  3. Obtain an interface to an enumerator object through a call to the IMultiLanguage::EnumCodePages or IMultiLanguage::EnumRfc1766 method.

    If you are enumerating code pages, you need to decide which of the MIMECONTF constants you want to use as the flag for the call. These constants specify the uses of a code page and can be used to tailor the list of code pages returned to suit your needs.

  4. Call the Next method of the enumeration interface you have obtained.

    This method retrieves an array of MIMECPINFO or RFC1766INFO structures, depending on whether you are enumerating code pages or locales, respectively. You must allocate memory for these arrays by using the task allocator. The following code sample demonstrates how to do this for code pages. It should be noted, however, that there is no function for locales that corresponds to IMultiLanguage::GetNumberOfCodePageInfo.

    // IMultiLanguage *pMultiLanguage;
    // IEnumCodePage *pEnumCodePage;
    
    UINT cnum = 0;
    PMIMECPINFO pcpInfo;
    long ccpInfo;
    
    pMultiLanguage->GetNumberOfCodePageInfo(&cnum);
    
    pcpInfo = (PMIMECPINFO)CoTaskMemAlloc(sizeof(MIMECPINFO)*cnum);
    
    hr = pEnumCodePage->Next(cnum, pcpInfo, &ccpInfo);
    
    if(SUCCEEDED)hr))
    {
        // Use the MIMECPINFO structures returned to allow the
        // user to select his or her own preferences.
    }
    
  5. Dynamically add the code pages or locales to a menu or list box.

    The MIMECPINFO and RFC1766INFO structures contain a description of the code page or locale in a wide-character string. The MLang Conversion object can be used to convert these strings to the proper code page for output (in this case, 1252). The following code shows how to add the code pages in an array of MIMECPINFO structures to a dynamically created pop-up menu.

    // IMultiLanguage *pMultiLanguage;
    // pcpInfo - pointer to an array of MIMECPINFO structures.
    // ccpInfo - number of structures in pcpInfo.
    
    HMENU hmenu, hsubmenu;
    static HMENU hpopup;
    IMLangConvertCharset* pMLCC;
    char pszDescription[100];
    UINT SrcLen;
    UINT DstLen;
    
    hmenu = GetMenu(hwnd);
    hsubmenu = GetSubMenu(hmenu, 0);
    hpopup = CreatePopupMenu();
    
    pMultiLanguage->CreateConvertCharset(1200, 1252, 0, &pMLCC);
    
    for(int i = 0; i < ccpInfo; i++)
    {
        DstLen = 99;
        size_t cchMax = MAX_MIMECP_NAME;
        size_t cchLength;
        HRESULT hr = StringCchLengthW(pcpInfo[i].wszDescription, cchMax, &cchLength);
    
        if(SUCCEEDED(hr))
        {
            SrcLen = cchLength;
    
            pMLCC->DoConversionFromUnicode(pcpInfo[i].wszDescription,
               &SrcLen, pszDescription, &DstLen);
            pszDescription[DstLen] = '\0';
    
            AppendMenu(hpopup, MF_ENABLED, IDM_CP + i, pszDescription);
         }
         else
         {
            //  TODO: Add error handling code here.
         }
    }
    
    AppendMenu(hsubmenu, MF_POPUP, UINT (hpopup), "&Code Pages");
    
  6. Remember to reallocate the memory for the arrays, release the interfaces, and uninitialize the Component Object Library before your program terminates.

    The memory for the arrays must be reallocated by using the task allocator. Although the IEnumCodePage, IEnumRfc1766, and IMLangConvertCharset interfaces are obtained through the IMultiLanguage interface, all must be released individually.

Reference

Code Page Enumeration

Locale Enumeration

Conceptual

MLang