MFC query reading order (RTL) from loaded dll resource?

924 Views Asked by At

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

There are 1 best solutions below

0
On BEST ANSWER

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;
                    }
                }
            }
        }
    }
}