Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2011, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #include <vlEGL/EGLWindow.hpp> 00033 #include <vlCore/Log.hpp> 00034 #include <vlCore/Say.hpp> 00035 #include <vlCore/Time.hpp> 00036 #include <shellapi.h> 00037 00038 using namespace vl; 00039 using namespace vlEGL; 00040 00041 //----------------------------------------------------------------------------- 00042 namespace 00043 { 00044 #if 0 00045 // used for debugging purposes 00046 void win32PrintError(LPTSTR lpszFunction) 00047 { 00048 TCHAR szBuf[80]; 00049 LPVOID lpMsgBuf; 00050 DWORD dw = GetLastError(); 00051 00052 FormatMessage( 00053 FORMAT_MESSAGE_ALLOCATE_BUFFER | 00054 FORMAT_MESSAGE_FROM_SYSTEM, 00055 NULL, 00056 dw, 00057 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 00058 (LPTSTR) &lpMsgBuf, 00059 0, NULL ); 00060 00061 wsprintf(szBuf, 00062 L"%s failed with error %d: %s", 00063 lpszFunction, dw, lpMsgBuf); 00064 00065 MessageBox(NULL, szBuf, L"Visualization Library Error", MB_OK); 00066 00067 LocalFree(lpMsgBuf); 00068 } 00069 #endif 00070 00071 bool registerClass() 00072 { 00073 static bool class_already_registered = false; 00074 if (!class_already_registered) 00075 { 00076 WNDCLASS wc; 00077 memset(&wc, 0, sizeof(wc)); 00078 /* only register the window class once. */ 00079 wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; 00080 wc.lpfnWndProc = (WNDPROC)EGLWindow::WindowProc; 00081 wc.cbClsExtra = 0; 00082 wc.cbWndExtra = 0; 00083 wc.hInstance = GetModuleHandle(NULL); 00084 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); 00085 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 00086 wc.hbrBackground = NULL; 00087 wc.lpszMenuName = NULL; 00088 wc.lpszClassName = EGLWindow::EGLWindowClassName; 00089 00090 if (!RegisterClass(&wc)) 00091 MessageBox(NULL, L"Class registration failed.", L"Visualization Library Error", MB_OK); 00092 else 00093 class_already_registered = true; 00094 } 00095 return class_already_registered; 00096 } 00097 } 00098 //----------------------------------------------------------------------------- 00099 const wchar_t* EGLWindow::EGLWindowClassName = L"VisualizationLibraryWindowClass"; 00100 //----------------------------------------------------------------------------- 00101 std::map< HWND, EGLWindow* > EGLWindow::mWinMap; 00102 //----------------------------------------------------------------------------- 00103 LONG WINAPI EGLWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 00104 { 00105 EGLWindow* win = EGLWindow::getWindow(hWnd); 00106 if (!win) 00107 return (LONG)DefWindowProc(hWnd, uMsg, wParam, lParam); 00108 00109 switch(uMsg) 00110 { 00111 case WM_PAINT: 00112 { 00113 // handle event and then dispatch: solves MessageBox dialog problem. 00114 LONG val = (LONG)DefWindowProc(hWnd, uMsg, wParam, lParam); 00115 if (win->eglContext() && win->eglSurface() && win->hwnd()) 00116 win->dispatchRunEvent(); 00117 return val; 00118 } 00119 00120 case WM_SIZE: 00121 { 00122 win->framebuffer()->setWidth( LOWORD(lParam) ); 00123 win->framebuffer()->setHeight( HIWORD(lParam) ); 00124 win->dispatchResizeEvent( LOWORD(lParam), HIWORD(lParam) ); 00125 break; 00126 } 00127 00128 case WM_MOUSEMOVE: 00129 { 00130 POINTS pt = MAKEPOINTS(lParam); 00131 win->dispatchMouseMoveEvent( pt.x, pt.y ); 00132 break; 00133 } 00134 00135 case WM_LBUTTONDBLCLK: 00136 case WM_LBUTTONDOWN: 00137 case WM_MBUTTONDBLCLK: 00138 case WM_MBUTTONDOWN: 00139 case WM_RBUTTONDBLCLK: 00140 case WM_RBUTTONDOWN: 00141 { 00142 win->mMouseDownCount++; 00143 if (win->mMouseDownCount == 1) 00144 SetCapture(win->hwnd()); 00145 EMouseButton button = UnknownButton; 00146 if (uMsg == WM_LBUTTONDBLCLK || uMsg == WM_LBUTTONDOWN) 00147 button = LeftButton; 00148 else if (uMsg == WM_MBUTTONDBLCLK || uMsg == WM_MBUTTONDOWN) 00149 button = MiddleButton; 00150 else if (uMsg == WM_RBUTTONDBLCLK || uMsg == WM_RBUTTONDOWN) 00151 button = RightButton; 00152 POINTS pt = MAKEPOINTS(lParam); 00153 win->dispatchMouseDownEvent( button, pt.x, pt.y ); 00154 break; 00155 } 00156 00157 case WM_LBUTTONUP: 00158 case WM_RBUTTONUP: 00159 case WM_MBUTTONUP: 00160 { 00161 win->mMouseDownCount--; 00162 if (win->mMouseDownCount <= 0) 00163 { 00164 ReleaseCapture(); 00165 win->mMouseDownCount = 0; 00166 } 00167 EMouseButton button = UnknownButton; 00168 if (uMsg == WM_LBUTTONUP) 00169 button = LeftButton; 00170 else if (uMsg == WM_MBUTTONUP) 00171 button = MiddleButton; 00172 else if (uMsg == WM_RBUTTONUP) 00173 button = RightButton; 00174 POINTS pt = MAKEPOINTS(lParam); 00175 win->dispatchMouseUpEvent( button, pt.x, pt.y ); 00176 break; 00177 } 00178 00179 // If you get a compilation error here: 00180 // 1 - you didn't define _WIN32_WINNT as 0x0400 or above. 00181 // 2 - you are trying to compile VL with a VERY old (unsupported) Visual Studio / Platform SDK. 00182 case WM_MOUSEWHEEL: 00183 { 00184 win->dispatchMouseWheelEvent( GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA ); 00185 break; 00186 } 00187 00188 /*case WM_CLOSE: 00189 { 00190 win->dispatchDestroyEvent(); 00191 win->destroyEGLGLWindow(); 00192 break; 00193 }*/ 00194 00195 case WM_DESTROY: 00196 { 00197 EGLWindow::mWinMap.erase(hWnd); 00198 win->dispatchDestroyEvent(); 00199 win->destroyEGLGLWindow(); 00200 break; 00201 } 00202 00203 case WM_KEYDOWN: 00204 { 00205 unsigned short unicode_out = 0; 00206 vl::EKey key_out = Key_None; 00207 translateKeyEvent(wParam, lParam, unicode_out, key_out); 00208 win->dispatchKeyPressEvent(unicode_out, key_out); 00209 break; 00210 } 00211 00212 case WM_KEYUP: 00213 { 00214 unsigned short unicode_out = 0; 00215 vl::EKey key_out = Key_None; 00216 translateKeyEvent(wParam, lParam, unicode_out, key_out); 00217 win->dispatchKeyReleaseEvent(unicode_out, key_out); 00218 break; 00219 } 00220 00221 case WM_DROPFILES: 00222 { 00223 HDROP hDrop = (HDROP)wParam; 00224 int count = DragQueryFile(hDrop, 0xFFFFFFFF, 0, 0); 00225 const int char_count = 1024; 00226 std::vector<String> files; 00227 for(int i=0; i<count; ++i) 00228 { 00229 wchar_t file_path[char_count]; 00230 memset(file_path, 0, char_count); 00231 DragQueryFile(hDrop,i,file_path,char_count); 00232 files.push_back(file_path); 00233 } 00234 win->dispatchFileDroppedEvent(files); 00235 break; 00236 } 00237 00238 // WM_SYSKEYDOWN 00239 // WM_SYSKEYUP 00240 // WM_GETICON 00241 // WM_SETCURSOR 00242 // WM_SETICON 00243 // WM_CAPTURECHANGED 00244 // WM_MOUSEFIRST 00245 } 00246 00247 return (LONG)DefWindowProc(hWnd, uMsg, wParam, lParam); 00248 } 00249 //----------------------------------------------------------------------------- 00250 // EGLWindow 00251 //----------------------------------------------------------------------------- 00252 EGLWindow::EGLWindow() 00253 { 00254 mEGL_Display = 0; 00255 mEGL_Context = 0; 00256 mEGL_Surface = 0; 00257 00258 mHWND = NULL; 00259 mMouseDownCount = 0; 00260 00261 mStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; 00262 mExStyle = WS_EX_APPWINDOW | WS_EX_ACCEPTFILES; 00263 mWindowClassName = EGLWindowClassName; 00264 } 00265 //----------------------------------------------------------------------------- 00266 EGLWindow::~EGLWindow() 00267 { 00268 destroyEGLGLWindow(); 00269 } 00270 //----------------------------------------------------------------------------- 00271 bool EGLWindow::initEGLWindow(HWND parent, const vl::String& title, const vl::OpenGLContextFormat& fmt, int x, int y, int width, int height) 00272 { 00273 destroyEGLGLWindow(); 00274 00275 if (!registerClass()) 00276 return false; 00277 00278 unsigned style = mStyle & ~(WS_CHILD|WS_OVERLAPPEDWINDOW);; 00279 style |= parent?WS_CHILD:WS_OVERLAPPEDWINDOW; 00280 00281 mHWND = CreateWindowEx( 00282 mExStyle, 00283 mWindowClassName, 00284 L"Visualization Library's EGLWindow", 00285 style, 00286 x, y, width, height, 00287 parent, NULL, GetModuleHandle(NULL), NULL); 00288 00289 setWindowTitle(title); 00290 00291 // EGL initialization 00292 00293 EGLint client_version[] = { EGL_CONTEXT_CLIENT_VERSION, fmt.contextClientVersion(), EGL_NONE }; 00294 00295 EGLint attrib_list[] = 00296 { 00297 EGL_RED_SIZE, fmt.rgbaBits().r(), 00298 EGL_GREEN_SIZE, fmt.rgbaBits().g(), 00299 EGL_BLUE_SIZE, fmt.rgbaBits().b(), 00300 EGL_ALPHA_SIZE, fmt.rgbaBits().a() ? fmt.rgbaBits().a() : EGL_DONT_CARE, 00301 EGL_DEPTH_SIZE, fmt.depthBufferBits() ? fmt.depthBufferBits() : EGL_DONT_CARE, 00302 EGL_STENCIL_SIZE, fmt.stencilBufferBits() ? fmt.stencilBufferBits() : EGL_DONT_CARE, 00303 EGL_SAMPLE_BUFFERS, fmt.multisample() ? 1 : 0, 00304 EGL_SAMPLES, fmt.multisample() ? fmt.multisampleSamples() : EGL_DONT_CARE, 00305 EGL_NONE 00306 }; 00307 00308 // Get Display 00309 mEGL_Display = eglGetDisplay(GetDC(mHWND)); 00310 if ( mEGL_Display == EGL_NO_DISPLAY ) 00311 { 00312 return false; 00313 } 00314 00315 // Initialize EGL 00316 EGLint maj_version=0, min_version=0; 00317 if ( !eglInitialize(mEGL_Display, &maj_version, &min_version) ) 00318 { 00319 return false; 00320 } 00321 00322 // Get configs 00323 EGLint num_configs = 0; 00324 if ( !eglGetConfigs(mEGL_Display, NULL, 0, &num_configs) ) 00325 { 00326 return false; 00327 } 00328 00329 // Choose config 00330 EGLConfig configurations[32] = {0}; 00331 if ( !eglChooseConfig(mEGL_Display, attrib_list, configurations, 32, &num_configs) ) 00332 { 00333 return false; 00334 } 00335 00336 #if 0 00337 for(int i=0; i<num_configs; ++i) 00338 { 00339 printf("EGLConfig #%d:\n", i); 00340 EGLint value = 0; 00341 eglGetConfigAttrib( mEGL_Display, configurations[i], EGL_RED_SIZE, &value); printf("EGL_RED_SIZE = %d\n", value); 00342 eglGetConfigAttrib( mEGL_Display, configurations[i], EGL_GREEN_SIZE, &value); printf("EGL_GREEN_SIZE = %d\n", value); 00343 eglGetConfigAttrib( mEGL_Display, configurations[i], EGL_BLUE_SIZE, &value); printf("EGL_BLUE_SIZE = %d\n", value); 00344 eglGetConfigAttrib( mEGL_Display, configurations[i], EGL_ALPHA_SIZE, &value); printf("EGL_ALPHA_SIZE = %d\n", value); 00345 eglGetConfigAttrib( mEGL_Display, configurations[i], EGL_DEPTH_SIZE, &value); printf("EGL_DEPTH_SIZE = %d\n", value); 00346 eglGetConfigAttrib( mEGL_Display, configurations[i], EGL_STENCIL_SIZE, &value); printf("EGL_STENCIL_SIZE = %d\n", value); 00347 } 00348 #endif 00349 00350 // Sorting explained here: http://www.khronos.org/opengles/documentation/opengles1_0/html/eglChooseConfig.html 00351 EGLConfig selected_config = configurations[0]; 00352 00353 // Create a surface 00354 mEGL_Surface = eglCreateWindowSurface(mEGL_Display, selected_config, (EGLNativeWindowType)mHWND, NULL); 00355 if ( mEGL_Surface == EGL_NO_SURFACE ) 00356 { 00357 return false; 00358 } 00359 00360 // Create a GL context 00361 mEGL_Context = eglCreateContext(mEGL_Display, selected_config, EGL_NO_CONTEXT, client_version ); 00362 if ( mEGL_Context == EGL_NO_CONTEXT ) 00363 { 00364 return false; 00365 } 00366 00367 // Make the context current 00368 if ( !eglMakeCurrent(mEGL_Display, mEGL_Surface, mEGL_Surface, mEGL_Context) ) 00369 { 00370 return false; 00371 } 00372 00373 if ( !initGLContext() ) 00374 return false; 00375 00376 // register window 00377 mWinMap[mHWND] = this; 00378 00379 // vSync 00380 eglSwapInterval(mEGL_Display, fmt.vSync() ? 1 : 0); 00381 00382 dispatchInitEvent(); 00383 00384 setPosition(x, y); 00385 00386 setSize(width, height); 00387 00388 return true; 00389 } 00390 //----------------------------------------------------------------------------- 00391 void EGLWindow::swapBuffers() 00392 { 00393 // Due to the fact that eglSwapBuffers() can call WM_DESTROY mEGL_Surface might become NULL after calling it. 00394 if ( !eglSwapBuffers(mEGL_Display, mEGL_Surface) && mEGL_Surface ) 00395 { 00396 Log::error("EGLWindow::swapBuffers() failed!\n"); 00397 } 00398 } 00399 //----------------------------------------------------------------------------- 00400 void EGLWindow::makeCurrent() 00401 { 00402 if ( !eglMakeCurrent(mEGL_Display, mEGL_Surface, mEGL_Surface, mEGL_Context) ) 00403 { 00404 Log::error("EGLWindow::makeCurrent() failed!\n"); 00405 } 00406 } 00407 //----------------------------------------------------------------------------- 00408 void EGLWindow::update() 00409 { 00410 if (mHWND) 00411 PostMessage(hwnd(), WM_PAINT, 0, 0); 00412 } 00413 //----------------------------------------------------------------------------- 00414 void EGLWindow::quitApplication() 00415 { 00416 PostQuitMessage(0); 00417 } 00418 //----------------------------------------------------------------------------- 00419 void EGLWindow::setMouseVisible(bool visible) 00420 { 00421 mMouseVisible = visible; 00422 if (visible) 00423 while(ShowCursor(TRUE ) < 0) {} 00424 else 00425 while(ShowCursor(FALSE) >= 0) {} 00426 } 00427 //----------------------------------------------------------------------------- 00428 void EGLWindow::setPosition(int x, int y) 00429 { 00430 if (hwnd()) 00431 SetWindowPos(hwnd(), 0, x, y, 0, 0, SWP_NOSIZE ); 00432 } 00433 //----------------------------------------------------------------------------- 00434 void EGLWindow::setSize(int w, int h) 00435 { 00436 if (hwnd()) 00437 { 00438 RECT windowRect = { 0, 0, w, h }; 00439 AdjustWindowRectEx(&windowRect, (DWORD)GetWindowLongPtr(hwnd(), GWL_STYLE), 0, (DWORD)GetWindowLongPtr(hwnd(), GWL_EXSTYLE) ); 00440 // computes the actual window based on the client dimensions 00441 int cx = windowRect.right - windowRect.left; 00442 int cy = windowRect.bottom - windowRect.top; 00443 SetWindowPos(hwnd(), 0, 0, 0, cx, cy, SWP_NOMOVE ); 00444 } 00445 } 00446 //----------------------------------------------------------------------------- 00447 void EGLWindow::setWindowSize(int w, int h) 00448 { 00449 // Sset by WM_SIZE event handler: 00450 // mFramebuffer->setWidth(w); 00451 // mFramebuffer->setHeight(h); 00452 00453 SetWindowPos(hwnd(), 0, 0, 0, w, h, SWP_NOMOVE); 00454 } 00455 //----------------------------------------------------------------------------- 00456 vl::ivec2 EGLWindow::position() const 00457 { 00458 RECT r = {0,0,0,0}; 00459 if (hwnd()) 00460 GetWindowRect(hwnd(), &r); 00461 return vl::ivec2(r.left,r.top); 00462 } 00463 //----------------------------------------------------------------------------- 00464 vl::ivec2 EGLWindow::windowSize() const 00465 { 00466 RECT r = {0,0,0,0}; 00467 if (hwnd()) 00468 GetWindowRect(hwnd(), &r); 00469 return vl::ivec2(r.right - r.left, r.bottom - r.top); 00470 } 00471 //----------------------------------------------------------------------------- 00472 vl::ivec2 EGLWindow::size() const 00473 { 00474 RECT r = {0,0,0,0}; 00475 if (hwnd()) 00476 GetClientRect(hwnd(), &r); 00477 return vl::ivec2(r.right - r.left, r.bottom - r.top); 00478 } 00479 //----------------------------------------------------------------------------- 00480 void EGLWindow::setWindowTitle(const String& title) 00481 { 00482 if (hwnd()) 00483 SetWindowText(hwnd(), (wchar_t*)title.ptr()); 00484 } 00485 //----------------------------------------------------------------------------- 00486 void EGLWindow::show() 00487 { 00488 if (hwnd()) 00489 ShowWindow(hwnd(), SW_SHOW); 00490 } 00491 //----------------------------------------------------------------------------- 00492 void EGLWindow::hide() 00493 { 00494 if (hwnd()) 00495 ShowWindow(hwnd(), SW_HIDE); 00496 } 00497 //----------------------------------------------------------------------------- 00498 void EGLWindow::getFocus() 00499 { 00500 if (hwnd()) 00501 SetFocus(hwnd()); 00502 } 00503 //----------------------------------------------------------------------------- 00504 void EGLWindow::setMousePosition(int x, int y) 00505 { 00506 if (hwnd()) 00507 { 00508 POINT pt = {x, y}; 00509 ClientToScreen( hwnd(), &pt ); 00510 SetCursorPos(pt.x, pt.y); 00511 } 00512 } 00513 //----------------------------------------------------------------------------- 00514 EGLWindow* EGLWindow::getWindow(HWND hWnd) 00515 { 00516 std::map< HWND, EGLWindow* >::const_iterator it = mWinMap.find(hWnd); 00517 if (it != mWinMap.end()) 00518 return it->second; 00519 else 00520 return NULL; 00521 } 00522 //----------------------------------------------------------------------------- 00523 void EGLWindow::destroyEGLGLWindow() 00524 { 00525 if (hwnd()) 00526 { 00527 bool destroy_win = mWinMap.find(mHWND) != mWinMap.end(); 00528 00529 // WM_DESTROY must be dispatched while the OpenGL context is still available! 00530 if (destroy_win) 00531 { 00532 DestroyWindow(mHWND); 00533 mHWND = NULL; 00534 } 00535 00536 eglDestroyContext ( eglDisplay(), eglContext() ); mEGL_Context = NULL; 00537 eglDestroySurface ( eglDisplay(), eglSurface() ); mEGL_Surface = NULL; 00538 eglTerminate ( eglDisplay() ); mEGL_Display = NULL; 00539 } 00540 } 00541 //----------------------------------------------------------------------------- 00542 void vlEGL::dispatchUpdate() 00543 { 00544 // iterate over all opengl contexts 00545 std::map< HWND, EGLWindow* > wins = EGLWindow::winMap(); 00546 for( std::map< HWND, EGLWindow* >::iterator it = wins.begin(); 00547 it != wins.end(); 00548 ++it ) 00549 { 00550 EGLWindow* win = it->second; 00551 if ( win->continuousUpdate() ) 00552 win->update(); 00553 else 00554 Sleep(10); 00555 } 00556 } 00557 //----------------------------------------------------------------------------- 00558 void vlEGL::peekMessage(MSG& msg) 00559 { 00560 if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) 00561 { 00562 if (msg.message != WM_QUIT) 00563 { 00564 TranslateMessage(&msg); 00565 DispatchMessage(&msg); 00566 } 00567 } 00568 else 00569 dispatchUpdate(); 00570 } 00571 //----------------------------------------------------------------------------- 00572 int vlEGL::messageLoop() 00573 { 00574 while(!EGLWindow::winMap().empty()) 00575 { 00576 MSG msg = {0,0,0,0,0,0,0}; 00577 peekMessage(msg); 00578 if (msg.message == WM_QUIT) 00579 return (int)msg.wParam; 00580 } 00581 return 0; /* never reached */ 00582 } 00583 //----------------------------------------------------------------------------- 00584 void vlEGL::translateKeyEvent(WPARAM wParam, LPARAM lParam, unsigned short& unicode_out, vl::EKey& key_out) 00585 { 00586 // translate non unicode characters 00587 key_out = Key_None; 00588 unicode_out = 0; 00589 00590 switch(wParam) 00591 { 00592 case VK_CLEAR: key_out = Key_Clear; break; 00593 case VK_CONTROL: key_out = Key_Ctrl; break; 00594 case VK_LCONTROL: key_out = Key_LeftCtrl; break; 00595 case VK_RCONTROL: key_out = Key_RightCtrl; break; 00596 case VK_MENU: key_out = Key_Alt; break; 00597 case VK_LMENU: key_out = Key_LeftAlt; break; 00598 case VK_RMENU: key_out = Key_RightAlt; break; 00599 case VK_SHIFT: key_out = Key_Shift; break; 00600 case VK_LSHIFT: key_out = Key_LeftShift; break; 00601 case VK_RSHIFT: key_out = Key_RightShift; break; 00602 case VK_INSERT: key_out = Key_Insert; break; 00603 case VK_DELETE: key_out = Key_Delete; break; 00604 case VK_HOME: key_out = Key_Home; break; 00605 case VK_END: key_out = Key_End; break; 00606 case VK_PRINT: key_out = Key_Print; break; 00607 case VK_PAUSE: key_out = Key_Pause; break; 00608 case VK_PRIOR: key_out = Key_PageUp; break; 00609 case VK_NEXT: key_out = Key_PageDown; break; 00610 case VK_LEFT: key_out = Key_Left; break; 00611 case VK_RIGHT: key_out = Key_Right; break; 00612 case VK_UP: key_out = Key_Up; break; 00613 case VK_DOWN: key_out = Key_Down; break; 00614 case VK_F1: key_out = Key_F1; break; 00615 case VK_F2: key_out = Key_F2; break; 00616 case VK_F3: key_out = Key_F3; break; 00617 case VK_F4: key_out = Key_F4; break; 00618 case VK_F5: key_out = Key_F5; break; 00619 case VK_F6: key_out = Key_F6; break; 00620 case VK_F7: key_out = Key_F7; break; 00621 case VK_F8: key_out = Key_F8; break; 00622 case VK_F9: key_out = Key_F9; break; 00623 case VK_F10: key_out = Key_F10; break; 00624 case VK_F11: key_out = Key_F11; break; 00625 case VK_F12: key_out = Key_F12; break; 00626 00627 /* 00628 * VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39) 00629 * 0x40 : is unassigned 00630 * VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A) 00631 */ 00632 00633 case L'0': key_out = Key_0; break; 00634 case L'1': key_out = Key_1; break; 00635 case L'2': key_out = Key_2; break; 00636 case L'3': key_out = Key_3; break; 00637 case L'4': key_out = Key_4; break; 00638 case L'5': key_out = Key_5; break; 00639 case L'6': key_out = Key_6; break; 00640 case L'7': key_out = Key_7; break; 00641 case L'8': key_out = Key_8; break; 00642 case L'9': key_out = Key_9; break; 00643 00644 case L'A': key_out = Key_A; break; 00645 case L'B': key_out = Key_B; break; 00646 case L'C': key_out = Key_C; break; 00647 case L'D': key_out = Key_D; break; 00648 case L'E': key_out = Key_E; break; 00649 case L'F': key_out = Key_F; break; 00650 case L'G': key_out = Key_G; break; 00651 case L'H': key_out = Key_H; break; 00652 case L'I': key_out = Key_I; break; 00653 case L'J': key_out = Key_J; break; 00654 case L'K': key_out = Key_K; break; 00655 case L'L': key_out = Key_L; break; 00656 case L'M': key_out = Key_M; break; 00657 case L'N': key_out = Key_N; break; 00658 case L'O': key_out = Key_O; break; 00659 case L'P': key_out = Key_P; break; 00660 case L'Q': key_out = Key_Q; break; 00661 case L'R': key_out = Key_R; break; 00662 case L'S': key_out = Key_S; break; 00663 case L'T': key_out = Key_T; break; 00664 case L'U': key_out = Key_U; break; 00665 case L'V': key_out = Key_V; break; 00666 case L'W': key_out = Key_W; break; 00667 case L'X': key_out = Key_X; break; 00668 case L'Y': key_out = Key_Y; break; 00669 case L'Z': key_out = Key_Z; break; 00670 } 00671 00672 // fill unicode 00673 BYTE mskeys[256]; 00674 memset( mskeys, 0, sizeof(BYTE)*256 ); 00675 WCHAR unicode[4] = { 0, 0 }; 00676 if ( ToUnicode( (UINT)wParam, (UINT)((lParam >> 16) & 0xFF), mskeys, unicode, 4, 0 ) == 1 ) 00677 { 00678 unicode_out = unicode[0]; 00679 00680 // fill key 00681 switch(unicode_out) 00682 { 00683 case L'0': key_out = Key_0; break; 00684 case L'1': key_out = Key_1; break; 00685 case L'2': key_out = Key_2; break; 00686 case L'3': key_out = Key_3; break; 00687 case L'4': key_out = Key_4; break; 00688 case L'5': key_out = Key_5; break; 00689 case L'6': key_out = Key_6; break; 00690 case L'7': key_out = Key_7; break; 00691 case L'8': key_out = Key_8; break; 00692 case L'9': key_out = Key_9; break; 00693 00694 case L'A': key_out = Key_A; break; 00695 case L'B': key_out = Key_B; break; 00696 case L'C': key_out = Key_C; break; 00697 case L'D': key_out = Key_D; break; 00698 case L'E': key_out = Key_E; break; 00699 case L'F': key_out = Key_F; break; 00700 case L'G': key_out = Key_G; break; 00701 case L'H': key_out = Key_H; break; 00702 case L'I': key_out = Key_I; break; 00703 case L'J': key_out = Key_J; break; 00704 case L'K': key_out = Key_K; break; 00705 case L'L': key_out = Key_L; break; 00706 case L'M': key_out = Key_M; break; 00707 case L'N': key_out = Key_N; break; 00708 case L'O': key_out = Key_O; break; 00709 case L'P': key_out = Key_P; break; 00710 case L'Q': key_out = Key_Q; break; 00711 case L'R': key_out = Key_R; break; 00712 case L'S': key_out = Key_S; break; 00713 case L'T': key_out = Key_T; break; 00714 case L'U': key_out = Key_U; break; 00715 case L'V': key_out = Key_V; break; 00716 case L'W': key_out = Key_W; break; 00717 case L'X': key_out = Key_X; break; 00718 case L'Y': key_out = Key_Y; break; 00719 case L'Z': key_out = Key_Z; break; 00720 00721 case L'a': key_out = Key_A; break; 00722 case L'b': key_out = Key_B; break; 00723 case L'c': key_out = Key_C; break; 00724 case L'd': key_out = Key_D; break; 00725 case L'e': key_out = Key_E; break; 00726 case L'f': key_out = Key_F; break; 00727 case L'g': key_out = Key_G; break; 00728 case L'h': key_out = Key_H; break; 00729 case L'i': key_out = Key_I; break; 00730 case L'j': key_out = Key_J; break; 00731 case L'k': key_out = Key_K; break; 00732 case L'l': key_out = Key_L; break; 00733 case L'm': key_out = Key_M; break; 00734 case L'n': key_out = Key_N; break; 00735 case L'o': key_out = Key_O; break; 00736 case L'p': key_out = Key_P; break; 00737 case L'q': key_out = Key_Q; break; 00738 case L'r': key_out = Key_R; break; 00739 case L's': key_out = Key_S; break; 00740 case L't': key_out = Key_T; break; 00741 case L'u': key_out = Key_U; break; 00742 case L'v': key_out = Key_V; break; 00743 case L'w': key_out = Key_W; break; 00744 case L'x': key_out = Key_X; break; 00745 case L'y': key_out = Key_Y; break; 00746 case L'z': key_out = Key_Z; break; 00747 00748 case 13: key_out = Key_Return; break; 00749 case 8: key_out = Key_BackSpace; break; 00750 case 9: key_out = Key_Tab; break; 00751 case L' ': key_out = Key_Space; break; 00752 00753 case 27: key_out = Key_Escape; break; 00754 case L'!': key_out = Key_Exclam; break; 00755 case L'"': key_out = Key_QuoteDbl; break; 00756 case L'#': key_out = Key_Hash; break; 00757 case L'$': key_out = Key_Dollar; break; 00758 case L'&': key_out = Key_Ampersand; break; 00759 case L'\'': key_out = Key_Quote; break; 00760 case L'(': key_out = Key_LeftParen; break; 00761 case L')': key_out = Key_RightParen; break; 00762 case L'*': key_out = Key_Asterisk; break; 00763 case L'+': key_out = Key_Plus; break; 00764 case L',': key_out = Key_Comma; break; 00765 case L'-': key_out = Key_Minus; break; 00766 case L'.': key_out = Key_Period; break; 00767 case L'\\': key_out = Key_Slash; break; 00768 case L':': key_out = Key_Colon; break; 00769 case L';': key_out = Key_Semicolon; break; 00770 case L'<': key_out = Key_Less; break; 00771 case L'=': key_out = Key_Equal; break; 00772 case L'>': key_out = Key_Greater; break; 00773 case L'?': key_out = Key_Question; break; 00774 case L'@': key_out = Key_At; break; 00775 case L'[': key_out = Key_LeftBracket; break; 00776 case L'/': key_out = Key_BackSlash; break; 00777 case L']': key_out = Key_RightBracket; break; 00778 case L'|': key_out = Key_Caret; break; 00779 case L'_': key_out = Key_Underscore; break; 00780 case L'`': key_out = Key_QuoteLeft; break; 00781 } 00782 } 00783 } 00784 //-----------------------------------------------------------------------------