I have some code setup with Windows GDI to create a transparent window and then draw a red transparent box in the upper left of the window. After a while, it moves the box a bit to the left and makes it bigger and redraws it. The problem is that when the new box is drawn, the old box still appears in the window. In my code, I m not drawing the new box in the message loop anymore (I ve already confirmed this multiple times) but it s not disappearing for some reason.
Here s my code:
#[macro_use]
extern crate lazy_static;
use std::{
sync::{Mutex},
thread,
time::Duration, ptr,
};
use winapi::{shared::windef::{self, HWND__}, um::winuser};
struct HWNDWrapper(*mut HWND__);
unsafe impl Send for HWNDWrapper {}
unsafe impl Sync for HWNDWrapper {}
lazy_static! {
static ref boxes: Mutex<Vec<windef::RECT>> = Mutex::new(vec![
windef::RECT {
left: 200,
top: 200,
right: 400,
bottom: 400,
}
]);
}
unsafe extern "system" fn wnd_proc(
hwnd: winapi::shared::windef::HWND,
msg: winapi::shared::minwindef::UINT,
wparam: winapi::shared::minwindef::WPARAM,
lparam: winapi::shared::minwindef::LPARAM,
) -> winapi::shared::minwindef::LRESULT {
match msg {
winuser::WM_PAINT => {
let mut ps: winuser::PAINTSTRUCT = std::mem::zeroed();
let hdc = winuser::BeginPaint(hwnd, &mut ps);
let boxes_unwrapped = boxes.lock().unwrap();
println!("drawing {}", boxes_unwrapped.len());
if boxes_unwrapped.len() > 0 {
for rect in boxes_unwrapped.iter() {
let red_brush = winapi::um::wingdi::CreateSolidBrush(winapi::um::wingdi::RGB(255, 0, 0));
winuser::FrameRect(hdc, rect as *const _, red_brush);
winapi::um::wingdi::DeleteObject(red_brush as *mut _);
}
}
drop(boxes_unwrapped);
winuser::EndPaint(hwnd, &ps);
},
winuser::WM_DESTROY => {
winuser::PostQuitMessage(0);
},
_ => {
return winuser::DefWindowProcA(hwnd, msg, wparam, lparam);
},
}
return 0;
}
fn initialize() -> winapi::shared::windef::HWND {
unsafe {
let h_instance = winapi::um::libloaderapi::GetModuleHandleA(std::ptr::null_mut());
let class_name = "GPUWindow";
let window_name = "GPU Window";
let wnd_class = winuser::WNDCLASSA {
style: winuser::CS_HREDRAW | winuser::CS_VREDRAW,
lpfnWndProc: Some(wnd_proc),
hInstance: h_instance,
lpszClassName: class_name.as_ptr() as *const i8,
cbClsExtra: 0,
cbWndExtra: 0,
hIcon: std::ptr::null_mut(),
hCursor: winuser::LoadCursorA(std::ptr::null_mut(), winuser::IDC_ARROW as *const i8),
hbrBackground: winapi::um::wingdi::GetStockObject(winapi::um::wingdi::NULL_BRUSH as i32) as *mut _,
lpszMenuName: std::ptr::null_mut(),
};
winuser::RegisterClassA(&wnd_class);
let hwnd = winuser::CreateWindowExA(
winuser::WS_EX_LAYERED | winuser::WS_EX_TRANSPARENT | winuser::WS_EX_TOPMOST,
class_name.as_ptr() as *const i8,
window_name.as_ptr() as *const i8,
winuser::WS_POPUP,
0,
0,
1000,
1000,
std::ptr::null_mut(),
std::ptr::null_mut(),
h_instance,
std::ptr::null_mut(),
);
winuser::SetLayeredWindowAttributes(hwnd, 0, 255, winuser::LWA_COLORKEY);
winuser::ShowWindow(hwnd, winuser::SW_SHOW);
winuser::UpdateWindow(hwnd);
hwnd
}
}
fn main() {
// let boxes_mutex: Arc<Mutex<Vec<windef::RECT>>> = Arc::new(Mutex::new(Vec::new()));
thread::spawn(move || {
unsafe {
let hwnd = initialize();
let hwnd_clone = hwnd.clone();
let hwnd_wrapper = HWNDWrapper(hwnd_clone);
thread::spawn(move || {
let wrapped = hwnd_wrapper;
let hwnd = wrapped.0;
let boxes_locked = boxes.lock().unwrap();
let mut boxes_len = boxes_locked.len();
drop(boxes_locked);
loop {
let boxes_locked = boxes.lock().unwrap();
let boxes_len_new = boxes_locked.len();
drop(boxes_locked);
if boxes_len_new != boxes_len {
winuser::InvalidateRect(hwnd, ptr::null(), 1);
}
boxes_len = boxes_len_new;
thread::sleep(Duration::from_millis(100));
}
});
let mut msg: winuser::MSG = std::mem::zeroed();
while winuser::GetMessageA(&mut msg, hwnd, 0, 0) > 0 {
winuser::TranslateMessage(&msg);
winuser::DispatchMessageA(&msg);
}
}
});
thread::sleep(Duration::from_secs(5));
let mut boxes_locked = boxes.lock().unwrap();
boxes_locked.pop(); // remove all boxes from screen
drop(boxes_locked); // release variable
thread::sleep(Duration::from_secs(5));
let mut boxes_locked = boxes.lock().unwrap();
boxes_locked.push(windef::RECT {
left: 300,
top: 300,
right: 900,
bottom: 900,
}); // add a new box that is close to the old box
drop(boxes_locked); // release variable
// keep alive
loop {}
}
I ve already looked through many documentations and I still can t figure out what s going on here. I m not redrawing the box, but it still shows up in the window.