[Quicker] 图像点击助手 - 源码归档

动作:图像点击助手

AI 混合动力自动点击工具。支持子程序扩展找图、可调节检测频率及悬浮控制面板。

更新时间:2025-12-31 21:28
原始文件:自动点击助手.cs

核心代码

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Windows.Interop;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Collections.Generic;
using System.Threading;
using System.Linq;
using System.Threading.Tasks;
using Quicker.Public;
using Brushes = System.Windows.Media.Brushes;

public static void Exec(IStepContext context)
{
    SetProcessDPIAware();
    var frame = new DispatcherFrame();
    System.Windows.Application.Current.Dispatcher.Invoke(() => {
        try {
            var panel = new FloatingControlPanel(context);
            panel.Closed += (s, e) => frame.Continue = false;
            panel.Show();
        } catch (Exception ex) {
            System.Windows.MessageBox.Show("启动失败: " + ex.Message);
            frame.Continue = false;
        }
    });
    Dispatcher.PushFrame(frame);
}

[DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();

public class FloatingControlPanel : Window
{
    private IStepContext _context;
    private DispatcherTimer _timer;
    private bool _isRunning = false;
    private bool _isAdjusting = false; // 是否处于调整锚点模式
    private string _currentBase64 = "";
    private TextBlock _logBoard;
    private ScrollViewer _logScroller;
    private System.Windows.Controls.Button _btnToggle;
    private System.Windows.Controls.Button _btnAdjust;
    private System.Windows.Controls.Image _previewImg;
    private Canvas _markerCanvas;
    private Grid _crossMarker; // 改为 Grid 容器以确保几何中心对齐
    private TextBox _txtInterval;
    private Border _previewBorder;
    private bool _isWorking = false;
    
    // 物理像素偏移量 (相对于原图中心)
    private double _offsetX = 0;
    private double _offsetY = 0;
    private Grid _rootGrid;
    private StackPanel _mainLayout;
    private Border _miniLayout;
    private Ellipse _miniStatus;
    private bool _isMini = false;

    [DllImport("user32.dll")] private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
    [DllImport("user32.dll")] private static extern bool SetCursorPos(int X, int Y);
    [DllImport("user32.dll")] private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    [DllImport("user32.dll")] private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    [DllImport("user32.dll")] private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
    [DllImport("user32.dll")] private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

    private const int HOTKEY_ID = 9527;
    private const int GWL_EXSTYLE = -20;
    private const int WS_EX_NOACTIVATE = 0x08000000;

    public FloatingControlPanel(IStepContext context)
    {
        _context = context;
        InitWindow();
        InitContent();
        LoadLocalData();
    }

    private void Log(string msg) {
        this.Dispatcher.Invoke(() => {
            _logBoard.Text += $"[{DateTime.Now:HH:mm:ss}] {msg}\n";
            _logScroller.ScrollToBottom();
            if (_logBoard.Text.Length > 3000) _logBoard.Text = _logBoard.Text.Substring(1500);
        });
    }

    private void LoadLocalData() {
        try {
            var b64 = _context.GetVarValue("targetImage")?.ToString();
            if (!string.IsNullOrEmpty(b64)) {
                UpdateTarget(Convert.FromBase64String(b64));
            }
            
            _offsetX = Convert.ToDouble(_context.GetVarValue("offsetX") ?? 0);
            _offsetY = Convert.ToDouble(_context.GetVarValue("offsetY") ?? 0);
            UpdateMarkerPosition();

            if (double.TryParse(_context.GetVarValue("winLeft")?.ToString(), out double l) && 
                double.TryParse(_context.GetVarValue("winTop")?.ToString(), out double t)) {
                this.Left = l; this.Top = t;
            }
        } catch {}
    }

    private void SaveWindowPosition() {
        if (!_isMini && this.WindowState == WindowState.Normal) {
             _context.SetVarValue("winLeft", this.Left);
             _context.SetVarValue("winTop", this.Top);
        }
    }

    private void UpdateTarget(byte[] bytes) {
        try {
            _currentBase64 = Convert.ToBase64String(bytes);
            using (var ms = new MemoryStream(bytes)) {
                var bi = new BitmapImage(); bi.BeginInit(); bi.StreamSource = ms; bi.CacheOption = BitmapCacheOption.OnLoad; bi.EndInit();
                _previewImg.Source = bi;
                _context.SetVarValue("targetImage", _currentBase64);
                
                // 强制 UI 渲染后更新标记
                this.Dispatcher.BeginInvoke(new Action(() => {
                    _previewBorder.BorderBrush = Brushes.DeepSkyBlue;
                    UpdateMarkerPosition();
                }), DispatcherPriority.ContextIdle);
                
                Log(" 目标图片已更新" + (bytes.Length > 0 ? $" ({bi.PixelWidth}x{bi.PixelHeight})" : ""));
            }
        } catch (Exception ex) { Log("加载失败: " + ex.Message); }
    }

    private void InitWindow() {
        this.Title = "图像点击助手"; this.Width = 300; this.Height = 460; this.Topmost = true; this.WindowStyle = WindowStyle.None; this.AllowsTransparency = true;
        this.Background = new SolidColorBrush(System.Windows.Media.Color.FromArgb(245, 20, 20, 20));
        this.BorderBrush = new SolidColorBrush(System.Windows.Media.Color.FromRgb(60, 60, 60)); this.BorderThickness = new Thickness(1);
        this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
        
        this.MouseLeftButtonDown += (s, e) => { if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed) this.DragMove(); };
        
        // 改进粘贴逻辑:全局拦截窗口按键
        this.PreviewKeyDown += (s, e) => {
            if (e.Key == System.Windows.Input.Key.V && (System.Windows.Input.Keyboard.Modifiers & System.Windows.Input.ModifierKeys.Control) != 0) {
                HandlePaste();
                e.Handled = true;
            }
        };
        // 确保窗口能接收焦点,以便响应粘贴
        this.Focusable = true;
        this.Loaded += (s, e) => this.Focus();
        this.LocationChanged += (s, e) => SaveWindowPosition();
        this.PreviewMouseDown += (s, e) => {
            if (!this.IsFocused) this.Focus();
        };
    }

    private void SwitchViewMode() {
        _isMini = !_isMini;
        if (_isMini) {
            _mainLayout.Visibility = Visibility.Collapsed;
            _miniLayout.Visibility = Visibility.Visible;
            this.Width = 60; this.Height = 60;
            this.Background = Brushes.Transparent;
            _previewBorder.Visibility = Visibility.Collapsed; // 隐藏预览避免资源占用
            this.ResizeMode = ResizeMode.NoResize;
        } else {
            _mainLayout.Visibility = Visibility.Visible;
            _miniLayout.Visibility = Visibility.Collapsed;
            this.Width = 300; this.Height = 460;
            this.Background = new SolidColorBrush(System.Windows.Media.Color.FromArgb(245, 20, 20, 20));
            _previewBorder.Visibility = Visibility.Visible;
            this.ResizeMode = ResizeMode.CanResize; // 如果原本需要resize的话
        }
    }

    private void InitContent() {
        _rootGrid = new Grid();
        _mainLayout = new StackPanel { Margin = new Thickness(15) };
        
        // --- 标题栏 ---
        var titleRow = new DockPanel();
        var lbl = new TextBlock { Text = " 图像点击助手", Foreground = Brushes.DeepSkyBlue, FontWeight = FontWeights.Bold, VerticalAlignment = VerticalAlignment.Center };
        
        var btnPanel = new StackPanel { Orientation = Orientation.Horizontal };
        DockPanel.SetDock(btnPanel, Dock.Right);
        
        var btnMini = new System.Windows.Controls.Button {
            Content = "_", Width = 30, Height = 30, Margin = new Thickness(0,0,5,0),
            Background = Brushes.Transparent, Foreground = Brushes.Gray, 
            BorderThickness = new Thickness(0), Cursor = System.Windows.Input.Cursors.Hand, FontWeight = FontWeights.Bold
        };
        btnMini.Click += (s, e) => SwitchViewMode();

        var btnCls = new System.Windows.Controls.Button { 
            Content = "✕", Width = 30, Height = 30, 
            Background = new SolidColorBrush(System.Windows.Media.Color.FromArgb(50, 255, 0, 0)), 
            Foreground = System.Windows.Media.Brushes.White, BorderThickness = new Thickness(0), Cursor = System.Windows.Input.Cursors.Hand
        };
        btnCls.Click += (s, e) => this.Close();
        
        btnPanel.Children.Add(btnMini);
        btnPanel.Children.Add(btnCls);
        titleRow.Children.Add(btnPanel); 
        titleRow.Children.Add(lbl); 
        _mainLayout.Children.Add(titleRow);

        // 预览容器
        _previewBorder = new Border { 
            Height = 110, Background = System.Windows.Media.Brushes.Black, 
            Margin = new Thickness(0, 15, 0, 10), 
            BorderBrush = new SolidColorBrush(System.Windows.Media.Color.FromRgb(80, 80, 80)), 
            BorderThickness = new Thickness(1.5), 
            AllowDrop = true, CornerRadius = new CornerRadius(4), ClipToBounds = true
        };
        
        var grid = new Grid();
        _previewImg = new System.Windows.Controls.Image { Stretch = Stretch.Uniform };
        _markerCanvas = new Canvas { IsHitTestVisible = false }; 
        _markerCanvas = new Canvas { IsHitTestVisible = false }; 
        
        // 使用 Grid 容器包裹 Path,确保中心点坐标明确 (10,10)
        _crossMarker = new Grid { Width = 20, Height = 20, Visibility = Visibility.Collapsed, IsHitTestVisible = false };
        var path = new System.Windows.Shapes.Path {
            Stroke = Brushes.Red, StrokeThickness = 2,
            Data = Geometry.Parse("M 0,10 L 20,10 M 10,0 L 10,20"), // 绝对坐标,中心在 10,10
            HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center,
            Effect = new System.Windows.Media.Effects.DropShadowEffect { Color = Colors.Black, BlurRadius = 2, ShadowDepth = 0 }
        };
        _crossMarker.Children.Add(path);
        _markerCanvas.Children.Add(_crossMarker);
        
        grid.Children.Add(_previewImg);
        grid.Children.Add(_markerCanvas);
        _previewBorder.Child = grid;

        // 拖拽以高亮显示
        _previewBorder.DragEnter += (s, e) => {
             if (e.Data.GetDataPresent(System.Windows.DataFormats.FileDrop)) {
                 e.Effects = DragDropEffects.Copy;
                 _previewBorder.BorderBrush = Brushes.SpringGreen;
                 _previewBorder.Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(30, 30, 30));
             } else {
                 e.Effects = DragDropEffects.None;
             }
             e.Handled = true; 
        };
        _previewBorder.DragLeave += (s, e) => {
             if (!_isAdjusting) _previewBorder.BorderBrush = new SolidColorBrush(System.Windows.Media.Color.FromRgb(80, 80, 80));
             else _previewBorder.BorderBrush = Brushes.DeepSkyBlue;
             _previewBorder.Background = Brushes.Black;
        };
        _previewBorder.Drop += (s, e) => { 
            _previewBorder.Background = Brushes.Black;
            if (e.Data.GetDataPresent(System.Windows.DataFormats.FileDrop)) {
                var files = (string[])e.Data.GetData(System.Windows.DataFormats.FileDrop);
                UpdateTarget(File.ReadAllBytes(files[0]));
            } else {
                // 恢复边框
                if (_isAdjusting) _previewBorder.BorderBrush = Brushes.DeepSkyBlue;
                else _previewBorder.BorderBrush = new SolidColorBrush(System.Windows.Media.Color.FromRgb(80, 80, 80));
            }
        };

        // 点击预览容器设置偏移 (仅在调整模式下生效)
        grid.MouseLeftButtonDown += (s, e) => {
            if (!_isAdjusting || _previewImg.Source == null) return;
            var pos = e.GetPosition(_previewImg);
            var rect = GetMainImageRect();
            
            // 简单判断是否点击在图片范围内
            if (rect.IsEmpty || !rect.Contains(pos)) return;

            // 计算相对于图片中心的偏移 (物理像素)
            // 逻辑: (点击位置 - 图片显示区域中心) / 缩放比例
            var source = (BitmapSource)_previewImg.Source;
            double scale = rect.Width / source.PixelWidth; // 当前显示比例
            
            // 图片显示的中心点
            double imgCenterX = rect.X + rect.Width / 2;
            double imgCenterY = rect.Y + rect.Height / 2;

            _offsetX = (pos.X - imgCenterX) / scale;
            _offsetY = (pos.Y - imgCenterY) / scale;
            
            _context.SetVarValue("offsetX", _offsetX);
            _context.SetVarValue("offsetY", _offsetY);
            
            UpdateMarkerPosition();
            Log($" 锚点已设: {Math.Round(_offsetX)},{Math.Round(_offsetY)}");
            e.Handled = true;
        };

        _mainLayout.Children.Add(_previewBorder);

        // 功能按钮组
        var btnStack = new StackPanel { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Center, Margin = new Thickness(0,0,0,10) };
        _btnAdjust = new System.Windows.Controls.Button { 
            Content = " 调整锚点", Width = 90, Height = 28, Margin = new Thickness(0,0,5,0),
            Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(60,60,60)), Foreground = Brushes.White,
            BorderThickness = new Thickness(0), Cursor = System.Windows.Input.Cursors.Hand
        };
        _btnAdjust.Click += (s, e) => {
            _isAdjusting = !_isAdjusting;
            _btnAdjust.Background = _isAdjusting ? Brushes.DeepSkyBlue : new SolidColorBrush(System.Windows.Media.Color.FromRgb(60,60,60));
            _previewBorder.BorderBrush = _isAdjusting ? Brushes.DeepSkyBlue : new SolidColorBrush(System.Windows.Media.Color.FromRgb(80, 80, 80));
            _previewImg.Cursor = _isAdjusting ? System.Windows.Input.Cursors.Cross : System.Windows.Input.Cursors.Arrow;
            Log(_isAdjusting ? " 请在上方预览图中点击目标位置" : "锚点模式已关闭");
        };
        
        var btnClear = new System.Windows.Controls.Button { 
            Content = "♻️ 重置", Width = 60, Height = 28, 
            Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(60,60,60)), Foreground = Brushes.White,
            BorderThickness = new Thickness(0), Cursor = System.Windows.Input.Cursors.Hand
        };
        btnClear.Click += (s, e) => { _offsetX = 0; _offsetY = 0; UpdateMarkerPosition(); Log("已重置为中心点击"); };
        
        btnStack.Children.Add(_btnAdjust); btnStack.Children.Add(btnClear);
        _mainLayout.Children.Add(btnStack);

        var settingRow = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 0, 0, 10) };
        settingRow.Children.Add(new TextBlock { Text = "检测频率: ", Foreground = Brushes.Gray, VerticalAlignment = VerticalAlignment.Center });
        _txtInterval = new TextBox { 
            Text = "3", Width = 40, Height = 24, 
            Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(40, 40, 40)), Foreground = Brushes.White, 
            BorderThickness = new Thickness(0, 0, 0, 1), BorderBrush = Brushes.Gray, TextAlignment = TextAlignment.Center
        };
        settingRow.Children.Add(_txtInterval);
        settingRow.Children.Add(new TextBlock { Text = " 秒/次", Foreground = Brushes.Gray, VerticalAlignment = VerticalAlignment.Center });
        _mainLayout.Children.Add(settingRow);

        _btnToggle = new System.Windows.Controls.Button { 
            Content = "▶ 开始自动点击", Height = 48, 
            Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(34, 139, 34)), Foreground = Brushes.White, 
            BorderThickness = new Thickness(0), FontWeight = FontWeights.Bold, FontSize = 15, Cursor = System.Windows.Input.Cursors.Hand
        };
        _btnToggle.Click += (s, e) => Toggle();
        _mainLayout.Children.Add(_btnToggle);

        _mainLayout.Children.Add(new TextBlock { Text = "运行日志:", Foreground = Brushes.DimGray, FontSize = 11, Margin = new Thickness(0,12,0,5) });
        _logScroller = new ScrollViewer { Height = 100, Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(15, 15, 15)) };
        _logBoard = new TextBlock { Foreground = Brushes.Silver, FontSize = 11, Padding = new Thickness(8), TextWrapping = TextWrapping.Wrap };
        _logScroller.Content = _logBoard; _mainLayout.Children.Add(_logScroller);

        // --- Mini Mode UI ---
        _miniLayout = new Border {
            Width = 50, Height = 50, CornerRadius = new CornerRadius(25),
            Background = new SolidColorBrush(System.Windows.Media.Color.FromArgb(200, 30, 30, 30)),
            BorderBrush = Brushes.Gray, BorderThickness = new Thickness(1),
            Visibility = Visibility.Collapsed, Cursor = System.Windows.Input.Cursors.Hand
        };
        // 双击还原
        _miniLayout.MouseLeftButtonDown += (s, e) => {
            if (e.ClickCount == 2) SwitchViewMode();
            else this.DragMove();
        };

        var miniGrid = new Grid();
        _miniStatus = new Ellipse { 
            Width = 40, Height = 40, Fill = Brushes.Gray, Stroke = Brushes.White, StrokeThickness = 2,
            Effect = new System.Windows.Media.Effects.DropShadowEffect { Color = Colors.Black, BlurRadius = 5, ShadowDepth = 0 }
        };
        var miniIcon = new TextBlock { 
            Text = "⤢", Foreground = Brushes.White, FontWeight = FontWeights.Bold, 
            HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, FontSize = 18 
        };
        miniGrid.Children.Add(_miniStatus);
        miniGrid.Children.Add(miniIcon);
        _miniLayout.Child = miniGrid;

        _rootGrid.Children.Add(_mainLayout);
        _rootGrid.Children.Add(_miniLayout);
        this.Content = _rootGrid;
        _timer = new DispatcherTimer();
        _timer.Tick += (s, e) => DoWork();
        
        // 当预览图尺寸变化时自动刷新红十字位置
        this.SizeChanged += (s, e) => UpdateMarkerPosition();
    }

    private Rect GetMainImageRect() {
        if (_previewImg.Source == null) return Rect.Empty;
        var source = (BitmapSource)_previewImg.Source;
        double cw = _previewImg.ActualWidth;
        double ch = _previewImg.ActualHeight;
        if (cw == 0 || ch == 0) return Rect.Empty;
        
        // 计算缩放 (Uniform)
        double scale = Math.Min(cw / source.PixelWidth, ch / source.PixelHeight);
        double w = source.PixelWidth * scale;
        double h = source.PixelHeight * scale;
        
        return new Rect((cw - w)/2, (ch - h)/2, w, h);
    }

    private void UpdateMarkerPosition() {
        if (_previewImg.Source == null) { _crossMarker.Visibility = Visibility.Collapsed; return; }
        
        _crossMarker.Visibility = Visibility.Visible;
        var rect = GetMainImageRect();
        
        if (rect.IsEmpty) return;
        
        var source = (BitmapSource)_previewImg.Source;
        double scale = rect.Width / source.PixelWidth;

        double centerX = rect.X + rect.Width / 2;
        double centerY = rect.Y + rect.Height / 2;
        
        // 坐标 = 渲染中心 + (物理偏移 * 缩放比例) - Marker半径(10)
        // 减去10是因为 Canvas.SetLeft 定位的是元素的左上角,而我们的中心在 (10,10)
        Canvas.SetLeft(_crossMarker, centerX + (_offsetX * scale) - 10);
        Canvas.SetTop(_crossMarker, centerY + (_offsetY * scale) - 10);
    }

    private void Toggle() {
        _isRunning = !_isRunning;
        if (_isRunning) { 
            if (double.TryParse(_txtInterval.Text, out double s)) _timer.Interval = TimeSpan.FromSeconds(Math.Max(0.1, s));
            else _timer.Interval = TimeSpan.FromSeconds(3);
            _btnToggle.Content = "⏸ 停止点击程序"; _btnToggle.Background = Brushes.Crimson;
            _miniStatus.Fill = Brushes.SpringGreen; // 运行中 - 绿色
            _txtInterval.IsEnabled = false; _timer.Start(); Log("✅ 点击助手开始执勤"); 
        } else { 
            _btnToggle.Content = "▶ 开始自动点击"; _btnToggle.Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(34, 139, 34)); 
            _miniStatus.Fill = Brushes.Gray; // 暂停 - 灰色
            _txtInterval.IsEnabled = true; _timer.Stop(); Log("⏸ 点击助手已休放"); 
        }
    }

    private async void DoWork() {
        if (!_isRunning || _isWorking || string.IsNullOrEmpty(_currentBase64)) return;
        try {
            _isWorking = true; _timer.Stop();
            var inputs = new Dictionary<string, object> { { "imgBase64", _currentBase64 } };
            IDictionary<string, object> result = null;
            try { result = await _context.RunSpAsync("Quicker找图", inputs); }
            catch { try { result = await _context.RunSpAsync("@Quicker找图", inputs); } catch { return; } }

            if (result != null && result.ContainsKey("found") && (bool)result["found"]) {
                if (result.ContainsKey("firstPoint") && result["firstPoint"] != null) {
                    string[] pts = result["firstPoint"].ToString().Split(',');
                    if (pts.Length == 2) {
                        int x = (int)float.Parse(pts[0]), y = (int)float.Parse(pts[1]);
                        
                        // 逻辑:Quicker 返回的是目标中心。我们加上存储的物理偏移。
                        int finalX = x + (int)_offsetX;
                        int finalY = y + (int)_offsetY;

                        this.Dispatcher.BeginInvoke(new Action(() => {
                            Log($"✨ 匹配! 点击坐标: ({finalX}, {finalY})");
                            SetCursorPos(finalX, finalY); 
                            mouse_event(0x02, finalX, finalY, 0, 0); 
                            mouse_event(0x04, finalX, finalY, 0, 0);
                        }));
                    }
                }
            }
        } catch (Exception ex) { Log("⚠ 异常: " + ex.Message); }
        finally { _isWorking = false; if (_isRunning) _timer.Start(); }
    }

    private void HandlePaste() {
        try {
            if (System.Windows.Clipboard.ContainsImage()) {
                var bs = System.Windows.Clipboard.GetImage();
                using (var ms = new MemoryStream()) {
                    var enc = new PngBitmapEncoder();
                    enc.Frames.Add(BitmapFrame.Create(bs)); enc.Save(ms);
                    UpdateTarget(ms.ToArray());
                }
                Log(" 已从剪贴板粘贴");
            } else if (System.Windows.Clipboard.ContainsFileDropList()) {
                var files = System.Windows.Clipboard.GetFileDropList();
                if (files.Count > 0 && File.Exists(files[0])) {
                     UpdateTarget(File.ReadAllBytes(files[0]));
                     Log(" 已从剪贴板粘贴文件");
                }
            } else {
                Log("⚠ 剪贴板中没有图片");
            }
        } catch (Exception ex) { Log("粘贴失败: " + ex.Message); }
    }

    protected override void OnSourceInitialized(EventArgs e) {
        base.OnSourceInitialized(e); 
        var h = new WindowInteropHelper(this).Handle; RegisterHotKey(h, HOTKEY_ID, 0, 0x78);
        SetWindowLong(h, GWL_EXSTYLE, GetWindowLong(h, GWL_EXSTYLE) | WS_EX_NOACTIVATE);
        HwndSource.FromHwnd(h).AddHook((IntPtr handle, int m, IntPtr w, IntPtr l, ref bool hd) => { if (m == 0x0312 && w.ToInt32() == HOTKEY_ID) { Toggle(); hd = true; } return IntPtr.Zero; });
    }

    protected override void OnClosed(EventArgs e) { 
        UnregisterHotKey(new WindowInteropHelper(this).Handle, HOTKEY_ID); _timer.Stop(); base.OnClosed(e); 
    }
}

