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

使用Rust结合Windows API创建子窗口控件不显示的问题求助

Rust结合Windows API创建子窗口控件不显示的问题求助

我尝试用标准Windows API窗口和子窗口作为控件(主要是静态文本、文本框和按钮)来创建一个窗体。我用了windows crate,代码编译运行都没报错,但只能看到空白窗口,看不到里面的控件。我哪里做错了?提前感谢!

原代码如下:

#![allow(non_snake_case)]

use windows::{
    core::*, 
    Win32::Foundation::*, 
    Win32::Graphics::Gdi::*,
    Win32::System::LibraryLoader::GetModuleHandleA, 
    Win32::UI::WindowsAndMessaging::*,
};


fn main() -> Result<()> {
    unsafe {
        let instance = GetModuleHandleA(None)?;
        let window_class = s!("window");

        let wc = WNDCLASSA {
            hCursor: LoadCursorW(None, IDC_ARROW)?,
            hInstance: instance.into(),
            lpszClassName: window_class,
            style: CS_HREDRAW | CS_VREDRAW,
            lpfnWndProc: Some(wndproc),
            ..Default::default()
        };

        let atom = RegisterClassA(&wc);
        debug_assert!(atom != 0);

        let _hwnd = CreateWindowExA(
            WINDOW_EX_STYLE::default(),
            window_class,
            s!("A simple Form"),
            WS_OVERLAPPEDWINDOW | WS_VISIBLE,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            None,
            None,
            instance,
            None,
        )?;

    let _hndLabel = CreateWindowExA(
               WINDOW_EX_STYLE::default(),
               s!("static"), 
               s!("What's your name? "),
               WINDOW_STYLE::default(),
                           50, 100, 200, 30, _hwnd, None, instance, None)?;

    let _hndCaixa = CreateWindowExA(
                WINDOW_EX_STYLE::default(),
                s!("edit"), 
                s!("Type Here!"),
                WINDOW_STYLE::default(),
                            200, 100, 200, 30, _hwnd, None, instance, None)?;

    let _hndButton = CreateWindowExA(
                WINDOW_EX_STYLE::default(),
                s!("Button"), 
                s!("  OK  "),
                WINDOW_STYLE::default(),
                            400, 100, 200, 30, _hwnd, None, instance, None)?;

        let _ = ShowWindow(_hwnd, SW_SHOW);
    let _ = UpdateWindow(_hwnd);

        let mut message = MSG::default();

        while GetMessageA(&mut message, None, 0, 0).into() {
            DispatchMessageA(&message);
        }

        Ok(())
    }
}

extern "system" fn wndproc(window: HWND, message: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
    unsafe {
        match message {
            WM_PAINT => {
                println!("WM_PAINT");
                _ = ValidateRect(window, None);

                LRESULT(0)
            }
            WM_DESTROY => {
                println!("WM_DESTROY");
                PostQuitMessage(0);
                LRESULT(0)
            }
            _ => DefWindowProcA(window, message, wparam, lparam),
        }
    }
}

嘿,我瞅了你的代码,发现核心问题出在子控件的窗口样式设置上,给你梳理下问题和解决方案:

  • 关键问题:子控件缺少必要的基础样式
    你创建所有子控件时都用了WINDOW_STYLE::default(),但Win32子控件必须具备WS_CHILD | WS_VISIBLE这两个样式——前者标记它是父窗口的子元素,后者让它在创建时就处于可见状态。另外,不同类型的控件还需要额外的样式来保证功能和显示正常,比如文本框需要ES_LEFT实现左对齐,按钮需要BS_PUSHBUTTON标记为标准按钮。

  • 修改后的完整代码
    我已经把需要调整的样式都加上了,还顺手把按钮宽度调小了点(避免超出默认窗口的可视范围),你可以直接运行试试:

#![allow(non_snake_case)]

use windows::{
    core::*, 
    Win32::Foundation::*, 
    Win32::Graphics::Gdi::*,
    Win32::System::LibraryLoader::GetModuleHandleA, 
    Win32::UI::WindowsAndMessaging::*,
};


fn main() -> Result<()> {
    unsafe {
        let instance = GetModuleHandleA(None)?;
        let window_class = s!("window");

        let wc = WNDCLASSA {
            hCursor: LoadCursorW(None, IDC_ARROW)?,
            hInstance: instance.into(),
            lpszClassName: window_class,
            style: CS_HREDRAW | CS_VREDRAW,
            lpfnWndProc: Some(wndproc),
            ..Default::default()
        };

        let atom = RegisterClassA(&wc);
        debug_assert!(atom != 0);

        let _hwnd = CreateWindowExA(
            WINDOW_EX_STYLE::default(),
            window_class,
            s!("A simple Form"),
            WS_OVERLAPPEDWINDOW | WS_VISIBLE,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            None,
            None,
            instance,
            None,
        )?;

        // 静态文本:添加WS_CHILD | WS_VISIBLE | SS_LEFT样式
        let _hndLabel = CreateWindowExA(
            WINDOW_EX_STYLE::default(),
            s!("static"), 
            s!("What's your name? "),
            WS_CHILD | WS_VISIBLE | SS_LEFT,
            50, 100, 200, 30, _hwnd, None, instance, None)?;

        // 文本框:添加WS_CHILD | WS_VISIBLE | ES_LEFT样式
        let _hndCaixa = CreateWindowExA(
            WINDOW_EX_STYLE::default(),
            s!("edit"), 
            s!("Type Here!"),
            WS_CHILD | WS_VISIBLE | ES_LEFT,
            200, 100, 200, 30, _hwnd, None, instance, None)?;

        // 按钮:添加WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON样式,同时缩小宽度避免超出窗口
        let _hndButton = CreateWindowExA(
            WINDOW_EX_STYLE::default(),
            s!("Button"), 
            s!("  OK  "),
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            400, 100, 100, 30, 
            _hwnd, None, instance, None)?;

        let _ = ShowWindow(_hwnd, SW_SHOW);
        let _ = UpdateWindow(_hwnd);

        let mut message = MSG::default();

        while GetMessageA(&mut message, None, 0, 0).into() {
            DispatchMessageA(&message);
        }

        Ok(())
    }
}

extern "system" fn wndproc(window: HWND, message: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
    unsafe {
        match message {
            WM_PAINT => {
                println!("WM_PAINT");
                _ = ValidateRect(window, None);

                LRESULT(0)
            }
            WM_DESTROY => {
                println!("WM_DESTROY");
                PostQuitMessage(0);
                LRESULT(0)
            }
            _ => DefWindowProcA(window, message, wparam, lparam),
        }
    }
}

这样修改后,运行代码就能看到所有控件正常显示在窗口里了!

备注:内容来源于stack exchange,提问作者Michel Almeida

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 10:29:35