use std::option::Option;
use windows::Win32::Foundation::{HANDLE, HWND};
use windows::Win32::Graphics::Gdi::HDC;
#[derive(Debug, Clone, Copy)]
pub struct WindowGeometry {
pub hwnd: HWND,
pub window_left: i32,
pub window_top: i32,
pub offset_x: i32,
pub offset_y: i32,
}
#[derive(Debug, Clone, Copy)]
pub struct ProcessContext {
pub hwnd: Option<HWND>,
pub window_geometry: Option<WindowGeometry>,
pub hdc: Option<HDC>,
pub process_handle: Option<HANDLE>,
}
impl ProcessContext {
#[inline]
pub fn new() -> Self {
Self {
hwnd: None,
window_geometry: None,
hdc: None,
process_handle: None,
}
}
pub fn set_hwnd(&mut self, hwnd: HWND) {
self.hwnd = Some(hwnd);
unsafe {
use windows::Win32::Foundation::RECT;
use windows::Win32::UI::WindowsAndMessaging::{GetClientRect, GetWindowRect};
let mut window_rect = RECT::default();
let mut client_rect = RECT::default();
if GetWindowRect(hwnd, &mut window_rect).is_ok()
&& GetClientRect(hwnd, &mut client_rect).is_ok()
{
self.window_geometry = Some(WindowGeometry {
hwnd,
window_left: window_rect.left,
window_top: window_rect.top,
offset_x: window_rect.left - client_rect.left,
offset_y: window_rect.top - client_rect.top,
});
} else {
self.window_geometry = None;
}
}
}
#[inline]
pub fn get_hwnd(&self) -> Option<HWND> {
self.hwnd
}
#[inline]
pub fn get_hwnd_or_err(&self) -> Result<HWND, crate::script_engine::instruction::ScriptError> {
self.hwnd.ok_or_else(|| {
crate::script_engine::instruction::ScriptError::ExecutionError(
"No target window set. Call process_ctx.set_hwnd(hwnd) before using background mode.".into()
)
})
}
#[inline]
pub fn has_hwnd(&self) -> bool {
self.hwnd.is_some()
}
#[inline]
pub fn set_hdc(&mut self, hdc: HDC) {
self.hdc = Some(hdc);
}
#[inline]
pub fn get_hdc(&self) -> Option<HDC> {
self.hdc
}
#[inline]
pub fn set_process_handle(&mut self, handle: HANDLE) {
self.process_handle = Some(handle);
}
#[inline]
pub fn get_process_handle(&self) -> Option<HANDLE> {
self.process_handle
}
#[inline]
pub fn clear(&mut self) {
self.hwnd = None;
self.window_geometry = None;
self.process_handle = None;
self.hdc = None;
}
#[inline]
pub fn is_empty(&self) -> bool {
self.hwnd.is_none()
&& self.window_geometry.is_none()
&& self.hdc.is_none()
&& self.process_handle.is_none()
}
}
impl Default for ProcessContext {
fn default() -> Self {
Self::new()
}
}