A comprehensive utility library for Windows API programming in Rust, providing type-safe abstractions for coordinate conversion, bit operations, and message parameter handling with full windows crate compatibility.
- 🎯 Coordinate Conversion: Client-to-screen and screen-to-client coordinate transformations
- 🔧 Bit Manipulation: Extract high/low words and bytes from integers (LOWORD, HIWORD, LOBYTE, HIBYTE)
- 📨 Message Handling: Type-safe WPARAM and LPARAM handling for Windows messages
- 🔄 Windows Interop: Seamless compatibility with the
windowscrate - 🌐 Cross-platform: Works on Windows, Linux, and macOS (no Windows API calls)
- 📦 No-std Support: Core functionality available without std
- 🎛️ Feature Gating: Enable only the functionality you need
- 📊 Serialization: Optional serde support for message types
[dependencies]
windows-api-utils = "0.1"use windows_api_utils::prelude::*;
// Coordinate conversion
let window = Window::new(12345, Rect::new(100, 100, 500, 400), Default::default());
let client_point = Point::new(50, 30);
let screen_point = window.client_to_screen(client_point).unwrap();
// Message handling
let message = WindowMessage::mouse_move(100, 200, KeyModifiers::default());
if let Some(mouse_event) = MessageParser::parse_mouse_message(message) {
println!("Mouse at ({}, {})", mouse_event.x, mouse_event.y);
}[dependencies]
windows-api-utils = { version = "0.1", features = ["windows-interop"] }
windows = "0.52"use windows_api_utils::prelude::*;
use windows::Win32::Foundation::{WPARAM, LPARAM};
// Seamless conversion - zero cost!
let win_wparam = WPARAM(0x1234);
let our_wparam = WParam::from(win_wparam);
let back_to_win: WPARAM = our_wparam.into();
assert_eq!(win_wparam.0, back_to_win.0);
// Full message conversion
let win_msg = MSG { /* ... */ };
let our_msg: WindowMessage = win_msg.into();[dependencies]
windows-api-utils = { version = "0.1", default-features = false, features = ["coordinates"] }use windows_api_utils::{Point, Rect, Window, CoordinateTransformer};
let window = Window::new(12345, Rect::new(100, 100, 500, 400), Default::default());
let client_point = Point::new(50, 30);
let screen_point = window.client_to_screen(client_point).unwrap();[dependencies]
windows-api-utils = { version = "0.1", default-features = false, features = ["bit-ops"] }use windows_api_utils::{loword, hiword, make_long, BitUtils};
let value = 0x12345678;
let low = loword(value); // 0x5678
let high = hiword(value); // 0x1234
let reconstructed = make_long(high, low);
// Advanced bit manipulation
let bits = BitUtils::get_bits(0b1010, 1, 2); // 0b01
let modified = BitUtils::set_bit(0b1010, 0); // 0b1011[dependencies]
windows-api-utils = { version = "0.1", default-features = false }use windows_api_utils::WindowsUtilsError;
// Only error types available in minimal modecoordinates- Coordinate conversion types and traitsbit-ops- Bit manipulation utilities (LOWORD, HIWORD, etc.)messages- Windows message handling (WPARAM, LPARAM)serde- Serialization support for typeswindows-interop- Seamless compatibility withwindowscratestd- Standard library support withthiserrorfull- All features enabledminimal- No optional features (default: enabled)
use windows_api_utils::prelude::*;
// Create a window with specific style
let style = WindowStyle {
has_border: true,
has_title_bar: true,
border_width: 8,
title_bar_height: 30,
};
let window_rect = Rect::new(100, 100, 800, 600);
let window = Window::new(12345, window_rect, style);
// Convert client coordinates to screen coordinates
let client_coords = Point::new(50, 75);
let screen_coords = window.client_to_screen(client_coords).unwrap();
println!("Client {:?} -> Screen {:?}", client_coords, screen_coords);
// Convert screen coordinates back to client coordinates
let converted_back = window.screen_to_client(screen_coords).unwrap();
assert_eq!(client_coords, converted_back);use windows_api_utils::prelude::*;
// Extract words from 32-bit value
let value = 0x12345678;
let low_word = loword(value); // 0x5678
let high_word = hiword(value); // 0x1234
// Reconstruct value
let reconstructed = make_long(high_word, low_word);
assert_eq!(value, reconstructed);
// Use the LowHighWord struct for more functionality
let lhw = LowHighWord::new(value);
assert_eq!(lhw.loword(), low_word);
assert_eq!(lhw.hiword(), high_word);
assert_eq!(lhw.to_string(), "0x12345678 (hi: 0x1234, lo: 0x5678)");
// Advanced bit manipulation
let value = 0b10101010;
let extracted = BitUtils::get_bits(value, 2, 3); // 0b101
let with_bit_set = BitUtils::set_bit(value, 0); // 0b10101011
let is_bit_set = BitUtils::is_bit_set(value, 3); // trueuse windows_api_utils::prelude::*;
// Create mouse messages
let mouse_move = WindowMessage::mouse_move(100, 200, KeyModifiers::default());
let mouse_click = WindowMessage::mouse_button(
MouseButton::Left,
true, // pressed
150, 250,
KeyModifiers { shift: true, ..Default::default() }
);
// Parse messages
if let Some(mouse_event) = MessageParser::parse_mouse_message(mouse_move) {
println!("Mouse moved to ({}, {})", mouse_event.x, mouse_event.y);
}
if let Some(mouse_event) = MessageParser::parse_mouse_message(mouse_click) {
println!("Mouse button {:?} clicked at ({}, {}) with shift: {}",
mouse_event.button, mouse_event.x, mouse_event.y, mouse_event.modifiers.shift);
}
// Create keyboard messages
let key_down = WindowMessage::key_event(
windows_messages::WM_KEYDOWN,
0x41, // 'A' key
0x1E, // scan code
1 // repeat count
);use windows_api_utils::prelude::*;
use windows::Win32::UI::WindowsAndMessaging;
// Convert from windows crate message
fn handle_win32_message(win_msg: windows::Win32::UI::WindowsAndMessaging::MSG) {
let our_msg: WindowMessage = win_msg.into();
// Process using our utilities
if let Some(mouse_event) = MessageParser::parse_mouse_message(our_msg) {
println!("Processing mouse event: {:?}", mouse_event);
}
// Convert back if needed
let mut modified_msg = our_msg;
// ... modify message ...
let win_msg_modified: windows::Win32::UI::WindowsAndMessaging::MSG = modified_msg.into();
}
// Direct type compatibility
fn process_parameters(wparam: windows::Win32::Foundation::WPARAM,
lparam: windows::Win32::Foundation::LPARAM) {
let our_wparam = WParam::from(wparam);
let our_lparam = LParam::from(lparam);
// Work with our types...
let message = WindowMessage::new(0x0200, our_wparam, our_lparam);
// Convert back seamlessly
let _back_wparam: windows::Win32::Foundation::WPARAM = our_wparam.into();
let _back_lparam: windows::Win32::Foundation::LPARAM = our_lparam.into();
}The crate supports no_std environments. When used without the std feature, only core functionality is available:
#![no_std]
use windows_api_utils::WindowsUtilsError;
fn handle_error() -> Result<(), WindowsUtilsError> {
// Error handling in no_std environment
Err(WindowsUtilsError::InvalidCoordinates { x: -1, y: -1 })
}Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.