asdfasdf
asdfasdf

Reputation: 316

Win32 Layered window not working correctly

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

Answers (0)

Related Questions