Reputation: 316
I am attempting to create a transparent window using the Win32 API. The window should display a red box at its center, allowing the user to see it while maintaining the ability to interact with objects positioned behind the window. Here is the code I have written for this purpose:
extern crate winapi;
use winapi::{
shared::{minwindef, windef},
um::{libloaderapi, wingdi, winuser, winuser::PAINTSTRUCT},
};
use std::ptr;
unsafe extern "system" fn wnd_proc(
hwnd: winapi::shared::windef::HWND,
msg: minwindef::UINT,
wparam: minwindef::WPARAM,
lparam: minwindef::LPARAM,
) -> minwindef::LRESULT {
match msg {
winuser::WM_PAINT => {
let mut ps: PAINTSTRUCT = std::mem::zeroed();
let hdc = winuser::BeginPaint(hwnd, &mut ps);
let rect = windef::RECT {
left: 200,
top: 200,
right: 800,
bottom: 600,
};
// Create a solid red brush
let red_brush = wingdi::CreateSolidBrush(wingdi::RGB(255, 0, 0));
// Set the window background mode to transparent
wingdi::SetBkMode(hdc, wingdi::TRANSPARENT as i32);
// Fill the background with the red brush
winuser::FillRect(hdc, &rect, red_brush);
// Clean up resources
wingdi::DeleteObject(red_brush as *mut _);
winuser::EndPaint(hwnd, &ps);
}
winuser::WM_DESTROY => {
winuser::PostQuitMessage(0);
}
_ => return winuser::DefWindowProcA(hwnd, msg, wparam, lparam),
}
return 0;
}
fn main() {
unsafe {
let h_instance = libloaderapi::GetModuleHandleA(ptr::null());
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: ptr::null_mut(),
hCursor: winuser::LoadCursorA(ptr::null_mut(), winuser::IDC_ARROW as *const i8),
hbrBackground: wingdi::GetStockObject(wingdi::NULL_BRUSH as i32) as *mut _,
lpszMenuName: ptr::null_mut(),
};
winuser::RegisterClassA(&wnd_class);
let hwnd = winuser::CreateWindowExA(
winuser::WS_EX_LAYERED | winuser::WS_EX_TRANSPARENT,
class_name.as_ptr() as *const i8,
window_name.as_ptr() as *const i8,
winuser::WS_POPUP,
0,
0,
winuser::GetSystemMetrics(winuser::SM_CXSCREEN),
winuser::GetSystemMetrics(winuser::SM_CYSCREEN),
ptr::null_mut(),
ptr::null_mut(),
h_instance,
ptr::null_mut(),
);
winuser::SetLayeredWindowAttributes(hwnd, 0, 0, winuser::LWA_ALPHA);
winuser::ShowWindow(hwnd, winuser::SW_SHOW);
winuser::UpdateWindow(hwnd);
let mut msg: winuser::MSG = std::mem::zeroed();
while winuser::GetMessageA(&mut msg, hwnd, 0, 0) > 0 {
winuser::TranslateMessage(&msg);
winuser::DispatchMessageA(&msg);
}
}
}
The issue is that I can't see the box on the screen. Everything else works fine but I don't see anything on my screen.
I noticed that when I increase the bAlpha
(3rd argument) in this line: winuser::SetLayeredWindowAttributes(hwnd, 0, 0, winuser::LWA_ALPHA);
to 255, I can see the red box but there's also a black background which isn't what I want (I want it to be fully transparent and only the red box should show).
Upvotes: 0
Views: 175