Why OutputDebugString is empty - c++

I create a Win32 app and I have a logIn form, but I can't get a Edit Window value. I did it like this, but get nothing. Where is my mistake?
#define passwordWindowId 2
HWND passwordWindowHandle = CreateWindow(TEXT("EDIT"), TEXT(""), WS_VISIBLE | WS_CHILD, 10, 80, 150, 20, hWnd, (HMENU)passwordWindowId, NULL, NULL);
int len = GetWindowTextLength(GetDlgItem(passwordWindowHandle, passwordEditId));
LPWSTR passwordWindowValue;
GetWindowText(passwordWindowHandle, passwordWindowValue, len + 1);
OutputDebugString(passwordWindowValue);
But if I do OutputDebugString(L"test"); I see test in output tab.

Lots of errors in your code, some subtle and others fatal.
#define passwordWindowId 2
Some of the low control IDs are used by the dialog manager, and should not be overloaded with user-defined controls. A common convention is to start assigning numbers starting at 100 (see Why do dialog editors start assigning control IDs with 100?).
Another common convention is to use all uppercase names for preprocessor symbols.
HWND passwordWindowHandle = CreateWindow(TEXT("EDIT"), TEXT(""), ...
This is creating an empty edit control (see the second parameter of CreateWindow). This is not a bug in itself, but you cannot assume that the control contains any text.
Again, not a bug, but using the generic text mappings is generally not helpful. Use the Unicode versions of the APIs together with wide character strings and string literals: HWND passwordWindowHandle = CreateWindowW(L"EDIT", L"", ....
LPWSTR passwordWindowValue;
LPWSTR is a typedef for wchar_t*, so the above defines a pointer without initializing it. Not a bug in itself, but when you start using that pointer you run into undefined behavior. You need to allocate storage for the following call to GetWindowText, either by creating a local array of fixed size, if you know the maximum size ahead of time, or use a dynamically sized container (e.g. std::vector<wchar_t> buffer(len + 1);).
GetWindowText(passwordWindowHandle, passwordWindowValue, len + 1);
This is where things break: You are requesting an API call to write to unallocated memory, pointed to by an uninitialized pointer. As pointed out above, you need to allocate memory before calling GetWindowText. Besides, you are calling the generic text mapping, but passing explicit wide character string types. Use GetWindowTextW instead.
OutputDebugString(passwordWindowValue);
The argument is still an uninitialized pointer. Even if it weren't, the memory pointed to would be an empty string, since the control text is empty. Again, you are calling a generic text mapping, while passing an explicit wide character string. Use OutputDebugStringW instead.
Plus, you aren't checking for errors at all. All Windows API calls you are using can fail, and you need to check for failure. See the documentation on how to check for errors for each API call.

Updated!!
LPWSTR passwordWindowValue;
GetWindowText(passwordWindowHandle, passwordWindowValue, len + 1);
This should be
LPWSTR passwordWindowValue = new wchar_t[len + 1];
GetWindowText(passwordWindowHandle, passwordWindowValue, len + 1);
You are passing an uninitalised pointer to GetWindowText
And delete [] passwordWindowValue after you are done.

Related

getting garbage using SendMessage to populate a Listbox

I'm trying to populate a Listbox using c++ on Visual Studio. I have an array of std:string and i want to use them. My solution doesn't seem to work:
std::string label = "something";
char *buffer;
buffer = _strdup((label).c_str());
I checked and the buffer variable contains the correct string, but then i call SendMessage
SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)buffer);
The ListBox gets populated, but instead of "something" i see some random japanese characters...
SendMessage is a macro and it may be defined to SendMessageW, which uses Unicode string.
You are using std::string and char, so try using SendMessageA, which uses ANSI strings, explicitly.

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.

Why is OPENFILENAME lpstrFileTitle param a LPSTR and not LPCSTR?

I am creating some file open dialog and stumbled across something inconsistent in the WinAPI (hehe).
I fully understand why lpstrFile is a LPSTR as the path is written into this variable.
Fine, but why is lpstrFileTitle not LPCSTR? I've read the docs at MSDN and googled around and found no satisfying explanation as it doesn't look like it is modified in any way.
Is this a compatibility remnant or something?
Causes annoying workarounds when passing a std::string as I cannot use c_str() and resort to &str[0].
lpstrFileTitle is also an output buffer. It contains the name and extension without path information of the selected file.
Related side-note: You must set lpstrFileTitle to a valid buffer for non-Unicode builds.
The docs for OPENFILENAME state that field is ignored if the pointer is null. However, since at least VS2008 the MFC CFileDialog code has included this code:
VC\atlmfc\src\mfc\dlgfile.cpp
void CFileDialog::UpdateOFNFromShellDialog()
{
...
#ifdef UNICODE
...
#else
::WideCharToMultiByte(CP_ACP, 0, wcPathName + offset,-1, m_ofn.lpstrFileTitle, m_ofn.nMaxFileTitle, NULL, NULL);
m_ofn.lpstrFileTitle[m_ofn.nMaxFileTitle - 1] = _T('\0');
#endif
...
The Unicode support correctly handles a NULL lpstrFileTitle and the WideCharToMultiByte basically does nothing. However, the added code to safely terminate the buffer does not check for a null pointer or a nMaxFileTitle==0. The result is an access violation.
Better of course to kill multibyte apps, but if you must compile that way, you have to supply that buffer.

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.

Converting LCID to Language string

In my application I have to query for System and User Locale and return them as strings(like en-US instead of language codes). I can get the LCID for these Languages from GetSystemDefaultLCID() and GetUserDefaultLCID() functions, but what I am struggling with is the conversion from LCID to Language strings.
My app has to run on Windows XP as well so I can't use the LCIDToLocaleName() Win API. The only I have been able to Get the locale name so far is to use the GetLocaleInfo() Win API by passing LOCALE_SYSTEM_DEFAULT and LOCALE_USER_DEFAULT as LCID and LOCALE_SISO639LANGNAME as LCType. My code looks somewhat like this to Query for System Locale
int localeBufferSize = GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO639LANGNAME, NULL, 0);
char *sysLocale = new char[localeBufferSize];
GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO639LANGNAME, sysLocale,localeBufferSize);
But the value I get is only the language name(only en of en-US). To get the full locale I have to call GetLocaleInfo() twice passing LOCALE_SISO3166CTRYNAME as the LCType the second time and then append the two values. Is there any better way to do this?
Sorry to say that, but no. Only the two (or more) letter codes are standardized, the concatenation of them are not. But! There is no need for the dynamic buffer allocation. Quoted from MSDN:
The maximum number of characters allowed for this string is nine,
including a terminating null character.
Reading this, it sounds overkill to dynamically allocate the required buffer, so if you really want to keep it extra-clean, you can do something like this:
char buf[19];
int ccBuf = GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO639LANGNAME, buf, 9);
buf[ccBuf++] = '-';
ccBuf += GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO3166CTRYNAME, buf+ccBuf, 9);