You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Rust中与Inno Setup的TNewCheckListBox交互遇阻求助

Inno Setup自动化:TNewCheckListBox交互瓶颈

问题概述

实现Inno Setup安装程序自动化时,已完成Button和Checkbox的交互,但无法与TNewCheckListBox正常交互:动态创建的TNewCheckBox句柄无法获取,也无法设置或切换选中状态,尝试CLBN_CHKCHANGE消息无效果。

现有代码

检查复选框状态函数

pub fn check_checklistbox_states() -> Vec<HWND> {
    let mut checkbox_handles: Vec<HWND> = Vec::new();

    if let Some(checklistbox_hwnd) = find_checklistbox() {
        unsafe {
            let count = SendMessageW(checklistbox_hwnd, LB_GETCOUNT, WPARAM(0), LPARAM(0));
            
            let count = count.0 as i32 as usize;
            println!("{:#?}", count);
            for index in 0..count {
                if let Some(text) = get_item_text(checklistbox_hwnd, index) {
                    let state = SendMessageW(checklistbox_hwnd, LB_GETITEMDATA, WPARAM(index as usize), LPARAM(0));
                    let checked = state.0 as i32;
                    let state_text = if checked != 0 {
                        "Checked"
                    } else {
                        "Unchecked"
                    };
                    let debug_checkbox = checklistbox_hwnd.0 as i32;
                    println!("Item {}: {} - {} - {}", index + 1, text, state_text, debug_checkbox);

                    // 示例:切换选中状态
                    let new_check_state = if checked != 0 { 0 } else { 1 }; // 在选中(1)和未选中(0)间切换
                    
                    if (index >= 1) {
                        // set_check(checklistbox_hwnd, index as c_int, new_check_state, BS_CHECKBOX as u32);
                        let _ = PostMessageW(checklistbox_hwnd, CLBN_CHKCHANGE, WPARAM(1), LPARAM(0));
                        println!("sent");
                    }
                    println!("should have clicked");
                    checkbox_handles.push(checklistbox_hwnd);  // 这是列表框的句柄,不是单个项的
                }
            }
        }
    } else {
        println!("TNewCheckListBox not found.");
    }

    checkbox_handles
}

参考WinSCP实现的set_check相关代码

const LB_ERR: LRESULT = windows::Win32::Foundation::LRESULT(-1);


#[repr(C)]
struct AfxCheckData {
    m_n_check: c_int,
    m_b_enabled: BOOL,
    m_dw_user_data: DWORD,
}

impl AfxCheckData {
    fn new() -> Self {
        Self {
            m_n_check: 0,
            m_b_enabled: TRUE,
            m_dw_user_data: 0,
        }
    }
}
fn invalidate_check(listbox_hwnd: HWND, n_index: i32) {
    unsafe {
        let mut rect: RECT = zeroed();
        if SendMessageW(listbox_hwnd, LB_GETITEMRECT, WPARAM(n_index as usize), LPARAM(&mut rect as *mut RECT as isize)) != LB_ERR {
                InvalidateRect(listbox_hwnd.0 as *mut winapi::shared::windef::HWND__, &rect as *const RECT, 1);
        }
    }
}
fn set_check(listbox_hwnd: HWND, n_index: i32, n_check: i32, m_n_style: u32) {
    if n_check == 2 && (m_n_style == BS_CHECKBOX as u32 || m_n_style == BS_AUTOCHECKBOX as u32) {
        return;
    }

    unsafe {
        let l_result = SendMessageW(listbox_hwnd, LB_GETITEMDATA, WPARAM(n_index as usize), LPARAM(0));
        println!("{:#?}",l_result);
        if l_result != LB_ERR {
        let p_state: *mut AfxCheckData = if l_result == LRESULT(0) {
            Box::into_raw(Box::new(AfxCheckData::new()))
        } else {
            // unsafe { transmute(l_result) }
            Box::into_raw(Box::new(AfxCheckData::new()))
        };
            (*p_state).m_n_check = n_check;

            if SendMessageW(listbox_hwnd, LB_SETITEMDATA, WPARAM(n_index as usize), LPARAM(p_state as isize)) == LB_ERR {
                eprintln!("Failed to set item data.");
            }

            invalidate_check(listbox_hwnd, n_index);
        }
    }}

遇到的具体问题

  • 无法获取单个TNewCheckBox的句柄,CLBN_CHKCHANGE消息(尝试过40和0x00000040两种常量定义)无效果
  • 转换WinSCP的C++代码到Rust时,transmute会触发STATUS_ACCESS_VIOLATION错误,移除后set_check函数无法正确工作
  • 选中状态判断异常:实际未选中的项,输出显示为"Checked"
  • 发送LBN_DBLCLK消息时,复选框会消失

当前输出

Item 1: Main game files - Unchecked - 198748
should have clicked
Item 2: Update DirectX - Checked - 198748
LRESULT(
    400048848,
)
sent
should have clicked

期望

寻求简便的解决方案,实现TNewCheckListBox的选中状态切换和状态正确获取。

内容的提问来源于stack exchange,提问作者Carotide

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 23:19:50