Guest User

Untitled

a guest
Jan 10th, 2025
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.14 KB | Source Code | 0 0
  1. /*
  2. */
  3.  
  4. #include <Windows.h>
  5. #include <hidsdi.h>
  6. #include <time.h>
  7. #include <stdio.h>
  8.  
  9. #define OUT_BUFFER_SIZE 4096
  10. #define IN_BUFFER_SIZE 4096
  11.  
  12. enum {
  13. SHIFT_MODE_NONE = 0,
  14. SHIFT_MODE_LIFT,
  15. SHIFT_MODE_DOWN
  16. };
  17.  
  18. int shiftMode = SHIFT_MODE_LIFT;
  19. unsigned twofinger_detect_delay_clocks = CLOCKS_PER_SEC * 50 / 1000;
  20. unsigned click_detect_delay_clocks = CLOCKS_PER_SEC * 50 / 1000;
  21. HHOOK miHook;
  22. unsigned num_fingers = 0;
  23. clock_t last_click = 0;
  24. clock_t last_problem_twofinger_time = 0;
  25. int touching;
  26. int drawX;
  27. int drawY;
  28.  
  29. INPUT outBuffer[OUT_BUFFER_SIZE];
  30. unsigned outBufferHead;
  31. unsigned outBufferTail;
  32.  
  33. #define KEY_MAIN_ACTIVATE_MOD 0x1D // ctrl
  34. #define KEY_QUICK_ACTIVATE_MOD 0x38 // alt
  35. #define KEY_ACTIVATE 0x5B // win
  36. #define KEY_LEFT_SHIFT 0x2a
  37. #define KEY_RIGHT_SHIFT 0x36
  38.  
  39. int downMainMod = 0;
  40. int downQuickMod = 0;
  41. int downActivate = 0;
  42. int downShift = 0;
  43.  
  44. #define INPUT_WAIT 1234
  45.  
  46. enum {
  47. MODE_NONE = 0,
  48. MODE_FIRST_CORNER = 1,
  49. MODE_ACTIVE = 2
  50. };
  51.  
  52. int mode = 0;
  53.  
  54. int active = 0;
  55. int mouseX = 0;
  56. int mouseY = 0;
  57. int topLeftX = 0;
  58. int topLeftY = 0;
  59. int bottomRightX = 1920;
  60. int bottomRightY = 1080;
  61.  
  62. HANDLE queueReady;
  63. char running = 1;
  64.  
  65. int popBuffer(INPUT* ip) {
  66. if (outBufferHead == outBufferTail)
  67. return -1;
  68. *ip = outBuffer[outBufferHead];s
  69. outBufferHead = (outBufferHead+1) % OUT_BUFFER_SIZE;
  70. return 0;
  71. }
  72.  
  73. int pushBuffer(INPUT* i) {
  74. unsigned newTail = (outBufferTail+1) % OUT_BUFFER_SIZE;
  75. if (newTail == outBufferHead)
  76. return -1;
  77. outBuffer[outBufferTail] = *i;
  78. outBufferTail = newTail;
  79. SetEvent(queueReady);
  80. return 0;
  81. }
  82.  
  83. DWORD WINAPI handleQueue(void* arg) {
  84. INPUT i;
  85. while(running) {
  86. WaitForSingleObject(queueReady, INFINITE);
  87. while (running && popBuffer(&i) >= 0) {
  88. if (i.type == INPUT_WAIT) {
  89. Sleep(i.hi.uMsg);
  90. }
  91. else {
  92. SendInput(1,&i,sizeof(INPUT));
  93. }
  94. }
  95. }
  96.  
  97. ExitThread(0);
  98. return 0;
  99. }
  100.  
  101. DWORD readRegistry(HKEY key, char* path, char* value, DWORD defaultValue) {
  102. DWORD dataSize = {0};
  103. DWORD out;
  104. DWORD length = sizeof(DWORD);
  105. LONG result = RegGetValue(
  106. key,
  107. path,
  108. value, // Value
  109. RRF_RT_DWORD, // Flags, REG_SZ
  110. NULL,
  111. &out, // Data, empty for now
  112. &length); // Getting the size only
  113. if (ERROR_SUCCESS != result)
  114. return defaultValue;
  115. else
  116. return out;
  117. }
  118.  
  119. LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
  120. static char remapped_down = 0;
  121. if(nCode == HC_ACTION) {
  122.  
  123. MSLLHOOKSTRUCT* p = (MSLLHOOKSTRUCT*)lParam;
  124.  
  125. if (wParam == WM_MOUSEMOVE) {
  126. mouseX = p->pt.x;
  127. mouseY = p->pt.y;
  128. }
  129.  
  130. if (p->flags & LLMHF_INJECTED) {
  131. }
  132. else {
  133. if (mode == MODE_ACTIVE)
  134. return 1;
  135. }
  136. }
  137.  
  138. return CallNextHookEx(miHook, nCode, wParam, lParam); // Important! Otherwise other mouse hooks may misbehave
  139. }
  140.  
  141. int haveValueCap(HIDP_VALUE_CAPS* cap, unsigned usagePage, unsigned usage) {
  142. if (cap->UsagePage != usagePage)
  143. return 0;
  144. if (cap->IsRange) {
  145. return cap->Range.UsageMin <= usage && usage <= cap->Range.UsageMax;
  146. }
  147. else {
  148. return cap->NotRange.Usage == usage;
  149. }
  150. }
  151.  
  152. int haveButtonCap(HIDP_BUTTON_CAPS* cap, unsigned usagePage, unsigned usage) {
  153. if (cap->UsagePage != usagePage)
  154. return 0;
  155. if (cap->IsRange) {
  156. return cap->Range.UsageMin <= usage && usage <= cap->Range.UsageMax;
  157. }
  158. else {
  159. return cap->NotRange.Usage == usage;
  160. }
  161. }
  162.  
  163. long getScaled(unsigned scale, unsigned usagePage, unsigned usage, unsigned scaleUsagePage, unsigned scaleUsage, PHIDP_PREPARSED_DATA preparsed, unsigned char* data, unsigned dataSize) {
  164. long x;
  165. long res = HidP_GetUsageValue(HidP_Input, usagePage, 0, usage, &x, preparsed, data, dataSize);
  166. if (res < 0)
  167. return -1;
  168. static HIDP_VALUE_CAPS cap[IN_BUFFER_SIZE / sizeof(HIDP_VALUE_CAPS)];
  169. SHORT length = sizeof(cap)/sizeof(HIDP_VALUE_CAPS);
  170. res = HidP_GetSpecificValueCaps(HidP_Input, scaleUsagePage, 0, scaleUsage, cap, &length, preparsed);
  171. if (res < 0)
  172. return -1;
  173. if (cap[0].LogicalMax <= cap[0].LogicalMin)
  174. return -1;
  175.  
  176. int range = cap[0].LogicalMax-cap[0].LogicalMin;
  177. return (scale * (x-cap[0].LogicalMin) + range/2) / range;
  178. }
  179.  
  180. void moveMouse(int x, int y) {
  181. SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
  182. INPUT ip;
  183. ip.type = INPUT_MOUSE;
  184. ip.mi.dx = x*65536/GetSystemMetrics(SM_CXSCREEN);
  185. ip.mi.dy = y*65536/GetSystemMetrics(SM_CYSCREEN);
  186. ip.mi.mouseData = 0;
  187. ip.mi.dwFlags = MOUSEEVENTF_MOVE|MOUSEEVENTF_ABSOLUTE;
  188. ip.mi.time = 0;
  189. pushBuffer(&ip);
  190. }
  191.  
  192. void pressMouse(int down) {
  193. INPUT ip;
  194. ip.type = INPUT_MOUSE;
  195. ip.mi.dx = 0;
  196. ip.mi.dy = 0;
  197. ip.mi.mouseData = 0;
  198. ip.mi.dwFlags = down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
  199. ip.mi.time = 0;
  200. pushBuffer(&ip);
  201. }
  202.  
  203. void delay(unsigned ms) {
  204. INPUT ip;
  205. ip.type = INPUT_WAIT;
  206. ip.hi.uMsg = ms;
  207. pushBuffer(&ip);
  208. }
  209.  
  210. void showActivate(int state, int ms) {
  211. pressMouse(0);
  212. if(state)
  213. puts("Activating drawing mode");
  214. else
  215. puts("Disabling drawing mode");
  216. int w = bottomRightX-topLeftX;
  217. int h = bottomRightY-topLeftY;
  218. if (state) {
  219. moveMouse(topLeftX, topLeftY);
  220. delay(ms);
  221. moveMouse(bottomRightX, topLeftY);
  222. delay(ms);
  223. moveMouse(bottomRightX, bottomRightY);
  224. delay(ms);
  225. moveMouse(topLeftX, bottomRightY);
  226. delay(ms);
  227. moveMouse(topLeftX, topLeftY);
  228. }
  229. else {
  230. moveMouse(bottomRightX, bottomRightY);
  231. delay(ms);
  232. moveMouse(bottomRightX, topLeftY);
  233. delay(ms);
  234. moveMouse(topLeftX, topLeftY);
  235. delay(ms);
  236. moveMouse(topLeftX, bottomRightY);
  237. delay(ms);
  238. moveMouse(bottomRightX, bottomRightY);
  239. }
  240. }
  241.  
  242. void handleKeyboard(USHORT code, USHORT flags) {
  243. int down = (flags & 1) ^ 1;
  244. if (code == KEY_MAIN_ACTIVATE_MOD)
  245. downMainMod = down;
  246. else if (code == KEY_QUICK_ACTIVATE_MOD)
  247. downQuickMod = down;
  248. else if (code == KEY_LEFT_SHIFT code == KEY_RIGHT_SHIFT)
  249. downShift = down;
  250. else if (code == KEY_ACTIVATE) {
  251. downActivate = down;
  252. if (downActivate && downMainMod) {
  253. switch(mode) {
  254. case MODE_NONE:
  255. topLeftX = mouseX;
  256. topLeftY = mouseY;
  257. mode = MODE_FIRST_CORNER;
  258. puts("Press ctrl+win to define other corner and enter drawing mode.");
  259. break;
  260. case MODE_FIRST_CORNER:
  261. if (mouseX < topLeftX) {
  262. bottomRightX = topLeftX;
  263. topLeftX = mouseX;
  264. }
  265. else {
  266. bottomRightX = mouseX;
  267. }
  268. if (mouseY < topLeftY) {
  269. bottomRightY = topLeftY;
  270. topLeftY = mouseY;
  271. }
  272. else {
  273. bottomRightY = mouseY;
  274. }
  275. mode = MODE_ACTIVE;
  276. touching = 0;
  277. showActivate(1,200);
  278. drawX = -1;
  279. drawY = -1;
  280. break;
  281. case MODE_ACTIVE:
  282. printf("area: (%d,%d)-(%d,%d)\n",topLeftX,topLeftY,bottomRightX,bottomRightY);
  283. showActivate(0,200);
  284. mode = MODE_NONE;
  285. puts("Press ctrl+win to define first corner or alt+win to return to previous area.");
  286. break;
  287. }
  288. }
  289. else if (downActivate && downQuickMod) {
  290. if (mode == MODE_ACTIVE) {
  291. showActivate(0,100);
  292. mode = MODE_NONE;
  293. }
  294. else {
  295. printf("area: (%d,%d)-(%d,%d)\n",topLeftX,topLeftY,bottomRightX,bottomRightY);
  296. mode = MODE_ACTIVE;
  297. touching = 0;
  298. showActivate(1,200);
  299. drawX = -1;
  300. drawY = -1;
  301. }
  302. }
  303. }
  304.  
  305. }
  306.  
  307. LRESULT CALLBACK EventHandler(
  308. HWND hwnd,
  309. unsigned event,
  310. WPARAM wparam,
  311. LPARAM lparam
  312. ) {
  313. static BYTE rawinputBuffer[sizeof(RAWINPUT)+IN_BUFFER_SIZE];
  314. static BYTE preparsedBuffer[IN_BUFFER_SIZE];
  315. static BYTE usageBuffer[IN_BUFFER_SIZE];
  316. USAGE* usages = (USAGE*)usageBuffer;
  317. RAWINPUT* data = (RAWINPUT*)rawinputBuffer;
  318. PHIDP_PREPARSED_DATA preparsed = (PHIDP_PREPARSED_DATA)preparsedBuffer;
  319.  
  320. static HIDP_CAPS caps;
  321.  
  322. switch (event) {
  323. case WM_DESTROY:
  324. PostQuitMessage(0);
  325. return 0;
  326. case WM_INPUT: {
  327. unsigned size = sizeof(rawinputBuffer);
  328. int res = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER));
  329. if (res < 0 size == 0)
  330. return 0;
  331. if (data->header.dwType == RIM_TYPEKEYBOARD) {
  332. handleKeyboard(data->data.keyboard.MakeCode,data->data.keyboard.Flags);
  333. return 0;
  334. }
  335. if (mode != MODE_ACTIVE)
  336. return 0;
  337. size = sizeof(preparsedBuffer);
  338. res = GetRawInputDeviceInfo(data->header.hDevice, RIDI_PREPARSEDDATA, preparsed, &size);
  339. if (res < 0 size == 0)
  340. return 0;
  341.  
  342. unsigned long usageLength = sizeof(usageBuffer)/sizeof(USAGE);
  343. int touch = 0;
  344.  
  345. res = HidP_GetUsages(HidP_Input, 0x0D, 0, usages, &usageLength, preparsed, data->data.hid.bRawData, data->data.hid.dwSizeHid);
  346. if (res < 0)
  347. return 0;
  348.  
  349. for (int j=0;j<usageLength;j++) {
  350. if (usages[j]==0x42) {
  351. touch = 1;
  352. break;
  353. }
  354. }
  355.  
  356. if (shiftMode == SHIFT_MODE_DOWN)
  357. touch = touch && downShift;
  358. else if (shiftMode == SHIFT_MODE_LIFT)
  359. touch = touch && !downShift;
  360.  
  361. int x,y;
  362. x = getScaled(bottomRightX-topLeftX, 0x01, 0x30, 0x01, 0x30, preparsed, data->data.hid.bRawData, data->data.hid.dwSizeHid);
  363. if (x>=0) {
  364. y = getScaled(bottomRightX-topLeftX, 0x01, 0x31, 0x01, 0x30, preparsed, data->data.hid.bRawData, data->data.hid.dwSizeHid);
  365. if (y>=0) {
  366. x+=topLeftX;
  367. y+=topLeftY;
  368. if (x!=drawX y!=drawY) {
  369. moveMouse(x,y);
  370. drawX = x;
  371. drawY = y;
  372. }
  373.  
  374. }
  375. }
  376. if (touch != touching) {
  377. pressMouse(touch);
  378. touching = touch;
  379. }
  380. } return 0;
  381. }
  382.  
  383. return DefWindowProc(hwnd, event, wparam, lparam);
  384. }
  385.  
  386. int processOptions(char* cmdLine) {
  387. char* token;
  388. char* src;
  389. src = cmdLine;
  390.  
  391. while (NULL != (token = strtok(src, " "))) {
  392. if (!strcmp(token, "--shift-lift")) {
  393. shiftMode = SHIFT_MODE_LIFT;
  394. }
  395. else if (!strcmp(token, "--shift-down")) {
  396. shiftMode = SHIFT_MODE_DOWN;
  397. }
  398. else if (!strcmp(token, "--shift-none")) {
  399. shiftMode = SHIFT_MODE_NONE;
  400. }
  401. else if (!strcmp(token, "--help") || !strcmp(token, "-h")) {
  402. MessageBox(0,
  403. "finger-draw [options]\n"
  404. "\n"
  405. "Options:\n\n"
  406. "--help : this message\n"
  407. "--shift-lift : lift pen on shift [default]\n"
  408. "--shift-down : lower pen on shift\n"
  409. "--shift-none : ignore shift key\n", "Help", 0);
  410. return 0;
  411. }
  412. src = NULL;
  413. }
  414. return 1;
  415. }
  416.  
  417. int WINAPI WinMain(HINSTANCE instance, HINSTANCE hPrevInstance,
  418. PSTR lpCmdLine, int nCmdShow)
  419. {
  420. if (!processOptions(lpCmdLine))
  421. return 0;
  422.  
  423. const char* class_name = "finger-draw-2941248-class";
  424.  
  425. //HINSTANCE instance = GetModuleHandle(0);
  426. WNDCLASS window_class = {};
  427. window_class.lpfnWndProc = EventHandler;
  428. window_class.hInstance = instance;
  429. window_class.lpszClassName = class_name;
  430.  
  431. if (!RegisterClass(&window_class))
  432. return -1;
  433.  
  434. HWND window = CreateWindow(class_name, "finger-draw-2941248", 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
  435.  
  436. if (window == NULL)
  437. return -1;
  438.  
  439. //SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
  440. //screenWidth = GetSystemMetrics(SM_CXSCREEN);
  441. //screenHeight = GetSystemMetrics(SM_CYSCREEN);
  442.  
  443. RAWINPUTDEVICE rid[2];
  444. //touchpad
  445. rid[0].usUsagePage = 0x0D;
  446. rid[0].usUsage = 0x05;
  447. rid[0].dwFlags = RIDEV_INPUTSINK;
  448. rid[0].hwndTarget = window;
  449. //keyboard
  450. rid[1].usUsagePage = 0x01;
  451. rid[1].usUsage = 0x06;
  452. rid[1].dwFlags = RIDEV_INPUTSINK;
  453. rid[1].hwndTarget = window;
  454. int res = RegisterRawInputDevices(rid, 2, sizeof(rid[0]));
  455.  
  456. miHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)(&LowLevelMouseProc), 0, 0);
  457.  
  458. queueReady = CreateEvent(NULL, FALSE, FALSE, (LPTSTR)("queueReady"));
  459. HANDLE queueThread = CreateThread(NULL, 0, handleQueue, NULL, 0, NULL);
  460.  
  461. puts("Move mouse to upper left of drawing area and press ctrl+win,\n"
  462. "then move mouse to lower right and press ctrl+win again to enter\n"
  463. "drawing mode. Then press ctrl+win or alt+win to exit drawing mode.\n"
  464. "Use alt+win to start drawing with a previously defined drawing area.\n");
  465. if (shiftMode == SHIFT_MODE_LIFT)
  466. puts("Hold SHIFT to lift pen when drawing.\n");
  467. else if (shiftMode == SHIFT_MODE_DOWN)
  468. puts("Hold SHIFT to press down pen when drawing.\n");
  469. puts("Press ctrl+c in this window to quit.");
  470.  
  471. MSG message;
  472. while(GetMessage(&message, NULL, 0, 0)) {
  473. TranslateMessage(&message);
  474. DispatchMessage(&message);
  475. }
  476.  
  477. running = 0;
  478. SetEvent(queueReady);
  479. UnhookWindowsHookEx(miHook);
  480. return 0;
  481. }
Tags: Myccode
Advertisement
Add Comment
Please, Sign In to add comment