#![allow(dead_code)]
use crate::types::*;
use crate::utils::to_wstring;
#[derive(Clone, Copy)]
pub struct Button { hwnd: HWND }
impl Button {
pub fn new(hwnd: HWND) -> Self { Self { hwnd } }
pub fn is_checked(&self) -> bool {
unsafe { SendMessageW(self.hwnd, BM_GETCHECK, 0, 0) == 1 }
}
pub fn set_checked(&self, checked: bool) {
unsafe { SendMessageW(self.hwnd, BM_SETCHECK, if checked { 1 } else { 0 }, 0); }
}
pub fn set_enabled(&self, enabled: bool) {
unsafe { EnableWindow(self.hwnd, if enabled { 1 } else { 0 }); }
}
pub fn set_text(&self, text: &str) {
let w = to_wstring(text);
unsafe { SetWindowTextW(self.hwnd, w.as_ptr()); }
}
pub fn set_text_w(&self, text: &[u16]) {
unsafe { SetWindowTextW(self.hwnd, text.as_ptr()); }
}
}
#[derive(Clone, Copy)]
pub struct ComboBox { hwnd: HWND }
impl ComboBox {
pub fn new(hwnd: HWND) -> Self { Self { hwnd } }
pub fn get_selected_index(&self) -> i32 {
unsafe { SendMessageW(self.hwnd, CB_GETCURSEL, 0, 0) as i32 }
}
pub fn set_selected_index(&self, index: i32) {
unsafe { SendMessageW(self.hwnd, CB_SETCURSEL, index as usize, 0); }
}
pub fn add_string(&self, text: &str) {
let w = to_wstring(text);
unsafe { SendMessageW(self.hwnd, CB_ADDSTRING, 0, w.as_ptr() as isize); }
}
pub fn clear(&self) {
unsafe { SendMessageW(self.hwnd, CB_RESETCONTENT, 0, 0); }
}
pub fn set_enabled(&self, enabled: bool) {
unsafe { EnableWindow(self.hwnd, if enabled { 1 } else { 0 }); }
}
}
#[derive(Clone, Copy)]
pub struct Label { hwnd: HWND }
impl Label {
pub fn new(hwnd: HWND) -> Self { Self { hwnd } }
pub fn set_text(&self, text: &str) {
let w = to_wstring(text);
unsafe { SetWindowTextW(self.hwnd, w.as_ptr()); }
}
pub fn set_text_w(&self, text: &[u16]) {
unsafe { SetWindowTextW(self.hwnd, text.as_ptr()); }
}
}
#[derive(Clone, Copy)]
pub struct ProgressBar { hwnd: HWND }
impl ProgressBar {
pub fn new(hwnd: HWND) -> Self { Self { hwnd } }
pub fn set_range(&self, min: i32, max: i32) {
unsafe { SendMessageW(self.hwnd, PBM_SETRANGE32, min as usize, max as isize); }
}
pub fn set_pos(&self, pos: i32) {
unsafe { SendMessageW(self.hwnd, PBM_SETPOS, pos as usize, 0); }
}
}
#[derive(Clone, Copy)]
pub struct Trackbar { hwnd: HWND }
impl Trackbar {
pub fn new(hwnd: HWND) -> Self { Self { hwnd } }
pub fn set_range(&self, min: u32, max: u32) {
let lparam = (min & 0xFFFF) | ((max << 16) & 0xFFFF0000);
unsafe { SendMessageW(self.hwnd, TBM_SETRANGE, 1, lparam as isize); }
}
pub fn set_pos(&self, pos: u32) {
unsafe { SendMessageW(self.hwnd, TBM_SETPOS, 1, pos as isize); }
}
pub fn get_pos(&self) -> u32 {
unsafe { SendMessageW(self.hwnd, TBM_GETPOS, 0, 0) as u32 }
}
}
pub fn get_window_text(hwnd: HWND) -> String {
unsafe {
let len = GetWindowTextLengthW(hwnd);
if len > 0 {
let mut buf = vec![0u16; (len + 1) as usize];
let copied = GetWindowTextW(hwnd, buf.as_mut_ptr(), len + 1);
if copied > 0 {
return String::from_utf16_lossy(&buf[..copied as usize]);
}
}
String::new()
}
}
#[derive(Clone, Copy)]
pub struct ListView { hwnd: HWND }
impl ListView {
pub fn new(hwnd: HWND) -> Self { Self { hwnd } }
pub fn clear_columns(&self) {
const LVM_DELETECOLUMN: u32 = 0x101C;
loop {
let result = unsafe { SendMessageW(self.hwnd, LVM_DELETECOLUMN, 0, 0) };
if result == 0 { break; } }
}
pub fn add_column(&self, index: i32, text: &str, width: i32) {
let w_text = to_wstring(text);
let mut col = unsafe { std::mem::zeroed::<LVCOLUMNW>() };
col.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_FMT;
col.fmt = LVCFMT_LEFT as i32;
col.cx = width;
col.pszText = w_text.as_ptr() as *mut _;
col.iSubItem = index;
unsafe { SendMessageW(self.hwnd, LVM_INSERTCOLUMNW, index as usize, &col as *const _ as isize); }
}
pub fn set_column_width(&self, index: i32, width: i32) {
const LVM_SETCOLUMNWIDTH: u32 = 0x101E;
unsafe { SendMessageW(self.hwnd, LVM_SETCOLUMNWIDTH, index as usize, width as isize); }
}
pub fn insert_item(&self, index: i32, text: &str, image_index: i32) {
let w_text = to_wstring(text);
let mut item = unsafe { std::mem::zeroed::<LVITEMW>() };
item.mask = LVIF_TEXT | LVIF_IMAGE;
item.iItem = index;
item.iSubItem = 0;
item.pszText = w_text.as_ptr() as *mut _;
item.iImage = image_index;
unsafe { SendMessageW(self.hwnd, LVM_INSERTITEMW, 0, &item as *const _ as isize); }
}
pub fn set_item_text(&self, index: i32, sub_index: i32, text: &str) {
let w_text = to_wstring(text);
let mut item = unsafe { std::mem::zeroed::<LVITEMW>() };
item.mask = LVIF_TEXT;
item.iItem = index;
item.iSubItem = sub_index;
item.pszText = w_text.as_ptr() as *mut _;
unsafe { SendMessageW(self.hwnd, LVM_SETITEMW, 0, &item as *const _ as isize); }
}
pub fn set_item_text_w(&self, index: i32, sub_index: i32, text: &[u16]) {
let mut item = unsafe { std::mem::zeroed::<LVITEMW>() };
item.mask = LVIF_TEXT;
item.iItem = index;
item.iSubItem = sub_index;
item.pszText = text.as_ptr() as *mut _;
unsafe { SendMessageW(self.hwnd, LVM_SETITEMW, 0, &item as *const _ as isize); }
}
pub fn clear(&self) {
unsafe { SendMessageW(self.hwnd, LVM_DELETEALLITEMS, 0, 0); }
}
pub fn get_selection_mark(&self) -> i32 {
unsafe { SendMessageW(self.hwnd, LVM_GETSELECTIONMARK, 0, 0) as i32 }
}
pub fn set_extended_style(&self, style: u32) {
unsafe {
SendMessageW(self.hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, style as isize);
}
}
pub fn apply_theme(&self, is_dark: bool) {
unsafe {
crate::ui::theme::allow_dark_mode_for_window(self.hwnd, is_dark);
if is_dark {
crate::ui::theme::apply_theme(self.hwnd, crate::ui::theme::ControlType::ItemsView, true);
} else {
crate::ui::theme::apply_theme(self.hwnd, crate::ui::theme::ControlType::List, false);
}
let (bg, text) = if is_dark {
(crate::ui::theme::COLOR_LIST_BG_DARK, crate::ui::theme::COLOR_LIST_TEXT_DARK)
} else {
(crate::ui::theme::COLOR_LIST_BG_LIGHT, crate::ui::theme::COLOR_LIST_TEXT_LIGHT)
};
SendMessageW(self.hwnd, LVM_SETBKCOLOR, 0, bg as isize);
SendMessageW(self.hwnd, LVM_SETTEXTCOLOR, 0, text as isize);
SendMessageW(self.hwnd, LVM_SETTEXTBKCOLOR, 0, bg as isize);
let h_header = SendMessageW(self.hwnd, LVM_GETHEADER, 0, 0) as HWND;
if h_header != std::ptr::null_mut() {
crate::ui::theme::allow_dark_mode_for_window(h_header, is_dark);
crate::ui::theme::apply_theme(h_header, crate::ui::theme::ControlType::Header, is_dark);
InvalidateRect(h_header, std::ptr::null(), 1);
}
}
}
pub fn fix_header_dark_mode(&self, parent_check_hwnd: HWND) {
unsafe {
let _ = SetWindowSubclass(
self.hwnd,
Some(header_subclass_proc),
4242, parent_check_hwnd as usize,
);
}
}
}
unsafe extern "system" fn header_subclass_proc(
hwnd: HWND,
umsg: u32,
wparam: WPARAM,
lparam: LPARAM,
_uidsubclass: usize,
dwrefdata: usize,
) -> LRESULT {
unsafe {
if umsg == WM_NOTIFY {
let nmhdr = &*(lparam as *const NMHDR);
if nmhdr.code == NM_CUSTOMDRAW {
let h_header = SendMessageW(hwnd, LVM_GETHEADER, 0, 0) as HWND;
if nmhdr.hwndFrom == h_header {
let _parent_hwnd = dwrefdata as HWND;
let is_dark = crate::ui::theme::is_system_dark_mode();
if is_dark {
let nmcd = &mut *(lparam as *mut NMCUSTOMDRAW);
if nmcd.dwDrawStage == CDDS_PREPAINT {
return CDRF_NOTIFYITEMDRAW as LRESULT;
}
if nmcd.dwDrawStage == CDDS_ITEMPREPAINT {
SetTextColor(nmcd.hdc, crate::ui::theme::COLOR_HEADER_TEXT_DARK);
SetBkMode(nmcd.hdc, TRANSPARENT as i32);
return CDRF_NEWFONT as LRESULT;
}
}
}
}
}
DefSubclassProc(hwnd, umsg, wparam, lparam)
}
}