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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 15:33:52