簡體   English   中英

使用GDI +繪制亞洲文字可在分層窗口上提供透明字符

[英]Drawing asian text with GDI+ gives transparent characters on a layered window

我有一個分層的窗口,可以使用WS_EX_LAYERED擴展樣式和UpdateLayeredWindow函數來創建自己。

然后,我使用GDI +庫Graphics :: DrawString方法在其中繪制一些文本。

結果是: 分層窗口的屏幕截圖

如您所見,日文,韓文和中文字符是完全透明的。 它們甚至使窗口的白色背景透明,而根本不透明。

僅當禁用“ 桌面合成” (Aero主題)時,才會在Windows Vista和Windows 7上出現此問題。
在Windows 10上它可以正常工作,因為始終在其中啟用了“桌面合成”。

為什么只有東亞字符會產生這種奇怪的效果?
以及如何解決?

我沒有要測試的Windows 7機器,所以我不知道alpha通道是否是真正的問題,但是假設它是真實的,您可以通過在編寫了Windows 7之后將alpha通道設置回正確的狀態來解決它。越野車文字:

enum { WIDTH = 255 * 3, HEIGHT = 25 };
#define CalcStride(w, bpp) ( ((((w) * (bpp)) + 31) & ~31) >> 3 )
#define PMC(c, a) ( (c) = ((int)(c) * (a) / 255) )
#define PM(q) PMC( (q).rgbRed, (q).rgbReserved), PMC( (q).rgbGreen, (q).rgbReserved), PMC( (q).rgbBlue, (q).rgbReserved)

RGBQUAD* GetPxPtr32(void*pBits, UINT x, UINT y)
{
    return ((RGBQUAD*) ( ((char*)pBits) + (y * CalcStride(WIDTH, 32)) )) + x;
}

void SaveAlpha32(void*pBits, BYTE*buf)
{
    for (UINT x = 0; x < WIDTH; ++x)
        for (UINT y = 0; y < HEIGHT; ++y)
            buf[(y * WIDTH) + x] = GetPxPtr32(pBits, x, y)->rgbReserved;
}

void RestoreAlpha32(void*pBits, const BYTE*buf)
{
    for (UINT x = 0; x < WIDTH; ++x)
        for (UINT y = 0; y < HEIGHT; ++y)
            GetPxPtr32(pBits, x, y)->rgbReserved = buf[(y * WIDTH) + x];
}

void Draw(HDC hDC, HBITMAP hBM, void*pBits, UINT w, UINT h, bool isDwmActive)
{
    // Fill with white and a silly gradient alpha channel:
    for (UINT y = 0; y < h; ++y)
        for (UINT x = 0; x < w; ++x)
            (*(UINT32*)GetPxPtr32(pBits, x, y)) = 0xffffffff, GetPxPtr32(pBits, x, y)->rgbReserved = max(42, x % 255);

    BYTE *alphas = isDwmActive ? 0 : (BYTE*) LocalAlloc(LPTR, sizeof(BYTE) * w * h), fillWithRed = true;
    if (!isDwmActive) SaveAlpha32(pBits, alphas);
    HGDIOBJ hBmOld = SelectObject(hDC, hBM);
    RECT r = { 0, 0, WIDTH, HEIGHT };
    int cbk = SetBkColor(hDC, RGB(255, 0, 0));
    if (fillWithRed) ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &r, NULL, 0, NULL);
    int ctx = SetTextColor(hDC, RGB(0, 0, 0));
    int mode = SetBkMode(hDC, TRANSPARENT);
    DrawText(hDC, TEXT("Hello World Hello World Hello World Hello World Hello World"), -1, &r, DT_SINGLELINE|DT_VCENTER|DT_CENTER); // Plain GDI always destroys the alpha
    SetBkMode(hDC, mode), SetBkColor(hDC, cbk), SetTextColor(hDC, ctx);
    SelectObject(hDC, hBmOld), GdiFlush();
    if (!isDwmActive) RestoreAlpha32(pBits, alphas), LocalFree(alphas);
    for (UINT y = 0; y < h; ++y) for (UINT x = 0; x < w; ++x) PM(*GetPxPtr32(pBits, x, y));
}

int main()
{
    const INT w = WIDTH, h = HEIGHT, bpp = 32, x = 222, y = 222;
    HWND hWnd = CreateWindowEx(WS_EX_LAYERED|WS_EX_TOPMOST, WC_STATIC, 0, WS_VISIBLE|WS_POPUP, x, y, WIDTH, HEIGHT, 0, 0, 0, 0);
    SetWindowLong(hWnd, GWLP_WNDPROC, (LONG_PTR) DefWindowProc); // HACK
    BITMAPINFO bi;
    ZeroMemory(&bi, sizeof(bi));
    BITMAPINFOHEADER&bih = bi.bmiHeader;
    bih.biSize = sizeof(BITMAPINFOHEADER);
    bih.biWidth = w, bih.biHeight = -h;
    bih.biPlanes = 1, bih.biBitCount = bpp;
    bih.biCompression = BI_RGB;
    void*bits;
    HBITMAP hBmp = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &bits, NULL, 0);
    HDC hDCScreen = GetDC(NULL), hDC = CreateCompatibleDC(hDCScreen);
    Draw(hDC, hBmp, bits, w, h, false);
    HGDIOBJ hBmOld = SelectObject(hDC, hBmp);
    BLENDFUNCTION blend = { 0 };
    blend.BlendOp = AC_SRC_OVER, blend.AlphaFormat = AC_SRC_ALPHA, blend.SourceConstantAlpha = 255;
    POINT location = { x, y }, srcpt = { 0, 0 };
    SIZE szWnd = { w, h };
    UpdateLayeredWindow(hWnd, hDCScreen, &location, &szWnd, hDC, &srcpt, 0, &blend, ULW_ALPHA);
    SelectObject(hDC, hBmOld), DeleteObject(hBmp);
    DeleteDC(hDC), ReleaseDC(NULL, hDCScreen);
    struct Closer { Closer(HWND h) { SetTimer(h, 1, 1000 * 11, TP); } static void CALLBACK TP(HWND h,UINT,UINT_PTR,DWORD) { ExitProcess(666); } } closer(hWnd); // HACK
    for (MSG msg; GetMessage(&msg, 0, 0, 0); ) DispatchMessage(&msg);
    return 666;
}

如果您不關心沒有平台更新的Vista,則可以嘗試使用Direct2D代替GDI +。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM