Reputation: 466
If I register a window class with RegisterClassExW
and I create a window of that class (let's call that window hwndA), If I send SendMessageA(hwndA, WM_SETTEXT, 0, (LPARAM)"Hello")
, when hwndA receives WM_SETTEXT, will lParam
always point to a unicode string even though I used SendMessageA()
?
Upvotes: 2
Views: 1215
Reputation: 157
Note that if you use SetWindowLongPtrA, the callback function lParam (WM_SETTEXT) will point to an ANSI string, so if you need wchar_t in the callback function, use SetWindowLongPtrW beforehand
Upvotes: 0
Reputation: 104524
If you used RegisterClassExW
to register the Window class, then yes. Windows has special case logic for SendMessage
and well known messages that use strings. This includes WM_SETTEXT
.
If the class of the Window was registered with the ANSI style function, RegisterClassA
or RegisterClassExA
, then all string parameters for subsequent window messages with strings will be ascii. If the class of the Window was registered with the wide version (RegisterClassW
or RegisterClassExW
), then all subsequent window messages with strings will be unicode.
So in the general case, assuming your code is using Unicode APIs (the default these days), you always get a Unicode string in WM_SETTEXT
. Windows will convert the ansi string passed in through SendMessageA
to a wide char string.
Here's what I did to confirm:
Take the following WndProc for example - modified from the default Visual Studio Win32 app template.
void LogPointer(const wchar_t* name, void* value, bool isUnicode)
{
std::wostringstream ss;
ss << L"Name=" << name << L" value=" << std::hex << value << std::dec;
if (isUnicode)
{
ss << L" printed: " << (const wchar_t*)value;
}
else
{
ss << L" printed: " << (const char*)value;
}
ss << L"\r\n";
std::wstring str = ss.str();
OutputDebugStringW(str.c_str());
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
char* psz = "Hello world";
wchar_t* wpsz = L"Bye Bye";
switch (message)
{
case WM_SETTEXT:
{
LogPointer(L"psz", psz, false);
LogPointer(L"wpsz", wpsz, true);
LogPointer(L"lParam", (void*)lParam, true);
return DefWindowProc(hWnd, message, wParam, lParam);
}
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
{
OutputDebugStringW(L"Invoking SendMessageA with ansi string\r\n");
SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)psz);
OutputDebugStringW(L"\r\nInvoking SendMessageW with wide string\r\n");
SendMessageW(hWnd, WM_SETTEXT, 0, (LPARAM)wpsz);
break;
}
The output is as follows:
Invoking SendMessageA with ansi string
Name=psz value=0096338C printed: Hello world
Name=wpsz value=0096339C printed: Bye Bye
Name=lParam value=005ADE78 printed: Hello world
Invoking SendMessageW with wide string
Name=psz value=0096338C printed: Hello world
Name=wpsz value=0096339C printed: Bye Bye
Name=lParam value=0096339C printed: Bye Bye
Now observe the value of lParam
in the two sets of output log lines.
In the case of SendMessageA
, the pointer value of lParam
matches neither that of psz
nor wpsz
. Windows, underneath the hood recognizes that it needs to convert the ansi string to a wide char. So it does the conversion for you and actually sends a different allocated string that it manages.
In the case of SendMessageW, lParam==wpsz
. No conversion was done. Windows just passed the lParam
value straight to the WndProc
call.
Upvotes: 4
Reputation: 33716
you can use
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Hello");
or
SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)L"Hello");
in both case lParam
(in windowproc) always point to a unicode string. in first case SendMessageA
- system allocate memory from heap or stack, and convert ansi "Hello"
to unicode and you got pointer to this memory.
in second case SendMessageW
- you got direct pointer to L"Hello"
in window proc
Upvotes: 1
Reputation: 415
CreateWindow A or W make changes not regstyle.W window may interpret it as wide chars.
Upvotes: -3