|
Blender
V2.59
|
00001 /* 00002 * $Id: GHOST_SystemWin32.cpp 39007 2011-08-04 03:14:00Z merwin $ 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): none yet. 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00042 #ifdef BF_GHOST_DEBUG 00043 #include <iostream> 00044 #endif 00045 00046 #include <stdio.h> // [mce] temporary debug, remove soon! 00047 00048 #include "GHOST_SystemWin32.h" 00049 #include "GHOST_EventDragnDrop.h" 00050 00051 #ifndef _WIN32_IE 00052 #define _WIN32_IE 0x0501 /* shipped before XP, so doesn't impose additional requirements */ 00053 #endif 00054 #include <shlobj.h> 00055 #include <tlhelp32.h> 00056 00057 // win64 doesn't define GWL_USERDATA 00058 #ifdef WIN32 00059 #ifndef GWL_USERDATA 00060 #define GWL_USERDATA GWLP_USERDATA 00061 #define GWL_WNDPROC GWLP_WNDPROC 00062 #endif 00063 #endif 00064 00065 #include "GHOST_DisplayManagerWin32.h" 00066 #include "GHOST_EventButton.h" 00067 #include "GHOST_EventCursor.h" 00068 #include "GHOST_EventKey.h" 00069 #include "GHOST_EventWheel.h" 00070 #include "GHOST_TimerTask.h" 00071 #include "GHOST_TimerManager.h" 00072 #include "GHOST_WindowManager.h" 00073 #include "GHOST_WindowWin32.h" 00074 00075 #ifdef WITH_INPUT_NDOF 00076 #include "GHOST_NDOFManagerWin32.h" 00077 #endif 00078 00079 // Key code values not found in winuser.h 00080 #ifndef VK_MINUS 00081 #define VK_MINUS 0xBD 00082 #endif // VK_MINUS 00083 #ifndef VK_SEMICOLON 00084 #define VK_SEMICOLON 0xBA 00085 #endif // VK_SEMICOLON 00086 #ifndef VK_PERIOD 00087 #define VK_PERIOD 0xBE 00088 #endif // VK_PERIOD 00089 #ifndef VK_COMMA 00090 #define VK_COMMA 0xBC 00091 #endif // VK_COMMA 00092 #ifndef VK_QUOTE 00093 #define VK_QUOTE 0xDE 00094 #endif // VK_QUOTE 00095 #ifndef VK_BACK_QUOTE 00096 #define VK_BACK_QUOTE 0xC0 00097 #endif // VK_BACK_QUOTE 00098 #ifndef VK_SLASH 00099 #define VK_SLASH 0xBF 00100 #endif // VK_SLASH 00101 #ifndef VK_BACK_SLASH 00102 #define VK_BACK_SLASH 0xDC 00103 #endif // VK_BACK_SLASH 00104 #ifndef VK_EQUALS 00105 #define VK_EQUALS 0xBB 00106 #endif // VK_EQUALS 00107 #ifndef VK_OPEN_BRACKET 00108 #define VK_OPEN_BRACKET 0xDB 00109 #endif // VK_OPEN_BRACKET 00110 #ifndef VK_CLOSE_BRACKET 00111 #define VK_CLOSE_BRACKET 0xDD 00112 #endif // VK_CLOSE_BRACKET 00113 #ifndef VK_GR_LESS 00114 #define VK_GR_LESS 0xE2 00115 #endif // VK_GR_LESS 00116 00117 #ifndef VK_MEDIA_NEXT_TRACK 00118 #define VK_MEDIA_NEXT_TRACK 0xB0 00119 #endif // VK_MEDIA_NEXT_TRACK 00120 #ifndef VK_MEDIA_PREV_TRACK 00121 #define VK_MEDIA_PREV_TRACK 0xB1 00122 #endif // VK_MEDIA_PREV_TRACK 00123 #ifndef VK_MEDIA_STOP 00124 #define VK_MEDIA_STOP 0xB2 00125 #endif // VK_MEDIA_STOP 00126 #ifndef VK_MEDIA_PLAY_PAUSE 00127 #define VK_MEDIA_PLAY_PAUSE 0xB3 00128 #endif // VK_MEDIA_PLAY_PAUSE 00129 00130 static void initRawInput() 00131 { 00132 #ifdef WITH_INPUT_NDOF 00133 #define DEVICE_COUNT 2 00134 #else 00135 #define DEVICE_COUNT 1 00136 #endif 00137 00138 RAWINPUTDEVICE devices[DEVICE_COUNT]; 00139 memset(devices, 0, DEVICE_COUNT * sizeof(RAWINPUTDEVICE)); 00140 00141 // Initiates WM_INPUT messages from keyboard 00142 // That way GHOST can retrieve true keys 00143 devices[0].usUsagePage = 0x01; 00144 devices[0].usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */ 00145 00146 #ifdef WITH_INPUT_NDOF 00147 // multi-axis mouse (SpaceNavigator, etc.) 00148 devices[1].usUsagePage = 0x01; 00149 devices[1].usUsage = 0x08; 00150 #endif 00151 00152 if (RegisterRawInputDevices(devices, DEVICE_COUNT, sizeof(RAWINPUTDEVICE))) 00153 ; // yay! 00154 else 00155 printf("could not register for RawInput: %d\n", (int)GetLastError()); 00156 00157 #undef DEVICE_COUNT 00158 } 00159 00160 GHOST_SystemWin32::GHOST_SystemWin32() 00161 : m_hasPerformanceCounter(false), m_freq(0), m_start(0) 00162 { 00163 m_displayManager = new GHOST_DisplayManagerWin32 (); 00164 GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n"); 00165 m_displayManager->initialize(); 00166 00167 m_consoleStatus = 1; 00168 00169 // Check if current keyboard layout uses AltGr and save keylayout ID for 00170 // specialized handling if keys like VK_OEM_*. I.e. french keylayout 00171 // generates VK_OEM_8 for their exclamation key (key left of right shift) 00172 this->handleKeyboardChange(); 00173 // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. 00174 OleInitialize(0); 00175 00176 #ifdef WITH_INPUT_NDOF 00177 m_ndofManager = new GHOST_NDOFManagerWin32(*this); 00178 #endif 00179 } 00180 00181 GHOST_SystemWin32::~GHOST_SystemWin32() 00182 { 00183 // Shutdown COM 00184 OleUninitialize(); 00185 toggleConsole(1); 00186 } 00187 00188 00189 GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const 00190 { 00191 // Hardware does not support high resolution timers. We will use GetTickCount instead then. 00192 if (!m_hasPerformanceCounter) { 00193 return ::GetTickCount(); 00194 } 00195 00196 // Retrieve current count 00197 __int64 count = 0; 00198 ::QueryPerformanceCounter((LARGE_INTEGER*)&count); 00199 00200 // Calculate the time passed since system initialization. 00201 __int64 delta = 1000*(count-m_start); 00202 00203 GHOST_TUns64 t = (GHOST_TUns64)(delta/m_freq); 00204 return t; 00205 } 00206 00207 00208 GHOST_TUns8 GHOST_SystemWin32::getNumDisplays() const 00209 { 00210 GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::getNumDisplays(): m_displayManager==0\n"); 00211 GHOST_TUns8 numDisplays; 00212 m_displayManager->getNumDisplays(numDisplays); 00213 return numDisplays; 00214 } 00215 00216 00217 void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const 00218 { 00219 width = ::GetSystemMetrics(SM_CXSCREEN); 00220 height= ::GetSystemMetrics(SM_CYSCREEN); 00221 } 00222 00223 00224 GHOST_IWindow* GHOST_SystemWin32::createWindow( 00225 const STR_String& title, 00226 GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, 00227 GHOST_TWindowState state, GHOST_TDrawingContextType type, 00228 bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow ) 00229 { 00230 GHOST_Window* window = 0; 00231 window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples, parentWindow); 00232 if (window) { 00233 if (window->getValid()) { 00234 // Store the pointer to the window 00235 // if (state != GHOST_kWindowStateFullScreen) { 00236 m_windowManager->addWindow(window); 00237 m_windowManager->setActiveWindow(window); 00238 // } 00239 } 00240 else { 00241 00242 // Invalid parent window hwnd 00243 if (((GHOST_WindowWin32*)window)->getNextWindow() == NULL) { 00244 delete window; 00245 window = 0; 00246 return window; 00247 } 00248 00249 // An invalid window could be one that was used to test for AA 00250 window = ((GHOST_WindowWin32*)window)->getNextWindow(); 00251 00252 // If another window is found, let the wm know about that one, but not the old one 00253 if (window->getValid()) { 00254 m_windowManager->addWindow(window); 00255 } 00256 else { 00257 delete window; 00258 window = 0; 00259 } 00260 00261 } 00262 } 00263 return window; 00264 } 00265 00266 00267 bool GHOST_SystemWin32::processEvents(bool waitForEvent) 00268 { 00269 MSG msg; 00270 bool anyProcessed = false; 00271 00272 do { 00273 GHOST_TimerManager* timerMgr = getTimerManager(); 00274 00275 if (waitForEvent && !::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) { 00276 #if 1 00277 ::Sleep(1); 00278 #else 00279 GHOST_TUns64 next = timerMgr->nextFireTime(); 00280 GHOST_TInt64 maxSleep = next - getMilliSeconds(); 00281 00282 if (next == GHOST_kFireTimeNever) { 00283 ::WaitMessage(); 00284 } else if(maxSleep >= 0.0) { 00285 ::SetTimer(NULL, 0, maxSleep, NULL); 00286 ::WaitMessage(); 00287 ::KillTimer(NULL, 0); 00288 } 00289 #endif 00290 } 00291 00292 if (timerMgr->fireTimers(getMilliSeconds())) { 00293 anyProcessed = true; 00294 } 00295 00296 // Process all the events waiting for us 00297 while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0) { 00298 ::DispatchMessage(&msg); 00299 anyProcessed = true; 00300 } 00301 } while (waitForEvent && !anyProcessed); 00302 00303 return anyProcessed; 00304 } 00305 00306 00307 GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const 00308 { 00309 POINT point; 00310 if(::GetCursorPos(&point)){ 00311 x = point.x; 00312 y = point.y; 00313 return GHOST_kSuccess; 00314 } 00315 return GHOST_kFailure; 00316 } 00317 00318 00319 GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) 00320 { 00321 if (!GetActiveWindow()) 00322 return GHOST_kFailure; 00323 return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure; 00324 } 00325 00326 00327 GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) const 00328 { 00329 bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0; 00330 keys.set(GHOST_kModifierKeyLeftShift, down); 00331 down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0; 00332 keys.set(GHOST_kModifierKeyRightShift, down); 00333 00334 down = HIBYTE(::GetKeyState(VK_LMENU)) != 0; 00335 keys.set(GHOST_kModifierKeyLeftAlt, down); 00336 down = HIBYTE(::GetKeyState(VK_RMENU)) != 0; 00337 keys.set(GHOST_kModifierKeyRightAlt, down); 00338 00339 down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 0; 00340 keys.set(GHOST_kModifierKeyLeftControl, down); 00341 down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0; 00342 keys.set(GHOST_kModifierKeyRightControl, down); 00343 00344 bool lwindown = HIBYTE(::GetKeyState(VK_LWIN)) != 0; 00345 bool rwindown = HIBYTE(::GetKeyState(VK_RWIN)) != 0; 00346 if(lwindown || rwindown) 00347 keys.set(GHOST_kModifierKeyOS, true); 00348 else 00349 keys.set(GHOST_kModifierKeyOS, false); 00350 return GHOST_kSuccess; 00351 } 00352 00353 00354 GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons& buttons) const 00355 { 00356 /* Check for swapped buttons (left-handed mouse buttons) 00357 * GetAsyncKeyState() will give back the state of the physical mouse buttons. 00358 */ 00359 bool swapped = ::GetSystemMetrics(SM_SWAPBUTTON) == TRUE; 00360 00361 bool down = HIBYTE(::GetKeyState(VK_LBUTTON)) != 0; 00362 buttons.set(swapped ? GHOST_kButtonMaskRight : GHOST_kButtonMaskLeft, down); 00363 00364 down = HIBYTE(::GetKeyState(VK_MBUTTON)) != 0; 00365 buttons.set(GHOST_kButtonMaskMiddle, down); 00366 00367 down = HIBYTE(::GetKeyState(VK_RBUTTON)) != 0; 00368 buttons.set(swapped ? GHOST_kButtonMaskLeft : GHOST_kButtonMaskRight, down); 00369 return GHOST_kSuccess; 00370 } 00371 00372 00373 GHOST_TSuccess GHOST_SystemWin32::init() 00374 { 00375 GHOST_TSuccess success = GHOST_System::init(); 00376 00377 /* Disable scaling on high DPI displays on Vista */ 00378 HMODULE 00379 user32 = ::LoadLibraryA("user32.dll"); 00380 typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)(); 00381 LPFNSETPROCESSDPIAWARE SetProcessDPIAware = 00382 (LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware"); 00383 if (SetProcessDPIAware) 00384 SetProcessDPIAware(); 00385 FreeLibrary(user32); 00386 initRawInput(); 00387 00388 // Determine whether this system has a high frequency performance counter. */ 00389 m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE; 00390 if (m_hasPerformanceCounter) { 00391 GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer available\n") 00392 ::QueryPerformanceCounter((LARGE_INTEGER*)&m_start); 00393 } 00394 else { 00395 GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer not available\n") 00396 } 00397 00398 if (success) { 00399 WNDCLASS wc; 00400 wc.style= CS_HREDRAW | CS_VREDRAW; 00401 wc.lpfnWndProc= s_wndProc; 00402 wc.cbClsExtra= 0; 00403 wc.cbWndExtra= 0; 00404 wc.hInstance= ::GetModuleHandle(0); 00405 wc.hIcon = ::LoadIcon(wc.hInstance, "APPICON"); 00406 00407 if (!wc.hIcon) { 00408 ::LoadIcon(NULL, IDI_APPLICATION); 00409 } 00410 wc.hCursor = ::LoadCursor(0, IDC_ARROW); 00411 wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH); 00412 wc.lpszMenuName = 0; 00413 wc.lpszClassName= GHOST_WindowWin32::getWindowClassName(); 00414 00415 // Use RegisterClassEx for setting small icon 00416 if (::RegisterClass(&wc) == 0) { 00417 success = GHOST_kFailure; 00418 } 00419 } 00420 00421 return success; 00422 } 00423 00424 00425 GHOST_TSuccess GHOST_SystemWin32::exit() 00426 { 00427 return GHOST_System::exit(); 00428 } 00429 00430 GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int * keyDown, char * vk) 00431 { 00432 GHOST_TKey key = GHOST_kKeyUnknown; 00433 00434 00435 if(!keyDown) 00436 return GHOST_kKeyUnknown; 00437 00438 00439 GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); 00440 00441 GHOST_ModifierKeys modifiers; 00442 system->retrieveModifierKeys(modifiers); 00443 00444 *keyDown = !(raw.data.keyboard.Flags & RI_KEY_BREAK); 00445 key = this->convertKey(window, raw.data.keyboard.VKey, raw.data.keyboard.MakeCode, (raw.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0))); 00446 00447 // extra handling of modifier keys: don't send repeats out from GHOST 00448 if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt) 00449 { 00450 bool changed = false; 00451 GHOST_TModifierKeyMask modifier; 00452 switch(key) { 00453 case GHOST_kKeyLeftShift: 00454 { 00455 changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown); 00456 modifier = GHOST_kModifierKeyLeftShift; 00457 } 00458 break; 00459 case GHOST_kKeyRightShift: 00460 { 00461 changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown); 00462 modifier = GHOST_kModifierKeyRightShift; 00463 } 00464 break; 00465 case GHOST_kKeyLeftControl: 00466 { 00467 changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown); 00468 modifier = GHOST_kModifierKeyLeftControl; 00469 } 00470 break; 00471 case GHOST_kKeyRightControl: 00472 { 00473 changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown); 00474 modifier = GHOST_kModifierKeyRightControl; 00475 } 00476 break; 00477 case GHOST_kKeyLeftAlt: 00478 { 00479 changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown); 00480 modifier = GHOST_kModifierKeyLeftAlt; 00481 } 00482 break; 00483 case GHOST_kKeyRightAlt: 00484 { 00485 changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown); 00486 modifier = GHOST_kModifierKeyRightAlt; 00487 } 00488 break; 00489 default: break; 00490 } 00491 00492 if(changed) 00493 { 00494 modifiers.set(modifier, (bool)*keyDown); 00495 system->storeModifierKeys(modifiers); 00496 } 00497 else 00498 { 00499 key = GHOST_kKeyUnknown; 00500 } 00501 } 00502 00503 00504 if(vk) *vk = raw.data.keyboard.VKey; 00505 00506 return key; 00507 } 00508 00510 // This function was added in response to bug [#25715] 00511 GHOST_TKey GHOST_SystemWin32::processSpecialKey(GHOST_IWindow *window, short vKey, short scanCode) const 00512 { 00513 GHOST_TKey key = GHOST_kKeyUnknown; 00514 switch(PRIMARYLANGID(m_langId)) { 00515 case LANG_FRENCH: 00516 if(vKey==VK_OEM_8) key = GHOST_kKeyF13; // oem key; used purely for shortcuts . 00517 break; 00518 } 00519 00520 return key; 00521 } 00522 00523 GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, short vKey, short scanCode, short extend) const 00524 { 00525 GHOST_TKey key; 00526 00527 if ((vKey >= '0') && (vKey <= '9')) { 00528 // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) 00529 key = (GHOST_TKey)(vKey - '0' + GHOST_kKey0); 00530 } 00531 else if ((vKey >= 'A') && (vKey <= 'Z')) { 00532 // VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) 00533 key = (GHOST_TKey)(vKey - 'A' + GHOST_kKeyA); 00534 } 00535 else if ((vKey >= VK_F1) && (vKey <= VK_F24)) { 00536 key = (GHOST_TKey)(vKey - VK_F1 + GHOST_kKeyF1); 00537 } 00538 else { 00539 switch (vKey) { 00540 case VK_RETURN: 00541 key = (extend)?GHOST_kKeyNumpadEnter : GHOST_kKeyEnter; break; 00542 00543 case VK_BACK: key = GHOST_kKeyBackSpace; break; 00544 case VK_TAB: key = GHOST_kKeyTab; break; 00545 case VK_ESCAPE: key = GHOST_kKeyEsc; break; 00546 case VK_SPACE: key = GHOST_kKeySpace; break; 00547 00548 case VK_INSERT: 00549 case VK_NUMPAD0: 00550 key = (extend) ? GHOST_kKeyInsert : GHOST_kKeyNumpad0; break; 00551 case VK_END: 00552 case VK_NUMPAD1: 00553 key = (extend) ? GHOST_kKeyEnd : GHOST_kKeyNumpad1; break; 00554 case VK_DOWN: 00555 case VK_NUMPAD2: 00556 key = (extend) ? GHOST_kKeyDownArrow : GHOST_kKeyNumpad2; break; 00557 case VK_NEXT: 00558 case VK_NUMPAD3: 00559 key = (extend) ? GHOST_kKeyDownPage : GHOST_kKeyNumpad3; break; 00560 case VK_LEFT: 00561 case VK_NUMPAD4: 00562 key = (extend) ? GHOST_kKeyLeftArrow : GHOST_kKeyNumpad4; break; 00563 case VK_CLEAR: 00564 case VK_NUMPAD5: 00565 key = (extend) ? GHOST_kKeyUnknown: GHOST_kKeyNumpad5; break; 00566 case VK_RIGHT: 00567 case VK_NUMPAD6: 00568 key = (extend) ? GHOST_kKeyRightArrow : GHOST_kKeyNumpad6; break; 00569 case VK_HOME: 00570 case VK_NUMPAD7: 00571 key = (extend) ? GHOST_kKeyHome : GHOST_kKeyNumpad7; break; 00572 case VK_UP: 00573 case VK_NUMPAD8: 00574 key = (extend) ? GHOST_kKeyUpArrow : GHOST_kKeyNumpad8; break; 00575 case VK_PRIOR: 00576 case VK_NUMPAD9: 00577 key = (extend) ? GHOST_kKeyUpPage : GHOST_kKeyNumpad9; break; 00578 case VK_DECIMAL: 00579 case VK_DELETE: 00580 key = (extend) ? GHOST_kKeyDelete : GHOST_kKeyNumpadPeriod; break; 00581 00582 case VK_SNAPSHOT: key = GHOST_kKeyPrintScreen; break; 00583 case VK_PAUSE: key = GHOST_kKeyPause; break; 00584 case VK_MULTIPLY: key = GHOST_kKeyNumpadAsterisk; break; 00585 case VK_SUBTRACT: key = GHOST_kKeyNumpadMinus; break; 00586 case VK_DIVIDE: key = GHOST_kKeyNumpadSlash; break; 00587 case VK_ADD: key = GHOST_kKeyNumpadPlus; break; 00588 00589 case VK_SEMICOLON: key = GHOST_kKeySemicolon; break; 00590 case VK_EQUALS: key = GHOST_kKeyEqual; break; 00591 case VK_COMMA: key = GHOST_kKeyComma; break; 00592 case VK_MINUS: key = GHOST_kKeyMinus; break; 00593 case VK_PERIOD: key = GHOST_kKeyPeriod; break; 00594 case VK_SLASH: key = GHOST_kKeySlash; break; 00595 case VK_BACK_QUOTE: key = GHOST_kKeyAccentGrave; break; 00596 case VK_OPEN_BRACKET: key = GHOST_kKeyLeftBracket; break; 00597 case VK_BACK_SLASH: key = GHOST_kKeyBackslash; break; 00598 case VK_CLOSE_BRACKET: key = GHOST_kKeyRightBracket; break; 00599 case VK_QUOTE: key = GHOST_kKeyQuote; break; 00600 case VK_GR_LESS: key = GHOST_kKeyGrLess; break; 00601 00602 case VK_SHIFT: 00603 key = (scanCode == 0x36)? GHOST_kKeyRightShift : GHOST_kKeyLeftShift; 00604 break; 00605 case VK_CONTROL: 00606 key = (extend)? GHOST_kKeyRightControl : GHOST_kKeyLeftControl; 00607 break; 00608 case VK_MENU: 00609 key = (extend)? GHOST_kKeyRightAlt : GHOST_kKeyLeftAlt; 00610 break; 00611 case VK_LWIN: 00612 case VK_RWIN: 00613 key = GHOST_kKeyOS; 00614 break; 00615 case VK_NUMLOCK: key = GHOST_kKeyNumLock; break; 00616 case VK_SCROLL: key = GHOST_kKeyScrollLock; break; 00617 case VK_CAPITAL: key = GHOST_kKeyCapsLock; break; 00618 case VK_OEM_8: 00619 key = ((GHOST_SystemWin32*)getSystem())->processSpecialKey(window, vKey, scanCode); 00620 break; 00621 case VK_MEDIA_PLAY_PAUSE: key = GHOST_kKeyMediaPlay; break; 00622 case VK_MEDIA_STOP: key = GHOST_kKeyMediaStop; break; 00623 case VK_MEDIA_PREV_TRACK: key = GHOST_kKeyMediaFirst; break; 00624 case VK_MEDIA_NEXT_TRACK: key = GHOST_kKeyMediaLast; break; 00625 default: 00626 key = GHOST_kKeyUnknown; 00627 break; 00628 } 00629 } 00630 00631 return key; 00632 } 00633 00634 GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask) 00635 { 00636 return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask); 00637 } 00638 00639 00640 GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow) 00641 { 00642 GHOST_TInt32 x_screen, y_screen; 00643 GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem()); 00644 GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow; 00645 00646 system->getCursorPosition(x_screen, y_screen); 00647 00648 if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal) 00649 { 00650 GHOST_TInt32 x_new= x_screen; 00651 GHOST_TInt32 y_new= y_screen; 00652 GHOST_TInt32 x_accum, y_accum; 00653 GHOST_Rect bounds; 00654 00655 /* fallback to window bounds */ 00656 if(window->getCursorGrabBounds(bounds)==GHOST_kFailure){ 00657 window->getClientBounds(bounds); 00658 } 00659 00660 /* could also clamp to screen bounds 00661 * wrap with a window outside the view will fail atm */ 00662 00663 bounds.wrapPoint(x_new, y_new, 2); /* offset of one incase blender is at screen bounds */ 00664 00665 window->getCursorGrabAccum(x_accum, y_accum); 00666 if(x_new != x_screen|| y_new != y_screen) { 00667 /* when wrapping we don't need to add an event because the 00668 * setCursorPosition call will cause a new event after */ 00669 system->setCursorPosition(x_new, y_new); /* wrap */ 00670 window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new)); 00671 }else{ 00672 return new GHOST_EventCursor(system->getMilliSeconds(), 00673 GHOST_kEventCursorMove, 00674 window, 00675 x_screen + x_accum, 00676 y_screen + y_accum 00677 ); 00678 } 00679 00680 } 00681 else { 00682 return new GHOST_EventCursor(system->getMilliSeconds(), 00683 GHOST_kEventCursorMove, 00684 window, 00685 x_screen, 00686 y_screen 00687 ); 00688 } 00689 return NULL; 00690 } 00691 00692 00693 GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam) 00694 { 00695 // short fwKeys = LOWORD(wParam); // key flags 00696 int zDelta = (short) HIWORD(wParam); // wheel rotation 00697 00698 // zDelta /= WHEEL_DELTA; 00699 // temporary fix below: microsoft now has added more precision, making the above division not work 00700 if (zDelta <= 0 ) zDelta= -1; else zDelta= 1; 00701 00702 // short xPos = (short) LOWORD(lParam); // horizontal position of pointer 00703 // short yPos = (short) HIWORD(lParam); // vertical position of pointer 00704 return new GHOST_EventWheel (getSystem()->getMilliSeconds(), window, zDelta); 00705 } 00706 00707 00708 GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw) 00709 { 00710 int keyDown=0; 00711 char vk; 00712 GHOST_SystemWin32 * system = (GHOST_SystemWin32 *)getSystem(); 00713 GHOST_TKey key = system->hardKey(window, raw, &keyDown, &vk); 00714 GHOST_EventKey* event; 00715 if (key != GHOST_kKeyUnknown) { 00716 char ascii = '\0'; 00717 00718 unsigned short utf16[2]={0}; 00719 BYTE state[256]; 00720 GetKeyboardState((PBYTE)state); 00721 00722 if(ToAsciiEx(vk, 0, state, utf16, 0, system->m_keylayout)) 00723 WideCharToMultiByte(CP_ACP, 0x00000400, 00724 (wchar_t*)utf16, 1, 00725 (LPSTR) &ascii, 1, 00726 NULL,NULL); 00727 00728 event = new GHOST_EventKey(system->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii); 00729 00730 #ifdef GHOST_DEBUG 00731 std::cout << ascii << std::endl; 00732 #endif 00733 } 00734 else { 00735 event = 0; 00736 } 00737 return event; 00738 } 00739 00740 00741 GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window) 00742 { 00743 GHOST_System* system = (GHOST_System*)getSystem(); 00744 00745 if (type == GHOST_kEventWindowActivate) { 00746 system->getWindowManager()->setActiveWindow(window); 00747 } 00748 00749 return new GHOST_Event(system->getMilliSeconds(), type, window); 00750 } 00751 00752 GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType, 00753 GHOST_TDragnDropTypes draggedObjectType, 00754 GHOST_IWindow* window, 00755 int mouseX, int mouseY, 00756 void* data) 00757 { 00758 GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem()); 00759 return system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(), 00760 eventType, 00761 draggedObjectType, 00762 window,mouseX,mouseY,data) 00763 ); 00764 } 00765 00766 void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax) 00767 { 00768 minmax->ptMinTrackSize.x=320; 00769 minmax->ptMinTrackSize.y=240; 00770 } 00771 00772 #ifdef WITH_INPUT_NDOF 00773 bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) 00774 { 00775 bool eventSent = false; 00776 GHOST_TUns64 now = getMilliSeconds(); 00777 00778 static bool firstEvent = true; 00779 if (firstEvent) { // determine exactly which device is plugged in 00780 RID_DEVICE_INFO info; 00781 unsigned infoSize = sizeof(RID_DEVICE_INFO); 00782 info.cbSize = infoSize; 00783 00784 GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize); 00785 if (info.dwType == RIM_TYPEHID) 00786 m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId); 00787 else 00788 puts("<!> not a HID device... mouse/kb perhaps?"); 00789 00790 firstEvent = false; 00791 } 00792 00793 // The NDOF manager sends button changes immediately, and *pretends* to 00794 // send motion. Mark as 'sent' so motion will always get dispatched. 00795 eventSent = true; 00796 00797 #ifdef _MSC_VER 00798 // using Microsoft compiler & header files 00799 // they invented the RawInput API, so this version is (probably) correct 00800 BYTE const* data = raw.data.hid.bRawData; 00801 // struct RAWHID { 00802 // DWORD dwSizeHid; 00803 // DWORD dwCount; 00804 // BYTE bRawData[1]; 00805 // }; 00806 #else 00807 // MinGW's definition (below) doesn't agree, so we need a slight 00808 // workaround until it's fixed 00809 BYTE const* data = &raw.data.hid.bRawData; 00810 // struct RAWHID { 00811 // DWORD dwSizeHid; 00812 // DWORD dwCount; 00813 // BYTE bRawData; // <== isn't this s'posed to be a BYTE*? 00814 // }; 00815 #endif 00816 00817 BYTE packetType = data[0]; 00818 switch (packetType) 00819 { 00820 case 1: // translation 00821 { 00822 short* axis = (short*)(data + 1); 00823 // massage into blender view coords (same goes for rotation) 00824 short t[3] = {axis[0], -axis[2], axis[1]}; 00825 m_ndofManager->updateTranslation(t, now); 00826 00827 if (raw.data.hid.dwSizeHid == 13) 00828 { // this report also includes rotation 00829 short r[3] = {-axis[3], axis[5], -axis[4]}; 00830 m_ndofManager->updateRotation(r, now); 00831 00832 // I've never gotten one of these, has anyone else? 00833 puts("ndof: combined T + R"); 00834 } 00835 break; 00836 } 00837 case 2: // rotation 00838 { 00839 short* axis = (short*)(data + 1); 00840 short r[3] = {-axis[0], axis[2], -axis[1]}; 00841 m_ndofManager->updateRotation(r, now); 00842 break; 00843 } 00844 case 3: // buttons 00845 { 00846 int button_bits; 00847 memcpy(&button_bits, data + 1, sizeof(button_bits)); 00848 m_ndofManager->updateButtons(button_bits, now); 00849 break; 00850 } 00851 } 00852 return eventSent; 00853 } 00854 #endif // WITH_INPUT_NDOF 00855 00856 LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 00857 { 00858 GHOST_Event* event = 0; 00859 bool eventHandled = false; 00860 00861 LRESULT lResult = 0; 00862 GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem()); 00863 GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized") 00864 00865 if (hwnd) { 00866 GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA); 00867 if (window) { 00868 switch (msg) { 00869 // we need to check if new key layout has AltGr 00870 case WM_INPUTLANGCHANGE: 00871 system->handleKeyboardChange(); 00872 break; 00874 // Keyboard events, processed 00876 case WM_INPUT: 00877 { 00878 // check WM_INPUT from input sink when ghost window is not in the foreground 00879 if (wParam == RIM_INPUTSINK) { 00880 if (GetFocus() != hwnd) // WM_INPUT message not for this window 00881 return 0; 00882 } //else wParam == RIM_INPUT 00883 00884 RAWINPUT raw; 00885 RAWINPUT* raw_ptr = &raw; 00886 UINT rawSize = sizeof(RAWINPUT); 00887 00888 GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); 00889 00890 switch (raw.header.dwType) 00891 { 00892 case RIM_TYPEKEYBOARD: 00893 event = processKeyEvent(window, raw); 00894 if (!event) { 00895 GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") 00896 GHOST_PRINT(msg) 00897 GHOST_PRINT(" key ignored\n") 00898 } 00899 break; 00900 #ifdef WITH_INPUT_NDOF 00901 case RIM_TYPEHID: 00902 if (system->processNDOF(raw)) 00903 eventHandled = true; 00904 break; 00905 #endif 00906 } 00907 break; 00908 } 00910 // Keyboard events, ignored 00912 case WM_KEYDOWN: 00913 case WM_SYSKEYDOWN: 00914 case WM_KEYUP: 00915 case WM_SYSKEYUP: 00916 /* These functions were replaced by WM_INPUT*/ 00917 case WM_CHAR: 00918 /* The WM_CHAR message is posted to the window with the keyboard focus when 00919 * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR 00920 * contains the character code of the key that was pressed. 00921 */ 00922 case WM_DEADCHAR: 00923 /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a 00924 * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR 00925 * specifies a character code generated by a dead key. A dead key is a key that 00926 * generates a character, such as the umlaut (double-dot), that is combined with 00927 * another character to form a composite character. For example, the umlaut-O 00928 * character (Ö) is generated by typing the dead key for the umlaut character, and 00929 * then typing the O key. 00930 */ 00931 break; 00932 case WM_SYSDEADCHAR: 00933 /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when 00934 * a WM_SYSKEYDOWN message is translated by the TranslateMessage function. 00935 * WM_SYSDEADCHAR specifies the character code of a system dead key - that is, 00936 * a dead key that is pressed while holding down the alt key. 00937 */ 00938 case WM_SYSCHAR: 00939 /* The WM_SYSCHAR message is sent to the window with the keyboard focus when 00940 * a WM_SYSCHAR message is translated by the TranslateMessage function. 00941 * WM_SYSCHAR specifies the character code of a dead key - that is, 00942 * a dead key that is pressed while holding down the alt key. 00943 * To prevent the sound, DefWindowProc must be avoided by return 00944 */ 00945 break; 00946 case WM_SYSCOMMAND: 00947 /* The WM_SYSCHAR message is sent to the window when system commands such as 00948 * maximize, minimize or close the window are triggered. Also it is sent when ALT 00949 * button is press for menu. To prevent this we must return preventing DefWindowProc. 00950 */ 00951 if(wParam==SC_KEYMENU) return 0; 00952 break; 00954 // Tablet events, processed 00956 case WT_PACKET: 00957 ((GHOST_WindowWin32*)window)->processWin32TabletEvent(wParam, lParam); 00958 break; 00959 case WT_CSRCHANGE: 00960 case WT_PROXIMITY: 00961 ((GHOST_WindowWin32*)window)->processWin32TabletInitEvent(); 00962 break; 00964 // Mouse events, processed 00966 case WM_LBUTTONDOWN: 00967 window->registerMouseClickEvent(0); 00968 event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft); 00969 break; 00970 case WM_MBUTTONDOWN: 00971 window->registerMouseClickEvent(0); 00972 event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle); 00973 break; 00974 case WM_RBUTTONDOWN: 00975 window->registerMouseClickEvent(0); 00976 event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight); 00977 break; 00978 case WM_XBUTTONDOWN: 00979 window->registerMouseClickEvent(0); 00980 if ((short) HIWORD(wParam) == XBUTTON1){ 00981 event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton4); 00982 }else if((short) HIWORD(wParam) == XBUTTON2){ 00983 event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton5); 00984 } 00985 break; 00986 case WM_LBUTTONUP: 00987 window->registerMouseClickEvent(1); 00988 event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); 00989 break; 00990 case WM_MBUTTONUP: 00991 window->registerMouseClickEvent(1); 00992 event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle); 00993 break; 00994 case WM_RBUTTONUP: 00995 window->registerMouseClickEvent(1); 00996 event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight); 00997 break; 00998 case WM_XBUTTONUP: 00999 window->registerMouseClickEvent(1); 01000 if ((short) HIWORD(wParam) == XBUTTON1){ 01001 event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton4); 01002 }else if((short) HIWORD(wParam) == XBUTTON2){ 01003 event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5); 01004 } 01005 break; 01006 case WM_MOUSEMOVE: 01007 event = processCursorEvent(GHOST_kEventCursorMove, window); 01008 break; 01009 case WM_MOUSEWHEEL: 01010 /* The WM_MOUSEWHEEL message is sent to the focus window 01011 * when the mouse wheel is rotated. The DefWindowProc 01012 * function propagates the message to the window's parent. 01013 * There should be no internal forwarding of the message, 01014 * since DefWindowProc propagates it up the parent chain 01015 * until it finds a window that processes it. 01016 */ 01017 event = processWheelEvent(window, wParam, lParam); 01018 break; 01019 case WM_SETCURSOR: 01020 /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor 01021 * to move within a window and mouse input is not captured. 01022 * This means we have to set the cursor shape every time the mouse moves! 01023 * The DefWindowProc function uses this message to set the cursor to an 01024 * arrow if it is not in the client area. 01025 */ 01026 if (LOWORD(lParam) == HTCLIENT) { 01027 // Load the current cursor 01028 window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); 01029 // Bypass call to DefWindowProc 01030 return 0; 01031 } 01032 else { 01033 // Outside of client area show standard cursor 01034 window->loadCursor(true, GHOST_kStandardCursorDefault); 01035 } 01036 break; 01037 01039 // Mouse events, ignored 01041 case WM_NCMOUSEMOVE: 01042 /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved 01043 * within the nonclient area of the window. This message is posted to the window 01044 * that contains the cursor. If a window has captured the mouse, this message is not posted. 01045 */ 01046 case WM_NCHITTEST: 01047 /* The WM_NCHITTEST message is sent to a window when the cursor moves, or 01048 * when a mouse button is pressed or released. If the mouse is not captured, 01049 * the message is sent to the window beneath the cursor. Otherwise, the message 01050 * is sent to the window that has captured the mouse. 01051 */ 01052 break; 01053 01055 // Window events, processed 01057 case WM_CLOSE: 01058 /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */ 01059 event = processWindowEvent(GHOST_kEventWindowClose, window); 01060 break; 01061 case WM_ACTIVATE: 01062 /* The WM_ACTIVATE message is sent to both the window being activated and the window being 01063 * deactivated. If the windows use the same input queue, the message is sent synchronously, 01064 * first to the window procedure of the top-level window being deactivated, then to the window 01065 * procedure of the top-level window being activated. If the windows use different input queues, 01066 * the message is sent asynchronously, so the window is activated immediately. 01067 */ 01068 { 01069 GHOST_ModifierKeys modifiers; 01070 modifiers.clear(); 01071 system->storeModifierKeys(modifiers); 01072 event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window); 01073 /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL 01074 will not be dispatched to OUR active window if we minimize one of OUR windows. */ 01075 lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); 01076 break; 01077 } 01078 case WM_PAINT: 01079 /* An application sends the WM_PAINT message when the system or another application 01080 * makes a request to paint a portion of an application's window. The message is sent 01081 * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage 01082 * function when the application obtains a WM_PAINT message by using the GetMessage or 01083 * PeekMessage function. 01084 */ 01085 event = processWindowEvent(GHOST_kEventWindowUpdate, window); 01086 ::ValidateRect(hwnd, NULL); 01087 break; 01088 case WM_GETMINMAXINFO: 01089 /* The WM_GETMINMAXINFO message is sent to a window when the size or 01090 * position of the window is about to change. An application can use 01091 * this message to override the window's default maximized size and 01092 * position, or its default minimum or maximum tracking size. 01093 */ 01094 processMinMaxInfo((MINMAXINFO *) lParam); 01095 /* Let DefWindowProc handle it. */ 01096 break; 01097 case WM_SIZE: 01098 /* The WM_SIZE message is sent to a window after its size has changed. 01099 * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 01100 * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient 01101 * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 01102 * message without calling DefWindowProc. 01103 */ 01104 event = processWindowEvent(GHOST_kEventWindowSize, window); 01105 break; 01106 case WM_CAPTURECHANGED: 01107 window->lostMouseCapture(); 01108 break; 01109 case WM_MOVING: 01110 /* The WM_MOVING message is sent to a window that the user is moving. By processing 01111 * this message, an application can monitor the size and position of the drag rectangle 01112 * and, if needed, change its size or position. 01113 */ 01114 case WM_MOVE: 01115 /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the 01116 * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient 01117 * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 01118 * message without calling DefWindowProc. 01119 */ 01120 event = processWindowEvent(GHOST_kEventWindowMove, window); 01121 break; 01123 // Window events, ignored 01125 case WM_WINDOWPOSCHANGED: 01126 /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place 01127 * in the Z order has changed as a result of a call to the SetWindowPos function or 01128 * another window-management function. 01129 * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 01130 * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient 01131 * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 01132 * message without calling DefWindowProc. 01133 */ 01134 case WM_ERASEBKGND: 01135 /* An application sends the WM_ERASEBKGND message when the window background must be 01136 * erased (for example, when a window is resized). The message is sent to prepare an 01137 * invalidated portion of a window for painting. 01138 */ 01139 case WM_NCPAINT: 01140 /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */ 01141 case WM_NCACTIVATE: 01142 /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed 01143 * to indicate an active or inactive state. 01144 */ 01145 case WM_DESTROY: 01146 /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window 01147 * procedure of the window being destroyed after the window is removed from the screen. 01148 * This message is sent first to the window being destroyed and then to the child windows 01149 * (if any) as they are destroyed. During the processing of the message, it can be assumed 01150 * that all child windows still exist. 01151 */ 01152 case WM_NCDESTROY: 01153 /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The 01154 * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY 01155 * message. WM_DESTROY is used to free the allocated memory object associated with the window. 01156 */ 01157 break; 01158 case WM_KILLFOCUS: 01159 /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. 01160 * We want to prevent this if a window is still active and it loses focus to nowhere*/ 01161 if(!wParam && hwnd==GetActiveWindow()) 01162 SetFocus(hwnd); 01163 case WM_SHOWWINDOW: 01164 /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */ 01165 case WM_WINDOWPOSCHANGING: 01166 /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in 01167 * the Z order is about to change as a result of a call to the SetWindowPos function or 01168 * another window-management function. 01169 */ 01170 case WM_SETFOCUS: 01171 /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */ 01172 case WM_ENTERSIZEMOVE: 01173 /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving 01174 * or sizing modal loop. The window enters the moving or sizing modal loop when the user 01175 * clicks the window's title bar or sizing border, or when the window passes the 01176 * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the 01177 * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when 01178 * DefWindowProc returns. 01179 */ 01180 break; 01181 01183 // Other events 01185 case WM_GETTEXT: 01186 /* An application sends a WM_GETTEXT message to copy the text that 01187 * corresponds to a window into a buffer provided by the caller. 01188 */ 01189 case WM_ACTIVATEAPP: 01190 /* The WM_ACTIVATEAPP message is sent when a window belonging to a 01191 * different application than the active window is about to be activated. 01192 * The message is sent to the application whose window is being activated 01193 * and to the application whose window is being deactivated. 01194 */ 01195 case WM_TIMER: 01196 /* The WIN32 docs say: 01197 * The WM_TIMER message is posted to the installing thread's message queue 01198 * when a timer expires. You can process the message by providing a WM_TIMER 01199 * case in the window procedure. Otherwise, the default window procedure will 01200 * call the TimerProc callback function specified in the call to the SetTimer 01201 * function used to install the timer. 01202 * 01203 * In GHOST, we let DefWindowProc call the timer callback. 01204 */ 01205 break; 01206 } 01207 } 01208 else { 01209 // Event found for a window before the pointer to the class has been set. 01210 GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n") 01211 /* These are events we typically miss at this point: 01212 WM_GETMINMAXINFO 0x24 01213 WM_NCCREATE 0x81 01214 WM_NCCALCSIZE 0x83 01215 WM_CREATE 0x01 01216 We let DefWindowProc do the work. 01217 */ 01218 } 01219 } 01220 else { 01221 // Events without valid hwnd 01222 GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n") 01223 } 01224 01225 if (event) { 01226 system->pushEvent(event); 01227 eventHandled = true; 01228 } 01229 01230 if (!eventHandled) 01231 lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); 01232 01233 return lResult; 01234 } 01235 01236 GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const 01237 { 01238 char *buffer; 01239 char *temp_buff; 01240 01241 if ( IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL) ) { 01242 size_t len = 0; 01243 HANDLE hData = GetClipboardData( CF_TEXT ); 01244 if (hData == NULL) { 01245 CloseClipboard(); 01246 return NULL; 01247 } 01248 buffer = (char*)GlobalLock( hData ); 01249 if (!buffer) { 01250 CloseClipboard(); 01251 return NULL; 01252 } 01253 01254 len = strlen(buffer); 01255 temp_buff = (char*) malloc(len+1); 01256 strncpy(temp_buff, buffer, len); 01257 temp_buff[len] = '\0'; 01258 01259 /* Buffer mustn't be accessed after CloseClipboard 01260 it would like accessing free-d memory */ 01261 GlobalUnlock( hData ); 01262 CloseClipboard(); 01263 01264 return (GHOST_TUns8*)temp_buff; 01265 } else { 01266 return NULL; 01267 } 01268 } 01269 01270 void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const 01271 { 01272 if(selection) {return;} // for copying the selection, used on X11 01273 01274 if (OpenClipboard(NULL)) { 01275 HLOCAL clipbuffer; 01276 char *data; 01277 01278 if (buffer) { 01279 EmptyClipboard(); 01280 01281 clipbuffer = LocalAlloc(LMEM_FIXED,((strlen(buffer)+1))); 01282 data = (char*)GlobalLock(clipbuffer); 01283 01284 strcpy(data, (char*)buffer); 01285 data[strlen(buffer)] = '\0'; 01286 LocalUnlock(clipbuffer); 01287 SetClipboardData(CF_TEXT,clipbuffer); 01288 } 01289 CloseClipboard(); 01290 } else { 01291 return; 01292 } 01293 } 01294 01295 int GHOST_SystemWin32::toggleConsole(int action) 01296 { 01297 switch(action) 01298 { 01299 case 3: //hide if no console 01300 { 01301 DWORD sp = GetCurrentProcessId(); 01302 HANDLE ptree = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 01303 PROCESSENTRY32 e = {0}; e.dwSize = sizeof(PROCESSENTRY32); 01304 01305 if( Process32First(ptree, &e)) { 01306 do { //Searches for Blender's PROCESSENTRY32 01307 if (e.th32ProcessID == sp) { 01308 sp = e.th32ParentProcessID; 01309 Process32First(ptree, &e); 01310 do { //Got parent id, searches for its PROCESSENTRY32 01311 if (e.th32ProcessID == sp) { 01312 if(strcmp("explorer.exe",e.szExeFile)==0) 01313 { //If explorer, hide cmd 01314 ShowWindow(GetConsoleWindow(),SW_HIDE); 01315 m_consoleStatus = 0; 01316 } 01317 break; 01318 } 01319 01320 } while( Process32Next(ptree, &e)); 01321 break; 01322 } 01323 } while( Process32Next(ptree, &e)); 01324 } 01325 01326 CloseHandle(ptree); 01327 break; 01328 } 01329 case 0: //hide 01330 ShowWindow(GetConsoleWindow(),SW_HIDE); 01331 m_consoleStatus = 0; 01332 break; 01333 case 1: //show 01334 ShowWindow(GetConsoleWindow(),SW_SHOW); 01335 m_consoleStatus = 1; 01336 break; 01337 case 2: //toggle 01338 ShowWindow(GetConsoleWindow(),m_consoleStatus?SW_HIDE:SW_SHOW); 01339 m_consoleStatus=!m_consoleStatus; 01340 break; 01341 01342 }; 01343 01344 01345 return m_consoleStatus; 01346 }