xw-devtool-cli 1.0.27 → 1.0.28

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
@@ -21,7 +21,8 @@
21
21
  > 2. 由于涉及跨进程通信,按下空格后可能存在轻微延时,请耐心等待结果。
22
22
  > 3. 取色模式下会显示全屏十字辅助线,按 **回车键** 退出模式。
23
23
  - **占位图生成**:快速生成指定尺寸、颜色、文字的占位图片 (Placeholder Image)。
24
- - **全屏十字辅助线**:显示跟随鼠标的全屏红色十字线,用于屏幕对齐和定位。
24
+ - **全屏十字辅助线**:显示跟随鼠标的全屏红色十字线,用于屏幕对齐和定位。
25
+ - **屏幕测距**:点击屏幕上任意两点,测量其像素距离。
25
26
  - **Mock 数据生成**:
26
27
  - 支持生成:英文段落 (Lorem Ipsum)、中文字符、中国居民身份证号、电子邮箱、URL、订单号、手机号、座机号。
27
28
  - 支持批量生成。
package/README_EN.md CHANGED
@@ -17,6 +17,7 @@ Key features include: Base64 encoding/decoding, image format conversion, image <
17
17
  - **Color Picker**: Pick a single pixel color or area average from an image; supports px/% coordinates; shows preview bar and auto-copies Hex/Hex8.
18
18
  - **Screen Picker**: Pick color directly from the screen at the mouse position; move the cursor and press Enter to sample; supports alpha preview.
19
19
  - **Screen Crosshair**: Display a full-screen red crosshair following the mouse for alignment.
20
+ - **Pixel Distance**: Measure pixel distance between two points on the screen.
20
21
  - **Mock Data**:
21
22
  - Generate: Lorem Ipsum, Chinese characters, ID cards, Emails, URLs, Order IDs, Phone numbers.
22
23
  - Supports batch generation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xw-devtool-cli",
3
- "version": "1.0.27",
3
+ "version": "1.0.28",
4
4
  "type": "module",
5
5
  "description": "基于node的开发者助手cli",
6
6
  "main": "index.js",
