-
January 18th, 2012, 10:40 AM
#1
ComboBox + LPWSTR
Hi,
I have MFC project, with character set is Multibyte. I want to put Unicode string into CComboBox.
I have done follow code.
CStringW strWText = L"Quảng Trị";
nIndex = (int)::SendMessageW(m_cboCustomer.GetSafeHwnd(), CB_ADDSTRING, 0, (LPARAM)((LPCWSTR)strWText));
But, ComboBox display "Qu?ng Tr?". What wrong with my code ?
(My project setting must be Multibyte character set)
-
January 18th, 2012, 10:50 AM
#2
Re: ComboBox + LPWSTR
Since your project is MBCS the text you send with the CB_ADDSTRING message is also assumed to be MBCS, so it is interpreted as MBCS.
To put a UNICODE text you have to build your project as UNICODE.
// Edit:
Sorry, it was not correct... (I wrote this post too fast to understand the problem....)
The problem is, however, that in MBCS build controls cannot display symbols not belonging to the currently used code page.
Last edited by VictorN; January 18th, 2012 at 01:09 PM.
Victor Nijegorodov
-
January 18th, 2012, 12:55 PM
#3
Re: ComboBox + LPWSTR
Convert the UNICODE string to MBCS, then insert it.
Code:
size_t size;
CHAR szString[256];
wcstombs_s(&size, szString, _countof(szString), (LPCWSTR)strWText, strWText.GetLength());
//nIndex = (int)::SendMessage(m_cboCustomer.GetSafeHwnd(), CB_ADDSTRING, 0, (LPARAM)szString);
nIndex = m_cboCustomer.AddString(szString);
-
January 18th, 2012, 02:55 PM
#4
Re: ComboBox + LPWSTR
(My project setting must be Multibyte character set)
No it's not. Your project setting must comply with the project high level design. Accepting characters not fitting in current code page naturally makes a part of HLD and implies a requirement to deal with some sort of Unicode instead. Windows controls are aware of only one flavor, UCS-2. So you either have your whole project Unicode aware, or otherwise, create the particular control by means of CreateWindowW call and never let your MBCS dialog do this for you.
Best regards,
Igor
-
January 18th, 2012, 03:55 PM
#5
Re: ComboBox + LPWSTR
Once the program has to deal with UNICODE, it's usually much easier to set the project to build for UNICODE.
Then convert any ANSI data that comes into or goes out of the program (like reading and/or saving a file).
If you take the straightforward approach of doing the data conversion all in one spot, then you avoid the nightmare of handling conversions all over the place, of using a mix of A and W controls and so on.
I almost want to take a he!! program that has ANSI/UNICODE conversions throughout, convert it into the approach I've outlined above and write an article about it to show folks how easy it can be.
I haven't done this because I don't have any he!! programs to use as a starting point.
If anyone would like to give me a he!! program to use as the starting point for the article, I would be sure to give them full credit as the original author of the program.
-
January 18th, 2012, 06:53 PM
#6
Re: ComboBox + LPWSTR
I have written several whitepapers on "Rootbeer" functions (A&W functions) for my work. If anyone is interested, I can dig them up and repost.
-Erik
-
January 18th, 2012, 09:16 PM
#7
Re: ComboBox + LPWSTR
Thank you all,
My project is extend from old project that set MBCS. If i change it to MBCS then i have to change thousand line codes too.
[egawtry]
Code:
size_t size;
CHAR szString[256];
wcstombs_s(&size, szString, _countof(szString), (LPCWSTR)strWText, strWText.GetLength());
//nIndex = (int)::SendMessage(m_cboCustomer.GetSafeHwnd(), CB_ADDSTRING, 0, (LPARAM)szString);
nIndex = m_cboCustomer.AddString(szString);
I tried your code, but szString = "" if strWText = L"Quảng Trị" after use wcstombs_s to convert.
I have read on MDSN http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx , it said
Use CBEM_SETUNICODEFORMAT message to sets the UNICODE character format flag for the control. This message enables you to change the character set used by the control at run time rather than having to re-create the control.
I have change m_cboCustomer to CComboxEx. and use follow line code
Code:
::SendMessage(m_cboCustomer.GetSafeHwnd(), CBEM_SETUNICODEFORMAT, (WPARAM)1L, 0L);
before
Code:
CStringW strWText = L"Quảng Trị";
nIndex = (int)::SendMessageW(m_cboCustomer.GetSafeHwnd(), CB_ADDSTRING, 0, (LPARAM)((LPCWSTR)strWText));
but the result is same. ComboBox still display "Qu?ng Tr?"
-
January 18th, 2012, 10:26 PM
#8
Re: ComboBox + LPWSTR
Originally Posted by pcuong1983
Code:
size_t size;
CHAR szString[256];
wcstombs_s(&size, szString, _countof(szString), (LPCWSTR)strWText, strWText.GetLength());
//nIndex = (int)::SendMessage(m_cboCustomer.GetSafeHwnd(), CB_ADDSTRING, 0, (LPARAM)szString);
nIndex = m_cboCustomer.AddString(szString);
I tried your code, but szString = "" if strWText = L"Quảng Trị" after use wcstombs_s to convert.
Functions that are used by thousands of programmers every day just don't fail for no reason.
Did you check the return value of wcstombs_s? Please read the "Return Value" section:
http://msdn.microsoft.com/en-us/libr...=vs.80%29.aspx
Regards,
Paul McKenzie
-
January 18th, 2012, 11:05 PM
#9
Re: ComboBox + LPWSTR
Originally Posted by Paul McKenzie
wcstombs_s return EILSEQ
If wcstombs_s encounters a wide character it cannot convert to a multibyte character, it puts 0 in *pReturnValue, sets the destination buffer to an empty string, sets errno to EILSEQ, and returns EILSEQ.
Here i got from step by step debug:
/* Actually, there are such wchar_t characters which are > 255,
* but they can be transformed to a valid single byte char
* (i.e. a char in the C locale case). Like, for example,
* alternative digits in unicode like Arabic-Indic U+0660..U+0669.
* The problem is that WideCharToMultiByte() does not translate those
* wchar_t unless we pass the correct codepage (1256, Arabic).
* See bug VSW:192653.
*/
Thank you!
-
January 19th, 2012, 01:44 AM
#10
Re: ComboBox + LPWSTR
Originally Posted by pcuong1983
Here i got from step by step debug:
/* Actually, there are such wchar_t characters which are > 255,
* but they can be transformed to a valid single byte char
* (i.e. a char in the C locale case). Like, for example,
* alternative digits in unicode like Arabic-Indic U+0660..U+0669.
* The problem is that WideCharToMultiByte() does not translate those
* wchar_t unless we pass the correct codepage (1256, Arabic).
* See bug VSW:192653.
*/
Well, it is exactly what I wrote in my edited post#2 yesterday.
Victor Nijegorodov
-
January 19th, 2012, 02:40 AM
#11
Re: ComboBox + LPWSTR
VictorN
What about
Use CBEM_SETUNICODEFORMAT message to sets the UNICODE character format flag for the control. This message enables you to change the character set used by the control at run time rather than having to re-create the control.
how to use CBEM_SETUNICODEFORMAT and When to use CBEM_SETUNICODEFORMAT ?
-
January 19th, 2012, 04:59 AM
#12
Re: ComboBox + LPWSTR
Originally Posted by pcuong1983
VictorN
What about
how to use CBEM_SETUNICODEFORMAT and When to use CBEM_SETUNICODEFORMAT ?
You have to set the code page correctly. Did you do that, and if so, did that solve the problem?
Regards,
Paul McKenzie
-
January 19th, 2012, 05:10 PM
#13
Re: ComboBox + LPWSTR
>> wcstombs_s return EILSEQ
For wcstombs() to work on anything other than "C" locale characters (A-Z, a-z, 0-9, etc...), you must call setlocale(LC_CTYPE, "") so that the CRT will convert using the system ANSI codepage (ACP).
Even then, wcstombs() will fail if it encounters any characters that aren't in the ACP. I don't think that "ả" (U+1EA3) or "ị" (U+1ECB) are in any of the Windows codepages, so wcstombs() will never work on windows for those characters.
>> strWText = L"Quảng Trị";
Putting extended characters directly into your source can be dangerous. Anyone who edits/saves that source file will have to save it with a Unicode encoding.
Code:
#include <windows.h>
#include <stdio.h>
HFONT CreateFont(HDC hdc, int pitch, const wchar_t *facename);
const wchar_t *g_wide_string = L"Qu\u1EA3ng Tr\u1ECB";
//------------------------------------------------------------------------------
int main()
{
const char *className = "ANSI_MsgLoop_Test";
WNDCLASSA wincl = {0};
wincl.hInstance = GetModuleHandle(0);
wincl.lpszClassName = className;
wincl.lpfnWndProc = DefWindowProcA;
wincl.style = CS_DBLCLKS;
wincl.hIcon = LoadIcon(0, IDI_APPLICATION);
wincl.hCursor = LoadCursor(0, IDC_ARROW);
wincl.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
if (!RegisterClassA(&wincl))
return 0;
HWND parent;
parent = CreateWindowA(className, "ANSI Msg Loop",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
300, 100, HWND_DESKTOP, 0,
GetModuleHandle(0), 0);
if (!parent)
return 0;
HWND combo;
combo = CreateWindowW(L"ComboBox", L"",
WS_CHILD | WS_VISIBLE | WS_DISABLED | CBS_DROPDOWNLIST,
10, 10, 260, 30,
parent, (HMENU)1,
GetModuleHandle(0), 0);
if (!combo)
return 0;
// give it a nice font
HDC hdc = GetDC(combo);
HFONT hfont = CreateFont(hdc, 12, L"Times New Roman");
ReleaseDC(combo, hdc);
SendMessageA(combo, WM_SETFONT, (WPARAM)hfont, 0);
// add string and select it
SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)g_wide_string);
SendMessageA(combo, CB_SETCURSEL, 0, 0);
MSG msg;
BOOL bRet;
for (;;)
{
bRet = GetMessageA(&msg, parent, 0, 0);
if ((bRet == 0) || (bRet == -1))
break;
if (!IsWindow(parent) || !IsDialogMessageA(parent, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}//if
}//while
DeleteObject(hfont);
return 0;
}//main
//------------------------------------------------------------------------------
HFONT CreateFont(HDC hdc, int pitch, const wchar_t *facename)
{
LOGFONTW lf = {0};
wcscpy_s(lf.lfFaceName, sizeof(lf.lfFaceName)/sizeof(*lf.lfFaceName),
facename);
lf.lfHeight = -MulDiv(pitch, GetDeviceCaps(hdc, LOGPIXELSY), 72);
lf.lfWeight = FW_NORMAL;
lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
lf.lfClipPrecision = CLIP_STROKE_PRECIS;
lf.lfQuality = CLEARTYPE_QUALITY;
return CreateFontIndirectW(&lf);
}//CreateFont
Notes:
- No extended characters in source (save source as Unicode otherwise)
- ComboBox created with CreateWindowW()
- Created a nice font that should have support for those Unicode characters (was getting "best fit" characters without it)
gg
-
January 19th, 2012, 08:45 PM
#14
Re: ComboBox + LPWSTR
Very good points, Codeplug. Especially the point of not having strings with embedded foreign characters in the source, and instead use the escape sequences in the string.
Regards,
Paul McKenzie
-
January 20th, 2012, 11:41 AM
#15
Re: ComboBox + LPWSTR
I got it, Thank you CodePlug. I also thank Paul McKenzie
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|