+ // we consider these message "not interesting" to OnChar
+ if ( wParam == VK_SHIFT || wParam == VK_CONTROL )
+ {
+ return Default();
+ }
+
+ switch ( wParam )
+ {
+ // avoid duplicate messages to OnChar for these ASCII keys: they
+ // will be translated by TranslateMessage() and received in WM_CHAR
+ case VK_ESCAPE:
+ case VK_SPACE:
+ case VK_RETURN:
+ case VK_BACK:
+ case VK_TAB:
+ return Default();
+
+#ifdef VK_APPS
+
+ // normally these macros would be defined in windows.h
+#ifndef GET_X_LPARAM
+ #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
+ #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
+#endif
+
+ // special case of VK_APPS: treat it the same as right mouse click
+ // because both usually pop up a context menu
+ case VK_APPS:
+ {
+ // construct the key mask
+ WPARAM fwKeys = MK_RBUTTON;
+ if ( (::GetKeyState(VK_CONTROL) & 0x100) != 0 )
+ fwKeys |= MK_CONTROL;
+ if ( (::GetKeyState(VK_SHIFT) & 0x100) != 0 )
+ fwKeys |= MK_SHIFT;
+
+ // simulate right mouse button click
+ DWORD dwPos = ::GetMessagePos();
+ int x = GET_X_LPARAM(dwPos),
+ y = GET_Y_LPARAM(dwPos);
+
+ ScreenToClient(&x, &y);
+ MSWOnRButtonDown(x, y, fwKeys);
+ }
+ break;
+#endif // VK_APPS
+
+ case VK_LEFT:
+ case VK_RIGHT:
+ case VK_DOWN:
+ case VK_UP:
+ default:
+ if ( !MSWOnChar((WORD)wParam, lParam) )
+ {
+ return Default();
+ }
+ break;
+ }
+ break;
+
+ case WM_KEYUP:
+ if ( !MSWOnKeyUp((WORD) wParam, lParam) )
+ return Default();
+ break;
+
+ case WM_CHAR: // Always an ASCII character
+ if ( !MSWOnChar((WORD)wParam, lParam, TRUE) )
+ return Default();
+ break;