用Rust和winapi
编写的桌面应用程序打开一个窗口,并在几个RedrawWindow()
调用中添加文本行。文本行如预期出现,并在(某些)调整窗口大小、移动和遮挡窗口时持续存在。然而,当窗口最小化并再次打开时,仅显示最后一行文本;前面的代码行都没了,代码里漏了什么
//[dependencies]
//winapi = { version = "0.3.9", features = ["wingdi", "winuser", "libloaderapi", "combaseapi", "objbase", "shobjidl", "winerror"] }
use std::error::Error;
use std::ptr::{null, null_mut};
use std::sync::Mutex;
use std::thread;
use std::time;
use winapi::shared::minwindef::*;
use winapi::shared::windef::*;
use winapi::um::libloaderapi::GetModuleHandleW;
use winapi::um::winuser::*;
// Custom signal to inform that new text is available
pub const WM_WEBUPDT: UINT = 0xFEDC;
/// Turns a Rust string slice into a null-terminated utf-16 vector.
pub fn wide_null(s: &str) -> Vec<u16> {
s.encode_utf16().chain(Some(0)).collect()
}
static TEXT: Mutex<String> = Mutex::new(String::new());
static mut UPPER_LINE: i32 = 0;
// Window procedure to handle events
pub unsafe extern "system" fn window_proc(
hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM,
) -> LRESULT {
match msg {
WM_CLOSE => {
DestroyWindow(hwnd);
}
WM_DESTROY => {
PostQuitMessage(0);
}
WM_WEBUPDT => {
RedrawWindow(hwnd, null(), null_mut(), RDW_INVALIDATE);
UPPER_LINE += 25;
}
WM_PAINT => {
let t: String = TEXT.lock().unwrap().clone();
let mut ps: PAINTSTRUCT = std::mem::zeroed();
let hdc: HDC;
hdc = BeginPaint(hwnd, &mut ps);
let mut rec: RECT = std::mem::zeroed();
GetClientRect(hwnd, &mut rec);
rec.top += 4 + UPPER_LINE;
let txt = wide_null(&t);
DrawTextW(
hdc,
txt.as_ptr(),
txt.len().try_into().unwrap(),
&mut rec,
DT_TOP | DT_LEFT,
);
EndPaint(hwnd, &ps);
}
_ => return DefWindowProcW(hwnd, msg, wparam, lparam),
}
return 0;
}
// Declare class and instantiate window
fn create_main_window(name: &str, title: &str) -> Result<HWND, Box<dyn Error>> {
let name = wide_null(name);
let title = wide_null(title);
unsafe {
let hinstance = GetModuleHandleW(null_mut());
let mut wc: WNDCLASSW = core::mem::zeroed();
wc.lpfnWndProc = Some(window_proc);
wc.hInstance = hinstance;
wc.hbrBackground = COLOR_WINDOWFRAME as HBRUSH;
wc.lpszClassName = name.as_ptr();
// Register window class
if RegisterClassW(&wc) == 0 {
MessageBoxW(
null_mut(),
wide_null("Window Registration Failed!").as_ptr(),
wide_null("Error").as_ptr(),
MB_ICONEXCLAMATION | MB_OK,
);
return Err("Window Registration Failed".into());
};
// Create a window based on registered class
let handle = CreateWindowExW(
0, // dwExStyle
name.as_ptr(), // lpClassName
title.as_ptr(), // lpWindowName
WS_OVERLAPPEDWINDOW | WS_VISIBLE, // dwStyle
810, // Int x
390, // Int y
300, // Int nWidth
300, // Int nHeight
null_mut(), // hWndParent
null_mut(), // hMenu
hinstance, // hInstance
null_mut(), // lpParam
);
if handle.is_null() {
MessageBoxW( null_mut(),
wide_null("Window Creation Failed!").as_ptr(),
wide_null("Error!").as_ptr(), MB_ICONEXCLAMATION | MB_OK,
);
return Err("Window Creation Failed!".into());
}
Ok(handle)
}
}
// Message handling loop
fn run_message_loop(hwnd: HWND) -> WPARAM {
unsafe {
let mut msg: MSG = std::mem::zeroed();
loop {
// Get message from message queue
if GetMessageW(&mut msg, hwnd, 0, 0) > 0 {
TranslateMessage(&msg);
DispatchMessageW(&msg);
} else {
// Return on error (<0) or exit (=0) cases
return msg.wParam;
}
}
}
}
fn main() {
*TEXT.lock().unwrap() = "This is first line".to_string();
let hwnd = create_main_window("Main Window", "Main Window").expect("Window creation failed!");
unsafe {
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
}
let hwnd2 = hwnd as usize;
thread::spawn(move || { unsafe {
thread::sleep(time::Duration::from_millis(100));
*TEXT.lock().unwrap() = "This is second line".to_string();
PostMessageW (hwnd2 as HWND, WM_WEBUPDT, 0 as WPARAM, 0 as LPARAM);
thread::sleep(time::Duration::from_millis(100));
*TEXT.lock().unwrap() = "This is third line".to_string();
PostMessageW (hwnd2 as HWND, WM_WEBUPDT, 0 as WPARAM, 0 as LPARAM);
}
}
);
run_message_loop(hwnd);
}
1条答案
按热度按时间yiytaume1#
就我和我的测试而言,如果不处理
WM_ERASEBKGND
,The default handling for the WM_ERASEBKGND message is to fill the area with the current window background color.
另请参见my answer。
其余的,正如评论所说,Windows在Minimized Windows之后没有缓冲。
最小化窗口可以减少应用程序在更新其主窗口时必须执行的工作量,从而提高系统性能。