MFC dialogs caption fails with Unicode - c++

I am trying to use Win32 functions like MessageBox or GetOpenFileName in Unicode mode but the caption always shows ??????????????. I have resources in different languages like Chinese or Hindi and all works well except for standard dialog functions.
I do use the W version, and I have tried it in both MBCS and Unicode linked libraries with no success. I can build my own MessageBoxW, but can't afford rewriting file or folder pick functions.
The typical call is as simple as:
Note the title is conveniently defined in Unicode with some Hindi characters. This can be seen with the debugger on the ofn structure:
But the dialog caption does not show the Hindi string
The dialog behind shows the right strings, in Hindi and Chinese besides latin characters, and it is built with the old Win32 dialog calls in a MBCS linked DLL. See though the comment below.
The front dialog is built in Unicode MFC linked DLL.
The odd thing is that normal dialogs built with Win32 or with MFC fail the same way with SetWindowTextW on the dialog handle. SetWindowTextW works fine on dialog items, and SetDlgItemTextW, works fine too. It is the dialog caption that does not work.
I found, though, a workaround: Instead of SetWindowTextW I use DefWindowProcW.
Hasn't anyone stumbled into this before ???

Related

C++ GUI in MFC - Pagination widget

I'm writing C++ code, targeting WinCE 6.0 device and I'm having hard time finalizing GUI for my app. VS 2005 window builder which I have to be using does not seem to simplify this task and I cant find documentation which will throw some light on API, hopefully somebody here can.
I need to be dynamically writing on widget page user is on / total number of pages. I expect CTEXT is correct widget to use
CTEXT IDC_PG, 168,183,63,63
However I dont seem to find correct way how to print on CTEXT (or any other suitable widget) Thanks in advance for any good advices.
If I'm understanding the question correctly, you want to display a bit of text on your UI of the form "Page x of n". A static text control (like CTEXT) is appropriate for this.
To set the text programmatically, you can call SetWindowText, but since this is on a dialog, it's probably easier to call SetDlgItemText.
From your example, the identifier is IDC_PG, and it should correspond to a numeric constant that is unique among all the controls on the dialog. Assuming you have an MFC object for the dialog (which I'll assume is myDialog) and a pointer to the zero-terminated text you want it to display (which I'll assume is szPageText), your call would look like:
myDialog.SetDlgItemText(IDC_PG, szPageText);
If you just have a handle to the dialog, your call would look like this:
SetDlgItemText(hDlg, IDC_PG, szPageText);
Since this is older code, it might be compiled for MBCS (often called ANSI in Windows documentation) or UTF-16 (often called Unicode or "wide" strings in MSDN), so you probably want to use the TCHAR and related macros to make sure it works either way.
TCHAR szPageText[64] = TEXT("");
wsprintf(szPageText, TEXT("Page %d of %d"), currentPage, totalPages);
myDialog.SetDlgItemText(IDC_PG, szPageText);
In more modern code, you'd probably explicitly use the wide versions of the APIs:
WCHAR szPageText[64] = L"";
::wsprintfW(szPageText, L"Page %d of %d", currentPage, totalPages);
myDialog.SetDlgItemTextW(IDC_PG, szPageText);

How can I change the language in AfxMessageBox?

I have an MFC app that uses AfxMessageBox to display message boxes. The app itself lets an end-user to change the user interface language. On the inside it does so by loading resources using LCIDs (or FindResourceEx API.) My issue is that I can't seem to make AfxMessageBox to take LCID to change the language for OK, Cancel buttons, etc. This also affects File and Folder Open dialog windows.
Any ideas how to do this?
PS. This approach must work under Windows XP and up.
According to this SO article, there are no standard functions for this, there's a link to a CodeProject article "Localizing System MessageBox" with source code for a DLL (it's in c# but seems simple enough to be rewritten in C++) which uses Windows Hook so that you can supply your own text for the MessageBox buttons; there's even a suggestion for sizing buttons to the text in the discussion part of the same article.

Could not display other unicode Eastern Asian Lanuage on Windows DialogBox

