Rust 虚拟键盘思路代码,Window

 思路:

 Cargo.toml添加如下的配置。

winapi = {version = "0.3.9",features = ["winuser","windef","ntdef","basetsd",
"minwindef","libloaderapi","wingdi","windowsx","errhandlingapi"]}

 简单版本的思路代码如下:复杂的代码是第二个。这两个代码二选一。


extern crate winapi;
use winapi::um::winuser::{INPUT, INPUT_KEYBOARD, KEYBDINPUT, SendInput, KEYEVENTF_KEYUP};
const VK_A: u16 = 0x41;  // "A"键的虚拟键码

// 定义一个按下键的函数
fn press_key(vk: u16) {
    // 创建一个INPUT结构体来存储键盘输入数据
    let mut input = INPUT {
        // 设置输入类型为键盘输入
        type_: INPUT_KEYBOARD,
        // 将联合体初始化为零
        u: unsafe { std::mem::zeroed() },
    };

    // 使用不安全代码来操作KEYBDINPUT结构体
    unsafe {
        // 将虚拟键码(vk)设置为输入参数
        *input.u.ki_mut() = KEYBDINPUT {
            // 设置虚拟键码(vk)
            wVk: vk,
            // 将扫描码设置为0(不使用)
            wScan: 0,
            // 将标志设置为0(无标志)
            dwFlags: 0,
            // 将时间设置为0(不使用)
            time: 0,
            // 将额外信息设置为0(不使用)
            dwExtraInfo: 0usize,
        };
        // 将输入事件发送到系统
        SendInput(
            // cInputs:发送的输入事件数量(这里是1)
            1,
            // lpInputs:INPUT结构体数组的指针(这里是一个单独的INPUT结构体)
            &mut input,
            // cbSize:INPUT结构体的字节数(转换为i32)
            std::mem::size_of::<INPUT>() as i32
        );
    }
}

// 定义一个释放键的函数
fn release_key(vk: u16) {
    // 创建一个INPUT结构体来存储键盘输入数据
    let mut input = INPUT {
        // 设置输入类型为键盘输入
        type_: INPUT_KEYBOARD,
        // 将联合体初始化为零
        u: unsafe { std::mem::zeroed() },
    };

    // 使用不安全代码来操作KEYBDINPUT结构体
    unsafe {
        // 将虚拟键码(vk)设置为输入参数
        *input.u.ki_mut() = KEYBDINPUT {
            // 设置虚拟键码(vk)
            wVk: vk,
            // 将扫描码设置为0(不使用)
            wScan: 0,
            // 将标志设置为KEYEVENTF_KEYUP(键释放)
            dwFlags: KEYEVENTF_KEYUP,
            // 将时间设置为0(不使用)
            time: 0,
            // 将额外信息设置为0(不使用)
            dwExtraInfo: 0usize,
        };
        // 将输入事件发送到系统
        SendInput(1, &mut input, std::mem::size_of::<INPUT>() as i32);
    }
}
#[test]
fn main() {
    press_key(VK_A);
    release_key(VK_A);
}

以下是带窗口的单一的虚拟键盘按钮。

 

//虚拟键盘

extern crate winapi;

use std::ptr;
use winapi::um::winuser::{CreateWindowExW, DefWindowProcW, DispatchMessageW, GetMessageW, PostQuitMessage, RegisterClassW, ShowWindow, UpdateWindow, INPUT, INPUT_KEYBOARD, KEYBDINPUT, SendInput, KEYEVENTF_KEYUP, MSG, WNDCLASSW, WS_OVERLAPPEDWINDOW, WM_DESTROY, WM_COMMAND, BS_PUSHBUTTON, WS_CHILD, WS_VISIBLE, GetForegroundWindow, SetForegroundWindow, WS_EX_TOPMOST, WS_EX_NOACTIVATE, TranslateMessage, GetSystemMetrics, SM_CXSCREEN, SM_CYSCREEN, KLF_SETFORPROCESS, ActivateKeyboardLayout, LoadKeyboardLayoutW, KLF_ACTIVATE, LoadKeyboardLayoutA, KL_NAMELENGTH};
use winapi::shared::windef::{HWND, POINT};
use winapi::shared::minwindef::{UINT, WPARAM, LPARAM, LRESULT, HKL};
use winapi::um::libloaderapi::GetModuleHandleW;
const VK_A: u16 = 0x41;  // "A"键的虚拟键码
const BUTTON_ID: i32 = 1;

fn press_key(vk: u16) {

    // ... 使用虚拟键盘输入 ...
    let mut input = INPUT {
        type_: INPUT_KEYBOARD,
        u: unsafe { std::mem::zeroed() },
    };

    unsafe {
        *input.u.ki_mut() = KEYBDINPUT {
            wVk: vk,
            wScan: 0,
            dwFlags: 0,
            time: 0,
            dwExtraInfo: 0usize,
        };
        SendInput(1, &mut input, std::mem::size_of::<INPUT>() as i32);
    }
}

