Rust Windows Crate CreateWindowExW

问题描述 投票:0回答:2

我正在编写一个函数来创建一个窗口,并且我提供了下面不起作用的代码。此代码使用 windows 板条箱和最新版本的 rust(在编写 rustc 1.74.0 时。

pub fn create_window() -> errors::Result<()> {
    let h_instance: HINSTANCE = match unsafe { GetModuleHandleW(None) } {
        Ok(h) => h.into(),
        Err(e) => return make_error!("{}", e),
    };
    let lp_sz_class_name = w!("window_class");
    let lp_sz_window_name = w!("window_title");

    let window_class: WNDCLASSW = WNDCLASSW {
        style: CS_HREDRAW | CS_VREDRAW,
        lpfnWndProc: Some(window_proc),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: h_instance,
        hIcon: HICON(0),
        hCursor: HCURSOR(0),
        hbrBackground: HBRUSH(2),
        lpszMenuName: PCWSTR(ptr::null_mut()),
        lpszClassName: lp_sz_class_name,
    };

    if unsafe { RegisterClassW(&window_class) } == 0 {
        match unsafe { GetLastError() } {
            Err(e) => {
                return make_error!("failed to register window class > {}", e);
            }
            _ => {}
        }
    };

    let hwnd = unsafe {
        CreateWindowExW(
            WINDOW_EX_STYLE(0),
            window_class.lpszClassName,
            lp_sz_window_name,
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            None,
            None,
            window_class.hInstance,
            None,
        )
    };

    if hwnd == HWND(0) {
        match unsafe { GetLastError() } {
            Err(e) => {
                return make_error!("failed to create window > {}", e); // ERROR OCCURS HERE!!
            }
            _ => {}
        };
    }

    Ok(())
}

当此代码运行时,它会生成错误“无法创建窗口 > 参数不正确。(0x80070057)”。指示函数

CreateWindowExW
的参数无效。

我尝试将参数一一隔离,但所有参数都有数据,并且我无法找到无效参数。我想知道是否有人可以看一下我是否错过了什么?

我期望成功注册窗口类,并创建不成功的窗口句柄。

windows rust window hwnd crate
2个回答
0
投票

您正在尝试创建一个重叠窗口,并将

hWndParent
设置为
None
,但是

对于弹出窗口,此参数是可选的。

表示重叠窗口不是可选的,因为它们不是弹出窗口,因此您必须提供 hWndParent

None
    


0
投票

warning: unreachable pattern --> src/main.rs:82:9 | 77 | WM_CLOSE => { | -------- matches any value ... 82 | WM_DESTROY => { | ^^^^^^^^^^ unreachable pattern | = note: `#[warn(unreachable_patterns)]` on by default

相关代码在
window_proc

是这样的:

    match msg {
        WM_CLOSE => { /*... */ ; LRESULT(0) }
        WM_DESTROY => { ... }
        _ => DefWindowProcW(hwnd, msg, wparam, lparam),
    }

但是常量 
WM_*

对于 Rust 编译器来说是未知的,所以这实际上等价于:

    match msg {
        _ => { /*... */ ; LRESULT(0) }
        /* blah, blah DefWindowProcW something that is never run */
    }

也就是说,无论正在处理什么消息,该函数始终返回 
LRESULT(0)

。正如我之前评论的,即使在

CreateWindow
返回之前,窗口函数收到的第一条消息也是
WM_NCCREATE
。但是返回该消息的 
0
将中止窗口创建。
GetLastError()
返回的值将是您使用
SetLastError()
设置的值,但您没有调用它,因此您会得到毫无意义的错误代码。
解决方案很简单,只需导入消息常量即可:

unsafe extern "system" fn window_proc( hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM, ) -> LRESULT { use windows::Win32::UI::WindowsAndMessaging::*; // <---- Here! match msg { WM_CLOSE => { ...

这就是为什么你永远不应该忽略 Rust 编译器警告。以及为什么您应该始终在 StackOverflow 问题中添加 MRE!

© www.soinside.com 2019 - 2024. All rights reserved.