diff --git a/dlls/user/message.c b/dlls/user/message.c index 01a48fb1587..2c2b96ad622 100644 --- a/dlls/user/message.c +++ b/dlls/user/message.c @@ -2298,3 +2298,69 @@ BOOL WINAPI GetGUIThreadInfo( DWORD id, GUITHREADINFO *info ) SERVER_END_REQ; return ret; } + + +/********************************************************************** + * GetKeyState (USER32.@) + * + * An application calls the GetKeyState function in response to a + * keyboard-input message. This function retrieves the state of the key + * at the time the input message was generated. + */ +SHORT WINAPI GetKeyState(INT vkey) +{ + SHORT retval = 0; + + SERVER_START_REQ( get_key_state ) + { + req->tid = GetCurrentThreadId(); + req->key = vkey; + if (!wine_server_call( req )) retval = (signed char)reply->state; + } + SERVER_END_REQ; + TRACE("key (0x%x) -> %x\n", vkey, retval); + return retval; +} + + +/********************************************************************** + * GetKeyboardState (USER32.@) + */ +BOOL WINAPI GetKeyboardState( LPBYTE state ) +{ + BOOL ret; + + TRACE("(%p)\n", state); + + memset( state, 0, 256 ); + SERVER_START_REQ( get_key_state ) + { + req->tid = GetCurrentThreadId(); + req->key = -1; + wine_server_set_reply( req, state, 256 ); + ret = !wine_server_call_err( req ); + } + SERVER_END_REQ; + return ret; +} + + +/********************************************************************** + * SetKeyboardState (USER32.@) + */ +BOOL WINAPI SetKeyboardState( LPBYTE state ) +{ + BOOL ret; + + TRACE("(%p)\n", state); + + memset( state, 0, 256 ); + SERVER_START_REQ( set_key_state ) + { + req->tid = GetCurrentThreadId(); + wine_server_add_data( req, state, 256 ); + ret = !wine_server_call_err( req ); + } + SERVER_END_REQ; + return ret; +} diff --git a/dlls/user/msg16.c b/dlls/user/msg16.c index c30fb9c585d..0ce268769c0 100644 --- a/dlls/user/msg16.c +++ b/dlls/user/msg16.c @@ -403,6 +403,33 @@ void WINAPI PostQuitMessage16( INT16 exitCode ) } +/********************************************************************** + * GetKeyState (USER.106) + */ +INT16 WINAPI GetKeyState16(INT16 vkey) +{ + return GetKeyState(vkey); +} + + +/********************************************************************** + * GetKeyboardState (USER.222) + */ +BOOL WINAPI GetKeyboardState16( LPBYTE state ) +{ + return GetKeyboardState( state ); +} + + +/********************************************************************** + * SetKeyboardState (USER.223) + */ +BOOL WINAPI SetKeyboardState16( LPBYTE state ) +{ + return SetKeyboardState( state ); +} + + /*********************************************************************** * SetMessageQueue (USER.266) */ diff --git a/dlls/user/user.exe.spec b/dlls/user/user.exe.spec index 4c57d2cee13..70072c9fbb2 100644 --- a/dlls/user/user.exe.spec +++ b/dlls/user/user.exe.spec @@ -219,8 +219,8 @@ 219 pascal16 CreateDialogIndirect(word ptr word segptr) CreateDialogIndirect16 220 pascal16 LoadMenuIndirect(ptr) LoadMenuIndirect16 221 pascal16 ScrollDC(word s_word s_word ptr ptr word ptr) ScrollDC16 -222 pascal16 GetKeyboardState(ptr) GetKeyboardState -223 pascal16 SetKeyboardState(ptr) SetKeyboardState +222 pascal16 GetKeyboardState(ptr) GetKeyboardState16 +223 pascal16 SetKeyboardState(ptr) SetKeyboardState16 224 pascal16 GetWindowTask(word) GetWindowTask16 225 pascal16 EnumTaskWindows(word segptr long) EnumTaskWindows16 226 stub LockInput # not in W2.0 diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 7d79c38a6b4..12713be3ffa 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2778,6 +2778,32 @@ struct get_thread_input_reply }; +struct get_key_state_request +{ + struct request_header __header; + thread_id_t tid; + int key; +}; +struct get_key_state_reply +{ + struct reply_header __header; + unsigned char state; + /* VARARG(keystate,bytes); */ +}; + + +struct set_key_state_request +{ + struct request_header __header; + thread_id_t tid; + /* VARARG(keystate,bytes); */ +}; +struct set_key_state_reply +{ + struct reply_header __header; +}; + + struct set_foreground_window_request { struct request_header __header; @@ -3112,6 +3138,8 @@ enum request REQ_get_window_properties, REQ_attach_thread_input, REQ_get_thread_input, + REQ_get_key_state, + REQ_set_key_state, REQ_set_foreground_window, REQ_set_focus_window, REQ_set_active_window, @@ -3289,6 +3317,8 @@ union generic_request struct get_window_properties_request get_window_properties_request; struct attach_thread_input_request attach_thread_input_request; struct get_thread_input_request get_thread_input_request; + struct get_key_state_request get_key_state_request; + struct set_key_state_request set_key_state_request; struct set_foreground_window_request set_foreground_window_request; struct set_focus_window_request set_focus_window_request; struct set_active_window_request set_active_window_request; @@ -3464,6 +3494,8 @@ union generic_reply struct get_window_properties_reply get_window_properties_reply; struct attach_thread_input_reply attach_thread_input_reply; struct get_thread_input_reply get_thread_input_reply; + struct get_key_state_reply get_key_state_reply; + struct set_key_state_reply set_key_state_reply; struct set_foreground_window_reply set_foreground_window_reply; struct set_focus_window_reply set_focus_window_reply; struct set_active_window_reply set_active_window_reply; @@ -3477,6 +3509,6 @@ union generic_reply struct get_next_hook_reply get_next_hook_reply; }; -#define SERVER_PROTOCOL_VERSION 93 +#define SERVER_PROTOCOL_VERSION 94 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index 19eca9e8684..9bbfde049c7 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1941,6 +1941,21 @@ enum message_type rectangle_t rect; /* caret rectangle */ @END +/* Retrieve queue keyboard state for a given thread */ +@REQ(get_key_state) + thread_id_t tid; /* id of thread */ + int key; /* optional key code or -1 */ +@REPLY + unsigned char state; /* state of specified key */ + VARARG(keystate,bytes); /* state array for all the keys */ +@END + +/* Set queue keyboard state for a given thread */ +@REQ(set_key_state) + thread_id_t tid; /* id of thread */ + VARARG(keystate,bytes); /* state array for all the keys */ +@END + /* Set the system foreground window */ @REQ(set_foreground_window) user_handle_t handle; /* handle to the foreground window */ diff --git a/server/queue.c b/server/queue.c index b913116364c..8eaba4d2a34 100644 --- a/server/queue.c +++ b/server/queue.c @@ -868,6 +868,68 @@ static struct timer *set_timer( struct msg_queue *queue, unsigned int rate ) return timer; } +/* change the input key state for a given key */ +static void set_input_key_state( struct thread_input *input, unsigned char key, int down ) +{ + if (down) + { + if (!(input->keystate[key] & 0x80)) input->keystate[key] ^= 0x01; + input->keystate[key] |= 0x80; + } + else input->keystate[key] &= ~0x80; +} + +/* update the input key state for a keyboard message */ +static void update_input_key_state( struct thread_input *input, const struct message *msg ) +{ + unsigned char key; + int down = 0, extended; + + switch (msg->msg) + { + case WM_LBUTTONDOWN: + down = 1; + /* fall through */ + case WM_LBUTTONUP: + set_input_key_state( input, VK_LBUTTON, down ); + break; + case WM_MBUTTONDOWN: + down = 1; + /* fall through */ + case WM_MBUTTONUP: + set_input_key_state( input, VK_MBUTTON, down ); + break; + case WM_RBUTTONDOWN: + down = 1; + /* fall through */ + case WM_RBUTTONUP: + set_input_key_state( input, VK_RBUTTON, down ); + break; + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + down = 1; + /* fall through */ + case WM_KEYUP: + case WM_SYSKEYUP: + key = (unsigned char)msg->wparam; + extended = ((msg->lparam >> 16) & KF_EXTENDED) != 0; + set_input_key_state( input, key, down ); + switch(key) + { + case VK_SHIFT: + set_input_key_state( input, extended ? VK_RSHIFT : VK_LSHIFT, down ); + break; + case VK_CONTROL: + set_input_key_state( input, extended ? VK_RCONTROL : VK_LCONTROL, down ); + break; + case VK_MENU: + set_input_key_state( input, extended ? VK_RMENU : VK_LMENU, down ); + break; + } + break; + } +} + /* release the hardware message currently being processed by the given thread */ static void release_hardware_message( struct thread *thread, int remove ) { @@ -879,6 +941,7 @@ static void release_hardware_message( struct thread *thread, int remove ) struct message *other; int clr_bit; + update_input_key_state( input, input->msg ); unlink_message( &input->msg_list, input->msg ); clr_bit = get_hardware_msg_bit( input->msg ); for (other = input->msg_list.first; other; other = other->next) @@ -892,13 +955,19 @@ static void release_hardware_message( struct thread *thread, int remove ) } /* find the window that should receive a given hardware message */ -static user_handle_t find_hardware_message_window( struct thread_input *input, struct message *msg ) +static user_handle_t find_hardware_message_window( struct thread_input *input, struct message *msg, + unsigned int *msg_code ) { user_handle_t win = 0; + *msg_code = msg->msg; if (is_keyboard_msg( msg )) { - if (input && !(win = input->focus)) win = input->active; + if (input && !(win = input->focus)) + { + win = input->active; + if (*msg_code < WM_SYSKEYDOWN) *msg_code += WM_SYSKEYDOWN - WM_KEYDOWN; + } } else /* mouse message */ { @@ -916,8 +985,9 @@ static void queue_hardware_message( struct msg_queue *queue, struct message *msg user_handle_t win; struct thread *thread; struct thread_input *input; + unsigned int msg_code; - win = find_hardware_message_window( queue ? queue->input : foreground_input, msg ); + win = find_hardware_message_window( queue ? queue->input : foreground_input, msg, &msg_code ); if (!win || !(thread = get_window_thread(win))) { free( msg ); @@ -943,6 +1013,7 @@ static int get_hardware_message( struct thread *thread, struct message *first, struct message *msg; user_handle_t win; int clear_bits, got_one = 0; + unsigned int msg_code; if (input->msg_thread && input->msg_thread != thread) return 0; /* locked by another thread */ @@ -960,11 +1031,12 @@ static int get_hardware_message( struct thread *thread, struct message *first, while (msg) { - win = find_hardware_message_window( input, msg ); + win = find_hardware_message_window( input, msg, &msg_code ); if (!win || !(win_thread = get_window_thread( win ))) { /* no window at all, remove it */ struct message *next = msg->next; + update_input_key_state( input, msg ); unlink_message( &input->msg_list, msg ); free_message( msg ); msg = next; @@ -998,7 +1070,7 @@ static int get_hardware_message( struct thread *thread, struct message *first, reply->type = MSG_HARDWARE; reply->win = win; - reply->msg = msg->msg; + reply->msg = msg_code; reply->wparam = msg->wparam; reply->lparam = msg->lparam; reply->x = msg->x; @@ -1458,6 +1530,40 @@ DECL_HANDLER(get_thread_input) } +/* retrieve queue keyboard state for a given thread */ +DECL_HANDLER(get_key_state) +{ + struct thread *thread; + struct thread_input *input; + + if (!(thread = get_thread_from_id( req->tid ))) return; + input = thread->queue ? thread->queue->input : NULL; + if (input) + { + if (req->key >= 0) reply->state = input->keystate[req->key & 0xff]; + set_reply_data( input->keystate, min( get_reply_max_size(), sizeof(input->keystate) )); + } + release_object( thread ); +} + + +/* set queue keyboard state for a given thread */ +DECL_HANDLER(set_key_state) +{ + struct thread *thread = NULL; + struct thread_input *input; + + if (!(thread = get_thread_from_id( req->tid ))) return; + input = thread->queue ? thread->queue->input : NULL; + if (input) + { + size_t size = min( sizeof(input->keystate), get_req_data_size() ); + if (size) memcpy( input->keystate, get_req_data(), size ); + } + release_object( thread ); +} + + /* set the system foreground window */ DECL_HANDLER(set_foreground_window) { diff --git a/server/request.h b/server/request.h index 213da9883dc..240238b4709 100644 --- a/server/request.h +++ b/server/request.h @@ -262,6 +262,8 @@ DECL_HANDLER(get_window_property); DECL_HANDLER(get_window_properties); DECL_HANDLER(attach_thread_input); DECL_HANDLER(get_thread_input); +DECL_HANDLER(get_key_state); +DECL_HANDLER(set_key_state); DECL_HANDLER(set_foreground_window); DECL_HANDLER(set_focus_window); DECL_HANDLER(set_active_window); @@ -438,6 +440,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_get_window_properties, (req_handler)req_attach_thread_input, (req_handler)req_get_thread_input, + (req_handler)req_get_key_state, + (req_handler)req_set_key_state, (req_handler)req_set_foreground_window, (req_handler)req_set_focus_window, (req_handler)req_set_active_window, diff --git a/server/trace.c b/server/trace.c index 322aeb4d505..fa2be02fc59 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2211,6 +2211,26 @@ static void dump_get_thread_input_reply( const struct get_thread_input_reply *re dump_rectangle( &req->rect ); } +static void dump_get_key_state_request( const struct get_key_state_request *req ) +{ + fprintf( stderr, " tid=%08x,", req->tid ); + fprintf( stderr, " key=%d", req->key ); +} + +static void dump_get_key_state_reply( const struct get_key_state_reply *req ) +{ + fprintf( stderr, " state=%02x,", req->state ); + fprintf( stderr, " keystate=" ); + dump_varargs_bytes( cur_size ); +} + +static void dump_set_key_state_request( const struct set_key_state_request *req ) +{ + fprintf( stderr, " tid=%08x,", req->tid ); + fprintf( stderr, " keystate=" ); + dump_varargs_bytes( cur_size ); +} + static void dump_set_foreground_window_request( const struct set_foreground_window_request *req ) { fprintf( stderr, " handle=%p", req->handle ); @@ -2509,6 +2529,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_window_properties_request, (dump_func)dump_attach_thread_input_request, (dump_func)dump_get_thread_input_request, + (dump_func)dump_get_key_state_request, + (dump_func)dump_set_key_state_request, (dump_func)dump_set_foreground_window_request, (dump_func)dump_set_focus_window_request, (dump_func)dump_set_active_window_request, @@ -2682,6 +2704,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_window_properties_reply, (dump_func)0, (dump_func)dump_get_thread_input_reply, + (dump_func)dump_get_key_state_reply, + (dump_func)0, (dump_func)dump_set_foreground_window_reply, (dump_func)dump_set_focus_window_reply, (dump_func)dump_set_active_window_reply, @@ -2855,6 +2879,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "get_window_properties", "attach_thread_input", "get_thread_input", + "get_key_state", + "set_key_state", "set_foreground_window", "set_focus_window", "set_active_window", diff --git a/windows/message.c b/windows/message.c index a59724b57af..8527cf95f48 100644 --- a/windows/message.c +++ b/windows/message.c @@ -51,8 +51,6 @@ WINE_DECLARE_DEBUG_CHANNEL(key); #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE #define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK -static BYTE QueueKeyStateTable[256]; - /*********************************************************************** * is_keyboard_message @@ -130,80 +128,6 @@ static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info ) #endif -/*********************************************************************** - * update_queue_key_state - */ -static void update_queue_key_state( UINT msg, WPARAM wp, LPARAM lp ) -{ - BOOL down = FALSE, iskey = FALSE; - WPARAM dualkey = 0; - - switch (msg) - { - case WM_LBUTTONDOWN: - down = TRUE; - /* fall through */ - case WM_LBUTTONUP: - wp = VK_LBUTTON; - break; - case WM_MBUTTONDOWN: - down = TRUE; - /* fall through */ - case WM_MBUTTONUP: - wp = VK_MBUTTON; - break; - case WM_RBUTTONDOWN: - down = TRUE; - /* fall through */ - case WM_RBUTTONUP: - wp = VK_RBUTTON; - break; - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - down = TRUE; - /* fall through */ - case WM_KEYUP: - case WM_SYSKEYUP: - wp = wp & 0xff; - iskey = TRUE; - break; - } - if (iskey) - { - switch(wp) - { - case VK_SHIFT: - dualkey = (HIWORD(lp) & KF_EXTENDED) ? VK_RSHIFT : VK_LSHIFT; - break; - case VK_CONTROL: - dualkey = (HIWORD(lp) & KF_EXTENDED) ? VK_RCONTROL : VK_LCONTROL; - break; - case VK_MENU: - dualkey = (HIWORD(lp) & KF_EXTENDED) ? VK_RMENU : VK_LMENU; - break; - - } - } - if (down) - { - BYTE *p = &QueueKeyStateTable[wp]; - if (!(*p & 0x80)) *p ^= 0x01; - *p |= 0x80; - } - else QueueKeyStateTable[wp] &= ~0x80; - if (dualkey) - { /* also update the "dual" keys properly */ - if (down) - { - BYTE *p = &QueueKeyStateTable[dualkey]; - if (!(*p & 0x80)) *p ^= 0x01; - *p |= 0x80; - } - else QueueKeyStateTable[dualkey] &= ~0x80; - } -} - - /*********************************************************************** * MSG_SendParentNotify * @@ -330,18 +254,10 @@ void MSG_JournalPlayBackMsg(void) * * returns TRUE if the contents of 'msg' should be passed to the application */ -static BOOL process_raw_keyboard_message( MSG *msg, ULONG_PTR extra_info ) +static void process_raw_keyboard_message( MSG *msg ) { EVENTMSG event; - if (!(msg->hwnd = GetFocus())) - { - /* Send the message to the active window instead, */ - /* translating messages to their WM_SYS equivalent */ - msg->hwnd = GetActiveWindow(); - if (msg->message < WM_SYSKEYDOWN) msg->message += WM_SYSKEYDOWN - WM_KEYDOWN; - } - event.message = msg->message; event.hwnd = msg->hwnd; event.time = msg->time; @@ -349,11 +265,6 @@ static BOOL process_raw_keyboard_message( MSG *msg, ULONG_PTR extra_info ) event.paramH = msg->lParam & 0x7FFF; if (HIWORD(msg->lParam) & 0x0100) event.paramH |= 0x8000; /* special_key - bit */ HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event, TRUE ); - - /* if we are going to throw away the message, update the queue state now */ - if (!msg->hwnd) update_queue_key_state( msg->message, msg->wParam, msg->lParam ); - - return (msg->hwnd != 0); } @@ -366,8 +277,6 @@ static BOOL process_cooked_keyboard_message( MSG *msg, BOOL remove ) { if (remove) { - update_queue_key_state( msg->message, msg->wParam, msg->lParam ); - /* Handle F1 key by sending out WM_HELP message */ if ((msg->message == WM_KEYUP) && (msg->wParam == VK_F1) && @@ -398,10 +307,8 @@ static BOOL process_cooked_keyboard_message( MSG *msg, BOOL remove ) /*********************************************************************** * process_raw_mouse_message - * - * returns TRUE if the contents of 'msg' should be passed to the application */ -static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL remove ) +static void process_raw_mouse_message( MSG *msg, BOOL remove ) { static MSG clk_msg; @@ -478,7 +385,6 @@ static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL remo if (!(info.flags & GUI_INMENUMODE)) ScreenToClient( msg->hwnd, &pt ); } msg->lParam = MAKELONG( pt.x, pt.y ); - return TRUE; } @@ -506,8 +412,6 @@ static BOOL process_cooked_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL r raw_message += WM_LBUTTONDOWN - WM_LBUTTONDBLCLK; } - if (remove) update_queue_key_state( raw_message, 0, 0 ); - hook.pt = msg->pt; hook.hwnd = msg->hwnd; hook.wHitTestCode = hittest; @@ -602,11 +506,11 @@ BOOL MSG_process_raw_hardware_message( MSG *msg, ULONG_PTR extra_info, HWND hwnd { if (is_keyboard_message( msg->message )) { - if (!process_raw_keyboard_message( msg, extra_info )) return FALSE; + process_raw_keyboard_message( msg ); } else if (is_mouse_message( msg->message )) { - if (!process_raw_mouse_message( msg, extra_info, remove )) return FALSE; + process_raw_mouse_message( msg, remove ); } else { @@ -635,63 +539,6 @@ BOOL MSG_process_cooked_hardware_message( MSG *msg, ULONG_PTR extra_info, BOOL r } -/********************************************************************** - * GetKeyState (USER.106) - */ -INT16 WINAPI GetKeyState16(INT16 vkey) -{ - return GetKeyState(vkey); -} - - -/********************************************************************** - * GetKeyState (USER32.@) - * - * An application calls the GetKeyState function in response to a - * keyboard-input message. This function retrieves the state of the key - * at the time the input message was generated. (SDK 3.1 Vol 2. p 390) - */ -SHORT WINAPI GetKeyState(INT vkey) -{ - INT retval; - - if (vkey >= 'a' && vkey <= 'z') vkey += 'A' - 'a'; - retval = ((WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) | - (QueueKeyStateTable[vkey] & 0x80) | - (QueueKeyStateTable[vkey] & 0x01); - TRACE("key (0x%x) -> %x\n", vkey, retval); - return retval; -} - - -/********************************************************************** - * GetKeyboardState (USER.222) - * GetKeyboardState (USER32.@) - * - * An application calls the GetKeyboardState function in response to a - * keyboard input message. This function retrieves the state of the keyboard - * at the time the input message was generated. (SDK 3.1 Vol 2. p 387) - */ -BOOL WINAPI GetKeyboardState(LPBYTE lpKeyState) -{ - TRACE_(key)("(%p)\n", lpKeyState); - if (lpKeyState) memcpy(lpKeyState, QueueKeyStateTable, 256); - return TRUE; -} - - -/********************************************************************** - * SetKeyboardState (USER.223) - * SetKeyboardState (USER32.@) - */ -BOOL WINAPI SetKeyboardState(LPBYTE lpKeyState) -{ - TRACE_(key)("(%p)\n", lpKeyState); - if (lpKeyState) memcpy(QueueKeyStateTable, lpKeyState, 256); - return TRUE; -} - - /*********************************************************************** * WaitMessage (USER.112) Suspend thread pending messages * WaitMessage (USER32.@) Suspend thread pending messages @@ -974,6 +821,7 @@ BOOL WINAPI TranslateMessage( const MSG *msg ) UINT message; WCHAR wp[2]; BOOL rc = FALSE; + BYTE state[256]; if (msg->message >= WM_KEYFIRST && msg->message <= WM_KEYLAST) { @@ -989,8 +837,9 @@ BOOL WINAPI TranslateMessage( const MSG *msg ) TRACE_(key)("Translating key %s (%04x), scancode %02x\n", SPY_GetVKeyName(msg->wParam), msg->wParam, LOBYTE(HIWORD(msg->lParam))); + GetKeyboardState( state ); /* FIXME : should handle ToUnicode yielding 2 */ - switch (ToUnicode(msg->wParam, HIWORD(msg->lParam), QueueKeyStateTable, wp, 2, 0)) + switch (ToUnicode(msg->wParam, HIWORD(msg->lParam), state, wp, 2, 0)) { case 1: message = (msg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;