3

I am trying to use listbox.Addstring(); in MFC application which will take LPCTSTR. I am passing a variable of char array that's 33 chars long.

ListBox.AddString(Adapter_List->pScanList->network[0].szSsid);

SzSsid is declared as char szSsid[33];

I am facing two problems:

1) if I typecast to LPCTSTR like

ListBox.AddString( (LPCTSTR ) Adapter_List->pScanList->network[0].szSsid );

I am not getting correct output - there are some Chinese characters displaying. I know it's some unicode problem but I am not knowledgeable about unicode.

2) if I dont typecast I get an error

Cannot convert char[33] to LPCTSTR

I am trying to build an MFC application which will display all access points. In szSsid I am able to see access point names.

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
david
  • 413
  • 5
  • 20

1 Answers1

4

LPCTSTR type-casting is just wrong. You may want to use an ATL conversion helper like CA2T to convert from char string to TCHAR (LPCTSTR) string, or CA2W to convert from char string to Unicode UTF-16 wchar_t string; e.g.:

// CA2T - Uses the TCHAR model (obsolete)
ListBox.AddString( CA2T(Adapter_List->pScanList->network[0].szSsid) );

or:

// CA2W - Conversion to Unicode UTF-16 (wchar_t) string
// More modern approach.
ListBox.AddString( CA2W(Adapter_List->pScanList->network[0].szSsid) );

But, more important, what is the encoding used by your char szSSid[] string? You may want to specify that encoding identifier (e.g. CP_UTF8 for UTF-8 strings) to CA2W constructor nCodePage parameter for proper conversion to Unicode UTF-16 string passed to AddString() method.

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
  • Thank you i will check. how to know the encoding used by the string? – david Dec 28 '12 at 11:54
  • Thank you Mr.C64, I tried to change the project settings. Configuration properties->general->project defaults-> character set is by default use unicode character set. i changed to Not Set or multibyte character set its working. I am not fully aware of unicode strings i tried trail and error. may be Mr.C64 solution is better to understand in depth – david Dec 28 '12 at 12:00
  • The encoding used by `char szSSid[]` string should be documented somewhere in the code or in your project documentation... I don't have psychic powers to guess it :) It may be simple ASCII, or Unicode UTF-8, or some other encoding... You may try with a simple call to `CA2W` without specifying the encoding, and see the results. Maybe the default is OK. Or you can specify some special encoding from [this list](http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx). – Mr.C64 Dec 28 '12 at 12:00
  • @david: Change the project settings? What project settings? That's not what I suggested. Since you got a compiler error when passing a `char[]` string to `CListBox::AddString()` method, I deduce that you are compiling in Unicode mode (which has been the default setting since VS2005, and it's OK). Just try with `CA2W`, in ordinary Unicode builds. – Mr.C64 Dec 28 '12 at 12:01
  • @david: Glad to know it. Note that in Unicode builds `CA2T` is expanded by the preprocesor to `CA2W` :) – Mr.C64 Dec 28 '12 at 12:08
  • -1 Calling `TCHAR` _obsolete_ and `wchar_t` _more modern_ is rightout wrong. The API is expecting an `LPCTSTR` so the correct conversion macro is `CA2CT`. Even if you never intend to compile a non-Unicode build you should still use the correct type. Don't code by coincidence. – IInspectable Dec 29 '12 at 02:20
  • @Tim: I don't agree with you. I do consider the `TCHAR` model _obsolete_, and in modern Windows C++ code I'd just use Unicode builds, `wchar_t`, `CString` (which is expanded to `CStringW`) and `std::wstring` with Win32 API's. The `TCHAR`/`LPCTSTR` is just for ANSI/MBCS compatibility, and in modern world this compatibility seems stupid and useless to me. Note also that more modern Win32 API's only use `WCHAR`'s/`LPCWSTR` (e.g. [`DrawThemeText()`](http://msdn.microsoft.com/en-us/library/windows/desktop/bb773312(v=vs.85).aspx)). – Mr.C64 Dec 30 '12 at 12:03
  • I'm not arguing against using `wchar_t`/`WCHAR`/`CStringW` where appropriate. `DrawThemeText()` is one of those cases, `CListBox::AddString()` is not. If you pass an `LPCWSTR` instead of an `LPCTSTR` then sometimes your code will not compile, provoking the same conversion error that started this question. Your recommendation to deliberately use the wrong data type is ill-advised. – IInspectable Dec 30 '12 at 16:03
  • @Tim: I don't agree with you; e.g. if I have a `std::wstring` and I want to pass it to a `LPCTSTR` parameter (like, say, in `SetWindowText()`), I just call `std::wstring::c_str()` method, without using the `CW2T` conversion helper, because I don't care about ANSI/MBCS builds, instead I'm only interested in Unicode builds (moreover, the conversion from Unicode to ANSI/MBCS could be lossy, etc.). I think that simply using the Unicode/`wchar_t` model (instead of the Unicode/ANSI/MBCS `TCHAR` model) is just fine for modern Win32 C++ code. – Mr.C64 Dec 30 '12 at 16:51
  • This is a public community with an emphasis on quality. If you cannot guarantee that the advice you give will work for everyone, including those that cannot easily limit themselves to Unicode, then your advice is bad. I would suggest you update the answer, remove the opinionated statements on character types, remove the code that you cannot guarantee to work for everyone and fix const-correctness on the conversion macro. Possibly add code that uses a temporary `CString` object to perform the required conversion in place of an ATL conversion macro. – IInspectable Dec 30 '12 at 23:41
  • @Tim: On const correctness, `CA2CW` seems not existing. On using a temporary `CString`, I think that the conversion helpers like `CA2W` are more _lightweight_ than building a `CString` (that will be also thrown away since it's a temporary). e.g. `CString` is ref counted, it has a ref count control block, and has more overhead than the simple conversion helper classes, which also implement a small string optimization allocating space on the stack instead of the heap for small strings. – Mr.C64 Dec 31 '12 at 10:47
  • `CA2CW` does not exist, for obvious reasons. Since I suggested to write **correct** code I recommended to use `CA2CT`, which **does** exist. As for your performance considerations, they are mundane; this question is about populating a ListBox. Apart from being misguided it is also highly irrelevant. I mentioned `CString` since it can convert from `char` to `TCHAR` on construction and is compatible with MFC classes. – IInspectable Dec 31 '12 at 11:07
  • @Tim: Those reasons are not obvious to me. I believe my code is *correct*. Feel free to write your own answer with your own code, supporting ANSI/MBCS and maybe MS-DOS ;) – Mr.C64 Jan 02 '13 at 08:23
  • BTW: I'm going to stop this discussion here. For those interested in the `TCHAR` model, there's [this question on SO](http://stackoverflow.com/questions/234365/is-tchar-still-relevant). To me, the `TCHAR` model is **obsolete** and **useless** these days: Windows C++ apps should be **Unicode**, so I just consider `std::wstring`, `wchar_t`, `L"..."` and `CString` (assuming it is a Unicode `CStringW`). – Mr.C64 Jan 02 '13 at 11:16