hello_world/
hello-world.rs1#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
2#![forbid(unsafe_op_in_unsafe_fn)]
3
4use hwnd::*;
5
6use abistr::cstr16;
7
8use bytemuck::*;
9
10use winapi::um::winuser::*;
11
12use winresult::ERROR;
13
14use std::ptr::*;
15use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
16
17
18
19fn main() {
20 std::process::exit(main_imp())
23}
24
25fn main_imp() -> i32 {
26 let hinstance = get_module_handle_entry_exe().unwrap();
27 let hcursor = load_cursor_w(None, IDC::ARROW).unwrap();
28 let hicon = load_icon_w(None, IDI::APPLICATION).unwrap();
29
30 let wc = WndClassW {
31 wnd_proc: Some(window_proc),
32 hinstance,
33 hcursor,
34 hicon,
35 class_name: cstr16!("SampleWndClass").into(),
36 .. WndClassW::zeroed()
37 };
38 let wc = unsafe { register_class_w(&wc) }.unwrap();
39
40 let ex_style = 0;
41 let style = WS::OVERLAPPEDWINDOW;
42 let size = adjust_window_rect_ex_copy(
43 Rect { left: 0, right: 800, top: 0, bottom: 600 },
44 style, false, ex_style
45 ).unwrap();
46
47 let hwnd = unsafe { create_window_ex_w(
48 ex_style,
49 wc,
50 cstr16!("hello-world"),
51 style,
52 CW_USEDEFAULT,
53 CW_USEDEFAULT,
54 size.right - size.left,
55 size.bottom - size.top,
56 null_mut(),
57 null_mut(),
58 hinstance,
59 null_mut(),
60 )}.unwrap();
61
62 show_window_async(hwnd, SW::SHOWNORMAL).unwrap();
63
64 let mut msg = Msg::zeroed();
65 while get_message_w(&mut msg, HWnd::NULL, 0, 0).unwrap() {
66 translate_message(&msg);
67 let _ = unsafe { dispatch_message_w(&msg) };
68 }
69
70 if msg.message == WM::QUIT { return msg.wparam as _ }
71 0 }
73
74unsafe extern "system" fn window_proc(hwnd: HWnd, umsg: WM32, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
78 if umsg == WM::GETMINMAXINFO {
79 EARLY.set(hwnd, "early").unwrap();
80 LATE .set(hwnd, "late" ).unwrap();
81 }
82
83 eprintln!("window_proc({hwnd:?}, {umsg:?}");
84 eprintln!(" early: {:?}", EARLY.get_copy(hwnd));
85 eprintln!(" late: {:?}", LATE .get_copy(hwnd));
86
87 match umsg {
88 WM::LBUTTONDOWN => {
89 unsafe { MessageBoxA(null_mut(), "Message Box\0".as_ptr().cast(), "Caption\0".as_ptr().cast(), MB_OK) };
92 0
93 },
94 WM::RBUTTONDOWN => {
95 unsafe { destroy_window(hwnd) }.unwrap();
96 assert_eq!(ERROR::INVALID_WINDOW_HANDLE, unsafe { destroy_window(hwnd) }.unwrap_err());
97 0
98 },
99 WM::DESTROY => {
100 assert!(is_window(hwnd));
101 assert_eq!(ERROR::INVALID_WINDOW_HANDLE, EARLY.set(hwnd, "early").unwrap_err()); LATE.set(hwnd, "late").unwrap(); static DESTROY : AtomicBool = AtomicBool::new(false);
105 if !DESTROY.load(Relaxed) {
106 DESTROY.store(true, Relaxed);
107 unsafe { destroy_window(hwnd) }.unwrap();
108 assert_eq!(ERROR::INVALID_WINDOW_HANDLE, LATE.set(hwnd, "late").unwrap_err()); }
110 post_quit_message(0);
111 0
112 },
113 _ => unsafe { def_window_proc_w(hwnd, umsg, wparam, lparam) },
114 }
115}
116
117static EARLY : assoc::local::Slot<&'static str> = assoc::local::Slot::new_drop_early();
118static LATE : assoc::local::Slot<&'static str> = assoc::local::Slot::new_drop_late();