I use the DialogBox API to display a dialog at my application. In the WM_INITDIALOG message handling at the DLGPROC procedure call back, I could see the text string is correct Unicode at debugger and SetDlgItemText is used to set the text on Rich Edit control in the dialog. However when I tried to get the text from dialog by using GetDlgItemText API , it was all question marks for those characters.
My project is compiled as Unicode. And I also used the spy++ and it shows the Windows Proc is Unicode.
I am testing Chinese on Windows 7 with English Locale, so I also installed the Chinese Language Pack for my machine and it doesn't help either.
I could not explain what I see here. It would be appreciated if any one could shed some lights on this or how to debug further.
It turns out that it is due to the RichEdit control there. If I just use a text box, the Chinese characters would be displayed correctly along with other English characters. So after doing some reading, particular this one, I gave some tries and I got it working. So basically I should not use SetDlgItemText, instead I should use the following code (where m_strDisplay is the text to display on rich edit):
::SendMessage(hWndText, EM_AUTOURLDETECT, TRUE, NULL);
SETTEXTEX TextInfo = {0};
TextInfo.flags = ST_DEFAULT|SF_UNICODE;
TextInfo.codepage = 1200;
SendMessage(hWndText, EM_SETTEXTEX, (WPARAM)&TextInfo, (LPARAM)(LPCTSTR)m_strDisplay);
to set the text on RichEdit control.

Unicode text appears as question marks in edit box, even though I use SetWindowTextW()

I have a problem with unicode filenames appearing as question marks in my edit boxes.
When I paste unicode characters in an edit box, for example Arabic or Thai, they show correctly, but after I run this code, they become question marks. How come?
WCHAR buf[100];
GetWindowTextW(hWndEditBox, buf, 100);
SetWindowTextW(hWndEditBox, buf);
Another thing - the project is ANSI (we have code that can't be ported so the entire project stays ANSI), i.e. _UNICODE macro is undefined, but I explicitly use the Unicode versions of the filenames.
The GetWindowText function actually sends a WM_GETTEXT message to the window (hWndEditBox). Since you're using the *A functions rather than the *W function (specifically CreateWindowExA in this case, I think) your message loop will be converting from wide characters to multi-byte characters using some locale.
Your only solution here seems to be changing the entire window setup - if your code that requires ANSI is not related to UI this should be possible. Alternatively, you may be able to replace the edit box with rich edit boxes, that provide extra messages (such as streaming, for example).
You may want to check whether it is the GetWindowTextW call or the SetWindowTextW call that is doing the bad conversion - if GetWindowTextW works correctly you may be able to convert to multibyte using the correct locale before you set it.
Finally, you can try adjusting the thread's code page before reading the text, though this may cause all sorts of other issues. The usual advice is to use Unicode.
Sources: GetWindowText and this comment from Raymond Chen on his blog.
A useful answer to address SetWindowTextW()is given in https://stackoverflow.com/a/11515400/1190077 :
intercept the resulting WM_SETTEXT message and re-route it to DefWindowProcW() instead of DefWindowProc().

Piecewise conversion of an MFC app to Unicode/MBCS

I have a large MFC application that I am extending to allow for multi-lingual input. At the moment I need to allow the user to enter Unicode data in edit boxes on a single dialog.
Is there a way to do this without turning UNICODE or MBCS on for the entire application? I only need a small part of the application converted at the moment. Is it possible to do this piecewise, and if so, how?
Clarification: I could use ::GetWindowTextW() to get Unicode information out of the window. I am trying to figure out how to allow the user to enter Unicode text in the window. Currently, characters the user types outside of the windows-1252 codepage show up as '?'. Is there a way to fix this?
To allow CEdit to show Unicode characters you should create it with CreateWindowW function. I've just tested it in ANSI MFC program.
// allows Unicode characters
CreateWindowW( L"EDIT", L"", WS_CHILD|WS_VISIBLE, 10, 10, 50, 20, GetSafeHwnd(), 0, 0, 0 );
// shows Unicode characters as ?
CreateWindow( "EDIT", "", WS_CHILD|WS_VISIBLE, 10, 10, 50, 20, GetSafeHwnd(), 0, 0, 0 );
You could create all edit boxes manually in OnInitDialog function of dialog box. And later subclass them to custom CMyEdit class with Unicode support.
Can you replace these edit boxes with rich edit controls? Then you could enter international characters even in a non-Unicode build; internally, they would be rtf-encoded, but then when you stream the text out from the control, you can use the SF_UNICODE format to get the Unicode representation.
This PowerPoint slideshow may be of interest to you -- it's a bit old (2000) but it talks about converting a program to mixed ANSI/Unicode.
Case Study: Porting an MFC Application to Unicode
Just a thought - you could try turning on UNICODE for your build and use ANSI calls where you need to (eg. CStringA).
(I understand that this may not be an option for you, but thought it worth pointing out that you could tackle this problem the other way round)