使用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
相关产品推荐
相关产品推荐

