使用Rust windows crate创建窗口失败:代码可运行但无窗口显示
Rust调用Windows API创建窗口不显示的问题排查与修复
在Rust中使用windows crate调用Windows API创建空白窗口时,代码可编译执行但窗口无法显示,等价C++代码可正常运行,问题出在以下几个关键错误:
原问题代码
use windows::{ core::*, Win32::{Foundation::*, Graphics::Gdi::{CreateSolidBrush, UpdateWindow, ValidateRect, COLOR_WINDOW, HBRUSH}, System::LibraryLoader::{GetModuleHandleA, GetModuleHandleW}, UI::WindowsAndMessaging::*}, }; fn main() -> Result<()> { unsafe{ let window_class = w!("the_window"); let window_name = w!("The Factory"); let instance = GetModuleHandleW(None)?; let kleur = COLORREF{ 0: 255, }; let brush: HBRUSH = CreateSolidBrush(kleur); debug_assert!(instance.0 != 0); //define the window let wc = WNDCLASSW { hCursor: LoadCursorW(None, IDC_ARROW)?, style: CS_HREDRAW | CS_VREDRAW, lpszClassName: window_name, hInstance: instance.into(), hbrBackground: brush, lpfnWndProc: Some(wndproc), ..Default::default() }; //register the class let atom = RegisterClassW(&wc); debug_assert!(atom != 0); let hwnd_desktop = GetDesktopWindow(); let hwnd = CreateWindowExW(WINDOW_EX_STYLE::default(), window_class, window_name, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 100, 100, hwnd_desktop, None, instance, None); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); let mut message = std::mem::zeroed(); println!("init the msg structure success."); while GetMessageA(&mut message, None, 0, 0).into() { TranslateMessage(&message); 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), } } }
关键错误与修复方案
窗口类注册时类名错误
注册窗口类WNDCLASSW时,lpszClassName字段错误使用了window_name(窗口标题),应改为定义好的window_class(窗口类名),否则后续创建窗口时无法匹配到正确的窗口类。消息循环混用ANSI与宽字符API
代码使用了宽字符版本的窗口创建API(CreateWindowExW、RegisterClassW),但消息循环却调用了ANSI版本的GetMessageA、TranslateMessage、DispatchMessageA,API版本不匹配会导致消息处理异常,窗口无法正常渲染。需统一替换为宽字符版本的GetMessageW、TranslateMessageW、DispatchMessageW。窗口过程使用错误的默认处理函数
窗口过程wndproc的默认分支调用了ANSI版本的DefWindowProcA,应对应使用宽字符版本的DefWindowProcW,否则会导致窗口基础消息处理失效。COLORREF初始化不规范(非致命但建议修正)
直接给COLORREF的0字段赋值255不符合Windows颜色值规范,应使用RGB宏构造合法的RGB颜色值,确保背景色设置符合预期。
修复后的完整代码
use windows::{ core::*, Win32::{Foundation::*, Graphics::Gdi::{CreateSolidBrush, UpdateWindow, ValidateRect, RGB, HBRUSH}, System::LibraryLoader::GetModuleHandleW, UI::WindowsAndMessaging::*}, }; fn main() -> Result<()> { unsafe { let window_class = w!("the_window"); let window_name = w!("The Factory"); let instance = GetModuleHandleW(None)?; // 正确构造白色背景的COLORREF let kleur = COLORREF::from(RGB(255, 255, 255)); let brush: HBRUSH = CreateSolidBrush(kleur); debug_assert!(instance.0 != 0); // 定义窗口类,修正lpszClassName为window_class let wc = WNDCLASSW { hCursor: LoadCursorW(None, IDC_ARROW)?, style: CS_HREDRAW | CS_VREDRAW, lpszClassName: window_class, hInstance: instance.into(), hbrBackground: brush, lpfnWndProc: Some(wndproc), ..Default::default() }; // 注册窗口类 let atom = RegisterClassW(&wc); debug_assert!(atom != 0); let hwnd_desktop = GetDesktopWindow(); let hwnd = CreateWindowExW( WINDOW_EX_STYLE::default(), window_class, window_name, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 100, 100, hwnd_desktop, None, instance, None ); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); let mut message = std::mem::zeroed(); println!("init the msg structure success."); // 使用宽字符版本的消息循环API while GetMessageW(&mut message, None, 0, 0).into() { TranslateMessageW(&message); DispatchMessageW(&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) } // 使用宽字符版本的默认窗口处理函数 _ => DefWindowProcW(window, message, wparam, lparam), } } }
内容的提问来源于stack exchange,提问作者Cyriel Lamerigts
相关产品推荐
相关产品推荐

