Mike32ab
Mike32ab

Reputation: 466

Sending ansi message to unicode window

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

Answers (4)

WRFan
WRFan

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

selbie
selbie

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

RbMm
RbMm

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

CreateWindow A or W make changes not regstyle.W window may interpret it as wide chars.

Upvotes: -3

Related Questions