windows-api-utils 0.2.0

Windows API utilities for coordinate conversion, bit operations, and message parameter handling with feature gating
Documentation

Windows API Utilities

Crates.io Documentation License Rust

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.

Features

  • 🎯 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 windows crate
  • 🌐 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

Quick Start

Using Default Features

[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);
}

With Windows Crate Interop

[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();

Coordinate Features Only

[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();

Bit Operations Only

[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

Minimal Usage (no-std compatible)

[dependencies]
windows-api-utils = { version = "0.1", default-features = false }
use windows_api_utils::WindowsUtilsError;

// Only error types available in minimal mode

Feature Flags

  • coordinates - Coordinate conversion types and traits
  • bit-ops - Bit manipulation utilities (LOWORD, HIWORD, etc.)
  • messages - Windows message handling (WPARAM, LPARAM)
  • serde - Serialization support for types
  • windows-interop - Seamless compatibility with windows crate
  • std - Standard library support with thiserror
  • full - All features enabled
  • minimal - No optional features (default: enabled)

Examples

Coordinate Conversion

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);

Bit Operations

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);  // true

Message Handling

use 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
);

Windows Crate Integration

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();
}

No-std Support

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 })
}

License

Licensed under either of

at your option.

Contribution

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.