@@ -0,0 +1,167 @@
1
+ import { spawn } from 'child_process';
2
+ import i18next from '../i18n.js';
3
+
4
+ export async function pixelDistanceHandler() {
5
+ if (process.platform !== 'win32') {
6
+ console.log(i18next.t('pixelDistance.notSupported'));
7
+ return;
8
+ }
9
+
10
+ console.log(i18next.t('pixelDistance.startPrompt'));
11
+
12
+ const overlayScript = `
13
+ Add-Type -AssemblyName System.Windows.Forms;
14
+ Add-Type -AssemblyName System.Drawing;
15
+
16
+ Add-Type -TypeDefinition @'
17
+ using System;
18
+ using System.Drawing;
19
+ using System.Windows.Forms;
20
+ using System.Runtime.InteropServices;
21
+
22
+ public class DistanceForm : Form {
23
+ private Point p1 = Point.Empty;
24
+ private Point p2 = Point.Empty;
25
+ private bool p1Set = false;
26
+ private bool p2Set = false;
27
+ private Bitmap screenCapture;
28
+
29
+ public DistanceForm() {
30
+ this.FormBorderStyle = FormBorderStyle.None;
31
+ this.TopMost = true;
32
+ this.Cursor = Cursors.Cross;
33
+ this.DoubleBuffered = true;
34
+
35
+ // Calculate total bounds
36
+ Rectangle totalBounds = Rectangle.Empty;
37
+ foreach(Screen s in Screen.AllScreens) {
38
+ totalBounds = Rectangle.Union(totalBounds, s.Bounds);
39
+ }
40
+
41
+ this.StartPosition = FormStartPosition.Manual;
42
+ this.Bounds = totalBounds;
43
+
44
+ // Capture screen
45
+ screenCapture = new Bitmap(totalBounds.Width, totalBounds.Height);
46
+ using (Graphics g = Graphics.FromImage(screenCapture)) {
47
+ g.CopyFromScreen(totalBounds.Location, Point.Empty, totalBounds.Size);
48
+ }
49
+ this.BackgroundImage = screenCapture;
50
+ }
51
+
52
+ private Point GetSnappedPoint(Point current) {
53
+ if (!p1Set) return current;
54
+
55
+ Point snapped = current;
56
+ int threshold = 5; // Snap threshold in pixels
57
+
58
+ // Check horizontal snap (same Y)
59
+ if (Math.Abs(current.Y - p1.Y) < threshold) {
60
+ snapped.Y = p1.Y;
61
+ }
62
+
63
+ // Check vertical snap (same X)
64
+ if (Math.Abs(current.X - p1.X) < threshold) {
65
+ snapped.X = p1.X;
66
+ }
67
+
68
+ return snapped;
69
+ }
70
+
71
+ protected override void OnMouseDown(MouseEventArgs e) {
72
+ if (e.Button == MouseButtons.Right) {
73
+ // Reset
74
+ p1Set = false;
75
+ p2Set = false;
76
+ this.Invalidate();
77
+ return;
78
+ }
79
+
80
+ if (e.Button == MouseButtons.Left) {
81
+ if (!p1Set) {
82
+ p1 = e.Location;
83
+ p1Set = true;
84
+ } else if (!p2Set) {
85
+ p2 = GetSnappedPoint(e.Location);
86
+ p2Set = true;
87
+ } else {
88
+ // Start over from new point
89
+ p1 = e.Location;
90
+ p1Set = true;
91
+ p2Set = false;
92
+ }
93
+ this.Invalidate();
94
+ }
95
+ }
96
+
97
+ protected override void OnMouseMove(MouseEventArgs e) {
98
+ if (p1Set && !p2Set) {
99
+ this.Invalidate();
100
+ }
101
+ }
102
+
103
+ protected override void OnPaint(PaintEventArgs e) {
104
+ Graphics g = e.Graphics;
105
+ g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
106
+
107
+ Pen pen = new Pen(Color.Red, 2);
108
+ Brush brush = Brushes.Red;
109
+ Font font = new Font("Segoe UI", 12, FontStyle.Bold);
110
+ Brush textBg = new SolidBrush(Color.FromArgb(180, 0, 0, 0));
111
+
112
+ if (p1Set) {
113
+ Point target = p2Set ? p2 : GetSnappedPoint(this.PointToClient(Cursor.Position));
114
+
115
+ // Draw line
116
+ g.DrawLine(pen, p1, target);
117
+
118
+ // Draw points
119
+ g.FillEllipse(brush, p1.X - 4, p1.Y - 4, 8, 8);
120
+ g.FillEllipse(brush, target.X - 4, target.Y - 4, 8, 8);
121
+
122
+ // Calculate distance
123
+ double dist = Math.Sqrt(Math.Pow(target.X - p1.X, 2) + Math.Pow(target.Y - p1.Y, 2));
124
+ string text = String.Format("{0:F2} px", dist);
125
+
126
+ // Draw text at midpoint
127
+ Point mid = new Point((p1.X + target.X) / 2, (p1.Y + target.Y) / 2);
128
+ SizeF size = g.MeasureString(text, font);
129
+
130
+ // Ensure text doesn't go off screen
131
+ float txtX = mid.X + 10;
132
+ float txtY = mid.Y + 10;
133
+
134
+ g.FillRectangle(textBg, txtX - 2, txtY - 2, size.Width + 4, size.Height + 4);
135
+ g.DrawString(text, font, Brushes.White, txtX, txtY);
136
+
137
+ // Also display coordinates
138
+ string coords = String.Format("P1: {0},{1} P2: {2},{3}", p1.X, p1.Y, target.X, target.Y);
139
+ g.DrawString(coords, font, Brushes.Yellow, 10, 10);
140
+ }
141
+ }
142
+
143
+ protected override void OnKeyDown(KeyEventArgs e) {
144
+ if (e.KeyCode == Keys.Escape) {
145
+ Application.Exit();
146
+ }
147
+ }
148
+ }
149
+
150
+ public static class Entry {
151
+ public static void Main() {
152
+ Application.EnableVisualStyles();
153
+ Application.SetCompatibleTextRenderingDefault(false);
154
+ Application.Run(new DistanceForm());
155
+ }
156
+ }
157
+ '@ -ReferencedAssemblies System.Windows.Forms,System.Drawing
158
+
159
+ [Entry]::Main()
160
+ `;
161
+
162
+ const proc = spawn('powershell', ['-NoProfile', '-Command', overlayScript], { stdio: 'inherit' });
163
+
164
+ proc.on('close', (code) => {
165
+ // console.log('Exited');
166
+ });
167
+ }
package/src/index.js CHANGED
@@ -30,6 +30,7 @@ import { vscodeSnippetHandler } from './commands/vscodeSnippet.js';
30
30
  import { dominantColorHandler } from './commands/dominantColor.js';
