HWND ForeWindow = GetForegroundWindow();
wchar_t WindowTxt[1024] = { L'\0' };
GetWindowTextW(ForeWindow, WindowTxt, 1024);
wprintf(L"%s\n", WindowTxt);
std::wstring Str(WindowTxt);
std::wcout << L"Wnd: " << Str << L"\n";
Using the above code to get the window of skype which is "Skype™" i get the output:
"Skype?"
(the wcout line fails to execute)
1) Why is the wide character version of GetWindowText unable to handle this character
2) Why does std::wstring fail to parse the wchar_t array and then print it to the console
CMD consoles don't handle Unicode well. Send the output to a file and open it in and editor, and I suspect you'll get the actual character you expect.
Related
I'm using this function to add my program to startup. But it doesn't work and I don't know why weird ascii characters and words are showing up in startup applications. What am I doing wrong?
Instead this is being added to starup. U㫅萹㐀蠀渐晁Ɉ U㫆萺㝈耀 U㫆萺㝈耀 and C. Which has no file location and also no details.
HKEY NewVal;
char loggeduser[UNLEN + 1];
std::ostringstream fileinhome;
GetUserNameA(loggeduser, &len);
fileinhome << "C:\\Users\\" << loggeduser << "\\AppData\\Roaming\\snetwork\\snetwork.exe";
std::string fp = fileinhome.str();
const char* file = fp.c_str();
if (RegOpenKey(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), &NewVal) != ERROR_SUCCESS)
{
return;
}
if (RegSetValueEx(NewVal, _T("CLI-Social-Network"), 0, REG_SZ, (LPBYTE)file, sizeof(file)) != ERROR_SUCCESS)
{
return;
}
else {
// std::cout << "Program added to Startup.\n";
// Do nothing, Program was added to Startup
}
RegCloseKey(NewVal);
A possibility: You have UNICODE and/or _UNICODE defined, so RegSetValueEx is actually RegSetValueExW. Therefore, this function passes Unicode data into the buffer file. But file is an ASCII buffer, so the otherwise-valid Unicode data is incorrectly parsed as ASCII, leading to the strange output.
To fix, use std::wstring and W functions explicitly.
Unicode considerations aside, you can't use a const char * as a buffer for receiving data. You must allocate sufficient memory for the buffer first.
I am having difficulty with the CreateDirectory function. In the following code I am getting a
"cannot convert argument 1 from 'const char *' to 'LPCWSTR'" compile error for the CreateDirectory call.
// make path to folder in program data
char szPath[MAX_PATH];
if ( ! SUCCEEDED( SHGetFolderPathA( NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath ) ) )
{
std::cout << "ERROR: Could not open server log - no common data folder " << std::endl;
exit(1);
}
std::string fname = szPath;
fname +="/Point";
CreateDirectory( fname.c_str(), NULL);
I am using Visual Studio 2015 and have "Character Set = Use Unicode Character Set".
In fileapi.h the following is defined:
#ifdef UNICODE
#define CreateDirectory CreateDirectoryW
#else
#define CreateDirectory CreateDirectoryA
#endif // !UNICODE
So I think the CreateDirectoryW function is being used
What do I need to do to get this to compile properly?
You need to use std::wstring instead of std::string in order to use wide character strings.
int main()
{
// make path to folder in program data
wchar_t szPath[MAX_PATH];
if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath)))
{
std::cout << "ERROR: Could not open server log - no common data folder " << std::endl;
exit(1);
}
std::wstring fname = szPath;
fname += L"/Point";
CreateDirectory(fname.c_str(), NULL);
}
If you do not want to use wide character strings you need to explicitly call the narrow character versions of the windows API functions such as CreateDirectoryA instead of CreateDirectory.
Use CreateDirectoryA.
That said you'd be better off changing to Unicode in your application, wide text.
The original code has some problems:
// make path to folder in program data
↑ This comment is misleading: the code is about finding the path, not creating it.
char szPath[MAX_PATH];
↑ This buffer is unnecessary, instead, for this code, you should just declare the later variable std::string fname here, with specified buffer size.
if ( ! SUCCEEDED( SHGetFolderPathA( NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath ) ) )
↑ !SUCCEEEDED is a misleading rewrite of idiomatic FAILED. And SHGetFolderPath is deprecated. Instead you should be using SHGetKnownFolderPath.
{
std::cout << "ERROR: Could not open server log - no common data folder " << std::endl;
exit(1);
}
↑ The console output makes this failure handling of little value in a GUI program. Anyway, instead of cout you should be using cerr or clog (they both map to the standard error stream by default). In the exit call you should either be using a standard value such as EXIT_FAILURE, or supply the HRESULT that you got (this is Windows convention, in particular for crashing programs), or for some function, the value that you get from GetLastError. Anyway exit is far too drastic. You should be either throwing an exception or returning an optional.
std::string fname = szPath;
fname +="/Point";
↑ Forward slashes are generally supported but still the Windows convention is backslash as item separator.
CreateDirectory( fname.c_str(), NULL);
↑ The only problem that it doesn't compile with UNICODE defined before including windows.h. Use CreateDirectoryA. Or better, switch to Unicode.
I am trying to load the name of an image using its VM address by calling GetModuleFileName() which seems to return the value correctly into a TCHAR[] array. I am able to display the data correctly using MessageBox() but cout << seems to display some funky hexadecimal number.
TCHAR buf[MAX_PATH];
HMODULE hProc = LoadLibrary(TEXT("kernel32.dll"));
GetModuleFileName(hProc, buf, MAX_PATH);
cout << buf; //Produces the odd number
MessageBox(NULL, buf, NULL, MB_OK); //Produces correct filepath
FreeLibrary(hProc);
Am I supposed to set a flag for cout so it knows to print it correctly? Thank you!
Probably you need to use wcout, because your TCHAR might be unicodish. Or convert it.
Maybe you will have better luck with
std::wcout << buf;
I have the lovely functions from my previous question, which work fine if I do this:
wstring temp;
wcin >> temp;
string whatever( toUTF8(getSomeWString()) );
// store whatever, copy, but do not use it as UTF8 (see below)
wcout << toUTF16(whatever) << endl;
The original form is reproduced, but the in between form often contains extra characters. If I enter for example àçé as the input, and add a cout << whatever statement, i'll get ┬à┬ç┬é as output.
Can I still use this string to compare to others, procured from an ASCII source? Or asked differently: if I would output ┬à┬ç┬é through the UTF8 cout in linux, would it read àçé? Is the byte content of a string àçé, read in UTF8 linux by cin, exactly the same as what the Win32 API gets me?
Thanks!
PS: the reason I'm asking is because I need to use the string a lot to compare to other read values (comparing and concatenating...).
Let's start by me saying that it appears that there is simply no way to output UTF-8 text to the console in Windows via cout (assuming you compile with Visual Studio).
What you can do however for your tests is to output your UTF-8 text via the Win32 API fn WriteConsoleA:
if(!SetConsoleOutputCP(CP_UTF8)) { // 65001
cerr << "Failed to set console output mode!\n";
return 1;
}
HANDLE const consout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD nNumberOfCharsWritten;
const char* utf8 = "Umlaut AE = \xC3\x84 / ue = \xC3\xBC \n";
if(!WriteConsoleA(consout, utf8, strlen(utf8), &nNumberOfCharsWritten, NULL)) {
DWORD const err = GetLastError();
cerr << "WriteConsole failed with << " << err << "!\n";
return 1;
}
This should output:
Umlaut AE = Ä / ue = ü if you set your console (cmd.exe) to use the Lucida Console font.
As for your question (taken from your comment) if
a win23 API converted string is the
same as a raw UTF8 (linux) string
I will say yes: Given a Unicode character sequence, it's UTF-16 (Windows wchar_t) representation converted to a UTF-8 (char) representation via the WideCharToMultiByte function will always yield the same byte sequence.
When you convert the string to a UTF 16 it is a 16 byte wide character, you can't compare it to the ASCII values because they aren't 16 byte values. You have to convert them to compare, or write a specialized comparision to ASCII function.
I doubt the UTF8 cout in linux would produce the same correct output unless it were regular ASCII values, as UTF8 UTF-8 encoding forms are binary-compatible with ASCII for code points below 128, and I assume UTF16 comes after UTF8 in a simliar fashion.
The good news is there are many converters out there written to convert these strings to different character sets.
For a C++ console application compiled with Visual Studio 2008 on English Windows (XP,Vista or 7). Is it possible to print out to the console and correctly display UTF-8 encoded Japanese using cout or wcout?
This should work:
#include <cstdio>
#include <windows.h>
#pragma execution_character_set( "utf-8" )
int main()
{
SetConsoleOutputCP( 65001 );
printf( "Testing unicode -- English -- Ελληνικά -- Español -- Русский. aäbcdefghijklmnoöpqrsßtuüvwxyz\n" );
}
Don't know if it affects anything, but source file is saved as Unicode (UTF-8 with signature) - Codepage 65001 at FILE -> Advanced Save Options ....
Project -> Properties -> Configuration Properties -> General -> Character Set is set to Use Unicode Character Set.
Some say you need to change console font to Lucida Console, but on my side it is displayed with both Consolas and Lucida Console.
The Windows console uses the OEM code page by default to display output.
To change the code page to Unicode enter chcp 65001 in the console, or try to change the code page programmatically with SetConsoleOutputCP.
Note that you probably have to change the font of the console to one that has glyphs in the unicode range.
Here's an article from MVP Michael Kaplan on how to correctly output UTF-16 through the console. You could convert your UTF-8 to UTF-16 and output that.
I've never actually tried setting the console code-page to UTF8 (not sure why it wouldn't work... the console can handle other multi-byte code-pages just fine), but there are a couple of functions to look up: SetConsoleCP and SetConsoleOutputCP.
You'll probably also need to make sure you're using a console font that is capable of displaying your characters. There's the SetCurrentConsoleFontEx function, but it's only available on Vista and above.
Hope that helps.
On app start console set to default OEM437 CP.
I was trying to output Unicode text to stdout, where console was switch to UTF8 translation _setmode(_fileno(stdout), _O_U8TEXT); and still had no luck on the screen even with Lucida TT font.
If console was redirected to file, correct UTF8 file were created.
Finally I was lucky. I have added single line "info.FontFamily = FF_DONTCARE;" and it is working now.
Hope this help for you.
void SetLucidaFont()
{
HANDLE StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_FONT_INFOEX info;
memset(&info, 0, sizeof(CONSOLE_FONT_INFOEX));
info.cbSize = sizeof(CONSOLE_FONT_INFOEX); // prevents err=87 below
if (GetCurrentConsoleFontEx(StdOut, FALSE, &info))
{
info.FontFamily = FF_DONTCARE;
info.dwFontSize.X = 0; // leave X as zero
info.dwFontSize.Y = 14;
info.FontWeight = 400;
_tcscpy_s(info.FaceName, L"Lucida Console");
if (SetCurrentConsoleFontEx(StdOut, FALSE, &info))
{
}
}
}
Just for additional information:
'ANSI' refers to windows-125x, used for win32 applications while 'OEM' refers to the code page used by console/MS-DOS applications.
Current active code-pages can be retrieved with functions GetOEMCP() and GetACP().
In order to output something correctly to the console, you should:
ensure the current OEM code page supports the characters you want to output
(if necessary, use SetConsoleOutputCP to set it properly)
convert the string from current ANSI code (win32) to the console OEM code page
Here are some utilities for doing so:
// Convert a UTF-16 string (16-bit) to an OEM string (8-bit)
#define UNICODEtoOEM(str) WCHARtoCHAR(str, CP_OEMCP)
// Convert an OEM string (8-bit) to a UTF-16 string (16-bit)
#define OEMtoUNICODE(str) CHARtoWCHAR(str, CP_OEMCP)
// Convert an ANSI string (8-bit) to a UTF-16 string (16-bit)
#define ANSItoUNICODE(str) CHARtoWCHAR(str, CP_ACP)
// Convert a UTF-16 string (16-bit) to an ANSI string (8-bit)
#define UNICODEtoANSI(str) WCHARtoCHAR(str, CP_ACP)
/* Convert a single/multi-byte string to a UTF-16 string (16-bit).
We take advantage of the MultiByteToWideChar function that allows to specify the charset of the input string.
*/
LPWSTR CHARtoWCHAR(LPSTR str, UINT codePage) {
size_t len = strlen(str) + 1;
int size_needed = MultiByteToWideChar(codePage, 0, str, len, NULL, 0);
LPWSTR wstr = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * size_needed);
MultiByteToWideChar(codePage, 0, str, len, wstr, size_needed);
return wstr;
}
/* Convert a UTF-16 string (16-bit) to a single/multi-byte string.
We take advantage of the WideCharToMultiByte function that allows to specify the charset of the output string.
*/
LPSTR WCHARtoCHAR(LPWSTR wstr, UINT codePage) {
size_t len = wcslen(wstr) + 1;
int size_needed = WideCharToMultiByte(codePage, 0, wstr, len, NULL, 0, NULL, NULL);
LPSTR str = (LPSTR) LocalAlloc(LPTR, sizeof(CHAR) * size_needed );
WideCharToMultiByte(codePage, 0, wstr, len, str, size_needed, NULL, NULL);
return str;
}
For anyone need to read UTF-8 from file and print to console can try wifstream, even in visual studio debugger shows UTF-8 words correctly (I'm processing traditional chinese), from this post:
#include <sstream>
#include <fstream>
#include <codecvt>
std::wstring readFile(const char* filename)
{
std::wifstream wif(filename);
wif.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
std::wstringstream wss;
wss << wif.rdbuf();
return wss.str();
}
// usage
std::wstring wstr2;
wstr2 = readFile("C:\\yourUtf8File.txt");
wcout << wstr2;
In the console, enter chcp 65001 to change the code page to that of UTF-8.