C++ vs Rust 实现 Windows 桌面时钟性能与开发效率对比

学习笔记作者:admin日期:2025-05-24点击:35

摘要:对比 C++ 和 Rust 实现 Windows 桌面时钟的性能、开发效率、安全性等方面,提供基于 Rust 的完整代码示例。

桌面时钟实现与技术对比

项目背景

      本项目旨在使用 C++ 和 Rust 分别实现一个 Windows 桌面时钟程序,要求窗口始终置顶、每 2 秒更新时间。

C++ vs Rust 对比

维度 C++ (Win32) Rust (Win32) Rust (egui/winit)
性能 极高 极高
安全性 低(手动管理) 高(借用检查)
开发效率 中等
可维护性 很好
跨平台 否(封装)
易学程度 中等 中等

Rust 实现代码示例

extern crate winapi;

use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::ptr::null_mut;
use std::time::{SystemTime, UNIX_EPOCH};
use winapi::shared::minwindef::*;
use winapi::shared::ntdef::*;
use winapi::um::libloaderapi::*;
use winapi::um::winuser::*;

const IDT_TIMER: usize = 1;

fn main() {
    unsafe {
        let h_instance = GetModuleHandleW(null_mut());

        let class_name: Vec = OsStr::new("ClockWindowClass")
            .encode_wide()
            .chain(Some(0).into_iter())
            .collect();

        let wnd_class = WNDCLASSW {
            style: 0,
            lpfnWndProc: Some(wnd_proc),
            cbClsExtra: 0,
            cbWndExtra: 0,
            hInstance: h_instance,
            hIcon: LoadIconW(null_mut(), IDI_APPLICATION),
            hCursor: LoadCursorW(null_mut(), IDC_ARROW),
            hbrBackground: (COLOR_WINDOW + 1) as HBRUSH,
            lpszMenuName: null_mut(),
            lpszClassName: class_name.as_ptr(),
        };

        RegisterClassW(&wnd_class);

        let hwnd = CreateWindowExW(
            WS_EX_TOPMOST,
            class_name.as_ptr(),
            to_wstring("桌面时钟").as_ptr(),
            WS_POPUP | WS_VISIBLE,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            300,
            100,
            null_mut(),
            null_mut(),
            h_instance,
            null_mut(),
        );

        if hwnd.is_null() {
            return;
        }

        SetTimer(hwnd, IDT_TIMER as UINT_PTR, 2000, None);
        ShowWindow(hwnd, SW_SHOW);
        UpdateWindow(hwnd);

        let mut msg: MSG = std::mem::zeroed();
        while GetMessageW(&mut msg, null_mut(), 0, 0) > 0 {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }
    }
}

unsafe extern "system" fn wnd_proc(
    hwnd: HWND,
    msg: UINT,
    wparam: WPARAM,
    lparam: LPARAM,
) -> LRESULT {
    static mut TIME_STR: [u16; 64] = [0; 64];

    match msg {
        WM_CREATE => {
            get_time_string(&mut TIME_STR);
            SetTimer(hwnd, IDT_TIMER as UINT_PTR, 2000, None);
            0
        }

        WM_TIMER => {
            if wparam == IDT_TIMER {
                get_time_string(&mut TIME_STR);
                InvalidateRect(hwnd, std::ptr::null(), TRUE);
            }
            0
        }

        WM_PAINT => {
            let mut ps: PAINTSTRUCT = std::mem::zeroed();
            let hdc = BeginPaint(hwnd, &mut ps);

            let rect: RECT = {
                let mut r = std::mem::zeroed();
                GetClientRect(hwnd, &mut r);
                r
            };

            DrawTextW(
                hdc,
                TIME_STR.as_ptr(),
                TIME_STR.iter().position(|&c| c == 0).unwrap_or(TIME_STR.len()) as i32,
                &rect,
                DT_CENTER | DT_VCENTER | DT_SINGLELINE,
            );

            EndPaint(hwnd, &ps);
            0
        }

        WM_DESTROY => {
            KillTimer(hwnd, IDT_TIMER as UINT_PTR);
            PostQuitMessage(0);
            0
        }

        _ => DefWindowProcW(hwnd, msg, wparam, lparam),
    }
}

fn get_time_string(buf: &mut [u16; 64]) {
    let now = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs();
    let tm = unsafe { *localtime(&now as *const u64 as *const i64) };

    let mut time_str = [0u8; 64];
    unsafe {
        strftime(
            time_str.as_mut_ptr() as *mut i8,
            time_str.len(),
            b"%Y-%m-%d %H:%M:%S\0".as_ptr() as *const i8,
            &tm,
        );
    }

    let utf16: Vec<u16> = OsStr::from_bytes(&time_str)
        .encode_wide()
        .take_while(|&c| c != 0)
        .collect();
    for (i, &c) in utf16.iter().enumerate() {
        buf[i] = c;
    }
    buf[utf16.len()] = 0;
}

fn to_wstring(s: &str) -> Vec<u16> {
    OsStr::new(s)
        .encode_wide()
        .chain(Some(0))
        .collect()
}

总结

      Rust 在保持高性能的同时提供了更高的安全性、开发效率和可维护性,是现代桌面开发的优秀选择。

上一篇      下一篇