V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iliaoliao
V2EX  ›  外包

有个私活,把一个 ahk 函数转成 rust 函数,预算 500

  •  
  •   iliaoliao · 37 天前 · 1383 次点击
    这是一个创建于 37 天前的主题,其中的信息可能已经有所发展或是发生改变。
    下面是 ahk 函数,用到了一个 ahk 库 Gdip.ahk ,要求用 rust 和 windows-rs 库实现一个相同功能的函数。
    实现出来了可以加我微信私聊,WX:bHgxMDc2OTg4OTQ0

    ```ahk
    可视化(var0 := "0", var1 := "0", var2 := "0")
    { ;显示坐标
    if !pToken := Gdip_Startup()
    {
    MsgBox, % 4096+262208, , Gdiplus 错误!, Gdiplus 无法启动.请确保系统中有 gdiplus.dll
    return
    }

    Gui, GUILX: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
    Gui, GUILX: Show, NA
    Width := A_ScreenWidth
    Height := A_ScreenHeight
    hwnd1 := WinExist()
    hbm := CreateDIBSection(Width, Height)
    hdc := CreateCompatibleDC()
    obm := SelectObject(hdc, hbm)
    G := Gdip_GraphicsFromHDC(hdc)
    pBrush1 := Gdip_CreatePen(0xFFFF0000, 1)
    pBrush2 := Gdip_CreatePen(0xFF00FFFF, 1)
    pBrush3 := Gdip_CreatePen(0xFFFFFF00, 1)

    for k, v in var0
    {
    Gdip_DrawRectangle(G, pBrush1, v.x, v.y, v.w, v.h)
    }

    if var1
    {
    x := "", y := "", c := ""
    For k, v in var1
    {
    if (y = "")
    {
    N := StrSplit(v,",")
    x := N[1],y := N[2]
    c .= "`n" . k . " : " . v
    }
    tx:=x
    ty:=y-20
    Gdip_TextToGraphics(G, k, "x" tx "y" ty "h20 Centre cFF00FF00 r4 s12 Left")
    Gdip_DrawLine(G, pBrush2, x - 5, y, x - 1 , y)
    Gdip_DrawLine(G, pBrush2, x + 5, y, x + 1 , y)
    Gdip_DrawLine(G, pBrush2, x, y - 5, x, y - 1)
    Gdip_DrawLine(G, pBrush2, x, y + 5, x, y + 1)
    }
    }
    if var2
    {
    Gdip_DrawRectangle(G, pBrush3, var2.x - 5, var2.y - 5, var2.w + 10, var2.h + 10)
    }
    Gdip_DeleteBrush(pBrush1)
    Gdip_DeleteBrush(pBrush2)
    Gdip_DeleteBrush(pBrush3)
    UpdateLayeredWindow(hwnd1, hdc, 0, 0, Width, Height)
    SelectObject(hdc, obm)
    DeleteObject(hbm)
    DeleteDC(hdc)
    Gdip_DeleteGraphics(G)
    Gdip_Shutdown(pToken)
    MsgBox, 4096, , % "点击确认关闭显示" c
    Gui, GUILX: Destroy
    return
    }
    ```
    8 条回复    2024-08-12 16:04:32 +08:00
    zdw189803631
        1
    zdw189803631  
       37 天前
    用 ai 转化下啊
    iliaoliao
        2
    iliaoliao  
    OP
       37 天前
    @zdw189803631 曾经我也迷信 ai ,为此还开了个 plus 会员,但不尽人意啊..
    zdw189803631
        3
    zdw189803631  
       37 天前
    肯定要自己改一些,当然如果完全不懂代码,那确实挺麻烦的
    wangyaominde
        4
    wangyaominde  
       37 天前
    我用 Claude 直接把你的表述复制过去的,你看看能不能用:

    我理解你想要将这个 AutoHotkey (AHK) 函数转换为使用 Rust 和 windows-rs 库的等效实现。这是一个涉及 Windows GUI 编程和图形绘制的复杂任务。我会为你创建一个基本的 Rust 实现,但请注意,由于功能的复杂性,这个实现可能需要进一步的优化和完善。

    首先,让我们创建一个新的 Rust 项目并添加必要的依赖。



    ```rust
    use windows::{
    core::*,
    Win32::Foundation::*,
    Win32::Graphics::Gdi::*,
    Win32::UI::WindowsAndMessaging::*,
    };
    use std::collections::HashMap;

    struct Rect {
    x: i32,
    y: i32,
    w: i32,
    h: i32,
    }

    struct Point {
    x: i32,
    y: i32,
    }

    fn main() -> Result<()> {
    unsafe {
    let instance = GetModuleHandleA(None)?;
    debug_assert!(instance.0 != 0);

    let window_class = s!("window");

    let wc = WNDCLASSA {
    hCursor: LoadCursorW(None, IDC_ARROW)?,
    hInstance: instance,
    lpszClassName: window_class,
    style: CS_HREDRAW | CS_VREDRAW,
    lpfnWndProc: Some(wndproc),
    ..Default::default()
    };

    let atom = RegisterClassA(&wc);
    debug_assert!(atom != 0);

    let hwnd = CreateWindowExA(
    WINDOW_EX_STYLE::default(),
    window_class,
    s!("Rust Visualization"),
    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    None,
    None,
    instance,
    None,
    );

    let mut message = MSG::default();

    while GetMessageA(&mut message, HWND(0), 0, 0).into() {
    DispatchMessageA(&message);
    }

    Ok(())
    }
    }

    extern "system" fn wndproc(window: HWND, message: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
    unsafe {
    match message {
    WM_PAINT => {
    let mut ps = PAINTSTRUCT::default();
    let hdc = BeginPaint(window, &mut ps);

    // Example data (replace with actual data passed to the function)
    let var0 = vec![Rect { x: 10, y: 10, w: 100, h: 100 }];
    let mut var1 = HashMap::new();
    var1.insert(String::from("Point1"), Point { x: 50, y: 50 });
    let var2 = Rect { x: 200, y: 200, w: 50, h: 50 };

    // Draw rectangles from var0
    for rect in &var0 {
    Rectangle(hdc, rect.x, rect.y, rect.x + rect.w, rect.y + rect.h);
    }

    // Draw points and labels from var1
    for (label, point) in &var1 {
    Ellipse(hdc, point.x - 5, point.y - 5, point.x + 5, point.y + 5);
    TextOutA(hdc, point.x, point.y - 20, label.as_bytes());
    }

    // Draw rectangle from var2
    Rectangle(hdc, var2.x - 5, var2.y - 5, var2.x + var2.w + 5, var2.y + var2.h + 5);

    EndPaint(window, &ps);
    LRESULT(0)
    }
    WM_DESTROY => {
    PostQuitMessage(0);
    LRESULT(0)
    }
    _ => DefWindowProcA(window, message, wparam, lparam),
    }
    }
    }

    ```

    这个 Rust 实现提供了一个基本框架,用于创建一个 Windows 窗口并在其中绘制一些基本图形。它大致对应于原始 AHK 脚本的功能,但有一些重要的区别和限制:

    1. 这个实现使用 GDI 而不是 GDI+。GDI+ 在 Rust 中的使用更复杂,可能需要额外的库或更复杂的 FFI 。

    2. 窗口创建和消息循环是显式的,而在 AHK 中这些通常是隐式处理的。

    3. 绘图是在 WM_PAINT 消息处理程序中完成的,这是 Windows 编程的标准方法。

    4. 这个实现没有包含透明窗口或分层窗口更新,这在原始 AHK 脚本中使用。

    5. 文本渲染和一些更复杂的绘图操作被简化了。

    6. 错误处理被简化了,在实际应用中应该更加健壮。

    要使用这个代码,你需要在你的 Cargo.toml 文件中添加以下依赖:

    ```toml
    [dependencies]
    windows = { version = "0.48", features = ["Win32_Foundation", "Win32_Graphics_Gdi", "Win32_UI_WindowsAndMessaging"] }
    ```

    这个实现提供了一个起点,但要完全复制原始 AHK 脚本的功能,还需要进行大量工作。你可能需要:

    1. 实现更复杂的绘图功能。
    2. 添加对透明窗口的支持。
    3. 实现更复杂的用户交互。
    4. 优化性能和资源使用。
    iliaoliao
        5
    iliaoliao  
    OP
       37 天前
    @wangyaominde 谢谢大佬。晚上我回去用 windows 电脑试试
    wyfig
        6
    wyfig  
       37 天前
    用 claude 应该可以直接转
    LinYaXuan
        7
    LinYaXuan  
       37 天前
    claude 的代码能力比 gpt4 强这么多啊,感觉自己续费的 gpt4 好冤大头。

    按照我的理解这个脚本就是绘制矩形和圆形的,上面的 rust 代码简单修几个错误就能达成这个功能。不过我跑那个 ahk 脚本只能看到最后的"点击确认关闭显示"提示,没能看到绘制的图形。
    iliaoliao
        8
    iliaoliao  
    OP
       37 天前
    @LinYaXuan 上面的 claude 代码差不多是我问几天 gpt 的答案了,但还是有个问题,怎么把参数传到 extern "system" fn wndproc 里面。
    上面的 ahk 代码,需要依赖传入的参数才能绘制图形。参数大概的结构是 var0: {x,y,w,h}[] ; var1: {label1: {x, y}, label2: {x, y}} ; var2: {x,y,w,h};
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5563 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 01:40 · PVG 09:40 · LAX 18:40 · JFK 21:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.