31
31
  import { colorPickHandler } from './commands/colorPick.js';
32
32
  import { crosshairHandler } from './commands/crosshair.js';
33
+ import { pixelDistanceHandler } from './commands/pixelDistance.js';
33
34
 
34
35
  process.on('SIGINT', () => {
35
36
  console.log(`\n${i18next.t('menu.bye')}`);
@@ -55,6 +56,7 @@ function getFeatures() {
55
56
  { name: i18next.t('menu.features.dominantColor'), value: 'dominantColor' },
56
57
  { name: i18next.t('menu.features.colorPick'), value: 'colorPick' },
57
58
  { name: i18next.t('menu.features.crosshair'), value: 'crosshair' },
59
+ { name: i18next.t('menu.features.pixelDistance'), value: 'pixelDistance' },
58
60
  { name: i18next.t('menu.features.placeholderImg'), value: 'placeholderImg' },
59
61
  { name: i18next.t('menu.features.qrcode'), value: 'qrcode' },
60
62
 
@@ -199,6 +201,9 @@ async function handleAction(action) {
199
201
  case 'crosshair':
200
202
  await crosshairHandler();
201
203
  break;
204
+ case 'pixelDistance':
205
+ await pixelDistanceHandler();
206
+ break;
202
207
  case 'timeFormat':
203
208
  await timeFormatHandler();
204
209
  break;
package/src/locales/en.js CHANGED
@@ -2,6 +2,10 @@ export default {
2
2
  common: {
3
3
  back: 'Back to previous step'
4
4
  },
5
+ pixelDistance: {
6
+ notSupported: 'Pixel distance tool not supported on this OS.',
7
+ startPrompt: 'Pixel distance tool started. Click 2 points to measure. Right-click to reset. ESC to exit.'
8
+ },
5
9
  menu: {
6
10
  title: 'xw-devtool-cli Menu',
7
11
  exit: 'Exit',
@@ -15,6 +19,7 @@ export default {
15
19
  dominantColor: 'Image Dominant Color',
16
20
  colorPick: 'Color Picker',
17
21
  crosshair: 'Screen Crosshair',
22
+ pixelDistance: 'Pixel Distance Tool',
18
23
  placeholderImg: 'Placeholder Image Generator',
19
24
  qrcode: 'QR Code Generator',
20
25
  url: 'URL Encode/Decode',
package/src/locales/zh.js CHANGED
@@ -6,6 +6,10 @@ export default {
6
6
  notSupported: '当前系统不支持屏幕辅助线。',
7
7
  startPrompt: '屏幕十字辅助线已启动。按任意键退出...'
8
8
  },
9
+ pixelDistance: {
10
+ notSupported: '当前系统不支持屏幕测距。',
11
+ startPrompt: '屏幕测距工具已启动。点击两点测量距离。右键重置。ESC 退出。'
12
+ },
9
13
  menu: {
10
14
  title: 'xw-devtool-cli 菜单',
11
15
  exit: '退出',
@@ -19,6 +23,7 @@ export default {
19
23
  dominantColor: '图片主色识别',
20
24
  colorPick: '颜色吸取',
21
25
  crosshair: '全屏十字辅助线',
26
+ pixelDistance: '屏幕测距 (像素)',
22
27
  placeholderImg: '占位图生成器',
23
28
  qrcode: '二维码生成器',
24
29
  url: 'URL 编码/解码',