首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何按生锈的‘`enigo`’键?

如何按生锈的‘`enigo`’键?
EN

Stack Overflow用户
提问于 2021-12-06 20:54:06
回答 1查看 206关注 0票数 0

有一个test.json

代码语言:javascript
运行
复制
[
    [1000,800,1],
    [1500,0,2],
    [1600,0,3],
    [2500,300,4]
]

第一个元素是启动时间(毫秒)。

第二个元素是时间的长度(毫秒)。

第三个元素是键,1\2\3\4分别表示a\b\c\d。

当开始时间到达第一个元素的值时,我希望按下相应的键,并保持第二个元素的长度。

以第一组数据为例:

当时间到1000毫秒时,按“a”键800毫秒。

我准备使用机箱计时尼戈json,下面是我的代码:

只有少量的自定义代码。使用关键字Here is my code start进行搜索。另一种代码是计时示例中的模板。

Cargo.toml

代码语言:javascript
运行
复制
[dependencies]
delay_timer = "0.10.1"
enigo = "0.0.14"
serde_json = "1.0"
anyhow = "1.0.51"
smol = "1.2.5"

main.rs

代码语言:javascript
运行
复制
use anyhow::Result;
use delay_timer::prelude::*;
use enigo::*;
use serde_json::{Result as SResult, Value};
use smol::Timer;
use std::fs::File;
use std::io::BufReader;
use std::thread;
use std::time::Duration;

fn main() -> Result<()> {
    let delay_timer = DelayTimerBuilder::default().build();
    // Create the task
    // A chain of task instances.
    let task_instance_chain = delay_timer
        .insert_task(build_task_async_print().unwrap())
        .unwrap();

    // Get the running instance of task 1.
    let task_instance = task_instance_chain.next_with_wait().unwrap();

    // This while loop avoids removing the task before it completes
    while task_instance.get_state() != delay_timer::prelude::instance::COMPLETED {}

    // Remove task which id is 1.
    delay_timer.remove_task(1).unwrap();
    Ok(())
}

fn build_task_async_print() -> Result<Task, TaskError> {
    let mut task_builder = TaskBuilder::default();

    let body = create_async_fn_body!({
        //Here is my code start
        let json_data = get_json().unwrap();

        for element in json_data.as_array().unwrap().iter() {
            Timer::after(Duration::from_millis(element[0].as_f64().unwrap() as u64)).await;
            println!("the value is: {}", element[0]);

            //How to complete the code that uses enigo to press the corresponding keys?
            let mut enigo = Enigo::new();
            enigo.key_down(Key::Layout('a'));
            thread::sleep(Duration::from_millis(element[1].as_f64().unwrap() as u64));
            enigo.key_up(Key::Layout('a'));
        }
        //Here is my code end
    });

    // Build the task and assign 1 to it
    task_builder.set_task_id(1).spawn(body)
}

//Get json data from json file
fn get_json() -> SResult<Value> {
    let file = File::open("test.json").expect("file should open read only");
    let reader = BufReader::new(file);
    let mut v: Value = serde_json::from_reader(reader)?;
    Ok(v.take())
}

问题:

如何完成使用enigo按下相应键的代码?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-07 10:58:51

又快又脏

假设您只使用小写ASCII字符,您可以这样做:

代码语言:javascript
运行
复制
use anyhow::Result;
use delay_timer::prelude::*;
use enigo::*;
use serde_json::{Result as SResult, Value};
use smol::Timer;
use std::fs::File;
use std::io::BufReader;
use std::thread;
use std::time::Duration;

fn main() -> Result<()> {
    let delay_timer = DelayTimerBuilder::default().build();
    // Create the task
    // A chain of task instances.
    let task_instance_chain = delay_timer
        .insert_task(build_task_async_print().unwrap())
        .unwrap();

    // Get the running instance of task 1.
    let task_instance = task_instance_chain.next_with_wait().unwrap();

    // This while loop avoids removing the task before it completes
    while task_instance.get_state() != delay_timer::prelude::instance::COMPLETED {}

    // Remove task which id is 1.
    delay_timer.remove_task(1).unwrap();
    Ok(())
}

