how to convert char* to LPCTSTR in c++(MFC) - c++

I have to make MFC application that accesses .txt files.
The following code is part of the template file given:
fopen(dlg.GetPathName());
However when I tried to run given template file, I got errors indicating that char* can not be converted to LPCTSTR.
I did some research online, and the program runs fine after correcting like this:
USES_CONVERSION;
const char* cstr;
cstr = T2A((LPCTSTR)dlg.GetPathName());
~
fp = fopen(cstr, "r");
I'm mentioning this because my compiler(VS 2017 community) may use unicode as default. And I think this is key to solving the aforementioned problem:
I have a problem printing result on the window edit control.
m_Result.SetWindowTextW((LPCTSTR)Result);
Result contains the message to be displayed in edit control and its type is char*. Whenever I run the program the result it is displayed either in blank box □ or Chinese. I tried converting Result using A2T and CA2T and but none of these worked.

The first error can be fixed by using Microsoft's _wfopen() function (or the TCHAR equivalent, _tfopen(), to match the TCHAR nature of GetPathName() instead of fopen(). That way, you don't need to convert the input string to char* at all:
fp = _wfopen(dlg.GetPathName(), L"r");
fp = _tfopen(dlg.GetPathName(), _T("r"));
In the second error, if Result is char* (or something that is implicitly convertible to char*) and LPCTSTR maps to const wchar_t* (because UNICODE is defined) then you can use CA2CT just fine:
m_Result.SetWindowTextW(CA2CT(Result));
However, since SetWindowTextW() expects only wchar_t* and never TCHAR*, use CA2CW instead:
m_Result.SetWindowTextW(CA2CW(Result));
Alternatively, if possible, you should change Result to use wchar_t instead of char in the first place, then you don't need a conversion anymore:
m_Result.SetWindowTextW(Result);

Related

Error : Cannot convert char to wchat_t*

Im trying to get the active window title using GetForegroundWindow and GetWindowText Functions and this is my code
HWND hwnd = GetForegroundWindow();
char wname[255];
GetWindowText(hwnd,wname,255);
And Everytime i try to build the project i get this error message "Error : Error : Cannot convert char to wchat_t*"
Im using c++builder xe7
So, What's wrong?
You are calling the TCHAR version of GetWindowText(). In your Project Options, you have the "TCHAR maps to" option set to wchar_t, so GetWindowText() maps to GetWindowTextW(), which takes a wchar_t* parameter. That is why you cannot pass in a char[] buffer.
So, you need to either:
Change "TCHAR maps to" to char so that GetWindowText() maps to GetWindowTextA() instead (also similarly affects every other TCHAR-based API function call in your code. Use this approach only when migrating legacy pre-Unicode code to C++Builder 2009+).
Change your code to use TCHAR instead:
TCHAR wname[255];
GetWindowText(hwnd,wname,255);
Change your code to use the Ansi or Unicode version of GetWindowText() directly:
char wname[255];
GetWindowTextA(hwnd,wname,255);
wchar_t wname[255];
GetWindowTextW(hwnd,wname,255);
You're building your application in Unicode-aware mode; a char is not large enough to hold a UTF-16 character. The type system is saving you from a lot of potential headache here by catching this for you. Either change to ASCII mode (easy but bad solution), switch to using wide strings everywhere (annoying solution), or use the provided macros to choose at compile time based on build parameters (even more annoying but most correct solution).
This is what this code snippet would look like with either of the above solutions implemented:
HWND hwnd = GetForegroundWindow();
wchar_t wname[255];
GetWindowText(hwnd, wname, 255);
HWND hwnd = GetForegroundWindow();
TCHAR wname[255];
GetWindowTextW(hwnd, wname, 255);
If you choose to build a Unicode-aware application (which you should), you must also remember to use wmain or _tmain as applicable, rather than plain old boring main. Because Windows.

Convert wide CString to char*

There are lots of times this question has been asked and as many answers - none of which work for me and, it seems, many others. The question is about wide CStrings and 8bit chars under MFC. We all want an answer that will work in ALL cases, not a specific instance.
void Dosomething(CString csFileName)
{
char cLocFileNamestr[1024];
char cIntFileNamestr[1024];
// Convert from whatever version of CString is supplied
// to an 8 bit char string
cIntFileNamestr = ConvertCStochar(csFileName);
sprintf_s(cLocFileNamestr, "%s_%s", cIntFileNamestr, "pling.txt" );
m_KFile = fopen(LocFileNamestr, "wt");
}
This is an addition to existing code (by somebody else) for debugging.
I don't want to change the function signature, it is used in many places.
I cannot change the signature of sprintf_s, it is a library function.
You are leaving out a lot of details, or ignoring them. If you are building with UNICODE defined (which it seems you are), then the easiest way to convert to MBCS is like this:
CStringA strAIntFileNameStr = csFileName.GetString(); // uses default code page
CStringA is the 8-bit/MBCS version of CString.
However, it will fill with some garbage characters if the unicode string you are translating from contains characters that are not in the default code page.
Instead of using fopen(), you could use _wfopen() which will open a file with a unicode filename. To create your file name, you would use swprintf_s().
an answer that will work in ALL cases, not a specific instance...
There is no such thing.
It's easy to convert "ABCD..." from wchar_t* to char*, but it doesn't work that way with non-Latin languages.
Stick to CString and wchar_t when your project is unicode.
If you need to upload data to webpage or something, then use CW2A and CA2W for utf-8 and utf-16 conversion.
CStringW unicode = L"Россия";
MessageBoxW(0,unicode,L"Russian",0);//should be okay
CStringA utf8 = CW2A(unicode, CP_UTF8);
::MessageBoxA(0,utf8,"format error",0);//WinApi doesn't get UTF-8
char buf[1024];
strcpy(buf, utf8);
::MessageBoxA(0,buf,"format error",0);//same problem
//send this buf to webpage or other utf-8 systems
//this should be compatible with notepad etc.
//text will appear correctly
ofstream f(L"c:\\stuff\\okay.txt");
f.write(buf, strlen(buf));
//convert utf8 back to utf16
unicode = CA2W(buf, CP_UTF8);
::MessageBoxW(0,unicode,L"okay",0);