动作配置 (JSON)

{
  "ActionId": "38d23af9-9ac3-4ab5-9a97-2219544354f5",
  "Title": "图像点击助手",
  "Description": "AI 混合动力自动点击工具。支持子程序扩展找图、可调节检测频率及悬浮控制面板。",
  "Icon": "fa:Solid_MousePointer:#FF00BFFF",
  "Variables": [
    {
      "Key": "text",
      "IsLocked": false,
      "Type": 0,
      "Desc": "结果文本(自动)",
      "DefaultValue": null,
      "SaveState": false,
      "IsInput": false,
      "IsOutput": false,
      "ParamName": null,
      "InputParamInfo": null,
      "OutputParamInfo": null,
      "TableDef": null,
      "CustomType": null,
      "Group": null
    },
    {
      "Key": "rtn",
      "IsLocked": false,
      "Type": 0,
      "Desc": "返回值(自动)",
      "DefaultValue": null,
      "SaveState": false,
      "IsInput": false,
      "IsOutput": false,
      "ParamName": null,
      "InputParamInfo": null,
      "OutputParamInfo": null,
      "TableDef": null,
      "CustomType": null,
      "Group": null
    },
    {
      "Key": "errMessage",
      "IsLocked": false,
      "Type": 0,
      "Desc": "错误信息(自动)",
      "DefaultValue": null,
      "SaveState": false,
      "IsInput": false,
      "IsOutput": false,
      "ParamName": null,
      "InputParamInfo": null,
      "OutputParamInfo": null,
      "TableDef": null,
      "CustomType": null,
      "Group": null
    },
    {
      "Key": "silent",
      "IsLocked": false,
      "Type": 2,
      "Desc": "静默启动",
      "DefaultValue": "true",
      "SaveState": false,
      "IsInput": false,
      "IsOutput": false,
      "ParamName": null,
      "InputParamInfo": null,
      "OutputParamInfo": null,
      "TableDef": null,
      "CustomType": null,
      "Group": null
    },
    {
      "Type": 0,
      "Desc": "用户名",
      "IsOutput": false,
      "DefaultValue": "luo18428029750",
      "Key": "userName"
    },
    {
      "Type": 0,
      "Desc": "密码",
      "IsOutput": false,
      "DefaultValue": "Aa13689663458",
      "Key": "password"
    },
    {
      "Key": "interval",
      "Type": 12,
      "Desc": "检测间隔(毫秒)",
      "DefaultValue": "500"
    },
    {
      "Key": "targetImage",
      "Type": 0,
      "Desc": "目标图片Base64",
      "DefaultValue": "iVBORw0KGgoAAAANSUhEUgAAAEcAAAAVCAYAAAAU9vPjAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJmSURBVFhH7ZVNSxxBEIYXhCCIRBSTScREYj4gfkTwp3kRIyYkUfMdxev+DK/+gz3quuu6Z2EPehH0IFT67ZqaqZ7pXpTNqpBueNnpqu5m6pm3eiuV5X2KCsgbjGJ5g1EsbzCK5Q1GsbzB/1jPvjbp9c8jmvrW1HBOqU5E9Zq7+K41/KFO81vH9oV1/OlGg2b/tGxex3vV5GbTnm3nWaJ2SWcdo4tzWpLYLanaCX8UgQBAY58OS3HAgfCcFdWDvHCqnSva2z2hvQv8uhv6rW5w4Jjnxuozpnj8SvxfwcHeN79aNJqC98AxLZU6Zql9RWftk2wzhJeXkecAMg2akRVnHJiNzIVo2Uuqqpyco8/O17Pw4oACxwggyQmcx18a1lWLO20rvQYSuDomGvl4aMG8MmvElVibrCs4DpDdc6e1kKPOKeeUUFQRogWj1ubn8n2W5zDPHRpyjgaCl9etdV3nhOCMf27Y3EMD6MX3I3r7u0Vz5nw8D64e8Dp2gG4lPQ+1WeoEJ5aCLA4LpLxef5AQnGIr6Xk3OJhrNxVd9cQ4A27JIHg0tGYueuuUtA498i9ehlB0l8hxoKObw4FDFrbDBfbinImNJr38EYYDMMhXvAVZYFyMvRNKbcX3TWmfvVM8MC0cDQDz7m2lW0oEYO8MMEDoBQ70yNxVyGHvtAEBp0FoL4DBfVTxtw0Xzy/MzzJyIFywDCmu2FocZ+fUATodDgy5qJUbiy0lQhxFaTiII6addR3hH6p4ITsqBfqiclvdFwEuAEU4AT14f0ADK577pxToi+43nKC8wSiWNxjFSpKEonxK6C8CfvJUD1ZGfQAAAABJRU5ErkJggg=="
    }
  ],
  "References": [
    "PresentationCore",
    "PresentationFramework",
    "WindowsBase",
    "System.Drawing",
    "System.Xaml",
    "Quicker.Public.dll"
  ]
}

使用方法

  1. 确保您已安装 动作构建 (Action Builder) 动作。
  2. 将本文提供的 .cs.json 文件下载到同一目录
  3. 选中 .json 文件,运行「动作构建」即可生成并安装动作。
posted @ 2025-12-31 21:28  luoluoluo22  阅读(5)  评论(0)    收藏  举报