Untitled

mail@pastecode.io avatarunknown
rust
a month ago
6.1 kB
8
Indexable
Never
use std::ffi::*;

use windows_sys::Win32::{
    Foundation::*, Graphics::Gdi::*, System::Diagnostics::Debug::*,
    UI::WindowsAndMessaging::*,
};

static mut hBitmap: HBITMAP = 0;

fn main() {
    unsafe {
        let hDesktopWnd = GetDesktopWindow();
        let mut desktopRect = std::mem::MaybeUninit::<RECT>::uninit().assume_init();
        GetWindowRect(hDesktopWnd, &mut desktopRect);

        let hdcScreen = GetDC(0);
        let hdcCapture = CreateCompatibleDC(hdcScreen);
        hBitmap = CreateCompatibleBitmap(hdcScreen, desktopRect.right - desktopRect.left, desktopRect.bottom - desktopRect.top);
        SelectObject(hdcCapture, hBitmap);

        // https://learn.microsoft.com/en-us/windows/win32/gdi/alpha-blending-a-bitmap
        // make image semi-transparent
        let bf = BLENDFUNCTION {
            BlendOp: AC_SRC_OVER as u8,
            BlendFlags: 0,
            SourceConstantAlpha: 0x7f,
            AlphaFormat: 0,
        };
        // let bf = { 0 };
        // bf.BlendOp = AC_SRC_OVER;
        // bf.BlendFlags = 0;
        // bf.SourceConstantAlpha = 0x7f;  // half of 0xff = 50% transparency 
        // bf.AlphaFormat = 0;             // ignore source alpha channel 

        AlphaBlend(hdcScreen, 0, 0,
            desktopRect.right - desktopRect.left, desktopRect.bottom - desktopRect.top,
            hdcCapture, 0, 0, desktopRect.right - desktopRect.left, desktopRect.bottom - desktopRect.top, bf);

        // copy modified image device context onto desktop screen
        BitBlt(hdcCapture, 0, 0, desktopRect.right - desktopRect.left, desktopRect.bottom - desktopRect.top, hdcScreen, 0, 0, SRCCOPY);

        ReleaseDC(0, hdcScreen);
        DeleteDC(hdcCapture);

        // Create a window to display the captured image
        let lpszClassName = CString::new("Window in Console").unwrap();
        let wcex = WNDCLASSA {
          style: CS_HREDRAW | CS_VREDRAW,
          lpfnWndProc: Some(wndproc),
          cbClsExtra: 0,
          cbWndExtra: 0,
          hInstance: 0,
          hIcon: 0,
          hCursor: LoadCursorW(0, IDC_ARROW),
        //   hbrBackground: (COLOR_WINDOW + 1), as isize,
          hbrBackground: GetStockObject(NULL_BRUSH),
          lpszMenuName: std::ptr::null(),
          lpszClassName: lpszClassName.as_ptr() as *const u8,
        };
        

        RegisterClassA(&wcex);

        let lpwindowname = CString::new("Window in Console").unwrap();
        let hImageWnd = CreateWindowExA(0,
            lpszClassName.as_ptr() as *const u8,
            lpwindowname.as_ptr() as *const u8,
            WS_POPUP,
            desktopRect.left, desktopRect.top,
            desktopRect.right - desktopRect.left,
            desktopRect.bottom - desktopRect.top,
            0,
            0,
            0,
            std::ptr::null());

        ShowWindow(hImageWnd, 0);
        UpdateWindow(hImageWnd);

        // Message loop for the image window
        let mut msg = std::mem::MaybeUninit::<MSG>::uninit().assume_init();
        while (GetMessageA(&mut msg, 0, 0, 0) == 0i32) {
            TranslateMessage(&msg);
            DispatchMessageA(&msg);
        }

        DeleteObject(hBitmap);
    }
}


type UINT = u32;

static mut bSnipping: bool = false;
static mut ptStart: POINT = POINT { x: 0, y: 0 };
static mut ptEnd: POINT = POINT { x: 0, y: 0 };

unsafe extern "system" fn wndproc(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> LRESULT { 
    let hdcScreen = GetDC(0);
    let hdcWindow = GetDC(hwnd);
    let mut rect = std::mem::MaybeUninit::<RECT>::uninit().assume_init();
    GetClientRect(hwnd, &mut rect);

    match msg {
        WM_NCCREATE => {
            println!("Continue creating window");
        }
        WM_CLOSE => {
            println!("Closing window...");
            DestroyWindow(hdcWindow);
        }
        WM_LBUTTONDOWN => {
    //         println!("detected mouse click down");
            bSnipping = true;
            GetCursorPos(&mut ptStart);
        }
        WM_LBUTTONUP => {
            if bSnipping {
                println!("detected mouse click up");
                GetCursorPos(&mut ptEnd);
                bSnipping = false;
    
                // Capture the snipped region
                // do something with the result
                // for now just copy it onto the screen to see if its correct
                BitBlt(hdcWindow, 0, 0, rect.right, rect.bottom, hdcScreen, ptStart.x, ptStart.y, SRCCOPY);
                
            }
        }
        WM_MOUSEMOVE => {
            if bSnipping {
                println!("CLIPPING REGION");
                GetCursorPos(&mut ptEnd);
    
                let bf = BLENDFUNCTION {
                    BlendOp: AC_SRC_OVER as u8,
                    BlendFlags: 0,
                    SourceConstantAlpha: 0xff,
                    AlphaFormat: 0
                };
    
                AlphaBlend(hdcWindow, 0, 0,
                    rect.right, rect.bottom,
                    hdcWindow, 0, 0, rect.right, rect.bottom, bf);
    
                BitBlt(hdcWindow, 0, 0, rect.right, rect.bottom, hdcScreen, ptStart.x, ptStart.y, SRCCOPY);
    
                InvalidateRect(hwnd, std::ptr::null(), 0);
            }
        }
        WM_PAINT => {
            let mut ps = std::mem::MaybeUninit::<PAINTSTRUCT>::uninit().assume_init();
            let hdc = BeginPaint(hwnd, &mut ps);

            // Draw the captured image onto the window
            let hdcMem = CreateCompatibleDC(hdc);
            SelectObject(hdcMem, hBitmap);
            let mut bm = std::mem::MaybeUninit::<BITMAP>::uninit().assume_init();

            GetObjectA(hBitmap, std::mem::size_of::<BITMAP>() as i32, &mut bm as *mut _ as *mut c_void);

            BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
            DeleteDC(hdcMem);

            EndPaint(hwnd, &ps);
        }
        WM_DESTROY => {
            PostQuitMessage(0);
        }
        _ => {
            DefWindowProcA(hwnd, msg, wparam, lparam);
        }
    }

    ReleaseDC(hwnd, hdcWindow);
    ReleaseDC(0, hdcScreen);
    return 0;
}