node-native-win-utils 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,25 +2,23 @@
2
2
 
3
3
  # Node Native Win Utils
4
4
 
5
- I did it for myself because I didn't feel like dealing with libraries like 'node-ffi' to implement this functionality. Maybe someone will find it useful. I'ts WINDOWS OS ONLY
5
+ I did it for myself because I didn't feel like dealing with libraries like 'node-ffi' to implement this functionality. Maybe someone will find it useful. It's WINDOWS OS ONLY
6
6
 
7
- This package provides a native addon for Node.js that allows you to perform various utility operations on Windows systems. It includes key event listeners, window data retrieval, and window screenshot capture functionality.
7
+ This package is a native addon for Node.js that allows you to perform various utility operations on Windows systems. It includes key event listeners, window data retrieval, window screenshot capture functionality, mouse movement, mouse click, mouse drag, and typing functionality.
8
8
 
9
9
  ## Installation
10
10
 
11
11
  You can install the package using npm:
12
12
 
13
13
  ```shell
14
-
15
- npm install node-native-win-utils
16
-
14
+ npm install node-native-win-utils
17
15
  ```
18
16
 
19
17
  ## Usage
20
18
 
21
19
  ### Importing the Package
22
20
 
23
- To use the package, import the necessary functions and types:
21
+ To use the package, import the necessary functions, types, and classes:
24
22
 
25
23
  ```javascript
26
24
  import {
@@ -28,6 +26,10 @@ import {
28
26
  keyUpHandler,
29
27
  getWindowData,
30
28
  captureWindow,
29
+ mouseMove,
30
+ mouseClick,
31
+ mouseDrag,
32
+ typeString,
31
33
  KeyListener,
32
34
  } from "node-native-win-utils";
33
35
  ```
@@ -72,6 +74,43 @@ captureWindow("Window Name", "output.png");
72
74
  // Output: output.png with a screenshot of the window
