Finding&moving mouse position (windows 10)

Hello, I'm just starting to learn to code and I'm wondering if anyone could analysis this code below for mistakes or potential mistakes or bad coding practices.

Also is this a good place to ask newbie questions like this? else where would be a good place to ask.

Thanks,

use winapi::shared::windef::POINT;

fn get_mouse_pos() -> (i32, i32) {
    let mut point = POINT { x: 0, y: 0 };
    unsafe { ::winapi::um::winuser::GetCursorPos(&mut point as *mut POINT) };
    (point.x, point.y)
}

fn set_mouse_pos(x: i32 , y: i32) {
    unsafe { ::winapi::um::winuser::SetCursorPos(x, y) };
}

fn main() {
    // store mouse postion
    let (x, y) = get_mouse_pos();

    // print mouse coords
    print!("coords = {},{}", x, y);

    // mouse mouse
    set_mouse_pos(250, 250);

}

// cargo.toml
// [dependencies]
// winapi = { version = "0.3", features = ["winuser"] }
1 Like

It looks fine, but you should be aware that both methods can fail, so you should probably test for failure. I'm not on windows so I can't test it, but I think that the cast from &mut to *mut is not needed.

And this is the correct place for this kind of question :slight_smile:

1 Like

Hi, thanks for the reply.

So, I don't really understand what you mean by

1.) which parts could fail exactly?
2.) how would I go about writing something to "test" for failure

winapi is pretty much a one-to-one mapping of the APIs exposed by Windows, so it's a good idea to cross-reference against the Microsoft docs when you use it.

For example, the docs for SetCursorPos note that it has a BOOL return value, which will be non-zero if the operation was successful, and zero otherwise (confusingly, BOOL is just a typedef for int).

In your Rust code, you don't check the return value of SetCursorPos, so any failures would just be ignored. This hopefully won't cause any unsafety with such simple functions, but it will mean your program doesn't do what you expect it to do!

To fix this, you need to check if the return value of the function is zero, and handle that case. For example, you could panic and exit the program:

fn set_mouse_pos(x: i32, y: i32) {
    unsafe {
        if winapi::um::winuser::SetCursorPos(x, y) == 0 {
            panic!("SetCursorPos failed");
        }
    }
}

Or you could make your function return a Result:

fn set_mouse_pos(x: i32, y: i32) -> Result<(), String> {
    unsafe {
        if winapi::um::winuser::SetCursorPos(x, y) == 0 {
            Err("SetCursorPos failed".into())
        } else {
            Ok(())
        }
    }
}

Also, note that this doesn't actually give you any context as to why the function call failed - if you want that information, you need to call GetLastError, which returns an error code.

4 Likes

thank you, that's makes sense to me now