fn release_key(vk: u16) {
    let mut input = INPUT {
        type_: INPUT_KEYBOARD,
        u: unsafe { std::mem::zeroed() },
    };

    unsafe {
        *input.u.ki_mut() = KEYBDINPUT {
            wVk: vk,
            wScan: 0,
            dwFlags: KEYEVENTF_KEYUP,
            time: 0,
            dwExtraInfo: 0usize,
        };
        SendInput(1, &mut input, std::mem::size_of::<INPUT>() as i32);
    }
}
use winapi::um::winuser::{ UnloadKeyboardLayout, GetKeyboardLayout};

fn set_english_keyboard_layout() {
    let hkl = unsafe { GetKeyboardLayout(0) };
    println!("hkl:{:?}",hkl);
    let keyboard_layout = 0x0409_u16; // English (United States)
    unsafe {
         let i = UnloadKeyboardLayout(hkl);
        println!("卸载情况:{}",i);
        LoadKeyboardLayoutW(&keyboard_layout as _ , 0); // Load English (United States) keyboard layout
        ActivateKeyboardLayout(keyboard_layout as _, 0);
    }
}
fn set_chinese_keyboard_layout() {
    let hkl = unsafe { GetKeyboardLayout(0) };
    println!("hkl:{:?}", hkl);
    let keyboard_layout = 0x0804_u16; // Chinese (Simplified)
    unsafe {
        let i = UnloadKeyboardLayout(hkl);
        println!("卸载情况:{}", i);
        LoadKeyboardLayoutW(&keyboard_layout as _, 0); // Load Chinese (Simplified) keyboard layout
        ActivateKeyboardLayout(keyboard_layout as _, 0);
    }
}
unsafe extern "system" fn window_proc(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
    match msg {
        WM_DESTROY => {
            PostQuitMessage(0);
            0
        }
        WM_COMMAND => {
            if wparam == BUTTON_ID as WPARAM {
                let foreground_hwnd = GetForegroundWindow();
                // set_english_keyboard_layout();
                press_key(VK_A);
                release_key(VK_A);
                set_chinese_keyboard_layout();
                SetForegroundWindow(foreground_hwnd);
            }
            0
        }
        _ => DefWindowProcW(hwnd, msg, wparam, lparam),
    }
}
#[test]
fn main() {
    let class_name = to_wstring("my_window");
    let hinstance = unsafe { GetModuleHandleW(ptr::null()) };
    let screen_width = unsafe { GetSystemMetrics(SM_CXSCREEN) };
    let screen_height = unsafe { GetSystemMetrics(SM_CYSCREEN) };
    let window_width = 500;
    let window_height = 300;
    let x = (screen_width - window_width) / 2;
    let y = screen_height - window_height * 3 / 2;
    let wnd_class = WNDCLASSW {
        style: 0,
        lpfnWndProc: Some(window_proc),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: hinstance,
        hIcon: ptr::null_mut(),
        hCursor: ptr::null_mut(),
        hbrBackground: ptr::null_mut(),
        lpszMenuName: ptr::null(),
        lpszClassName: class_name.as_ptr(),
    };
    unsafe {
        RegisterClassW(&wnd_class);
        let hwnd = CreateWindowExW(
            WS_EX_TOPMOST | WS_EX_NOACTIVATE,
            class_name.as_ptr(),
            to_wstring("Virtual Keyboard").as_ptr(),
            WS_OVERLAPPEDWINDOW,
            x,
            y,
            window_width,
            window_height,
            ptr::null_mut(),
            ptr::null_mut(),
            hinstance,
            ptr::null_mut(),
        );

        CreateWindowExW(
            0,
            to_wstring("button").as_ptr(),
            to_wstring("Press A").as_ptr(),
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            50, 50, 100, 30,
            hwnd,
            BUTTON_ID as _,
            hinstance,
            ptr::null_mut(),
        );

        ShowWindow(hwnd, 1);
        UpdateWindow(hwnd);

        let mut msg = MSG {
            hwnd: ptr::null_mut(),
            message: 0,
            wParam: 0,
            lParam: 0,
            time: 0,
            pt: POINT { x: 100, y: 100 },
        };

        while GetMessageW(&mut msg, ptr::null_mut(), 0, 0) > 0 {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }
    }
}

fn to_wstring(str: &str) -> Vec<u16> {
    use std::ffi::OsStr;
    use std::iter::once;
    use std::os::windows::ffi::OsStrExt;

    OsStr::new(str).encode_wide().chain(once(0)).collect()
}

效果

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值