73
75
  ```
74
76
 
77
+ ### Mouse Movement
78
+
79
+ The `mouseMove` function allows you to move the mouse to a specific position on the screen. Provide the `posX` and `posY` coordinates as parameters:
80
+
81
+ ```javascript
82
+ mouseMove(100, 200);
83
+ ```
84
+
85
+ ### Mouse Click
86
+
87
+ The `mouseClick` function allows you to perform a mouse click event. Optionally, you can specify the mouse button as a parameter (`"left"`, `"middle"`, or `"right"`). If no button is specified, a left mouse click is performed by default:
88
+
89
+ ```javascript
90
+ mouseClick(); // Left mouse click
91
+ mouseClick("right"); // Right mouse click
92
+ ```
93
+
94
+ ### Mouse Drag
95
+
96
+ The `mouseDrag` function allows you to simulate dragging the mouse from one position to another. Provide the starting and ending coordinates (`startX`, `startY`, `endX`, `endY`) as parameters. Optionally, you can specify the speed at which the mouse should be dragged:
97
+
98
+ ```javascript
99
+ mouseDrag(100, 200, 300, 400);
100
+ mouseDrag(100, 200, 300, 400, 100); // Drag with speed 100
101
+ ```
102
+
103
+ ### Typing
104
+
105
+ The `typeString` function allows you to simulate typing a string of characters. Provide the string to type as the `stringToType` parameter. Optionally, you can specify
106
+
107
+ a delay between each character (in milliseconds) using the `delay` parameter:
108
+
109
+ ```javascript
110
+ typeString("Hello, world!");
111
+ typeString("Hello, world!", 100); // Type with a delay of 100ms between characters
112
+ ```
113
+
75
114
  ### Key Listener Class
76
115
 
77
116
  The `KeyListener` class extends the EventEmitter class and simplifies working with the `keyDownHandler` and `keyUpHandler` functions. You can register event listeners for the "keyDown" and "keyUp" events using the `on` method:
@@ -100,6 +139,10 @@ listener.on("keyUp", (data) => {
100
139
  | keyUpHandler | `callback: (keyCode: number) => void` | `void` |
101
140
  | getWindowData | `windowName: string` | `WindowData` |
102
141
  | captureWindow | `windowName: string, outputPath: string` | `void` |
142
+ | mouseMove | `posX: number, posY: number` | `boolean` |
143
+ | mouseClick | `button?: "left" \| "middle" \| "right"` | `boolean` |
144
+ | mouseDrag | `startX: number, startY: number, endX: number, endY: number, speed?: number` | `boolean` |
145
+ | typeString | `stringToType: string, delay?: number` | `boolean` |
103
146
  | KeyListener.on | `event: "keyDown"`,<br>`callback: (data: { keyCode: number; keyName: string }) => void` | `this` (EventListener) |
104
147
  | KeyListener.on | `event: "keyUp"`,<br>`callback: (data: { keyCode: number; keyName: string }) => void` | `this` (EventListener) |
105
148
 
@@ -113,6 +156,10 @@ import {
113
156
  keyUpHandler,
114
157
  getWindowData,
115
158
  captureWindow,
159
+ mouseMove,
160
+ mouseClick,
161
+ mouseDrag,
162
+ typeString,
116
163
  KeyListener,
117
164
  } from "node-native-win-utils";
118
165
 
@@ -144,6 +191,25 @@ captureWindow("My Window", "output.png");
144
191
 
145
192
  // Output: output.png with a screenshot of the window
146
193
 
194
+ // Move the mouse
195
+
196
+ mouseMove(100, 200);
197
+
198
+ // Perform mouse click
199
+
200
+ mouseClick(); // Left mouse click
201
+ mouseClick("right"); // Right mouse click
202
+
203
+ // Simulate mouse drag
204
+
205
+ mouseDrag(100, 200, 300, 400);
206
+ mouseDrag(100, 200, 300, 400, 100); // Drag with speed 100
207
+
208
+ // Simulate typing
209
+
210
+ typeString("Hello, world!");
211
+ typeString("Hello, world!", 100); // Type with a delay of 100ms between characters
212
+
147
213
  // Use KeyListener class
148
214
 
149
215
  const listener = new KeyListener();
package/dist/index.d.ts CHANGED
@@ -10,6 +10,10 @@ export type GetWindowData = (windowName: string) => WindowData;
10
10
  export type CaptureWindow = (windowName: string, outputPath: string) => void;
11
11
  export type KeyDownHandler = (callback: (keyCode: number) => void) => void;
12
12
  export type KeyUpHandler = (callback: (keyCode: number) => void) => void;
13
+ export type MouseMove = (posX: number, posY: number) => boolean;
14
+ export type MouseClick = (button?: "left" | "middle" | "right") => boolean;
15
+ export type TypeString = (stringToType: string, delay?: number) => boolean;
16
+ export type MouseDrag = (starX: number, startY: number, endX: Number, endY: number, speed?: number) => boolean;
13
17
  export interface KeyListener extends EventEmitter {
14
18
  on(event: "keyDown", callback: (data: {
15
19
  keyCode: number;
@@ -20,8 +24,8 @@ export interface KeyListener extends EventEmitter {
20
24
  keyName: string;
21
25
  }) => void): this;
22
26
  }
23
- declare const keyDownHandler: KeyDownHandler, keyUpHandler: KeyUpHandler, getWindowData: GetWindowData, captureWindow: CaptureWindow;
27
+ declare const keyDownHandler: KeyDownHandler, keyUpHandler: KeyUpHandler, getWindowData: GetWindowData, captureWindow: CaptureWindow, mouseMove: MouseMove, mouseClick: MouseClick, mouseDrag: MouseDrag, typeString: TypeString;
24
28
  export declare class KeyListener extends EventEmitter {
25
29
  constructor();
26
30
  }
27
- export { keyDownHandler, keyUpHandler, getWindowData, captureWindow };
31
+ export { keyDownHandler, keyUpHandler, getWindowData, captureWindow, mouseMove, mouseClick, mouseDrag, typeString, };
package/dist/index.js CHANGED
@@ -3,16 +3,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.captureWindow = exports.getWindowData = exports.keyUpHandler = exports.keyDownHandler = exports.KeyListener = void 0;
6
+ exports.typeString = exports.mouseDrag = exports.mouseClick = exports.mouseMove = exports.captureWindow = exports.getWindowData = exports.keyUpHandler = exports.keyDownHandler = exports.KeyListener = void 0;
7
7
  const EventEmitter = require("events");
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const bindings = require("node-gyp-build")(path_1.default.resolve(__dirname, ".."));
10
10
  const keyCodes_1 = __importDefault(require("./keyCodes"));
11
- const { keyDownHandler, keyUpHandler, getWindowData, captureWindow, } = bindings;
11
+ const { keyDownHandler, keyUpHandler, getWindowData, captureWindow, mouseMove, mouseClick, mouseDrag, typeString, } = bindings;
12
12
  exports.keyDownHandler = keyDownHandler;
13
13
  exports.keyUpHandler = keyUpHandler;
14
14
  exports.getWindowData = getWindowData;
15
15
  exports.captureWindow = captureWindow;
16
+ exports.mouseMove = mouseMove;
17
+ exports.mouseClick = mouseClick;
18
+ exports.mouseDrag = mouseDrag;
19
+ exports.typeString = typeString;
16
20
  class KeyListener extends EventEmitter {
17
21
  constructor() {
18
22
  super();
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "node-native-win-utils",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "author": "RynerNO",
5
5
  "license": "MIT",
6
+ "git": "https://github.com/RynerNO/node-native-win-utils.git",
6
7
  "description": "Native addon for Node.js providing utility operations on Windows systems",
7
8
  "keywords": [
8
9
  "node.js",
Binary file
@@ -162,4 +162,44 @@ Napi::Value SetKeyUpCallback(const Napi::CallbackInfo &info)
162
162
  monitorThreadRunning = true;
163
163
  }
164
164
  return env.Undefined();
165
+ }
166
+
167
+ Napi::Value TypeString(const Napi::CallbackInfo &info)
168
+ {
169
+ Napi::Env env = info.Env();
170
+
171
+ if (info.Length() < 1 || !info[0].IsString())
172
+ {
173
+ Napi::TypeError::New(env, "You should provide a string to type").ThrowAsJavaScriptException();
174
+ return env.Null();
175
+ }
176
+ int delay = 15;
177
+ std::string text = info[0].As<Napi::String>();
178
+ if (info.Length() > 1 && info[1].IsNumber())
179
+ {
180
+ delay = info[1].As<Napi::Number>();
181
+ }
182
+ // Convert the string to wide string
183
+ std::wstring wideText(text.begin(), text.end());
184
+
185
+ // Simulate typing by sending keyboard events
186
+ for (const wchar_t &character : wideText)
187
+ {
188
+ INPUT keyboardInput = {0};
189
+ keyboardInput.type = INPUT_KEYBOARD;
190
+ keyboardInput.ki.wVk = 0;
191
+ keyboardInput.ki.wScan = character;
192
+ keyboardInput.ki.dwFlags = KEYEVENTF_UNICODE;
193
+ keyboardInput.ki.time = 0; // System will provide the timestamp
194
+
195
+ SendInput(1, &keyboardInput, sizeof(keyboardInput));
196
+
197
+ keyboardInput.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
198
+ SendInput(1, &keyboardInput, sizeof(keyboardInput));
199
+
200
+ // Sleep for 15 milliseconds between each character input
201
+ Sleep(delay);
202
+ }
203
+
204
+ return Napi::Boolean::New(env, true);
165
205
  }
package/src/cpp/main.cpp CHANGED
@@ -2,7 +2,8 @@
2
2
  #include <helpers.cpp>
3
3
  #include "captureWindow.cpp"
4
4
  #include <getWindowData.cpp>
5
- #include <keyBoardHandler.cpp>
5
+ #include <keyboard.cpp>
6
+ #include <mouse.cpp>
6
7
 
7
8
  Napi::Object Init(Napi::Env env, Napi::Object exports)
8
9
  {
@@ -10,6 +11,10 @@ Napi::Object Init(Napi::Env env, Napi::Object exports)
10
11
  exports.Set("captureWindow", Napi::Function::New(env, CaptureWindow));
11
12
  exports.Set("keyDownHandler", Napi::Function::New(env, SetKeyDownCallback));
12
13
  exports.Set("keyUpHandler", Napi::Function::New(env, SetKeyUpCallback));
14
+ exports.Set("mouseMove", Napi::Function::New(env, MoveMouse));
15
+ exports.Set("mouseClick", Napi::Function::New(env, ClickMouse));
16
+ exports.Set("mouseDrag", Napi::Function::New(env, DragMouse));
17
+ exports.Set("typeString", Napi::Function::New(env, TypeString));
13
18
  return exports;
14
19
  }
15
20
 
@@ -0,0 +1,175 @@
1
+ // patrially used code from https://github.com/octalmage/robotjs witch is under MIT License Copyright (c) 2014 Jason Stallings
2
+ #include <napi.h>
3
+ #include <windows.h>
4
+ /**
5
+ * Move the mouse to a specific point.
6
+ * @param point The coordinates to move the mouse to (x, y).
7
+ */
8
+
9
+ Napi::Value MoveMouse(const Napi::CallbackInfo &info)
10
+ {
11
+ Napi::Env env = info.Env();
12
+
13
+ if (info.Length() < 2 || !info[0].IsNumber() || !info[1].IsNumber())
14
+ {
15
+ Napi::TypeError::New(env, "You should provide x and y position of type number").ThrowAsJavaScriptException();
16
+ return env.Null();
17
+ }
18
+
19
+ int posX = info[0].As<Napi::Number>();
20
+ int posY = info[1].As<Napi::Number>();
21
+
22
+ // Get the screen metrics
23
+ int screenWidth = GetSystemMetrics(SM_CXSCREEN);
24
+ int screenHeight = GetSystemMetrics(SM_CYSCREEN);
25
+
26
+ // Convert coordinates to absolute values
27
+ int absoluteX = static_cast<int>((65536 * posX) / screenWidth);
28
+ int absoluteY = static_cast<int>((65536 * posY) / screenHeight);
29
+
30
+ // Move the mouse
31
+ INPUT mouseInput = {0};
32
+ mouseInput.type = INPUT_MOUSE;
33
+ mouseInput.mi.dx = absoluteX;
34
+ mouseInput.mi.dy = absoluteY;
35
+ mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_VIRTUALDESK;
36
+ mouseInput.mi.time = 0; // System will provide the timestamp
37
+
38
+ SendInput(1, &mouseInput, sizeof(mouseInput));
39
+
40
+ return Napi::Boolean::New(env, true);
41
+ }
42
+
43
+ Napi::Value ClickMouse(const Napi::CallbackInfo &info)
44
+ {
45
+ Napi::Env env = info.Env();
46
+ std::string button;
47
+
48
+ if (info.Length() < 1 || !info[0].IsString())
49
+ button = "left";
50
+ else
51
+ button = info[0].As<Napi::String>();
52
+
53
+ WORD mouseEvent = 0;
54
+
55
+ if (button == "left")
56
+ {
57
+ mouseEvent = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP;
58
+ }
59
+ else if (button == "right")
60
+ {
61
+ mouseEvent = MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP;
62
+ }
63
+ else if (button == "middle")
64
+ {
65
+ mouseEvent = MOUSEEVENTF_MIDDLEDOWN | MOUSEEVENTF_MIDDLEUP;
66
+ }
67
+ else
68
+ {
69
+ Napi::TypeError::New(env, "Invalid button name").ThrowAsJavaScriptException();
70
+ return env.Null();
71
+ }
72
+
73
+ // Perform the mouse click
74
+ INPUT mouseInput = {0};
75
+ mouseInput.type = INPUT_MOUSE;
76
+ mouseInput.mi.dwFlags = mouseEvent;
77
+ mouseInput.mi.time = 0; // System will provide the timestamp
78
+
79
+ SendInput(1, &mouseInput, sizeof(mouseInput));
80
+
81
+ return Napi::Boolean::New(env, true);
82
+ }
83
+
84
+ Napi::Value DragMouse(const Napi::CallbackInfo &info)
85
+ {
86
+ Napi::Env env = info.Env();
87
+
88
+ if (info.Length() < 4 || !info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber() || !info[3].IsNumber())
89
+ {
90
+ Napi::TypeError::New(env, "You should provide startX, startY, endX, endY").ThrowAsJavaScriptException();
91
+ return env.Null();
92
+ }
93
+
94
+ int startX = info[0].As<Napi::Number>();
95
+ int startY = info[1].As<Napi::Number>();
96
+ int endX = info[2].As<Napi::Number>();
97
+ int endY = info[3].As<Napi::Number>();
98
+ int speed = 100;
99
+ if (info.Length() > 4 && info[4].IsNumber())
100
+ {
101
+ speed = info[4].As<Napi::Number>();
102
+ }
103
+
104
+ // Get the screen metrics
105
+ int screenWidth = GetSystemMetrics(SM_CXSCREEN);
106
+ int screenHeight = GetSystemMetrics(SM_CYSCREEN);
107
+
108
+ // Convert coordinates to absolute values
109
+ int absoluteStartX = static_cast<int>((65536 * startX) / screenWidth);
110
+ int absoluteStartY = static_cast<int>((65536 * startY) / screenHeight);
111
+ int absoluteEndX = static_cast<int>((65536 * endX) / screenWidth);
112
+ int absoluteEndY = static_cast<int>((65536 * endY) / screenHeight);
113
+
114
+ // Calculate the distance and duration based on speed
115
+ double distanceX = absoluteEndX - absoluteStartX;
116
+ double distanceY = absoluteEndY - absoluteStartY;
117
+ double distance = sqrt(distanceX * distanceX + distanceY * distanceY);
118
+ double duration = distance / speed;
119
+
120
+ // Move the mouse to the starting position
121
+ INPUT startMouseInput = {0};
122
+ startMouseInput.type = INPUT_MOUSE;
123
+ startMouseInput.mi.dx = absoluteStartX;
124
+ startMouseInput.mi.dy = absoluteStartY;
125
+ startMouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_VIRTUALDESK;
126
+ startMouseInput.mi.time = 0; // System will provide the timestamp
127
+
128
+ SendInput(1, &startMouseInput, sizeof(startMouseInput));
129
+
130
+ // Perform mouse button down event
131
+ INPUT mouseDownInput = {0};
132
+ mouseDownInput.type = INPUT_MOUSE;
133
+ mouseDownInput.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
134
+ mouseDownInput.mi.time = 0; // System will provide the timestamp
135
+
136
+ SendInput(1, &mouseDownInput, sizeof(mouseDownInput));
137
+
138
+ // Calculate the number of steps based on the duration and desired speed
139
+ const int steps = 100; // Adjust the number of steps for smoother movement
140
+
141
+ // Calculate the incremental values for each step
142
+ double stepX = distanceX / steps;
143
+ double stepY = distanceY / steps;
144
+
145
+ // Move the mouse in increments to simulate dragging with speed control
146
+ for (int i = 0; i < steps; ++i)
147
+ {
148
+ // Calculate the position for the current step
149
+ int currentX = static_cast<int>(absoluteStartX + (stepX * i));
150
+ int currentY = static_cast<int>(absoluteStartY + (stepY * i));
151
+
152
+ // Move the mouse to the current position
153
+ INPUT mouseMoveInput = {0};
154
+ mouseMoveInput.type = INPUT_MOUSE;
155
+ mouseMoveInput.mi.dx = currentX;
156
+ mouseMoveInput.mi.dy = currentY;
157
+ mouseMoveInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_VIRTUALDESK;
158
+ mouseMoveInput.mi.time = 0; // System will provide the timestamp
159
+
160
+ SendInput(1, &mouseMoveInput, sizeof(mouseMoveInput));
161
+
162
+ // Sleep for a short duration to control the speed
163
+ Sleep(static_cast<DWORD>(duration / steps));
164
+ }
165
+
166
+ // Perform mouse button up event
167
+ INPUT mouseUpInput = {0};
168
+ mouseUpInput.type = INPUT_MOUSE;
169
+ mouseUpInput.mi.dwFlags = MOUSEEVENTF_LEFTUP;
170
+ mouseUpInput.mi.time = 0; // System will provide the timestamp
171
+
172
+ SendInput(1, &mouseUpInput, sizeof(mouseUpInput));
173
+
174
+ return Napi::Boolean::New(env, true);
175
+ }