2

Using the Windows API, I'm trying to draw opaque text on a semi-transparent background. Using SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 128, LWA_ALPHA); and a window style of WS_EX_LAYERED, I've managed to make the entire window semi-transparent, but that also includes the text. How do I keep the text opaque and the background translucent?

AndrWeisR
  • 1,110
  • 11
  • 21

1 Answers1

3

In order to do "proper" alpha in a layered window you need to supply the window manager with a PARGB bitmap by a call to UpdateLayeredWindow.

Try the code below, it works for me.

#include <Windows.h>
#include <stdio.h>
#include <iostream>
#include <ObjIdl.h>
#include <gdiplus.h>
#include <gdiplusheaders.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")

#define MAX_WIDTH 800
#define MAX_HEIGHT 600

using namespace std;

void Drawtext(HWND hwnd, HDC hdc);

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    if (message == WM_DESTROY) {

        PostQuitMessage(0);
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
};

HINSTANCE hinst;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, PSTR szCmdLine, int iCmdShow) {
    HWND hWnd;
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;

    //Initialize GDI+
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    hinst = GetModuleHandle(NULL);
    // create a window class:
    WNDCLASS wc = {};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hinst;
    wc.lpszClassName = L"win32";

    // register class with operating system:
    RegisterClass(&wc);

    // create and show window:
    hWnd = CreateWindowExW(
        WS_EX_LAYERED | WS_EX_TOPMOST,
        L"win32",
        L"WinSoup",
        WS_POPUP,
        0, 0, 1000, 500,
        nullptr,
        nullptr,
        hInstance,
        nullptr
    );

    if (hWnd == NULL) {
        return 0;
    }

    Drawtext(hWnd, GetDC(hWnd));

    ShowWindow(hWnd, SW_SHOW);


    MSG msg = {};

    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

}

void Drawtext(HWND hwnd, HDC hdc)
{
    FontFamily  fontFamily(L"Times New Roman");
    Font        font(&fontFamily, 32, FontStyleRegular, UnitPixel);
    PointF      pointF(30.0f, 10.0f);
    SolidBrush  solidBrush(Color(255, 0, 0, 0));

    Bitmap softwareBitmap(MAX_WIDTH, MAX_HEIGHT, PixelFormat32bppARGB);
    Graphics g(&softwareBitmap);

    g.Clear(Gdiplus::Color(30, 0, 0, 0));  // 30: alpha value 

    g.DrawString(L"Hello Hello Hello Hello Hello Hello Hello Hello", -1, &font, pointF, &solidBrush);

    HBITMAP bmp;
    softwareBitmap.GetHBITMAP(Color(0, 0, 0, 0), &bmp);

    HDC memdc = CreateCompatibleDC(hdc);
    HGDIOBJ original = SelectObject(memdc, bmp);


    BLENDFUNCTION blend = { 0 };
    blend.BlendOp = AC_SRC_OVER;
    blend.SourceConstantAlpha = 255;
    blend.AlphaFormat = AC_SRC_ALPHA;
    POINT ptLocation = { 200, 300 };
    SIZE szWnd = { MAX_WIDTH, MAX_HEIGHT };
    POINT ptSrc = { 0, 0 };
    UpdateLayeredWindow(hwnd, hdc, &ptLocation, &szWnd, memdc, &ptSrc, 0, &blend, ULW_ALPHA);
    SelectObject(hdc, original);

    DeleteObject(bmp);
    DeleteObject(memdc);
}

Debug:

enter image description here

For more details, you can refer to @Koro's answer.

Strive Sun
  • 5,988
  • 1
  • 9
  • 26