fn build_task_async_print() -> Result<Task, TaskError> {
    let mut task_builder = TaskBuilder::default();

    let body = create_async_fn_body!({
        //Here is my code start
        let json_data = get_json().unwrap();

        for element in json_data.as_array().unwrap().iter() {
            Timer::after(Duration::from_millis(element[0].as_f64().unwrap() as u64)).await;
            println!("the value is: {}", element[0]);

            //How to complete the code that uses enigo to press the corresponding keys?
            let mut enigo = Enigo::new();
            enigo.key_down(Key::Layout(((element[2].as_u64().unwrap() + 96) as u8) as char));
            thread::sleep(Duration::from_millis(element[1].as_f64().unwrap() as u64));
            enigo.key_up(Key::Layout(((element[2].as_u64().unwrap() + 96) as u8) as char));
        }
        //Here is my code end
    });

    // Build the task and assign 1 to it
    task_builder.set_task_id(1).spawn(body)
}

//Get json data from json file
fn get_json() -> SResult<Value> {
    let file = File::open("test.json").expect("file should open read only");
    let reader = BufReader::new(file);
    let mut v: Value = serde_json::from_reader(reader)?;
    Ok(v.take())
}

较好方法

如果您控制了JSON,我将直接将字符放在数组中(或者至少使用它们的十进制ASCII代码),或者更好地使用易于解析为生锈结构的JSON对象。

所以我提议的JSON应该是这样的:

代码语言:javascript
运行
复制
[
    {
        "startTime": 1000,
        "duration": 800,
        "key": "a"
    },
    {
        "startTime": 1500,
        "duration": 0,
        "key": "b"
    },
    {
        "startTime": 1600,
        "duration": 0,
        "key": "c"
    },
    {
        "startTime": 2500,
        "duration": 300,
        "key": "d"
    }
]

然后您就可以像这样轻松地解析它:

代码语言:javascript
运行
复制
use anyhow::Result;
use delay_timer::prelude::*;
use enigo::*;
use serde::Deserialize;
use smol::Timer;
use std::thread;
use std::time::Duration;

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct EnigoCommand {
    pub start_time: u64,
    pub duration: u64,
    pub key: char
}

fn main() -> Result<()> {
    let delay_timer = DelayTimerBuilder::default().build();

    let task_instance_chain = delay_timer
        .insert_task(build_task_async_print().unwrap())
        .unwrap();
    let task_instance = task_instance_chain.next_with_wait().unwrap();

    while task_instance.get_state() != delay_timer::prelude::instance::COMPLETED {}

    delay_timer.remove_task(1).unwrap();
    Ok(())
}

fn build_task_async_print() -> Result<Task, TaskError> {
    let mut task_builder = TaskBuilder::default();

    let body = create_async_fn_body!({
        let commands = get_commands().expect("Failed to read commands from json file.");

        for command in commands.iter() {
            Timer::after(Duration::from_millis(command.start_time)).await;

            let mut enigo = Enigo::new();
            enigo.key_down(Key::Layout(command.key));
            thread::sleep(Duration::from_millis(command.duration));
            enigo.key_up(Key::Layout(command.key));
        }
    });
    task_builder.set_task_id(1).spawn(body)
}

fn get_commands() -> Result<Vec<EnigoCommand>, Box<dyn std::error::Error>> {
    let file = std::fs::read_to_string("test.json")?;
    let commands: Vec<EnigoCommand> = serde_json::from_str(file.as_str())?;
    Ok(commands)
}

请注意,这还需要具有serde特性的derive依赖项:

代码语言:javascript
运行
复制
[dependencies]
delay_timer = "0.10.1"
enigo = "0.0.14"
serde={version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0.51"
smol = "1.2.5"
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70251830

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档