📄 windows.c
字号:
/*Copyright (c) 2003-2007 Ryan C. Gordon and others.http://icculus.org/manymouse/This software is provided 'as-is', without any express or implied warranty.In no event will the authors be held liable for any damages arising fromthe use of this software.Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute itfreely, subject to the following restrictions:1. The origin of this software must not be misrepresented; you must notclaim that you wrote the original software. If you use this software in aproduct, an acknowledgment in the product documentation would beappreciated but is not required.2. Altered source versions must be plainly marked as such, and must not bemisrepresented as being the original software.3. This notice may not be removed or altered from any source distribution. Ryan C. Gordon <icculus@icculus.org>*///Support for Windows via the WM_INPUT message.#include "mm.h"#if (defined(_WIN32) || defined(__CYGWIN__))/* WinUser.h won't include rawinput stuff without this... */#if (_WIN32_WINNT < 0x0501)#undef _WIN32_WINNT#define _WIN32_WINNT 0x0501#endif#include <windows.h>#include <malloc.h> /* needed for alloca(). *//* Cygwin's headers don't have WM_INPUT right now... */#ifndef WM_INPUT#define WM_INPUT 0x00FF#endif/* that should be enough, knock on wood. */#define MAX_MICE 32/* * Just trying to avoid malloc() here...we statically allocate a buffer * for events and treat it as a ring buffer. *//* !!! FIXME: tweak this? */#define MAX_EVENTS 1024static ManyMouseEvent input_events[MAX_EVENTS];static volatile int input_events_read = 0;static volatile int input_events_write = 0;static unsigned int available_mice = 0;static int did_api_lookup = 0;static HWND raw_hwnd = NULL;static const char *class_name = "ManyMouseRawInputCatcher";static const char *win_name = "ManyMouseRawInputMsgWindow";static ATOM class_atom = 0;static CRITICAL_SECTION mutex;typedef struct{ HANDLE handle; char name[256];} MouseStruct;static MouseStruct mice[MAX_MICE];/* * The RawInput APIs only exist in Windows XP and later, so you want this * to fail gracefully on earlier systems instead of refusing to start the * process due to missing symbols. To this end, we do a symbol lookup on * User32.dll, etc to get the entry points. * * A lot of these are available all the way back to the start of win32 in * Windows 95 and WinNT 3.1, but just so you don't have to track down any * import libraries, I've added those here, too. That fits well with the * idea of just adding the sources to your build and going forward. */static UINT (WINAPI *pGetRawInputDeviceList)( PRAWINPUTDEVICELIST pRawInputDeviceList, PUINT puiNumDevices, UINT cbSize);/* !!! FIXME: use unicode version */static UINT (WINAPI *pGetRawInputDeviceInfoA)( HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize);static BOOL (WINAPI *pRegisterRawInputDevices)( PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize);static LRESULT (WINAPI *pDefRawInputProc)( PRAWINPUT *paRawInput, INT nInput, UINT cbSizeHeader);static UINT (WINAPI *pGetRawInputBuffer)( PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader);static UINT (WINAPI *pGetRawInputData)( HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader);static LONG (WINAPI *pRegQueryValueExA)( HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);static LONG (WINAPI *pRegOpenKeyExA)( HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);static LONG (WINAPI *pRegCloseKey)( HKEY hKey);static HWND (WINAPI *pCreateWindowExA)( DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);static ATOM (WINAPI *pRegisterClassExA)( CONST WNDCLASSEX *lpwcx);static LRESULT (WINAPI *pDefWindowProcA)( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);static BOOL (WINAPI *pUnregisterClassA)( LPCTSTR lpClassName, HINSTANCE hInstance);static HMODULE (WINAPI *pGetModuleHandleA)( LPCTSTR lpModuleName);static BOOL (WINAPI *pPeekMessageA)( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg);static BOOL (WINAPI *pTranslateMessage)( const MSG *lpMsg);static LRESULT (WINAPI *pDispatchMessageA)( const MSG *lpmsg);static BOOL (WINAPI *pDestroyWindow)( HWND hWnd);static void (WINAPI *pInitializeCriticalSection)( LPCRITICAL_SECTION lpCriticalSection);static void (WINAPI *pEnterCriticalSection)( LPCRITICAL_SECTION lpCriticalSection);static void (WINAPI *pLeaveCriticalSection)( LPCRITICAL_SECTION lpCriticalSection);static void (WINAPI *pDeleteCriticalSection)( LPCRITICAL_SECTION lpCriticalSection);static int symlookup(HMODULE dll, void **addr, const char *sym){ *addr = GetProcAddress(dll, sym); if (*addr == NULL) { FreeLibrary(dll); return(0); } /* if */ return(1);} /* symlookup */static int find_api_symbols(void){ HMODULE dll; if (did_api_lookup) return(1); #define LOOKUP(x) { if (!symlookup(dll, (void **) &p##x, #x)) return(0); } dll = LoadLibrary("user32.dll"); if (dll == NULL) return(0); LOOKUP(GetRawInputDeviceInfoA); LOOKUP(RegisterRawInputDevices); LOOKUP(GetRawInputDeviceList); LOOKUP(DefRawInputProc); LOOKUP(GetRawInputBuffer); LOOKUP(GetRawInputData); LOOKUP(CreateWindowExA); LOOKUP(RegisterClassExA); LOOKUP(UnregisterClassA); LOOKUP(DefWindowProcA); LOOKUP(PeekMessageA); LOOKUP(TranslateMessage); LOOKUP(DispatchMessageA); LOOKUP(DestroyWindow); dll = LoadLibrary("advapi32.dll"); if (dll == NULL) return(0); LOOKUP(RegOpenKeyExA); LOOKUP(RegQueryValueExA); LOOKUP(RegCloseKey); dll = LoadLibrary("kernel32.dll"); if (dll == NULL) return(0); LOOKUP(GetModuleHandleA); LOOKUP(InitializeCriticalSection); LOOKUP(EnterCriticalSection); LOOKUP(LeaveCriticalSection); LOOKUP(DeleteCriticalSection); #undef LOOKUP did_api_lookup = 1; return(1);} /* find_api_symbols */static void queue_event(const ManyMouseEvent *event){ /* copy the event info. We'll process it in ManyMouse_PollEvent(). */ CopyMemory(&input_events[input_events_write], event, sizeof (ManyMouseEvent)); input_events_write = ((input_events_write + 1) % MAX_EVENTS); /* Ring buffer full? Lose oldest event. */ if (input_events_write == input_events_read) { /* !!! FIXME: we need to not lose mouse buttons here. */ input_events_read = ((input_events_read + 1) % MAX_EVENTS); } /* if */} /* queue_event */static void queue_from_rawinput(const RAWINPUT *raw){ unsigned int i; const RAWINPUTHEADER *header = &raw->header; const RAWMOUSE *mouse = &raw->data.mouse; ManyMouseEvent event; if (raw->header.dwType != RIM_TYPEMOUSE) return; for (i = 0; i < available_mice; i++) /* find the device for event. */ { if (mice[i].handle == header->hDevice) break; } /* for */ if (i == available_mice) return; /* not found?! */ /* * RAWINPUT packs a bunch of events into one, so we split it up into * a bunch of ManyMouseEvents here and store them in an internal queue. * Then ManyMouse_PollEvent() just shuffles items off that queue * without any complicated processing. */ event.device = i; pEnterCriticalSection(&mutex); if (mouse->usFlags & MOUSE_MOVE_ABSOLUTE) { /* !!! FIXME: How do we get the min and max values for absmotion? */ event.type = MANYMOUSE_EVENT_ABSMOTION; event.item = 0; event.value = mouse->lLastX; queue_event(&event); event.item = 1; event.value = mouse->lLastY; queue_event(&event); } /* if */ else /*if (mouse->usFlags & MOUSE_MOVE_RELATIVE)*/ { event.type = MANYMOUSE_EVENT_RELMOTION; if (mouse->lLastX != 0) { event.item = 0; event.value = mouse->lLastX; queue_event(&event); } /* if */ if (mouse->lLastY != 0) { event.item = 1; event.value = mouse->lLastY; queue_event(&event); } /* if */ } /* else if */ event.type = MANYMOUSE_EVENT_BUTTON; #define QUEUE_BUTTON(x) { \ if (mouse->usButtonFlags & RI_MOUSE_BUTTON_##x##_DOWN) { \ event.item = x-1; \ event.value = 1; \ queue_event(&event); \ } \ if (mouse->usButtonFlags & RI_MOUSE_BUTTON_##x##_UP) { \ event.item = x-1; \ event.value = 0; \ queue_event(&event); \ } \ } QUEUE_BUTTON(1); QUEUE_BUTTON(2); QUEUE_BUTTON(3); QUEUE_BUTTON(4); QUEUE_BUTTON(5); #undef QUEUE_BUTTON if (mouse->usButtonFlags & RI_MOUSE_WHEEL) { if (mouse->usButtonData != 0) /* !!! FIXME: can this ever be zero? */ { event.type = MANYMOUSE_EVENT_SCROLL; event.item = 0; /* !!! FIXME: horizontal wheel? */ event.value = ( ((SHORT) mouse->usButtonData) > 0) ? 1 : -1; queue_event(&event); } /* if */ } /* if */ pLeaveCriticalSection(&mutex);} /* queue_from_rawinput */static void wminput_handler(WPARAM wParam, LPARAM lParam){ UINT dwSize = 0; LPBYTE lpb; pGetRawInputData((HRAWINPUT) lParam, RID_INPUT, NULL, &dwSize,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -