user32: Support for the magic WM_CHAR W->A conversion in Get/PeekMessage.
This commit is contained in:
parent
b9540cf9e7
commit
2ce799c4f6
|
@ -307,6 +307,18 @@ static inline BOOL check_hwnd_filter( const MSG *msg, HWND hwnd_filter )
|
||||||
return (msg->hwnd == hwnd_filter || IsChild( hwnd_filter, msg->hwnd ));
|
return (msg->hwnd == hwnd_filter || IsChild( hwnd_filter, msg->hwnd ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check for pending WM_CHAR message with DBCS trailing byte */
|
||||||
|
static inline BOOL get_pending_wmchar( MSG *msg, UINT first, UINT last, BOOL remove )
|
||||||
|
{
|
||||||
|
struct wm_char_mapping_data *data = get_user_thread_info()->wmchar_data;
|
||||||
|
|
||||||
|
if (!data || !data->get_msg.message) return FALSE;
|
||||||
|
if ((first || last) && (first > WM_CHAR || last < WM_CHAR)) return FALSE;
|
||||||
|
if (!msg) return FALSE;
|
||||||
|
*msg = data->get_msg;
|
||||||
|
if (remove) data->get_msg.message = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* broadcast_message_callback
|
* broadcast_message_callback
|
||||||
|
@ -435,39 +447,60 @@ BOOL map_wparam_AtoW( UINT message, WPARAM *wparam, enum wm_char_mapping mapping
|
||||||
*
|
*
|
||||||
* Convert the wparam of a Unicode message to ASCII.
|
* Convert the wparam of a Unicode message to ASCII.
|
||||||
*/
|
*/
|
||||||
static WPARAM map_wparam_WtoA( UINT message, WPARAM wparam )
|
static void map_wparam_WtoA( MSG *msg, BOOL remove )
|
||||||
{
|
{
|
||||||
switch(message)
|
BYTE ch[2];
|
||||||
|
WCHAR wch[2];
|
||||||
|
DWORD len;
|
||||||
|
|
||||||
|
switch(msg->message)
|
||||||
{
|
{
|
||||||
|
case WM_CHAR:
|
||||||
|
if (!HIWORD(msg->wParam))
|
||||||
|
{
|
||||||
|
wch[0] = LOWORD(msg->wParam);
|
||||||
|
ch[0] = ch[1] = 0;
|
||||||
|
RtlUnicodeToMultiByteN( (LPSTR)ch, 2, &len, wch, sizeof(wch[0]) );
|
||||||
|
if (len == 2) /* DBCS char */
|
||||||
|
{
|
||||||
|
struct wm_char_mapping_data *data = get_user_thread_info()->wmchar_data;
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) ))) return;
|
||||||
|
get_user_thread_info()->wmchar_data = data;
|
||||||
|
}
|
||||||
|
if (remove)
|
||||||
|
{
|
||||||
|
data->get_msg = *msg;
|
||||||
|
data->get_msg.wParam = ch[1];
|
||||||
|
}
|
||||||
|
msg->wParam = ch[0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* else fall through */
|
||||||
case WM_CHARTOITEM:
|
case WM_CHARTOITEM:
|
||||||
case EM_SETPASSWORDCHAR:
|
case EM_SETPASSWORDCHAR:
|
||||||
case WM_CHAR:
|
|
||||||
case WM_DEADCHAR:
|
case WM_DEADCHAR:
|
||||||
case WM_SYSCHAR:
|
case WM_SYSCHAR:
|
||||||
case WM_SYSDEADCHAR:
|
case WM_SYSDEADCHAR:
|
||||||
case WM_MENUCHAR:
|
case WM_MENUCHAR:
|
||||||
{
|
wch[0] = LOWORD(msg->wParam);
|
||||||
WCHAR wch[2];
|
wch[1] = HIWORD(msg->wParam);
|
||||||
BYTE ch[2];
|
ch[0] = ch[1] = 0;
|
||||||
wch[0] = LOWORD(wparam);
|
RtlUnicodeToMultiByteN( (LPSTR)ch, 2, NULL, wch, sizeof(wch) );
|
||||||
wch[1] = HIWORD(wparam);
|
msg->wParam = MAKEWPARAM( ch[0] | (ch[1] << 8), 0 );
|
||||||
WideCharToMultiByte( CP_ACP, 0, wch, 2, (LPSTR)ch, 2, NULL, NULL );
|
|
||||||
wparam = MAKEWPARAM( ch[0] | (ch[1] << 8), 0 );
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case WM_IME_CHAR:
|
case WM_IME_CHAR:
|
||||||
{
|
wch[0] = LOWORD(msg->wParam);
|
||||||
WCHAR wch = LOWORD(wparam);
|
ch[0] = ch[1] = 0;
|
||||||
BYTE ch[2];
|
RtlUnicodeToMultiByteN( (LPSTR)ch, 2, &len, wch, sizeof(wch[0]) );
|
||||||
|
if (len == 2)
|
||||||
if (WideCharToMultiByte( CP_ACP, 0, &wch, 1, (LPSTR)ch, 2, NULL, NULL ) == 2)
|
msg->wParam = MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(msg->wParam) );
|
||||||
wparam = MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(wparam) );
|
else
|
||||||
else
|
msg->wParam = MAKEWPARAM( ch[0], HIWORD(msg->wParam) );
|
||||||
wparam = MAKEWPARAM( ch[0], HIWORD(wparam) );
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return wparam;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2876,9 +2909,10 @@ BOOL WINAPI PeekMessageW( MSG *msg_out, HWND hwnd, UINT first, UINT last, UINT f
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI PeekMessageA( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags )
|
BOOL WINAPI PeekMessageA( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags )
|
||||||
{
|
{
|
||||||
BOOL ret = PeekMessageW( msg, hwnd, first, last, flags );
|
if (get_pending_wmchar( msg, first, last, (flags & PM_REMOVE) )) return TRUE;
|
||||||
if (ret) msg->wParam = map_wparam_WtoA( msg->message, msg->wParam );
|
if (!PeekMessageW( msg, hwnd, first, last, flags )) return FALSE;
|
||||||
return ret;
|
map_wparam_WtoA( msg, (flags & PM_REMOVE) );
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2940,8 +2974,9 @@ BOOL WINAPI GetMessageW( MSG *msg, HWND hwnd, UINT first, UINT last )
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI GetMessageA( MSG *msg, HWND hwnd, UINT first, UINT last )
|
BOOL WINAPI GetMessageA( MSG *msg, HWND hwnd, UINT first, UINT last )
|
||||||
{
|
{
|
||||||
|
if (get_pending_wmchar( msg, first, last, TRUE )) return TRUE;
|
||||||
GetMessageW( msg, hwnd, first, last );
|
GetMessageW( msg, hwnd, first, last );
|
||||||
msg->wParam = map_wparam_WtoA( msg->message, msg->wParam );
|
map_wparam_WtoA( msg, TRUE );
|
||||||
return (msg->message != WM_QUIT);
|
return (msg->message != WM_QUIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9281,6 +9281,8 @@ static void test_dbcs_wm_char(void)
|
||||||
WCHAR wch, bad_wch;
|
WCHAR wch, bad_wch;
|
||||||
HWND hwnd, hwnd2;
|
HWND hwnd, hwnd2;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
DWORD time;
|
||||||
|
POINT pt;
|
||||||
DWORD_PTR res;
|
DWORD_PTR res;
|
||||||
CPINFOEXA cpinfo;
|
CPINFOEXA cpinfo;
|
||||||
UINT i, j, k;
|
UINT i, j, k;
|
||||||
|
@ -9481,6 +9483,72 @@ static void test_dbcs_wm_char(void)
|
||||||
ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch );
|
ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch );
|
||||||
ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
|
ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
|
||||||
|
|
||||||
|
/* test retrieving messages */
|
||||||
|
|
||||||
|
PostMessageW( hwnd, WM_CHAR, wch, 0 );
|
||||||
|
ok( PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" );
|
||||||
|
ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
|
||||||
|
ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
|
||||||
|
ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
|
||||||
|
ok( PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" );
|
||||||
|
ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
|
||||||
|
ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
|
||||||
|
ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
|
||||||
|
ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
|
||||||
|
|
||||||
|
/* message filters */
|
||||||
|
PostMessageW( hwnd, WM_CHAR, wch, 0 );
|
||||||
|
ok( PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" );
|
||||||
|
ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
|
||||||
|
ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
|
||||||
|
ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
|
||||||
|
/* message id is filtered, hwnd is not */
|
||||||
|
ok( !PeekMessageA( &msg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ), "no message\n" );
|
||||||
|
ok( PeekMessageA( &msg, hwnd2, 0, 0, PM_REMOVE ), "no message\n" );
|
||||||
|
ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
|
||||||
|
ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
|
||||||
|
ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
|
||||||
|
ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
|
||||||
|
|
||||||
|
/* mixing GetMessage and PostMessage */
|
||||||
|
PostMessageW( hwnd, WM_CHAR, wch, 0xbeef );
|
||||||
|
ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" );
|
||||||
|
ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
|
||||||
|
ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
|
||||||
|
ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
|
||||||
|
ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam );
|
||||||
|
time = msg.time;
|
||||||
|
pt = msg.pt;
|
||||||
|
ok( time - GetTickCount() <= 100, "bad time %x\n", msg.time );
|
||||||
|
ok( PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "no message\n" );
|
||||||
|
ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
|
||||||
|
ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
|
||||||
|
ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
|
||||||
|
ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam );
|
||||||
|
ok( msg.time == time, "bad time %x/%x\n", msg.time, time );
|
||||||
|
ok( msg.pt.x == pt.x && msg.pt.y == pt.y, "bad point %u,%u/%u,%u\n", msg.pt.x, msg.pt.y, pt.x, pt.y );
|
||||||
|
ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
|
||||||
|
|
||||||
|
/* without PM_REMOVE */
|
||||||
|
PostMessageW( hwnd, WM_CHAR, wch, 0 );
|
||||||
|
ok( PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "no message\n" );
|
||||||
|
ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
|
||||||
|
ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
|
||||||
|
ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
|
||||||
|
ok( PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "no message\n" );
|
||||||
|
ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
|
||||||
|
ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
|
||||||
|
ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
|
||||||
|
ok( PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "no message\n" );
|
||||||
|
ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
|
||||||
|
ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
|
||||||
|
ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
|
||||||
|
ok( PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "no message\n" );
|
||||||
|
ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
|
||||||
|
ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
|
||||||
|
ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
|
||||||
|
ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
|
||||||
|
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,7 @@ enum wm_char_mapping
|
||||||
struct wm_char_mapping_data
|
struct wm_char_mapping_data
|
||||||
{
|
{
|
||||||
BYTE lead_byte[WMCHAR_MAP_COUNT];
|
BYTE lead_byte[WMCHAR_MAP_COUNT];
|
||||||
|
MSG get_msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* this is the structure stored in TEB->Win32ClientInfo */
|
/* this is the structure stored in TEB->Win32ClientInfo */
|
||||||
|
|
Loading…
Reference in New Issue