0
votes

We have an old MFC app that we localized to multiple languages. We have a language menu that allows the user to select the language (restart of app is required). When an RTL language such as Arabic is selected, the main window frame, and dialogs created in code via calls like AfxMessageBox, remain in LTR; even when run on a system that runs windows in Arabic. I want to set the WS_EX_LAYOUTRTL bit on all windows we create based on the kind of resource that is loaded. Is there a way to use the handle retrieved from AfxGetResourceHandle to query if the resources are RTL? If not, is there another way to do this?

EDIT:

So just to clarify, my problem is that my main window frame, and all dynamic dialogs remains in LTR layout even when the loaded resource dll is RTL. I load the resource dll first thing in my app initinstance function based on a three letter code stored in the registry which the user sets by selecting a language from the language menu drop down. All my resources from the dll work fine. I only have an issue on the main frame, and the generic dialogs that we load such as message boxes when an error occurs. Perhaps this code snippet can help explain what I'm looking for:

BOOL CWinGFMainFrame::PreCreateWindow( CREATESTRUCT& cs )
{
    HINSTANCE hInst = AfxGetResourceHandle ();
    if( hInst )
    {
        //Add some logic here to determine if the loaded resource dll is RTL
        cs.dwExStyle |= WS_EX_RTLREADING | WS_EX_LAYOUTRTL;
    }

    if( !CFrameWnd::PreCreateWindow( cs ) )
    {
        return FALSE;
    }

    cs.style = WS_OVERLAPPED  | WS_CAPTION  | FWS_ADDTOTITLE
             | WS_THICKFRAME  | WS_SYSMENU  | WS_MINIMIZEBOX 
             | WS_MAXIMIZEBOX | WS_MAXIMIZE;

    return TRUE;
}

If not this method, then is there any function that I can use to determine the reading order based on the locale info like the three letter country code, or the language ID? On a windows7 build I could do the following, but we need to support windows xp :(.

int nResult = GetLocaleInfo ( lcid, LOCALE_IREADINGLAYOUT, NULL, 0 );
TCHAR* szReadingLayout = new TCHAR[ nResult ];
nResult = GetLocaleInfo ( lcid, LOCALE_IREADINGLAYOUT, szReadingLayout, nResult );

EDIT2:

Still trying to get this going. I have the following code which I think should work, but it doesn't. I know the dialog that I'm getting the handle to has layoutrtl set to true, and it has three items. When the following code executes the dwextendstyle is 0, and the cdit is also 0, but it should be 3. Does anyone see what I am doing wrong in this code? I did verify that AfxGetResourceHandle is returning a handle to my Arabic resources.

HINSTANCE hInst = AfxGetResourceHandle ();
if( hInst )
{
    //Make sure I'm looking at the right file.
    char szPath[ MAX_PATH ];
    DWORD result = ::GetModuleFileName( hInst, szPath, MAX_PATH );
    if( result )
    {
        ATLTRACE( "Setting resource handle to %s\n", szPath );
    }

    // Locate the dialog box resource
    HRSRC hRes = FindResource( hInst, MAKEINTRESOURCE( IDD_ABOUTBOX ), RT_DIALOG );
    if ( hRes )
    {
        // Load the dialog box
        HGLOBAL hResLoad = LoadResource( hInst, hRes );
        if ( hResLoad )
        {
            // Get a real pointer to the resource
            LPVOID lpResLock = LockResource( hResLoad );
            if (lpResLock )
            {
                // Cast the raw bits to something useful
                LPDLGTEMPLATE pDlgTemplate = (LPDLGTEMPLATE)lpResLock;
                if( pDlgTemplate )
                {
                    if( pDlgTemplate->dwExtendedStyle & WS_EX_RTLREADING || 
                        pDlgTemplate->dwExtendedStyle & WS_EX_LAYOUTRTL )
                    {
                        cs.dwExStyle |= WS_EX_RTLREADING | WS_EX_LAYOUTRTL;
                    }
                }
            }
        }
    }
}

In my resource file the about dialog is defined like this, but I can't seem to get my hands on the EXSTYLE inside the code...

100 DIALOGEX 0, 0, 257, 83, 0
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_DLGFRAME
EXSTYLE WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_LAYOUTRTL
CAPTION "حول جهاز التدريب على طلب المساندة في إطلاق النيران"
LANGUAGE LANG_ARABIC, SUBLANG_ARABICNEUTRAL
FONT 8, "Tahoma"
{
     ICON   128, -1, 7, 8, 20, 20
     DEFPUSHBUTTON   "موافق", 1, 178, 7, 50, 14, WS_GROUP, WS_EX_LEFT |  WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_LAYOUTRTL
     CTEXT   "معلومات عن الإصدار", 1692, 44, 10, 130, 48, SS_NOPREFIX, WS_EX_LEFT |  WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_LAYOUTRTL
}

Thanks.

1
For AfxMessageBox, you need MB_RTLREADING. What do you mean by querying if resources are RTL ?FKDev
Hi FKDev,When the app starts up, if a language other than English was chosen, it loads a resource dll that has been localized. Three of the languages we are adding support for are Arabic (Bahrain), Dari, and Pashto. These are RTL languages. I'm looking for a way to discover if the loaded resource dll contains resourced that were localized to an RTL language. I'm going this route because it would be easier if I can just call AfxGetResourceHandle and use the returned handle to see if the resources in it are localized for an RTL language.jdwieber
The dialog resource should have the WS_EX_LAYOUTRTL in the RTL DLL.FKDev
Yes, the controls in the resource dll are correctly displaying in RTL mode. However, my problem is that the code generated dialogs are defaulting to LTR. Thus, I want to look at the loaded resources, determine if they are RTL, and set the appropriate flags when I create dialogs from code. If I just blindly set everything to RTL then the LTR customers will be annoyed. I need a way to look at the contents of the resourse dll in my PreCreateWindow functions and add WS_EX_RTLREADING | WS_EX_LAYOUTRTL to the CREATESTRUCT when appropriate. Likewise for when I create message boxes, etc.jdwieber

1 Answers

0
votes

Well, I'm not happy about it, but I had to resort to some bit twiddling to move on. Here is what I have that works. I tested with English and Arabic. Hopefully it will help someone else. cheers.

HINSTANCE hInst = AfxGetResourceHandle ();
if( hInst )
{
    // Locate the dialog box resource
    HRSRC hRes = FindResource( hInst, MAKEINTRESOURCE( IDD_ABOUTBOX ), RT_DIALOG );
    if ( hRes )
    {
        // Load the dialog box
        HGLOBAL hResLoad = LoadResource( hInst, hRes );
        if ( hResLoad )
        {
            // Get a real pointer to the resource
            LPVOID lpResLock = LockResource( hResLoad );
            if ( lpResLock )
            {
                // Do some raw bit manipulations
                BYTE* pRaw = (BYTE*)lpResLock;
                WORD signature = *(WORD*)( pRaw + sizeof( WORD ) );
                bool isDialogEx = ( signature == 0xFFFF );
                if( isDialogEx )
                {
                    size_t offset = sizeof( WORD ) + sizeof( WORD ) + sizeof( DWORD );
                    DWORD exStyle = *(DWORD*)( pRaw + offset );
                    if( exStyle & WS_EX_RTLREADING || exStyle & WS_EX_LAYOUTRTL )
                    {
                        cs.dwExStyle |= WS_EX_RTLREADING | WS_EX_LAYOUTRTL;
                    }
                }
            }
        }
    }
}