1 /*! 2 @file 3 @author Albert Semenov 4 @date 09/2009 5 */ 6 7 #include "Precompiled.h" 8 #include "InputManager.h" 9 #include "../InputConverter.h" 10 11 #ifdef INPUT_KEY_NAME 12 #include <MyGUI.h> 13 #endif 14 15 namespace input 16 { 17 18 // указатель на менеджер, куда транслируються сообщения 19 InputManager* InputManager::msInputManager = 0; 20 21 // старая процедура, которую мы заменили 22 LRESULT InputManager::msOldWindowProc = 0; 23 24 bool InputManager::msSkipMove = false; 25 26 // наша процедура для фильтрации сообщений windowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)27 LRESULT CALLBACK InputManager::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 28 { 29 // если колесо не определенно 30 #ifndef WM_MOUSEWHEEL 31 #define WM_MOUSEWHEEL 0x020A 32 #define __WM_REALMOUSELAST WM_MOUSEWHEEL 33 #else 34 #define __WM_REALMOUSELAST WM_MOUSELAST 35 #endif // WM_MOUSEWHEEL 36 37 // для взятия знаковых значений 38 #define GET_HIWORD(param) ((short)HIWORD(param)) 39 #define GET_LOWORD(param) ((short)LOWORD(param)) 40 41 // на нас кидают файлы 42 if (WM_DROPFILES == uMsg) 43 { 44 HDROP hDrop = (HDROP)wParam; 45 wchar_t buff[MAX_PATH] = { 0 }; 46 UINT fcount = DragQueryFileW(hDrop, 0xFFFFFFFF, nullptr, 0); 47 48 for (UINT index = 0; index < fcount; ++index) 49 { 50 DragQueryFileW(hDrop, index, buff, MAX_PATH); 51 msInputManager->onFileDrop(buff); 52 } 53 54 DragFinish(hDrop); 55 return 0; 56 } 57 // нас пытаются закрыть 58 else if (WM_CLOSE == uMsg) 59 { 60 if (!msInputManager->onWindowClose((size_t)hWnd)) 61 return 0; 62 } 63 else if ((uMsg >= WM_MOUSEFIRST) && (uMsg <= __WM_REALMOUSELAST)) 64 { 65 static int old_x = 0; 66 static int old_y = 0; 67 static int old_z = 0; 68 static bool left_button = false; 69 static bool right_button = false; 70 71 switch (uMsg) 72 { 73 case WM_MOUSEMOVE: 74 { 75 int x = GET_LOWORD(lParam); 76 int y = GET_HIWORD(lParam); 77 78 if (x < 0) x = 0; 79 else if (x > msInputManager->mWidth) x = msInputManager->mWidth; 80 if (y < 0) y = 0; 81 else if (y > msInputManager->mHeight) y = msInputManager->mHeight; 82 83 old_x = x; 84 old_y = y; 85 86 if (msSkipMove) 87 msSkipMove = false; 88 else 89 msInputManager->mouseMove(old_x, old_y, old_z); 90 } 91 92 break; 93 94 case WM_MOUSEWHEEL: 95 old_z += GET_HIWORD(wParam); 96 msInputManager->mouseMove(old_x, old_y, old_z); 97 break; 98 99 case WM_LBUTTONDOWN: 100 left_button = true; 101 if (!right_button) 102 ::SetCapture(hWnd); 103 msInputManager->mousePress(old_x, old_y, MyGUI::MouseButton::Left); 104 break; 105 106 case WM_LBUTTONDBLCLK: 107 left_button = true; 108 if (!right_button) 109 ::SetCapture(hWnd); 110 msInputManager->mousePress(old_x, old_y, MyGUI::MouseButton::Left); 111 break; 112 113 case WM_RBUTTONDOWN: 114 right_button = true; 115 if (!left_button) 116 ::SetCapture(hWnd); 117 msInputManager->mousePress(old_x, old_y, MyGUI::MouseButton::Right); 118 break; 119 120 case WM_RBUTTONDBLCLK: 121 right_button = true; 122 if (!left_button) 123 ::SetCapture(hWnd); 124 msInputManager->mousePress(old_x, old_y, MyGUI::MouseButton::Right); 125 break; 126 127 case WM_MBUTTONDOWN: 128 msInputManager->mousePress(old_x, old_y, MyGUI::MouseButton::Middle); 129 break; 130 131 case WM_LBUTTONUP: 132 msInputManager->mouseRelease(old_x, old_y, MyGUI::MouseButton::Left); 133 left_button = false; 134 if (!right_button) 135 ::SetCapture(0); 136 break; 137 case WM_RBUTTONUP: 138 right_button = false; 139 if (!left_button) 140 ::SetCapture(0); 141 msInputManager->mouseRelease(old_x, old_y, MyGUI::MouseButton::Right); 142 break; 143 case WM_MBUTTONUP: 144 msInputManager->mouseRelease(old_x, old_y, MyGUI::MouseButton::Middle); 145 break; 146 } 147 } 148 else if (WM_KEYDOWN == uMsg) 149 { 150 bool repeat = (lParam & (1 >> 30)) != 0; 151 if (!repeat) 152 { 153 int scan_code = VirtualKeyToScanCode(wParam); 154 int text = VirtualKeyToText(wParam); 155 msInputManager->injectKeyPress(MyGUI::KeyCode::Enum(scan_code), (MyGUI::Char)text); 156 157 #ifdef INPUT_KEY_NAME 158 MyGUI::MYGUI_OUT("VirtKey : ", VirtualKeyToName(wParam), " to ScanCode : ", ScanCodeToName(scan_code)); 159 #endif 160 } 161 } 162 else if (WM_IME_CHAR == uMsg) 163 { 164 int text = 0; 165 #ifdef _UNICODE 166 text = wParam; 167 #else 168 char mbstr[3]; 169 BYTE hiByte = static_cast<BYTE>(wParam >> 8); 170 BYTE loByte = wParam & 0x000000FF; 171 if (hiByte == 0) 172 { 173 mbstr[0] = loByte; 174 mbstr[1] = '\0'; 175 } 176 else 177 { 178 mbstr[0] = hiByte; 179 mbstr[1] = loByte; 180 mbstr[2] = '\0'; 181 } 182 183 wchar_t wstr[2]; 184 /*int num = */MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mbstr, -1, wstr, sizeof(wstr)/sizeof(wstr[0])); 185 text = wstr[0]; 186 #endif // _UNICODE 187 msInputManager->injectKeyPress(MyGUI::KeyCode::None, (MyGUI::Char)text); 188 } 189 else if (WM_KEYUP == uMsg) 190 { 191 int scan_code = VirtualKeyToScanCode(wParam); 192 MyGUI::KeyCode code = MyGUI::KeyCode::Enum(scan_code); 193 194 // принтскрин приходит только отжатие 195 if (code == MyGUI::KeyCode::SysRq) 196 msInputManager->injectKeyPress(code, (MyGUI::Char)0); 197 198 msInputManager->injectKeyRelease(code); 199 } 200 201 // вызываем полюбому 202 return CallWindowProc((WNDPROC)msOldWindowProc, hWnd, uMsg, wParam, lParam); 203 } 204 InputManager()205 InputManager::InputManager() : 206 mHwnd(0), 207 mWidth(0), 208 mHeight(0), 209 mMouseX(0), 210 mMouseY(0), 211 mMouseZ(0), 212 mMouseMove(false) 213 { 214 assert(!msInputManager); 215 msInputManager = this; 216 } 217 ~InputManager()218 InputManager::~InputManager() 219 { 220 assert(msInputManager); 221 msInputManager = 0; 222 } 223 createInput(size_t _handle)224 void InputManager::createInput(size_t _handle) 225 { 226 mHwnd = (HWND)_handle; 227 228 // подсовываем нашу функцию калбеков 229 if (!msOldWindowProc) 230 { 231 msOldWindowProc = GetWindowLongPtr(mHwnd, GWLP_WNDPROC); 232 SetWindowLongPtr(mHwnd, GWLP_WNDPROC, (LONG_PTR)windowProc); 233 } 234 235 // устанавливаем поддержку дропа файлов 236 LONG_PTR style = GetWindowLongPtr(mHwnd, GWL_EXSTYLE); 237 SetWindowLongPtr(mHwnd, GWL_EXSTYLE, style | WS_EX_ACCEPTFILES); 238 239 MyGUI::Gui::getInstance().eventFrameStart += MyGUI::newDelegate(this, &InputManager::frameEvent); 240 } 241 destroyInput()242 void InputManager::destroyInput() 243 { 244 MyGUI::Gui::getInstance().eventFrameStart -= MyGUI::newDelegate(this, &InputManager::frameEvent); 245 246 // если мы подменили процедуру, то вернем на место 247 if (msOldWindowProc) 248 { 249 SetWindowLongPtr((HWND)mHwnd, GWLP_WNDPROC, (LONG_PTR)msOldWindowProc); 250 msOldWindowProc = 0; 251 } 252 } 253 captureInput()254 void InputManager::captureInput() 255 { 256 } 257 setInputViewSize(int _width,int _height)258 void InputManager::setInputViewSize(int _width, int _height) 259 { 260 mWidth = _width; 261 mHeight = _height; 262 } 263 setMousePosition(int _x,int _y)264 void InputManager::setMousePosition(int _x, int _y) 265 { 266 POINT point = { _x, _y }; 267 ::ClientToScreen(mHwnd, &point); 268 269 msSkipMove = true; 270 ::SetCursorPos(point.x, point.y); 271 } 272 updateCursorPosition()273 void InputManager::updateCursorPosition() 274 { 275 } 276 frameEvent(float _time)277 void InputManager::frameEvent(float _time) 278 { 279 computeMouseMove(); 280 } 281 computeMouseMove()282 void InputManager::computeMouseMove() 283 { 284 if (mMouseMove) 285 { 286 injectMouseMove(mMouseX, mMouseY, mMouseZ); 287 mMouseMove = false; 288 } 289 } 290 mouseMove(int _absx,int _absy,int _absz)291 void InputManager::mouseMove(int _absx, int _absy, int _absz) 292 { 293 mMouseX = _absx; 294 mMouseY = _absy; 295 mMouseZ = _absz; 296 mMouseMove = true; 297 } 298 mousePress(int _absx,int _absy,MyGUI::MouseButton _id)299 void InputManager::mousePress(int _absx, int _absy, MyGUI::MouseButton _id) 300 { 301 computeMouseMove(); 302 injectMousePress(_absx, _absy, _id); 303 } 304 mouseRelease(int _absx,int _absy,MyGUI::MouseButton _id)305 void InputManager::mouseRelease(int _absx, int _absy, MyGUI::MouseButton _id) 306 { 307 computeMouseMove(); 308 injectMouseRelease(_absx, _absy, _id); 309 } 310 311 } // namespace input 312