Create a window use winapi, ask for help


#1

I want to create a window use winapi on win7_x86_64, the code has no compile errors, but no window appears.

extern crate winapi;
use winapi::LRESULT;
use winapi::LPARAM;
use winapi::WPARAM;
use winapi::UINT;
use winapi::HWND;
use winapi::LPCWSTR;
use winapi::HBRUSH;
use winapi::HINSTANCE;
use winapi::HICON;
use winapi::HCURSOR;
use winapi::HMENU;
use winapi::SW_SHOWNORMAL;
use winapi::DWORD;
use winapi::CW_USEDEFAULT;
use winapi::WS_EX_CLIENTEDGE;


use winapi::winuser::WS_OVERLAPPEDWINDOW;
use winapi::winuser::WS_VISIBLE;
use winapi::winuser::WNDCLASSW;

extern crate user32;
use std::ffi::OsStr;
use std::io::Error;
use std::iter::once;
use std::os::windows::ffi::OsStrExt;
use std::ptr::null_mut;

fn to_wide(msg:&str) -> Vec<u16> {
    let wide: Vec<u16> = OsStr::new(msg).encode_wide().chain(once(0)).collect();
    wide
}

pub unsafe extern "system" fn win_proc(h_wnd :HWND, 
	msg :UINT, w_param :WPARAM, l_param :LPARAM) -> LRESULT {
    if msg == winapi::winuser::WM_DESTROY {
        user32::PostQuitMessage(0);
    }
    return user32::DefWindowProcW(h_wnd, msg, w_param, l_param);
}

fn main() {
    let class_name = to_wide("my_window");
    let icon = unsafe {
        user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION)
    };
    let cursor = unsafe {
        user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION)
    };
    let wnd = WNDCLASSW {
        style: 0,
        lpfnWndProc: Some(win_proc), 
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: 0 as HINSTANCE,
        hIcon: icon,
        hCursor: cursor,
        hbrBackground: 16 as HBRUSH,
        lpszMenuName: 0 as LPCWSTR,
        lpszClassName: class_name.as_ptr(),
    };
    let ret = unsafe {
        user32::RegisterClassW(&wnd)    
    };
    if ret == 0 {
        let msg = to_wide("register failed.");
        unsafe {
            user32::MessageBoxW(null_mut(), msg.as_ptr(), msg.as_ptr(), winapi::MB_OK);
        }
    }
    let h_wnd_desktop = unsafe {
        user32::GetDesktopWindow()
    };
    unsafe {
        let hwnd = user32::CreateWindowExA(WS_EX_CLIENTEDGE, "my_window".as_ptr() as *mut _, 
            "Simple Window".as_ptr() as *mut _, WS_OVERLAPPEDWINDOW, 
            CW_USEDEFAULT, CW_USEDEFAULT, 400, 400, h_wnd_desktop, 0 as HMENU, 0 as HINSTANCE, std::ptr::null_mut());
        user32::ShowWindow(hwnd, SW_SHOWNORMAL);
        user32::UpdateWindow(hwnd);

        let mut msg = winapi::winuser::MSG {
            hwnd : 0 as HWND,
            message : 0 as UINT,
            wParam : 0 as WPARAM,
            lParam : 0 as LPARAM,
            time : 0 as DWORD,
            pt : winapi::windef::POINT { x: 0, y: 0, },
        };

        println!("init the msg structure success.");
        // Finally we run the standard application loop - 
        loop
        {
            println!("get msg from the queue");
            let pm = user32::GetMessageW(&mut msg, hwnd, 0, 0);
            println!("msg received.");
            if pm > 0 {
                user32::TranslateMessage(&mut msg);
                user32::DispatchMessageW(&mut msg);
            }
        }      
  }

}

the Cargo.toml

[package]
name = "win_test"
version = "0.0.1"
authors = [ "mingli" ]

[dependencies]
libc = "0.2.17"
winapi = "0.2.8"
user32-sys = "0.2.0"
kernel32-sys = "0.2.2"

How to use nonstandard crate with path?
#2

Not sure; the only things I can see that you do differently to what I do are:

  • you’re calling CreateWindowExA, not CreateWindowExW
  • I don’t set an ex style
  • I don’t set a parent window
  • you don’t check the result of CreateWindowEx

About the only defense I’ve found works with Win32 is to always wrap any call in a function that checks the return value.


#3

Thank you very much.It works. Just change one line.

let hwnd = user32::CreateWindowExW(WS_EX_CLIENTEDGE, class_name.as_ptr(), 
            class_name.as_ptr(), WS_OVERLAPPEDWINDOW, 
            CW_USEDEFAULT, CW_USEDEFAULT, 400, 400, h_wnd_desktop, 0 as HMENU, 0 as HINSTANCE, std::ptr::null_mut());

#4

Yet, something is wrong with the CreateWindowExA, but i can’t find the difference.


#5

At a guess: "my_window".as_ptr(). Rust strings aren’t NULL-terminated. You really, really shouldn’t be making raw API calls if you can help it; it’s just too easy to screw up.

There’s a very, very bare-bones, ad-hoc binding to some Win32 UI stuff you can use as a starting point.


#6

Hi,

I have written some code that opens a window over here https://github.com/emoon/rust_minifb/blob/master/src/os/windows/mod.rs#L422 so that might help you.