gpt4 book ai didi

winapi - UpdateLayeredWindow 和 DrawText

转载 作者:行者123 更新时间:2023-12-02 23:18:37 24 4
gpt4 key购买 nike

我正在使用 UpdateLayeredWindow 来显示应用程序窗口。我已经创建了自己的自定义按钮,并且想创建自己的静态文本。问题是,当我尝试在 hdc 上绘制文本时,DrawText 或 TextOut 函数会覆盖图片的 Alpha channel ,文本将变得透明。我试图找到解决方案,但找不到任何解决方案。我的自定义控件的设计方式是,它们将在名为 Draw(HDC hDc) 的成员函数中完成所有绘图,因此它们只能访问 hdc。我想保留这个设计。谁能帮我?我正在使用 MFC,并且希望在不使用 GDI+ 的情况下获得所需的结果。

最佳答案

我知道这是一篇旧帖子...但我也遇到了同样的问题...这让我发疯。

最终,我偶然发现了这个post作者:Mike Sutton 在 microsoft.public.win32.programmer.gdi 新闻组...大约 7 年前!

基本上,DrawText(和 TextOut)与 Alpha channel 和 UpdateLayeredWindow 不能很好地配合...并且您需要将 R、G 和 B channel 与 Alpha channel 预乘

在 Mike 的帖子中,他展示了如何创建另一个 DIB(与设备无关的位图),并在其上绘制文本……并将其进行 Alpha 混合到另一个位图中。

完成此操作后,我的文本看起来很完美!

以防万一,新闻组帖子的链接失效了……我将在此处包含代码。所有功劳均归功于 Mike Sutton (@mikedsutton)。

下面是创建带有文本的 Alpha 混合位图的代码:

HBITMAP CreateAlphaTextBitmap(LPCSTR inText, HFONT inFont, COLORREF inColour)
{
int TextLength = (int)strlen(inText);
if (TextLength <= 0) return NULL;

// Create DC and select font into it
HDC hTextDC = CreateCompatibleDC(NULL);
HFONT hOldFont = (HFONT)SelectObject(hTextDC, inFont);
HBITMAP hMyDIB = NULL;

// Get text area
RECT TextArea = {0, 0, 0, 0};
DrawText(hTextDC, inText, TextLength, &TextArea, DT_CALCRECT);
if ((TextArea.right > TextArea.left) && (TextArea.bottom > TextArea.top))
{
BITMAPINFOHEADER BMIH;
memset(&BMIH, 0x0, sizeof(BITMAPINFOHEADER));
void *pvBits = NULL;

// Specify DIB setup
BMIH.biSize = sizeof(BMIH);
BMIH.biWidth = TextArea.right - TextArea.left;
BMIH.biHeight = TextArea.bottom - TextArea.top;
BMIH.biPlanes = 1;
BMIH.biBitCount = 32;
BMIH.biCompression = BI_RGB;

// Create and select DIB into DC
hMyDIB = CreateDIBSection(hTextDC, (LPBITMAPINFO)&BMIH, 0, (LPVOID*)&pvBits, NULL, 0);
HBITMAP hOldBMP = (HBITMAP)SelectObject(hTextDC, hMyDIB);
if (hOldBMP != NULL)
{
// Set up DC properties
SetTextColor(hTextDC, 0x00FFFFFF);
SetBkColor(hTextDC, 0x00000000);
SetBkMode(hTextDC, OPAQUE);

// Draw text to buffer
DrawText(hTextDC, inText, TextLength, &TextArea, DT_NOCLIP);
BYTE* DataPtr = (BYTE*)pvBits;
BYTE FillR = GetRValue(inColour);
BYTE FillG = GetGValue(inColour);
BYTE FillB = GetBValue(inColour);
BYTE ThisA;
for (int LoopY = 0; LoopY < BMIH.biHeight; LoopY++) {
for (int LoopX = 0; LoopX < BMIH.biWidth; LoopX++) {
ThisA = *DataPtr; // Move alpha and pre-multiply with RGB
*DataPtr++ = (FillB * ThisA) >> 8;
*DataPtr++ = (FillG * ThisA) >> 8;
*DataPtr++ = (FillR * ThisA) >> 8;
*DataPtr++ = ThisA; // Set Alpha
}
}

// De-select bitmap
SelectObject(hTextDC, hOldBMP);
}
}

// De-select font and destroy temp DC
SelectObject(hTextDC, hOldFont);
DeleteDC(hTextDC);

// Return DIBSection
return hMyDIB;
}

以下是驱动 CreateAlphaTextBitmap 方法的代码:

void TestAlphaText(HDC inDC, int inX, int inY)
{
const char *DemoText = "Hello World!\0";
RECT TextArea = {0, 0, 0, 0};
HFONT TempFont = CreateFont(50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Arial\0");
HBITMAP MyBMP = CreateAlphaTextBitmap(DemoText, TempFont, 0xFF);
DeleteObject(TempFont);
if (MyBMP)
{
// Create temporary DC and select new Bitmap into it
HDC hTempDC = CreateCompatibleDC(inDC);
HBITMAP hOldBMP = (HBITMAP)SelectObject(hTempDC, MyBMP);
if (hOldBMP)
{
// Get Bitmap image size
BITMAP BMInf;
GetObject(MyBMP, sizeof(BITMAP), &BMInf);

// Fill blend function and blend new text to window
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 0x80;
bf.AlphaFormat = AC_SRC_ALPHA;
AlphaBlend(inDC, inX, inY, BMInf.bmWidth, BMInf.bmHeight, hTempDC, 0, 0, BMInf.bmWidth, BMInf.bmHeight, bf);

// Clean up
SelectObject(hTempDC, hOldBMP);
DeleteObject(MyBMP);
DeleteDC(hTempDC);
}
}
}

关于winapi - UpdateLayeredWindow 和 DrawText,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5309914/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com