问题是这样的,使用gdi绘制带文本的窗口,在win7和win8下显示的时候有时候文本会变成透明的,显示的时候会穿透过去,显示出后面的背景颜色。
具体现象如下图所示:
先说一下原因吧,在绘制文字的时候,在win7和win8下颜色不支持Alpha通道,导致绘制的文字的透明度,变成一个随机值,不一定是255,这就导致在有些情况下透明度可能变成0导致文字显示变成透明。
针对问题的解决方案是遍历绘制文本的每个像素点,然后将透明度修改为255,修改的代码示例如下所示:
#include <win_version.h>
//创建位图的时候拿到位图的数据指针
//然后依据数据指针取进行像素处理
BYTE* createBitmap(HBITMAP &bitmap, int width, int height)
{
BYTE * pDIBBits = nullptr;
BITMAPINFO bitmapInfo = { 0 };
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = width;
bitmapInfo.bmiHeader.biHeight = height;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = 0;
bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
bitmapInfo.bmiHeader.biClrUsed = 0;
bitmapInfo.bmiHeader.biClrImportant = 0;
bitmap = CreateDIBSection(nullptr, &bitmapInfo,
DIB_RGB_COLORS, (VOID**)&pDIBBits, nullptr, 0);
return pDIBBits;
}
//将对应像素点的透明度修改为255
void modify_alpha_value(BYTE* bitmap_bits,Rect vision_rect){
WinVer winver;
if (!winver.IsWin10())
{ //win10不需要做透明度修正
struct RGBALPHA
{
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbAlpha;
};
auot get_rgb_alpha= [&](int pos_x,int pos_y)->RGBALPHA*{
return (RGBALPHA*)bitmap_bits+ (pos_y) * vision_rect.Width + (pos_x)
};
for (size_t y = vision_rect.Y; y < (vision_rect.Y + vision_rect.Height); y++)
{
for (size_t x = vision_rect.X; x < (vision_rect.X + vision_rect.Width); x++)
{
if (bitmap_bits != nullptr)
{
RGBALPHA *ppxl = get_rgb_alpha(x, y);
if (ppxl->rgbAlpha != 255)
ppxl->rgbAlpha = 255;
}
}
}
}
}
void onPaint()
{
//创建200*200的位图
BITMAP bitmap;
BYTE* bit_info = createBitmap(bitmap, 200,200);
......//进行对应的绘制操作
Rect update_rect; //需要刷线显示透明字的文字区域
modify_alpha_value(bit_info,update_rect);
}
文字变透明这个问题,跟平台相关,并且还是在特殊场景下触发,比较诡异,很难发现,建议在win7/win8下进行gdi文字绘制的时候,都对文字透明度进行修正,这样就能规避这个问题了。希望有帮助。