带有Rust的WinAPI:CreateWindowExW第二次以相同的WNDCLASSEXW调用失败

时间:2019-03-06 07:49:30

标签: winapi rust

我觉得我在生锈方面做错了。在学习WinAPI时,我尝试使用相同的WNDCLASSEXW创建第二个窗口,但是该调用失败,并显示错误1407(ERROR_CANNOT_FIND_WND_CLASS)。

由于我非常确定它应该在概念上可以正常工作,因此我重写了c ++中的“相同”(可能不相同)程序:

我在这里做什么错了?

显示所解释行为的小型示例:

C ++:

class WindowClass{
public:
    WindowClass(WNDCLASSEXW wndclass, HMODULE hmodule){
        _wndclass = wndclass;
        _hmodule = hmodule;
    }

    WNDCLASSEXW _wndclass;
    HMODULE _hmodule;
};

class Window{
public:
    Window(LPCWSTR title, WindowClass& window_class){
        auto hwnd = CreateWindowExW(
            0,
            window_class._wndclass.lpszClassName,
            title,
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            nullptr,
            nullptr,
            window_class._hmodule,
            nullptr);

    if ( hwnd == nullptr ) {
        std::cout << "Error CreateWindowExW " << GetLastError() << std::endl;
    }

    _handle = hwnd;
}

void show(){
    ShowWindow(_handle, SW_SHOWDEFAULT);
}

static WindowClass create_window_class(LPCWSTR class_name){
    auto hmodule = GetModuleHandleW(nullptr);

    WNDCLASSEXW wndclass = {};
    wndclass.cbSize = sizeof(WNDCLASSEXW);
    wndclass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = DefWindowProcW;
    wndclass.hInstance = hmodule;
    wndclass.lpszClassName = class_name;

    if ( RegisterClassExW(&wndclass) == 0 ) {
        std::cout << "Error RegisterClassExW: " << GetLastError() << std::endl;
    }

    return WindowClass{wndclass, hmodule};
}

private:
    HWND _handle;
};

int main(){
    auto window_class = Window::create_window_class(L"windowclass");
    Window window1(L"Window1", window_class);
    window1.show();
    Window window2(L"Window2", window_class);
    window2.show();
    auto foo = 0;
    std::cin >> foo;
}

铁锈:

trait Win32String{
    fn as_win32_string(&self) -> Vec<u16>;
}

impl Win32String for str{
    fn as_win32_string(&self) -> Vec<u16> {
        OsStr::new( self ).encode_wide().chain( once( 0 ) ).collect()
    }
}

pub struct Window{
    pub handle: HWND
}

impl Window{
    pub fn create_window_class(class_name: &str, styles: u32) -> Result<WindowClass, Error>{
        let class_name = class_name.as_win32_string();
        let hmodule = unsafe{
            GetModuleHandleW( null_mut())
        };

        let wnd_class = WNDCLASSEXW {
            cbSize: mem::size_of::<WNDCLASSEXW>() as u32,
            style : styles,
            lpfnWndProc : Some( DefWindowProcW ),
            hInstance : hmodule,
            lpszClassName : class_name.as_ptr(),
            cbClsExtra : 0,
            cbWndExtra : 0,
            hIcon: null_mut(),
            hCursor: null_mut(),
            hbrBackground: null_mut(),
            lpszMenuName: null_mut(),
            hIconSm: null_mut(),
        };

        if unsafe { RegisterClassExW(&wnd_class) } == 0 { // <-- This fails the second time
            return Err(Error::last_os_error());
        } else {
            return Ok(WindowClass{ class: wnd_class, hmodule})
        }
    }

    pub fn new(title: &str, window_class: &WindowClass) -> Result<Window, Error>{
        let title = title.as_win32_string();

        let hwnd = unsafe { CreateWindowExW(
            0,
            window_class.class.lpszClassName,
            title.as_ptr(),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            null_mut(),
            null_mut(),
            window_class.hmodule as *mut _,
            null_mut()
        )};

        if hwnd == null_mut() { return Err(Error::last_os_error()); }

        Ok(Window{handle: hwnd})
    }

    pub fn show(&self) -> bool {
        unsafe {
            let ret = ShowWindow(self.handle, SW_SHOWDEFAULT);
            ret != 0
        }
    }
}


pub struct WindowClass{
    class: WNDCLASSEXW,
    hmodule: HMODULE
}


fn main() {
    let window_class = Window::create_window_class(
        "windowclass",
        CS_OWNDC | CS_HREDRAW |CS_VREDRAW
    ).unwrap();
    let window = Window::new("Window1", &window_class).unwrap();
    window.show();
    let window2 = Window::new("Window2", &window_class).unwrap();
    window2.show();
}

0 个答案:

没有答案