亲宝软件园·资讯

展开

Rust利用tauri制作个效率小工具

_十九 人气:0

日常使用电脑中经常会用到一个quicke工具中的轮盘菜单工具。

但quicke免费版很多功能不支持,且它的触发逻辑用的不舒服,经常误触。

本着靠人不让靠自己,自己动手丰衣足食的理念,用tauri撸一个小工具。

先看效果

要解决的问题

唤起方式

因为要通过鼠标进行交互,所以必然会影响系统默认的鼠标行为。

为了减少交互冲突,选择长按右键唤起菜单。

就要解决如下问题:

1、默认情况要阻止右键鼠标的事件传递给操作系统

2、当右键按住时间小于设置长按唤起时间,要自动给系统发送一个右键按下和右键松开的事件

由于tauri没有提供相关的api,所以要从Rust的crate中找看看有没有相关包。

经过一番搜索,找到了rdev这个包,它提供了基础的系统级的鼠标键盘事件处理。

使用rdev::grab就可以监听鼠标键盘事件, 并且阻止事件传递

tauri::async_runtime::spawn(async move {
    rdev::grab(move |event| {
        let is_block: bool = match event.event_type {
            EventType::ButtonPress(button) => {
                match button {
                    Button::Right => {
                         unsafe {
                            !IS_SIMULATE
                         }
                    }
                    _ => { false }
                }
            }
            EventType::ButtonRelease(button) => {
                match button {
                    Button::Right => {
                        unsafe {
                            !IS_SIMULATE
                        }
                    }
                    _ => { false }
                }
            }
            _ => { false }
        };
        if is_block {
            None
        } else {
            Some(event)
        }
    }).unwrap();
});

通过tauri::async_runtime::spawn创建个异步任务

IS_SIMULATE是一个全局变量默认false会阻止右击事件,自动触发事件前会设置为true,使事件不被阻止,完成后再设置为false

rdev::grab通过流处理让右键的按下和松开返回个None阻止事件传递。

菜单出现的位置

我们希望唤起菜单中心在鼠标当前位置,所以

1、获取右击按下时的系统坐标信息

2、把系统的坐标传递给菜单窗口实现定位

由于rdev的鼠标点击事件没有鼠标位置信息,所以我们要在鼠标移动时保存坐标信息

EventType::MouseMove { x, y } => {
    unsafe {
        MOUSE_POSITION = (x, y);
    }
    false
}

按下鼠标是传递坐标

EventType::ButtonPress(button) => {
    unsafe {
        if !IS_SIMULATE {
            roulette_window.emit("buttondown", ButtonPayload { button: get_button_name(&button), x: MOUSE_POSITION.0, y: MOUSE_POSITION.1 }).unwrap();
        }
    }
    match button {
        Button::Right => {
            unsafe {
                !IS_SIMULATE
            }
        }
        _ => { false }
    }
}

同时我们把窗口设置全屏展示,这样系统的坐标 == 鼠标在窗口的坐标

接下来在窗口内绘制需要数量的扇形就完成了基本的制作。

这里使用SVG来绘制扇形菜单

菜单数据:

const config: {
  id: string;
  text?: string;
  image?: string;
  callback?: () => void;
}[] = []

tip: 根据菜单数量已经提前计算path需要的坐标信息

在react内渲染

  <svg className='menu' width={SIZE * 2} height={SIZE * 2} xmlns="http://www.w3.org/2000/svg">
    <g>
      <circle id='center' className='center' cx={SIZE} cy={SIZE} r={CENTER_SIZE} />
      {
        active
        && (
          active.id === 'close'
            ? (
              <text
                className='center-text'
                x={SIZE}
                y={SIZE}
                fill='red'
              >
                关闭
              </text>
            )
            : (
              <text
                className='center-text'
                x={SIZE}
                y={SIZE}
              >
                {active?.text}
              </text>
            )
        )
      }
    </g>
    {
      menu.map(({ id, text, image, points, center }) => (
        <g key={id}>
          <path
            id={id}
            className='item' d={`M ${points[0][0]} ${points[0][1]} A ${SIZE} ${SIZE}, 0, 0, 1, ${points[1][0]} ${points[1][1]} L ${points[2][0]} ${points[2][1]} A ${CENTER_SIZE} ${CENTER_SIZE}, 0, 0, 0, ${points[3][0]} ${points[3][1]} Z`}
          />
          {
            image
            && (
              <image
                className='item-img'
                xlinkHref={image}
                x={center[0] - 15}
                y={center[1] - 25}
                width='30'
              />
            )
          }
          {
            text
            && (
              <text
                className='item-text'
                x={center[0]}
                y={center[1] + 25}
              >
                {text}
              </text>
            )
          }
        </g>
      ))
    }
  </svg>

在窗口内通过document.addEventListener监听mousemove获取鼠标所在的块上,当松开鼠标时就能执行对应的任务。

最后

目前的菜单功能都是写死在代码里的,之后会加上配置功能,并且支持自己编写代码来控制每个菜单对应的具体操作。

后续还可以加上根据焦点应用来分别展示不同的菜单数据。

加载全部内容

相关教程
猜你喜欢
用户评论