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)
Related
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 ???
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);
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.
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().
I have written a DLL which exports a function that creates a window using RegisterClassExW and CreateWindowExW. Every message is retrieved via
GetMessageW(&msg, wnd_handle, 0, 0);
TranslateMessage(&msg);
DispatchMessageW(&msg);
Also there is a program which loads the DLL and calls the function.
Despite the Unicode window creation method, the wParam in the WM_CHAR message always contains ASCII characters, even if I type some non-ASCII symbols or use Alt+(code). Instead of UTF-16, the wParam contains some ASCII character between 'A' and 'z'.
The WndProc is a static function inside the DLL.
The problem doesn't occur when all the window-related code is inside one program.
Is there a way to always have Unicode WM_CHAR messages inside the DLL's window?
the problem was in the message retrieval process. I used GetMessage() with the handle of my window instead of just 0, GetMessageW(&msg, wnd_handle, 0, 0) instead of GetMessageW(&msg, 0, 0, 0). In this way, the WM_INPUTLANGCHANGEREQUEST messages were swallowed and the locale remained English.
Your approach seems like it should work.
Is it possible that you're calling the ANSI DefWindowProc instead of the wide version? That would translate a WM_UNICHAR into ANSI WM_CHAR messages. Maybe that would explain what you're seeing.
As an experiment, I'd handle the WM_UNICHAR messages directly, and see what the data looks like at that point.
I am not 100% sure, but it might help:
Take a look to the settings of the project where you implement the code that calls the DLL functions. Make sure that the character set is UNICODE as well, and not multibyte:
(go to Project Properties, then to General section, and put Character Set option to "Use Unicode Character Set"). I was assuming that you're using Visual Studio 2003 or later.