Converting QString to LPCWSTR qt c++

Currently I am attempting to convert a QString to a LPCWSTR that will be used in URLDownloadToFile(). The following is a simple version of my current code:
QString url = "http://whatever_file...";
HRESULT hRez = URLDownloadToFile(NULL, (LPCWSTR)url.toLocal8Bit().constData(), TEXT("C:\\etc..."), 0, NULL);
The conversion was found working, in the post I found it in, with conversion of QString to LPCWSTR. I am rather new in the field of programming and I simply added a letter to that solution as URLDownloadToFile require it. It return no error however the download fail.
What am I missing here?
To get LPCWSTR from QString you can use QString::constData method, because QChar is 2 byte Unicode symbol, exactly as WCHAR (if wchar_t is 2 byte on target machine).
And I aware you from the using of "TEXT" macro in one line with "LPCWSTR". You should use "L" instead.
"TEXT" is created for using in pair with the "LPCTSTR" macro. You can read this about them.

Adding a string to a listbox results in weird characters

I have made a function that send strings to listbox using WIN32
char data[] = "abcd";
addToList(hWnd,data);
void addToList(HWND hWnd,char data[] ){
SendMessage(GetDlgItem(hWnd,IDC_LISTBOX),LB_ADDSTRING,0,(LPARAM)data);
}
when I execute this it's send data to list box but the problem they appeared in weird characters, I have tried wchar_t also but the problem still issued
First of all, you should be checking your API calls for errors. You need to check the return values of all your calls to API functions.
That said, given the code in the question,
SendMessage(GetDlgItem(hWnd,IDC_LISTBOX),LB_ADDSTRING,0,(LPARAM)data);
If that results in an item being added to the list box, then it means that GetDlgItem did indeed return a valid window handle, and data did indeed point to valid memory. In which case the only explanation for what you report is that the text encoded did not match.
So, we can assume that the SendMessage macro evaluates to SendMessageW. And since you are passing ANSI encoded text, that mismatch explains the symptoms. The function treats the text as UTF-16 encoded.
One obvious solution is to use SendMessageA instead. However, a better solution, in my view, would be to pass UTF-16 encoded data.
wchar_t data[] = L"abcd";
....
void addToList(HWND hWnd, const wchar_t *data)
{
SendMessage(GetDlgItem(hWnd,IDC_LISTBOX), LB_ADDSTRING, 0, (LPARAM)data);
}
Obviously your code would add in the error checking that I mentioned at the start.

How do I store value to string with RegOpenKeyEx?

I need to grab the path from the registry. The following code works except for the last part where I'm storing the path to the string. Running the debugger in Visual Studio 2008 the char array has the path, but every other character is a zero. This results in the string only being assigned the first letter. I've tried changing char res[1024] to char *res = new char[1024] and this just makes it store the first letter in the char array instead of the string. The rest of the program needs the path as a string datatype so it can't stay as a char array. What am I missing here?
unsigned long type=REG_SZ, size=1024;
string path;
char res[1024];
HKEY key;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Classes\\dsn\\shell\\open\\command"), NULL, KEY_READ, &key)==ERROR_SUCCESS){
RegQueryValueEx(key,
NULL,// YOUR value
NULL,
&type,
(LPBYTE)res,
&size);
RegCloseKey(key);
path = string(res);
}
You're getting back a Unicode string, but assigning it to a char-based string.
You could switch path's class to being a 'tstring' or 'wstring', or use RegQueryValueExA (A for ASCII).
You are compiling in Unicode. Go to Project Settings>Configuration Properties>General and change "Character Set" to "Not Set", and rebuild your project.
RegOpenKey is actually a macro defined in the WINAPI headers. If Unicode is enabled, it resolves to RegOpenKeyW, if not then it resolves to RegOpenKeyA. If you want to continue to compile under unicode, then you can just call RetgOpenKeyA directly instead of using the macro.
Otherwise, you'll need to deal with Unicode strings which, if needed, we can help you with also.
For C++, you may prefer to access the Registry using the ATL helper class CRegKey. The method for storing string values is QueryStringValue. There are other (somewhat) typesafe methods for retrieving and setting different registry value types.
It's not the best C++ interface (eg. no std::string support) but a little smoother than native Win32.