rust 如何在WM_COMMAND消息的window_proc函数中检索结构体?

w8rqjzmb  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(98)

我尝试用rust编写一个简单的windows应用程序,使用windows-rs crate。我想在Counter结构中封装一个状态,并将其传递给window_proc函数。它成功地检索指针并通过GWLP_USERDATA索引存储它。我的问题是,为什么它在WM_CREATE msg中没有错误地增加,但在WM_COMMAND msg中不起作用?

struct Counter {
    counter: i32
}

fn main() -> Result<()> {
    let lparam: *mut Counter = Box::leak(Box::new(Counter{
        counter: 1
    }));

    unsafe {
        let mut instance = Default::default();
        GetModuleHandleExW(0, None, &mut instance)?;

        let wnd_class = WNDCLASSEXW {
           // ... ...
        };

        let atom = RegisterClassExW(&wnd_class);
        debug_assert!(atom != 0);

        let hwnd = CreateWindowExW(
            // ... ...
            Some(lparam as *mut c_void),
        );

        // ... ...
    }
}

fn increase_and_print(parent: HWND) {
    unsafe {
        let ptr = GetWindowLongPtrW(parent, GWLP_USERDATA);
        println!("GetWindowLongPtrW: {}", ptr);

        let ptr = GetWindowLongPtrW(parent, GWLP_USERDATA) as *mut Box<Counter>;
        debug_assert!(!ptr.is_null());
        let c =  &mut *ptr;
        c.counter += 1;
        println!("counter: {}", c.counter);
    }
}

extern "system" fn window_proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
    unsafe {
        match msg {
            WM_CREATE => {

                // Create a click button
        
                // Retrieve the pointer to your state and store it in the window's user data
                SetWindowLongPtrW(hwnd, GWLP_USERDATA, lparam.0 as isize);
                increase_and_print(hwnd);

                LRESULT(0)
            },
            WM_DESTROY => {
                PostQuitMessage(0);
                LRESULT(0)
            },
            WM_COMMAND => {
                increase_and_print(hwnd);
                return LRESULT(0);
            },
            _ => DefWindowProcW(hwnd, msg, wparam, lparam)
        }
    }
}

字符串
计数器初始化为1,然后在WM_CREATE msg中增加到2。我希望它在单击按钮后打印3(即调用WM_COMMAND msg)控制台中的输出

GetWindowLongPtrW: 359815702944
counter: 2
GetWindowLongPtrW: 359815702944
thread 'main' panicked at 'misaligned pointer dereference: address must be a multiple of 0x4 but is 0xb', apps\counter\src\main.rs:73:9


Complete code

qni6mghb

qni6mghb1#

我在GitHub上搜索由windows-rs创建的应用程序,最后我得到了这个robmikh/minesweeper-rs windows.rs。
将计数器设置为用户数据

let cs = lparam.0 as *const CREATESTRUCTW;
let counter = (*cs).lpCreateParams as *mut Counter;
SetWindowLongPtrW(hwnd, GWLP_USERDATA, counter as _);

字符串
计数器并更新其值

unsafe {
    let counter_ptr = GetWindowLongPtrW(hwnd, GWLP_USERDATA) as *mut Counter;
    if let Some(c) = counter_ptr.as_mut() {
        c.counter += 1;
        println!("counter: {}", c.counter);
    }
}


由于我是Rust的新手,如果有人能详细解释这一点,我将不胜感激。

相关问题