如果我用RegisterClassExW
注册一个窗口类,我创建一个该类的窗口(让我们调用该窗口hwndA),如果我发送SendMessageA(hwndA, WM_SETTEXT, 0, (LPARAM)"Hello")
,当hwndA收到WM_SETTEXT时, lParam
始终指向unicode字符串,即使我使用了SendMessageA()
?
答案 0 :(得分:4)
如果您使用RegisterClassExW
注册Window类,那么是。 Windows具有SendMessage
的特殊情况逻辑和使用字符串的众所周知的消息。这包括WM_SETTEXT
。
如果使用ANSI样式函数RegisterClassA
或RegisterClassExA
注册了Window的类,则后续带字符串的窗口消息的所有字符串参数都将为ascii。如果窗口的类已使用宽版本(RegisterClassW
或RegisterClassExW
)注册,则所有带字符串的后续窗口消息都将是unicode。
因此,在一般情况下,假设您的代码使用Unicode API(这些天是默认值),您总是在WM_SETTEXT
中获得Unicode字符串。 Windows会将通过SendMessageA
传入的ansi字符串转换为宽字符串。
这是我做的确认:
以下面的WndProc为例 - 从默认的Visual Studio Win32应用程序模板修改。
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;
}
输出如下:
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
现在在两组输出日志行中观察lParam
的值。
如果是SendMessageA
,lParam
的指针值既不匹配psz
也不匹配wpsz
。引擎盖下的Windows识别出它需要将ansi字符串转换为宽字符。因此它为您进行转换,并实际发送它管理的不同分配字符串。
对于SendMessageW,lParam==wpsz
。没有转换。 Windows只是将lParam
值直接传递给WndProc
来电。
答案 1 :(得分:1)
你可以使用
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Hello");
或
SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)L"Hello");
在两种情况下lParam
(在windowproc中)总是指向一个unicode字符串。在第一种情况下SendMessageA
- 系统从堆或堆栈分配内存,并将ansi "Hello"
转换为unicode,并且您获得了指向此内存的指针。
在第二种情况SendMessageW
中 - 您在窗口过程中直接指向L"Hello"
答案 2 :(得分:0)
注意,如果使用SetWindowLongPtrA,回调函数lParam(WM_SETTEXT)会指向一个ANSI字符串,所以如果回调函数中需要wchar_t,请提前使用SetWindowLongPtrW
答案 3 :(得分:-3)
CreateWindow A或W进行更改而非regstyle.W窗口可能会将其解释为宽字符。