00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <vlWin32/Win32Window.hpp>
00033 #include <vlCore/Time.hpp>
00034 #include <shellapi.h>
00035
00036 using namespace vl;
00037 using namespace vlWin32;
00038
00039
00040 namespace vlWin32
00041 {
00042 const wchar_t* gWin32WindowClassName = L"VisualizationLibraryWindowClass";
00043
00044 bool registerClass()
00045 {
00046 static bool class_already_registered = false;
00047 if (!class_already_registered)
00048 {
00049 WNDCLASS wc;
00050 memset(&wc, 0, sizeof(wc));
00051
00052 wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
00053 wc.lpfnWndProc = (WNDPROC)Win32Window::WindowProc;
00054 wc.cbClsExtra = 0;
00055 wc.cbWndExtra = 0;
00056 wc.hInstance = GetModuleHandle(NULL);
00057 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
00058 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
00059 wc.hbrBackground = NULL;
00060 wc.lpszMenuName = NULL;
00061 wc.lpszClassName = gWin32WindowClassName;
00062
00063 if (!RegisterClass(&wc))
00064 MessageBox(NULL, L"Class registration failed.", L"Visualization Library Error", MB_OK);
00065 else
00066 class_already_registered = true;
00067 }
00068 return class_already_registered;
00069 }
00070
00071 #if 0
00072
00073 void win32PrintError(LPTSTR lpszFunction)
00074 {
00075 TCHAR szBuf[80];
00076 LPVOID lpMsgBuf;
00077 DWORD dw = GetLastError();
00078
00079 FormatMessage(
00080 FORMAT_MESSAGE_ALLOCATE_BUFFER |
00081 FORMAT_MESSAGE_FROM_SYSTEM,
00082 NULL,
00083 dw,
00084 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00085 (LPTSTR) &lpMsgBuf,
00086 0, NULL );
00087
00088 wsprintf(szBuf,
00089 L"%s failed with error %d: %s",
00090 lpszFunction, dw, lpMsgBuf);
00091
00092 MessageBox(NULL, szBuf, L"Visualization Library Error", MB_OK);
00093
00094 LocalFree(lpMsgBuf);
00095 }
00096 #endif
00097 }
00098
00099 std::map< HWND, Win32Window* > Win32Window::mWinMap;
00100
00101 LONG WINAPI Win32Window::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00102 {
00103 Win32Window* win = Win32Window::getWindow(hWnd);
00104 if (!win)
00105 return (LONG)DefWindowProc(hWnd, uMsg, wParam, lParam);
00106
00107 switch(uMsg)
00108 {
00109 case WM_PAINT:
00110 {
00111
00112 LONG val = (LONG)DefWindowProc(hWnd, uMsg, wParam, lParam);
00113 if (win->hglrc() && win->hdc() && win->hwnd())
00114 win->dispatchRunEvent();
00115 return val;
00116 }
00117
00118 case WM_SIZE:
00119 {
00120 win->framebuffer()->setWidth( LOWORD(lParam) );
00121 win->framebuffer()->setHeight( HIWORD(lParam) );
00122 win->dispatchResizeEvent( LOWORD(lParam), HIWORD(lParam) );
00123 break;
00124 }
00125
00126 case WM_MOUSEMOVE:
00127 {
00128 POINTS pt = MAKEPOINTS(lParam);
00129 win->dispatchMouseMoveEvent( pt.x, pt.y );
00130 break;
00131 }
00132
00133 case WM_LBUTTONDBLCLK:
00134 case WM_LBUTTONDOWN:
00135 case WM_MBUTTONDBLCLK:
00136 case WM_MBUTTONDOWN:
00137 case WM_RBUTTONDBLCLK:
00138 case WM_RBUTTONDOWN:
00139 {
00140 win->mMouseDownCount++;
00141 if (win->mMouseDownCount == 1)
00142 SetCapture(win->hwnd());
00143 EMouseButton button = UnknownButton;
00144 if (uMsg == WM_LBUTTONDBLCLK || uMsg == WM_LBUTTONDOWN)
00145 button = LeftButton;
00146 else if (uMsg == WM_MBUTTONDBLCLK || uMsg == WM_MBUTTONDOWN)
00147 button = MiddleButton;
00148 else if (uMsg == WM_RBUTTONDBLCLK || uMsg == WM_RBUTTONDOWN)
00149 button = RightButton;
00150 POINTS pt = MAKEPOINTS(lParam);
00151 win->dispatchMouseDownEvent( button, pt.x, pt.y );
00152 break;
00153 }
00154
00155 case WM_LBUTTONUP:
00156 case WM_RBUTTONUP:
00157 case WM_MBUTTONUP:
00158 {
00159 win->mMouseDownCount--;
00160 if (win->mMouseDownCount <= 0)
00161 {
00162 ReleaseCapture();
00163 win->mMouseDownCount = 0;
00164 }
00165 EMouseButton button = UnknownButton;
00166 if (uMsg == WM_LBUTTONUP)
00167 button = LeftButton;
00168 else if (uMsg == WM_MBUTTONUP)
00169 button = MiddleButton;
00170 else if (uMsg == WM_RBUTTONUP)
00171 button = RightButton;
00172 POINTS pt = MAKEPOINTS(lParam);
00173 win->dispatchMouseUpEvent( button, pt.x, pt.y );
00174 break;
00175 }
00176
00177
00178
00179
00180 case WM_MOUSEWHEEL:
00181 {
00182 win->dispatchMouseWheelEvent( GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA );
00183 break;
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 case WM_DESTROY:
00194 {
00195 Win32Window::mWinMap.erase(hWnd);
00196 win->dispatchDestroyEvent();
00197 win->destroyWin32GLWindow();
00198 break;
00199 }
00200
00201 case WM_KEYDOWN:
00202 {
00203 unsigned short unicode_out = 0;
00204 vl::EKey key_out = Key_None;
00205 translateKeyEvent(wParam, lParam, unicode_out, key_out);
00206 win->dispatchKeyPressEvent(unicode_out, key_out);
00207 break;
00208 }
00209
00210 case WM_KEYUP:
00211 {
00212 unsigned short unicode_out = 0;
00213 vl::EKey key_out = Key_None;
00214 translateKeyEvent(wParam, lParam, unicode_out, key_out);
00215 win->dispatchKeyReleaseEvent(unicode_out, key_out);
00216 break;
00217 }
00218
00219 case WM_DROPFILES:
00220 {
00221 HDROP hDrop = (HDROP)wParam;
00222 int count = DragQueryFile(hDrop, 0xFFFFFFFF, 0, 0);
00223 const int char_count = 1024;
00224 std::vector<String> files;
00225 for(int i=0; i<count; ++i)
00226 {
00227 wchar_t file_path[char_count];
00228 memset(file_path, 0, char_count);
00229 DragQueryFile(hDrop,i,file_path,char_count);
00230 files.push_back(file_path);
00231 }
00232 win->dispatchFileDroppedEvent(files);
00233 break;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243 }
00244
00245 return (LONG)DefWindowProc(hWnd, uMsg, wParam, lParam);
00246 }
00247
00248
00249
00250 Win32Window::Win32Window()
00251 {
00252 mHWND = NULL;
00253 mHDC = NULL;
00254 mHGLRC = NULL;
00255 mMouseDownCount = 0;
00256
00257 mStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
00258 mExStyle = WS_EX_APPWINDOW | WS_EX_ACCEPTFILES;
00259 mWindowClassName = gWin32WindowClassName;
00260 }
00261
00262 Win32Window::~Win32Window()
00263 {
00264 destroyWin32GLWindow();
00265 }
00266
00267 bool Win32Window::initWin32GLWindow(HWND parent, HGLRC share_context, const vl::String& title, const vl::OpenGLContextFormat& fmt, int x, int y, int width, int height)
00268 {
00269 destroyWin32GLWindow();
00270
00271 if (!registerClass())
00272 return false;
00273
00274 unsigned style = mStyle & ~(WS_CHILD|WS_OVERLAPPEDWINDOW);;
00275 style |= parent?WS_CHILD:WS_OVERLAPPEDWINDOW;
00276
00277 mHWND = CreateWindowEx(
00278 mExStyle,
00279 mWindowClassName,
00280 L"Visualization Library Win32",
00281 style,
00282 x, y, width, height,
00283 parent, NULL, GetModuleHandle(NULL), NULL);
00284
00285 if (initWin32GLContext(share_context, title, fmt, x, y, width, height))
00286 {
00287 mWinMap[mHWND] = this;
00288 return true;
00289 }
00290 else
00291 return false;
00292 }
00293
00294 Win32Window* Win32Window::getWindow(HWND hWnd)
00295 {
00296 std::map< HWND, Win32Window* >::const_iterator it = mWinMap.find(hWnd);
00297 if (it != mWinMap.end())
00298 return it->second;
00299 else
00300 return NULL;
00301 }
00302
00303 void Win32Window::destroyWin32GLWindow()
00304 {
00305
00306
00307 if (hwnd())
00308 {
00309 bool destroy_win = mWinMap.find(mHWND) != mWinMap.end();
00310
00311
00312 if (destroy_win)
00313 {
00314 DestroyWindow(mHWND);
00315 mHWND = NULL;
00316 }
00317 if (mHGLRC)
00318 {
00319 if ( wglDeleteContext(mHGLRC) == FALSE )
00320 {
00321 MessageBox(NULL, L"OpenGL context creation failed.\n"
00322 L"The handle either doesn't specify a valid context or the context is being used by another thread.", L"Visualization Library Error", MB_OK);
00323 }
00324 mHGLRC = NULL;
00325 }
00326 if (mHDC)
00327 {
00328 DeleteDC(mHDC);
00329 mHDC = NULL;
00330 }
00331 }
00332 }
00333
00334 void vlWin32::dispatchUpdate()
00335 {
00336
00337 std::map< HWND, Win32Window* > wins = Win32Window::winMap();
00338 for( std::map< HWND, Win32Window* >::iterator it = wins.begin();
00339 it != wins.end();
00340 ++it )
00341 {
00342 Win32Window* win = it->second;
00343 if ( win->continuousUpdate() )
00344 win->update();
00345 else
00346 Sleep(10);
00347 }
00348 }
00349
00350 void vlWin32::peekMessage(MSG& msg)
00351 {
00352 if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
00353 {
00354 if (msg.message != WM_QUIT)
00355 {
00356 TranslateMessage(&msg);
00357 DispatchMessage(&msg);
00358 }
00359 }
00360 else
00361 dispatchUpdate();
00362 }
00363
00364 int vlWin32::messageLoop()
00365 {
00366 while(!Win32Window::winMap().empty())
00367 {
00368 MSG msg = {0,0,0,0,0,0,0};
00369 peekMessage(msg);
00370 if (msg.message == WM_QUIT)
00371 return (int)msg.wParam;
00372 }
00373 return 0;
00374 }
00375
00376 void vlWin32::translateKeyEvent(WPARAM wParam, LPARAM lParam, unsigned short& unicode_out, vl::EKey& key_out)
00377 {
00378
00379 key_out = Key_None;
00380 unicode_out = 0;
00381
00382 switch(wParam)
00383 {
00384 case VK_CLEAR: key_out = Key_Clear; break;
00385 case VK_CONTROL: key_out = Key_Ctrl; break;
00386 case VK_LCONTROL: key_out = Key_LeftCtrl; break;
00387 case VK_RCONTROL: key_out = Key_RightCtrl; break;
00388 case VK_MENU: key_out = Key_Alt; break;
00389 case VK_LMENU: key_out = Key_LeftAlt; break;
00390 case VK_RMENU: key_out = Key_RightAlt; break;
00391 case VK_SHIFT: key_out = Key_Shift; break;
00392 case VK_LSHIFT: key_out = Key_LeftShift; break;
00393 case VK_RSHIFT: key_out = Key_RightShift; break;
00394 case VK_INSERT: key_out = Key_Insert; break;
00395 case VK_DELETE: key_out = Key_Delete; break;
00396 case VK_HOME: key_out = Key_Home; break;
00397 case VK_END: key_out = Key_End; break;
00398 case VK_PRINT: key_out = Key_Print; break;
00399 case VK_PAUSE: key_out = Key_Pause; break;
00400 case VK_PRIOR: key_out = Key_PageUp; break;
00401 case VK_NEXT: key_out = Key_PageDown; break;
00402 case VK_LEFT: key_out = Key_Left; break;
00403 case VK_RIGHT: key_out = Key_Right; break;
00404 case VK_UP: key_out = Key_Up; break;
00405 case VK_DOWN: key_out = Key_Down; break;
00406 case VK_F1: key_out = Key_F1; break;
00407 case VK_F2: key_out = Key_F2; break;
00408 case VK_F3: key_out = Key_F3; break;
00409 case VK_F4: key_out = Key_F4; break;
00410 case VK_F5: key_out = Key_F5; break;
00411 case VK_F6: key_out = Key_F6; break;
00412 case VK_F7: key_out = Key_F7; break;
00413 case VK_F8: key_out = Key_F8; break;
00414 case VK_F9: key_out = Key_F9; break;
00415 case VK_F10: key_out = Key_F10; break;
00416 case VK_F11: key_out = Key_F11; break;
00417 case VK_F12: key_out = Key_F12; break;
00418
00419
00420
00421
00422
00423
00424
00425 case L'0': key_out = Key_0; break;
00426 case L'1': key_out = Key_1; break;
00427 case L'2': key_out = Key_2; break;
00428 case L'3': key_out = Key_3; break;
00429 case L'4': key_out = Key_4; break;
00430 case L'5': key_out = Key_5; break;
00431 case L'6': key_out = Key_6; break;
00432 case L'7': key_out = Key_7; break;
00433 case L'8': key_out = Key_8; break;
00434 case L'9': key_out = Key_9; break;
00435
00436 case L'A': key_out = Key_A; break;
00437 case L'B': key_out = Key_B; break;
00438 case L'C': key_out = Key_C; break;
00439 case L'D': key_out = Key_D; break;
00440 case L'E': key_out = Key_E; break;
00441 case L'F': key_out = Key_F; break;
00442 case L'G': key_out = Key_G; break;
00443 case L'H': key_out = Key_H; break;
00444 case L'I': key_out = Key_I; break;
00445 case L'J': key_out = Key_J; break;
00446 case L'K': key_out = Key_K; break;
00447 case L'L': key_out = Key_L; break;
00448 case L'M': key_out = Key_M; break;
00449 case L'N': key_out = Key_N; break;
00450 case L'O': key_out = Key_O; break;
00451 case L'P': key_out = Key_P; break;
00452 case L'Q': key_out = Key_Q; break;
00453 case L'R': key_out = Key_R; break;
00454 case L'S': key_out = Key_S; break;
00455 case L'T': key_out = Key_T; break;
00456 case L'U': key_out = Key_U; break;
00457 case L'V': key_out = Key_V; break;
00458 case L'W': key_out = Key_W; break;
00459 case L'X': key_out = Key_X; break;
00460 case L'Y': key_out = Key_Y; break;
00461 case L'Z': key_out = Key_Z; break;
00462 }
00463
00464
00465 BYTE mskeys[256];
00466 memset( mskeys, 0, sizeof(BYTE)*256 );
00467 WCHAR unicode[4] = { 0, 0 };
00468 if ( ToUnicode( (UINT)wParam, (UINT)((lParam >> 16) & 0xFF), mskeys, unicode, 4, 0 ) == 1 )
00469 {
00470 unicode_out = unicode[0];
00471
00472
00473 switch(unicode_out)
00474 {
00475 case L'0': key_out = Key_0; break;
00476 case L'1': key_out = Key_1; break;
00477 case L'2': key_out = Key_2; break;
00478 case L'3': key_out = Key_3; break;
00479 case L'4': key_out = Key_4; break;
00480 case L'5': key_out = Key_5; break;
00481 case L'6': key_out = Key_6; break;
00482 case L'7': key_out = Key_7; break;
00483 case L'8': key_out = Key_8; break;
00484 case L'9': key_out = Key_9; break;
00485
00486 case L'A': key_out = Key_A; break;
00487 case L'B': key_out = Key_B; break;
00488 case L'C': key_out = Key_C; break;
00489 case L'D': key_out = Key_D; break;
00490 case L'E': key_out = Key_E; break;
00491 case L'F': key_out = Key_F; break;
00492 case L'G': key_out = Key_G; break;
00493 case L'H': key_out = Key_H; break;
00494 case L'I': key_out = Key_I; break;
00495 case L'J': key_out = Key_J; break;
00496 case L'K': key_out = Key_K; break;
00497 case L'L': key_out = Key_L; break;
00498 case L'M': key_out = Key_M; break;
00499 case L'N': key_out = Key_N; break;
00500 case L'O': key_out = Key_O; break;
00501 case L'P': key_out = Key_P; break;
00502 case L'Q': key_out = Key_Q; break;
00503 case L'R': key_out = Key_R; break;
00504 case L'S': key_out = Key_S; break;
00505 case L'T': key_out = Key_T; break;
00506 case L'U': key_out = Key_U; break;
00507 case L'V': key_out = Key_V; break;
00508 case L'W': key_out = Key_W; break;
00509 case L'X': key_out = Key_X; break;
00510 case L'Y': key_out = Key_Y; break;
00511 case L'Z': key_out = Key_Z; break;
00512
00513 case L'a': key_out = Key_A; break;
00514 case L'b': key_out = Key_B; break;
00515 case L'c': key_out = Key_C; break;
00516 case L'd': key_out = Key_D; break;
00517 case L'e': key_out = Key_E; break;
00518 case L'f': key_out = Key_F; break;
00519 case L'g': key_out = Key_G; break;
00520 case L'h': key_out = Key_H; break;
00521 case L'i': key_out = Key_I; break;
00522 case L'j': key_out = Key_J; break;
00523 case L'k': key_out = Key_K; break;
00524 case L'l': key_out = Key_L; break;
00525 case L'm': key_out = Key_M; break;
00526 case L'n': key_out = Key_N; break;
00527 case L'o': key_out = Key_O; break;
00528 case L'p': key_out = Key_P; break;
00529 case L'q': key_out = Key_Q; break;
00530 case L'r': key_out = Key_R; break;
00531 case L's': key_out = Key_S; break;
00532 case L't': key_out = Key_T; break;
00533 case L'u': key_out = Key_U; break;
00534 case L'v': key_out = Key_V; break;
00535 case L'w': key_out = Key_W; break;
00536 case L'x': key_out = Key_X; break;
00537 case L'y': key_out = Key_Y; break;
00538 case L'z': key_out = Key_Z; break;
00539
00540 case 13: key_out = Key_Return; break;
00541 case 8: key_out = Key_BackSpace; break;
00542 case 9: key_out = Key_Tab; break;
00543 case L' ': key_out = Key_Space; break;
00544
00545 case 27: key_out = Key_Escape; break;
00546 case L'!': key_out = Key_Exclam; break;
00547 case L'"': key_out = Key_QuoteDbl; break;
00548 case L'#': key_out = Key_Hash; break;
00549 case L'$': key_out = Key_Dollar; break;
00550 case L'&': key_out = Key_Ampersand; break;
00551 case L'\'': key_out = Key_Quote; break;
00552 case L'(': key_out = Key_LeftParen; break;
00553 case L')': key_out = Key_RightParen; break;
00554 case L'*': key_out = Key_Asterisk; break;
00555 case L'+': key_out = Key_Plus; break;
00556 case L',': key_out = Key_Comma; break;
00557 case L'-': key_out = Key_Minus; break;
00558 case L'.': key_out = Key_Period; break;
00559 case L'\\': key_out = Key_Slash; break;
00560 case L':': key_out = Key_Colon; break;
00561 case L';': key_out = Key_Semicolon; break;
00562 case L'<': key_out = Key_Less; break;
00563 case L'=': key_out = Key_Equal; break;
00564 case L'>': key_out = Key_Greater; break;
00565 case L'?': key_out = Key_Question; break;
00566 case L'@': key_out = Key_At; break;
00567 case L'[': key_out = Key_LeftBracket; break;
00568 case L'/': key_out = Key_BackSlash; break;
00569 case L']': key_out = Key_RightBracket; break;
00570 case L'|': key_out = Key_Caret; break;
00571 case L'_': key_out = Key_Underscore; break;
00572 case L'`': key_out = Key_QuoteLeft; break;
00573 }
00574 }
00575 }
00576