#![allow(unsafe_op_in_unsafe_fn)]
use crate::ui::builder::ControlBuilder;
use crate::utils::to_wstring;
use crate::ui::framework::{WindowHandler, WindowBuilder, WindowAlignment, show_modal};
use windows_sys::Win32::Foundation::{HWND, LPARAM, LRESULT, WPARAM};
use windows_sys::Win32::UI::WindowsAndMessaging::{
CreateWindowExW,
WS_VISIBLE, WS_CHILD, WS_CAPTION, WS_SYSMENU, WS_POPUP,
WM_NOTIFY,
STM_SETICON, LoadImageW, IMAGE_ICON, LR_DEFAULTCOLOR,
WS_TABSTOP,
ShowWindow, SetForegroundWindow, SW_RESTORE, WM_SETFONT, SendMessageW,
};
use windows_sys::Win32::System::LibraryLoader::GetModuleHandleW;
use windows_sys::Win32::UI::Controls::{
NMHDR, NM_CLICK, NM_RETURN, NMLINK, WC_LINK, ICC_LINK_CLASS, INITCOMMONCONTROLSEX, InitCommonControlsEx,
};
use windows_sys::Win32::UI::Shell::ShellExecuteW;
use windows_sys::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL;
use windows_sys::Win32::Graphics::Gdi::{
CreateFontW, FW_BOLD, FW_NORMAL, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY,
DEFAULT_PITCH, FF_DONTCARE, FW_LIGHT, InvalidateRect, HFONT,
};
const ABOUT_TITLE: &str = "About CompactRS";
const GITHUB_URL: &str = "https://github.com/IRedDragonICY/compactrs";
const LICENSE_URL: &str = "https://github.com/IRedDragonICY/compactrs/blob/main/LICENSE";
struct AboutState {
is_dark: bool,
}
pub unsafe fn show_about_modal(parent: HWND, is_dark: bool) {
let class_name = to_wstring("CompactRS_About");
let existing_hwnd = windows_sys::Win32::UI::WindowsAndMessaging::FindWindowW(class_name.as_ptr(), std::ptr::null());
if existing_hwnd != std::ptr::null_mut() {
ShowWindow(existing_hwnd, SW_RESTORE);
SetForegroundWindow(existing_hwnd);
return;
}
let mut state = AboutState { is_dark };
let bg_brush = crate::ui::theme::get_background_brush(is_dark);
show_modal(
WindowBuilder::new(&mut state, "CompactRS_About", ABOUT_TITLE)
.style(WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE)
.size(450, 500)
.align(WindowAlignment::CenterOnParent)
.background(bg_brush),
parent
);
}
impl WindowHandler for AboutState {
fn is_dark_mode(&self) -> bool {
self.is_dark
}
fn on_create(&mut self, hwnd: HWND) -> LRESULT {
unsafe {
crate::ui::theme::set_window_frame_theme(hwnd, self.is_dark);
let iccex = INITCOMMONCONTROLSEX {
dwSize: std::mem::size_of::<INITCOMMONCONTROLSEX>() as u32,
dwICC: ICC_LINK_CLASS,
};
InitCommonControlsEx(&iccex);
let content_width = 410; let margin = 20;
let segoe_ui_var = to_wstring("Segoe UI Variable Display");
let segoe_ui = to_wstring("Segoe UI");
let title_font = CreateFontW(
-28, 0, 0, 0, FW_BOLD as i32, 0, 0, 0, DEFAULT_CHARSET as u32,
OUT_DEFAULT_PRECIS as u32, CLIP_DEFAULT_PRECIS as u32, CLEARTYPE_QUALITY as u32,
(DEFAULT_PITCH | FF_DONTCARE) as u32, segoe_ui_var.as_ptr()) as HFONT;
let version_font = CreateFontW(
-14, 0, 0, 0, FW_LIGHT as i32, 0, 0, 0, DEFAULT_CHARSET as u32,
OUT_DEFAULT_PRECIS as u32, CLIP_DEFAULT_PRECIS as u32, CLEARTYPE_QUALITY as u32,
(DEFAULT_PITCH | FF_DONTCARE) as u32, segoe_ui_var.as_ptr()) as HFONT;
let body_font = CreateFontW(
-13, 0, 0, 0, FW_NORMAL as i32, 0, 0, 0, DEFAULT_CHARSET as u32,
OUT_DEFAULT_PRECIS as u32, CLIP_DEFAULT_PRECIS as u32, CLEARTYPE_QUALITY as u32,
(DEFAULT_PITCH | FF_DONTCARE) as u32, segoe_ui.as_ptr()) as HFONT;
let creator_font = CreateFontW(
-12, 0, 0, 0, FW_NORMAL as i32, 1, 0, 0, DEFAULT_CHARSET as u32, OUT_DEFAULT_PRECIS as u32, CLIP_DEFAULT_PRECIS as u32, CLEARTYPE_QUALITY as u32,
(DEFAULT_PITCH | FF_DONTCARE) as u32, segoe_ui.as_ptr()) as HFONT;
let instance = GetModuleHandleW(std::ptr::null());
let icon_size = 128;
let icon_x = (450 - icon_size) / 2;
let hicon = LoadImageW(
instance,
1 as *const u16, IMAGE_ICON,
icon_size, icon_size,
LR_DEFAULTCOLOR
);
let icon_static = ControlBuilder::new(hwnd, 0)
.icon_display()
.pos(icon_x, 20)
.size(icon_size, icon_size)
.dark_mode(self.is_dark)
.build();
SendMessageW(icon_static, STM_SETICON, hicon as WPARAM, 0);
let _app_name = ControlBuilder::new(hwnd, 0)
.label(true) .text("CompactRS")
.pos(margin, 160)
.size(content_width, 40)
.font(title_font)
.dark_mode(self.is_dark)
.build();
let ver_string = format!("Version {}", env!("APP_VERSION"));
let _version = ControlBuilder::new(hwnd, 0)
.label(true)
.text(&ver_string)
.pos(margin, 205)
.size(content_width, 20)
.font(version_font)
.dark_mode(self.is_dark)
.build();
let _desc = ControlBuilder::new(hwnd, 0)
.label(true)
.text("Ultra-lightweight, native Windows transparent file compressor built in Rust. Leverages the Windows Overlay Filter (WOF) to save disk space without performance loss.\n\nFeatures a modern, bloat-free Win32 GUI, batch processing, and multithreaded compression (XPRESS/LZX). Zero dependencies, <1MB binary.")
.pos(margin, 240)
.size(content_width, 130)
.font(body_font)
.dark_mode(self.is_dark)
.build();
let _creator = ControlBuilder::new(hwnd, 0)
.label(true)
.text("Created by IRedDragonICY\n(Mohammad Farid Hendianto)")
.pos(margin, 385)
.size(content_width, 40)
.font(creator_font)
.dark_mode(self.is_dark)
.build();
let link_text = to_wstring("<a href=\"https://github.com/IRedDragonICY/compactrs\">GitHub</a> • <a href=\"https://github.com/IRedDragonICY/compactrs/blob/main/LICENSE\">License</a>");
let link_cls = WC_LINK;
let link = CreateWindowExW(
0,
link_cls,
link_text.as_ptr(),
WS_VISIBLE | WS_CHILD | WS_TABSTOP,
margin, 440, content_width, 25,
hwnd,
std::ptr::null_mut(),
instance,
std::ptr::null()
);
SendMessageW(link, WM_SETFONT, body_font as WPARAM, 1);
if self.is_dark {
crate::ui::theme::apply_theme(link, crate::ui::theme::ControlType::Window, true);
}
}
0
}
fn on_message(&mut self, hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> Option<LRESULT> {
unsafe {
match msg {
0x8002 => {
let new_is_dark = wparam == 1;
self.is_dark = new_is_dark;
crate::ui::theme::set_window_frame_theme(hwnd, new_is_dark);
InvalidateRect(hwnd, std::ptr::null(), 1);
Some(0)
},
WM_NOTIFY => {
let nmhdr = &*(lparam as *const NMHDR);
if nmhdr.code == NM_CLICK || nmhdr.code == NM_RETURN {
let nmlink = &*(lparam as *const NMLINK);
let item = nmlink.item;
let open = to_wstring("open");
let github = to_wstring(GITHUB_URL);
let license = to_wstring(LICENSE_URL);
if item.iLink == 0 {
ShellExecuteW(std::ptr::null_mut(), open.as_ptr(), github.as_ptr(), std::ptr::null(), std::ptr::null(), SW_SHOWNORMAL);
} else if item.iLink == 1 {
ShellExecuteW(std::ptr::null_mut(), open.as_ptr(), license.as_ptr(), std::ptr::null(), std::ptr::null(), SW_SHOWNORMAL);
}
}
Some(0)
},
_ => None,
}
}
}
}