use crate::co;
use crate::decl::*;
use crate::msg::*;
use crate::prelude::*;
pub(in crate::gui) const DONTFAIL: &str = "GUI internals are not supposed to fail.";
#[derive(Clone, Copy, PartialEq, Eq)]
pub(in crate::gui) enum WndTy {
Raw,
Dlg,
}
impl WndTy {
#[must_use]
pub(in crate::gui) const fn creation_msg(&self) -> co::WM {
match self {
Self::Raw => co::WM::CREATE,
Self::Dlg => co::WM::INITDIALOG,
}
}
#[must_use]
pub(in crate::gui) const fn def_proc_val(&self) -> isize {
match self {
Self::Raw => 0,
Self::Dlg => 1, }
}
}
pub(in crate::gui) static mut DPI: (i32, i32) = (0, 0);
pub(in crate::gui) fn initial_gui_setup() {
if unsafe { DPI } == (0, 0) {
if IsWindowsVistaOrGreater().expect(DONTFAIL) {
SetProcessDPIAware().expect(DONTFAIL);
}
InitCommonControls();
if IsWindows8OrGreater().expect(DONTFAIL) {
let mut b_val = 0; match unsafe {
HPROCESS::GetCurrentProcess().SetUserObjectInformation(
co::UOI::TIMERPROC_EXCEPTION_SUPPRESSION, &mut b_val,
)
} {
Err(e) if e == co::ERROR::INVALID_PARAMETER => {
},
Err(e) => panic!("TIMERPROC_EXCEPTION_SUPPRESSION failed: {e:?}"), _ => {},
}
}
let hdc_screen = HWND::NULL.GetDC().expect(DONTFAIL);
let x = hdc_screen.GetDeviceCaps(co::GDC::LOGPIXELSX);
let y = hdc_screen.GetDeviceCaps(co::GDC::LOGPIXELSY);
unsafe {
DPI = (x, y);
}
}
}
pub(in crate::gui) mod quit_error {
use std::error::Error;
use std::sync::Mutex;
use crate::decl::*;
use crate::gui::*;
use crate::msg::*;
pub(in crate::gui) static QUIT_ERROR: Mutex<Option<MsgError>> = Mutex::new(None);
pub(in crate::gui) fn post_quit_error(src_msg: WndMsg, err: Box<dyn Error + Send + Sync>) {
{
let mut msg_error = QUIT_ERROR.lock().unwrap();
*msg_error = Some(MsgError::new(src_msg, err)); };
PostQuitMessage(-1); }
}
pub(in crate::gui) mod ui_font {
use crate::co;
use crate::decl::*;
use crate::guard::*;
use crate::gui::privs::*;
use crate::msg::*;
static mut UI_HFONT: Option<DeleteObjectGuard<HFONT>> = None;
pub(in crate::gui) fn get() -> HFONT {
unsafe {
match &*&raw const UI_HFONT {
None => {
let mut ncm = NONCLIENTMETRICS::default(); SystemParametersInfo(
co::SPI::GETNONCLIENTMETRICS,
std::mem::size_of::<NONCLIENTMETRICS>() as _,
&mut ncm,
co::SPIF::NoValue,
)
.expect(DONTFAIL);
let font = HFONT::CreateFontIndirect(&ncm.lfMenuFont).expect(DONTFAIL);
let ret_font = font.raw_copy();
UI_HFONT = Some(font);
ret_font
},
Some(font) => font.raw_copy(),
}
}
}
pub(in crate::gui) fn set(hwnd: &HWND) {
unsafe {
hwnd.SendMessage(wm::SetFont { hfont: get(), redraw: true });
}
}
pub(in crate::gui) fn delete() {
unsafe {
UI_HFONT = None; }
}
}
pub(in crate::gui) mod auto_id {
static mut BASE_CTRL_ID: u16 = 0xdfff;
#[must_use]
pub(in crate::gui) const fn next() -> u16 {
unsafe {
let ret_id = BASE_CTRL_ID;
BASE_CTRL_ID -= 1; ret_id
}
}
#[must_use]
pub(in crate::gui) const fn set_if_zero(id: u16) -> u16 {
if id == 0 { next() } else { id }
}
}
pub(in crate::gui) mod text_calc {
use crate::co;
use crate::decl::*;
use crate::gui::privs::*;
#[must_use]
pub(in crate::gui) fn remove_accel_ampersands(text: &str) -> String {
let mut txt_no_ampersands = String::with_capacity(text.len());
let mut last_ch = 'a';
for (idx, ch) in text.char_indices() {
if idx == 0 {
if ch != '&' {
txt_no_ampersands.push(ch);
}
} else if ch != '&' || (ch == '&' && last_ch == '&') {
txt_no_ampersands.push(ch);
}
last_ch = ch;
}
txt_no_ampersands
}
#[must_use]
pub(in crate::gui) fn bound_box(text: &str) -> SIZE {
let desktop_hwnd = HWND::GetDesktopWindow();
let desktop_hdc = desktop_hwnd.GetDC().expect(DONTFAIL);
let clone_dc = desktop_hdc.CreateCompatibleDC().expect(DONTFAIL);
let _prev_font = clone_dc.SelectObject(&ui_font::get()).expect(DONTFAIL);
let mut bounds = clone_dc
.GetTextExtentPoint32(if text.trim().is_empty() { "Pj" } else { text }) .expect(DONTFAIL);
if text.is_empty() {
bounds.cx = 0; }
bounds
}
#[must_use]
pub(in crate::gui) fn bound_box_with_check(text: &str) -> SIZE {
let mut bounds = bound_box(text);
bounds.cx += GetSystemMetrics(co::SM::CXMENUCHECK) + GetSystemMetrics(co::SM::CXEDGE);
let cy_check = GetSystemMetrics(co::SM::CYMENUCHECK);
if cy_check > bounds.cy {
bounds.cy = cy_check; }
bounds
}
}
pub(in crate::gui) fn paint_control_borders(hwnd: &HWND, wm_ncp: wm::NcPaint) {
unsafe {
hwnd.DefWindowProc(wm_ncp); }
if !hwnd.style_ex().has(co::WS_EX::CLIENTEDGE) || !IsThemeActive()
|| !IsAppThemed()
{
return;
}
let mut rc = hwnd.GetWindowRect().expect(DONTFAIL); rc = hwnd.ScreenToClientRc(rc).expect(DONTFAIL);
rc = OffsetRect(rc, 2, 2).expect(DONTFAIL);
let hdc = hwnd.GetWindowDC().expect(DONTFAIL);
let hrgn_hole =
HRGN::CreateRectRgnIndirect(InflateRect(rc, -2, -2).expect(DONTFAIL)).expect(DONTFAIL);
let hrgn_clip = HRGN::CreateRectRgnIndirect(rc).expect(DONTFAIL);
hrgn_clip
.CombineRgn(&hrgn_clip, &hrgn_hole, co::RGN::DIFF)
.expect(DONTFAIL);
hdc.SelectClipRgn(&hrgn_clip).expect(DONTFAIL);
if let Some(htheme) = hwnd.OpenThemeData("EDIT") {
htheme
.DrawThemeBackground(&hdc, co::VS::EDIT_EDITTEXT_NORMAL, rc, None)
.expect(DONTFAIL);
}
}