Skip to content

Instantly share code, notes, and snippets.

@Kreijstal
Created April 4, 2023 16:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kreijstal/ed20c7740ffc7e9be1ae7afad7456db5 to your computer and use it in GitHub Desktop.
Save Kreijstal/ed20c7740ffc7e9be1ae7afad7456db5 to your computer and use it in GitHub Desktop.
Difference between rust winapi and windows-rs
use std::ptr::null_mut;
use winapi::shared::{
minwindef::{HIWORD, LOWORD, LPARAM, LRESULT, UINT, WPARAM},
windef::{HWND, POINT, RECT},
};
use std::ffi::CString;
use winapi::shared::basetsd::LONG_PTR;
use winapi::um::wingdi::GetStockObject;
use winapi::um::wingdi::SYSTEM_FONT;
use winapi::um::winuser::{GetSysColor,COLOR_WINDOWTEXT,GetDlgItem,GetSysColorBrush,SendMessageA,SetClassLongPtrA,COLOR_WINDOW,GCLP_HBRBACKGROUND,WM_SETFONT,
CreateWindowExA, DefWindowProcA, DispatchMessageA, GetMessageA, PostQuitMessage,
RegisterClassA, ShowWindow, TranslateMessage, BS_DEFPUSHBUTTON, BS_PUSHBUTTON, CW_USEDEFAULT,
ES_AUTOHSCROLL, IDCANCEL, IDOK, MSG, SW_SHOW, WM_COMMAND, WM_DESTROY, WNDCLASSA, WS_CHILD,
WS_OVERLAPPEDWINDOW, WS_SYSMENU, WS_VISIBLE,
};
extern "system" fn window_proc(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
match msg {
WM_COMMAND => {
let id = LOWORD(wparam as u32) as usize;
let code = HIWORD(wparam as u32);
let control_hwnd = lparam as HWND;
if code == 0 && id == IDOK as usize && control_hwnd == unsafe { GetDlgItem(hwnd, IDOK) }
{
println!("Ok clicked!");
} else if code == 0
&& id == IDCANCEL as usize
&& control_hwnd == unsafe { GetDlgItem(hwnd, IDCANCEL) }
{
println!("Cancel Clicked");
}
0
}
WM_DESTROY => {
unsafe { PostQuitMessage(0) };
0
}
_ => unsafe { DefWindowProcA(hwnd, msg, wparam, lparam) },
}
}
fn main() {
unsafe {
let class_name = "MyWindowClass\0".as_ptr() as *const i8;
//let class_name = CString::new("MyWindowClass").unwrap();
// Register a window class
let wnd_class = WNDCLASSA {
style: 0,
lpfnWndProc: Some(window_proc), //Some(DefWindowProcA),
hInstance: null_mut(),
lpszClassName: class_name,
cbClsExtra: 0,
cbWndExtra: 0,
hIcon: null_mut(),
hCursor: null_mut(),
hbrBackground: null_mut(),
lpszMenuName: null_mut(),
};
RegisterClassA(&wnd_class);
// Create the main window
let hwnd_main = CreateWindowExA(
0,
class_name,
"Hello World\0".as_ptr() as *const i8,
WS_OVERLAPPEDWINDOW | WS_SYSMENU,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
null_mut(),
null_mut(),
null_mut(),
null_mut(),
);
// Create the text box
let hwnd_text = CreateWindowExA(
0,
"EDIT\0".as_ptr() as *const i8,
null_mut(),
WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL,
10,
10,
300,
20,
hwnd_main,
null_mut(),
null_mut(),
null_mut(),
);
// Create the OK button
let hwnd_ok = CreateWindowExA(
0,
"BUTTON\0".as_ptr() as *const i8,
"OK\0".as_ptr() as *const i8,
WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
320,
10,
80,
20,
hwnd_main,
IDOK as isize as *mut _,
null_mut(),
null_mut(),
);
// Create the Cancel button
let hwnd_cancel = CreateWindowExA(
0,
"BUTTON\0".as_ptr() as *const i8,
"Cancel\0".as_ptr() as *const i8,
WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
410,
10,
80,
20,
hwnd_main,
IDCANCEL as isize as *mut _,
null_mut(),
null_mut(),
);
// Show the main window
ShowWindow(hwnd_main, SW_SHOW);
// Run the message loop
let mut msg = MSG {
hwnd: null_mut(),
message: 0,
wParam: 0,
lParam: 0,
time: 0,
pt: POINT { x: 0, y: 0 },
};
loop {
let result = GetMessageA(&mut msg, null_mut(), 0, 0);
if result == 0 {
break;
} else if result == -1 {
//handle error
} else {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
}
// Clean up
PostQuitMessage(0);
}
}
use windows::{
core::*,
w,
Win32::{
Foundation::*,
Graphics::Gdi::*,
System::LibraryLoader::*,
UI::{Controls::RichEdit::*, WindowsAndMessaging::*},
},
};
pub fn LOWORD(l: usize) -> usize {
l & 0xffff
}
pub fn HIWORD(l: usize) -> usize {
(l >> 16) & 0xffff
}
unsafe extern "system" fn window_proc(
hwnd: HWND,
msg: u32,
wparam: WPARAM,
lparam: LPARAM,
) -> LRESULT {
match msg {
WM_COMMAND => {
let control_id = LOWORD(wparam.0);
let notification_code = HIWORD(wparam.0);
let control_handle = lparam;
if control_id == IDOK.0 as usize && notification_code == 0 && control_handle.0 == GetDlgItem(hwnd, IDOK.0).0 {
println!("OK button clicked!");
} else if control_id == IDCANCEL.0 as usize && notification_code == 0 && control_handle.0 == GetDlgItem(hwnd, IDCANCEL.0).0 {
println!("Cancel button clicked!");
}
}
WM_DESTROY => {
PostQuitMessage(0);
}
_ => {
return DefWindowProcW(hwnd, msg, wparam, lparam);
}
}
return LRESULT(0);
}
fn main() {
// Get the HINSTANCE for the current process
let h_instance = unsafe { GetModuleHandleW(None).unwrap() };
// Load the default application icon
let h_icon = unsafe { LoadIconW(None, IDI_APPLICATION).unwrap() };
// Load the default arrow cursor
let h_cursor = unsafe { LoadCursorW(None, IDC_ARROW).unwrap() };
// Register a window class
//let class_name = "MyWindowClass\0".encode_utf16().collect::<Vec<u16>>();
let class_name = w!("MyWindowClass");
let wnd_class = WNDCLASSW {
style: WNDCLASS_STYLES(0),
lpfnWndProc: Some(window_proc),
hInstance: h_instance,
lpszClassName: windows::core::PCWSTR(class_name.as_ptr()),
cbClsExtra: 0,
cbWndExtra: 0,
hIcon: h_icon,
hCursor: h_cursor,
hbrBackground: unsafe { GetSysColorBrush(COLOR_WINDOW) },
lpszMenuName: PCWSTR::null(),
};
unsafe {
RegisterClassW(&wnd_class);
// Create the main window
let hwnd_main = CreateWindowExW(
WINDOW_EX_STYLE(0),
class_name,
w!("Only 1 letter in title"),
WS_OVERLAPPEDWINDOW | WS_SYSMENU,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
HWND(0),
HMENU(0),
h_instance,
None,
);
// Create the text box
let hwnd_text = CreateWindowExW(
WINDOW_EX_STYLE(0),
w!("EDIT"),
w!(""),
WS_CHILD | WS_VISIBLE | WINDOW_STYLE(ES_LEFT as u32) | WINDOW_STYLE(ES_AUTOHSCROLL as u32),
10,
10,
300,
20,
hwnd_main,
HMENU(0),
h_instance,
None,
);
// Create the OK button
let hwnd_ok = CreateWindowExW(
WINDOW_EX_STYLE(0),
w!("BUTTON"),
w!("Ok"),
WS_VISIBLE | WS_CHILD | WINDOW_STYLE(BS_DEFPUSHBUTTON as u32),
320,
10,
80,
20,
hwnd_main,
HMENU(IDOK.0 as isize),
h_instance,
None,
);
// Create the Cancel button
let hwnd_cancel = CreateWindowExW(
WINDOW_EX_STYLE(0),
w!("BUTTON"),
w!("Cancel"),
WS_VISIBLE | WS_CHILD | WINDOW_STYLE(BS_DEFPUSHBUTTON as u32),
410,
10,
80,
20,
hwnd_main,
HMENU(IDCANCEL.0 as isize),
h_instance,
None,
);
// Show the main window
ShowWindow(hwnd_main, SW_SHOW);
// Run the message loop
let mut msg = MSG::default();
loop {
let result = GetMessageW(&mut msg, HWND(0), 0, 0);
if result == BOOL(0) {
break;
} else if result == BOOL(-1) {
//handle error
} else {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
// Clean up
PostQuitMessage(0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment