Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to create a winapi window with only borders

Tags:

c++

winapi

dxgi

So I'm trying to create a window that only shows its borders and have the rest of the body be see through. I've created a mockup of what that would look like in my head:

Transparent window, only displaying a border and showing whatever would be underneath it

I tried blitting in a buffer with transparent pixels but that did not have the desired effect.

Any ideas ?

like image 598
justin kohlenberg Avatar asked Mar 20 '18 09:03

justin kohlenberg


People also ask

How do I create a window without the title bar?

If we are required to create a resizable window without the title bar programmatically, then we can use Sizegrip(parent) widget in Tkinter.

How to Create window in Win32?

const wchar_t CLASS_NAME[] = L"Sample Window Class"; WNDCLASS wc = { }; wc. lpfnWndProc = WindowProc; wc. hInstance = hInstance; wc. lpszClassName = CLASS_NAME; RegisterClass(&wc); // Create the window.

What is hwnd in c++?

A Windows window is identified by a "window handle" ( HWND ) and is created after the CWnd object is created by a call to the Create member function of class CWnd . The window may be destroyed either by a program call or by a user's action.


1 Answers

This is possible by passing the WS_EX_NOREDIRECTIONBITMAP1 extended window style to a call to CreateWindowEx. This prevents the system from allocating a render surface for the window's client area, leaving the client area completely transparent.

Note, that this does not make the window transparent to mouse clicks. Hit testing is still governed by the window, even if it doesn't have a visible client area.

The following code provides a minimal code sample that showcases the use:

#define UNICODE
#include <Windows.h>
#pragma comment(lib, "user32.lib")

int CALLBACK wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int) {

    WNDCLASSW wc{};
    wc.hCursor = ::LoadCursorW(nullptr, IDC_ARROW);
    wc.hInstance = hInstance;
    wc.lpszClassName = L"TransparentWindow";
    wc.lpfnWndProc = [](HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -> LRESULT
    {
        switch (message) {
        case WM_DESTROY:
            ::PostQuitMessage(0);
            return 0;
        default:
            return ::DefWindowProcW(hWnd, message, wParam, lParam);
        }
    };
    ::RegisterClassW(&wc);

    ::CreateWindowExW(WS_EX_NOREDIRECTIONBITMAP, wc.lpszClassName, L"Transparent window",
                      WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                      CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                      nullptr, nullptr, hInstance, nullptr);

    MSG msg{};
    while (::GetMessageW(&msg, nullptr, 0, 0) > 0) {
        ::DispatchMessageW(&msg);
    }

    return msg.wParam;
}

This produces output similar to the following screenshot:

Screenshot of sample application


More information on the internals, as well as a common use case can be found in Kenny Kerr's excellent June 2014 MSDN Magazine article Windows with C++ : High-Performance Window Layering Using the Windows Composition Engine.


1This requires desktop composition to be enabled. Desktop composition is available in all supported versions of Windows, but can be disabled by the user/system administrator prior to Windows 8.

like image 71
IInspectable Avatar answered Oct 08 '22 17:10

IInspectable