1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
#![allow(clippy::needless_doctest_main)]
#![cfg_attr(docsrs, feature(doc_cfg))]
//! A window library in Rust for Windows.
//!
//! `wita` is a library that create a window and run an event loop.
//! It is only for Windows.
//!
//! # Example
//!
//! ```no_run
//! struct Application;
//!
//! impl Application {
//! fn new() -> Result<Self, wita::ApiError> {
//! wita::Window::builder()
//! .title("hello, world!")
//! .build()?;
//! Ok(Self)
//! }
//! }
//!
//! impl wita::EventHandler for Application {
//! fn closed(&mut self, _: wita::event::Closed) {
//! println!("closed");
//! }
//! }
//!
//! fn main() {
//! wita::run(wita::RunType::Wait, Application::new).unwrap();
//! }
//! ```
//!
//! # Event handling
//!
//! You must implement [`EventHandler`] for the your defined object, and can handle events in the `impl EventHandler`.
//! Next, pass the your defined object to [`run`].
//!
//! ```no_run
//! struct Foo {}
//!
//! impl Foo {
//! fn new() -> Result<Self, wita::ApiError> {
//! wita::Window::builder().build()?;
//! Ok(Self {})
//! }
//! }
//!
//! impl wita::EventHandler for Foo {
//! // You define handlers.
//! // For example, handle the event that closed the window.
//! fn closed(&mut self, _: wita::event::Closed) {
//! // write handling codes
//! }
//! }
//!
//! wita::run(wita::RunType::Wait, Foo::new).unwrap();
//! ```
//!
//! # Drawing on the window
//! There are directly no any methods for drawing on a [`Window`] in `wita`.
//! However, a [`Window`] provides the [`raw_handle`] that return a pointer which is `HWND`.
//! You can create a drawing context by using the [`raw_handle`] such as DirectX, Vulkan, etc.
//!
//! [`raw_handle`]: struct.Window.html#method.raw_handle
//!
mod api;
mod context;
mod device;
pub mod event;
mod geometry;
pub mod ime;
mod monitor;
mod procedure;
#[cfg(any(feature = "raw_input", doc))]
#[cfg_attr(docsrs, doc(cfg(feature = "raw_input")))]
pub mod raw_input;
mod resource;
mod window;
#[macro_use]
mod error;
pub use context::RunType;
pub use device::WHEEL_DELTA;
pub use device::*;
#[doc(inline)]
pub use error::ApiError;
#[doc(inline)]
pub use event::{EventHandler, ResizingEdge};
pub use geometry::*;
pub use monitor::*;
pub use resource::*;
pub use window::*;
use context::*;
use windows::Win32::{Foundation::*, UI::WindowsAndMessaging::*};
/// The value is an unit in logical coordinates.
pub const DEFAULT_DPI: i32 = 96;
/// Run the event loop.
pub fn run<F, T, E>(run_type: RunType, f: F) -> Result<(), E>
where
F: FnOnce() -> Result<T, E>,
T: EventHandler + 'static,
{
api::enable_dpi_awareness();
api::enable_gui_thread();
window::register_class::<T>();
context::create_context();
let handler = f();
match handler {
Ok(handler) => set_event_handler(handler),
Err(e) => return Err(e),
}
let mut msg = MSG::default();
match run_type {
RunType::Idle => unsafe {
while msg.message != WM_QUIT {
call_handler(|eh: &mut T, _| eh.pre_processing());
if PeekMessageW(&mut msg, HWND(0), 0, 0, PM_REMOVE) != BOOL(0) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
} else {
call_handler(|eh: &mut T, _| eh.idle());
}
maybe_resume_unwind();
call_handler(|eh: &mut T, _| eh.post_processing());
}
},
RunType::Wait => unsafe {
loop {
let ret = GetMessageW(&mut msg, HWND(0), 0, 0);
if ret == BOOL(0) || ret == BOOL(-1) {
break;
}
TranslateMessage(&msg);
DispatchMessageW(&msg);
maybe_resume_unwind();
}
},
}
destroy_context();
Ok(())
}