Reputation: 2275
I attached a project which shows a problem with DrawText()
not outputting the correct color via SetTextColor()
.
Note that if you don't include the manifest for themes, it works.
So the question is, with theming enabled, how do you set your own color for DrawText()
.
Download the project I threw together from here for the "minimal reproducible sample" (as the x64 version).
The bitmap has "TEXT" added to it but it's not red text (unless themes are disabled), it's the background color.
This is the main routine which was already listed but they wanted a reproducible example, so I provided one, then apparently it's too much, so here's the main routine again from the reproducible project:
void AddTextToBitmap(HBITMAP hbitmap)
{
HICON iconnew=NULL;
// buffer for text
TCHAR textbuffer[32];
textbuffer[_countof(textbuffer)-1]=0;
_tcsncpy(textbuffer, _T("TEST"), _countof(textbuffer)-1);
BITMAP bm;
if (GetObject(hbitmap, sizeof(bm), &bm)==sizeof(bm)) {
// get dc to where the icon will go
HDC hdc=GetDC(NULL);
if (hdc) {
// create a DC to modify our bitmap
HDC hmemdc=CreateCompatibleDC(hdc);
if (hmemdc!=NULL) {
// apply the icon bitmap to the dc we created
HGDIOBJ orgmemdcbitmap=SelectObject(hmemdc, hbitmap);
if (orgmemdcbitmap!=NULL) {
// set our white color
SetTextColor(hmemdc, RGB(255, 0, 0)); // RGB(255, 255, 255));
// make text background transparent when writing text
SetBkMode(hmemdc, TRANSPARENT);
// setup rect of dc area for drawing text
RECT rect;
rect.bottom=bm.bmHeight-1;
rect.right=bm.bmWidth-1;
rect.top=2;
rect.left=2;
// draw the text to bar on our icon
DrawText(hmemdc, textbuffer, -1, &rect, DT_TOP|DT_CENTER);
// release our icon bitmap and put back the original bitmap
SelectObject(hmemdc, orgmemdcbitmap);
}
// delete the dc we created
DeleteDC(hmemdc);
}
// release the dc we acquired
ReleaseDC(NULL, hdc);
}
}
}
Again: If you don't enable visual themes it works (red text), if you do (via manifest) it doesn't (text is background color).
Here's the manifest to enable themes for x64 - input file of project manifest option (see the full download project linked above):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="amd64"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
In the test app, I tried setting SetThemeAppProperties(0);
at the top if InitInstance()
(before creating class/window) but that didn't change anything. It's all dependent on the manifest being used or not. When the manifest is not used, you get the red text, also the 32bit graphic has black background area instead of transparent. I think the text is also actually transparent. This gives me an idea that maybe DrawText()
is drawing with the alpha being transparent (0).
The Answer
Not sure why this can't be answered but the issue is related to enabling themes via the manifest which enables support for alpha channel in 32 bit graphics. When DrawText()
draws, it sets the alpha channel to zero (transparent).
To work around it, you can check for themes enabled and 32bit graphic and use a unique oddball color with DrawText()
then use a separate routine to set the actual color and transparency desired. Here's an example of such routine.
void FixDrawTextColor(HBITMAP hbitmap, COLORREF searchcolor, COLORREF desiredcolor, BYTE desiredalpha)
{
BITMAP bm;
if (GetObject(hbitmap, sizeof(bm), &bm)==sizeof(bm)) {
// scan though bits to check
if (bm.bmBitsPixel==32 && bm.bmBits) {
// look for colors to make opaque
for (int y=0; y<bm.bmHeight; ++y) {
BYTE* ppixel=(BYTE*) bm.bmBits + (bm.bmWidthBytes * y);
for (int x=0; x<bm.bmWidth; x++) {
// check if search color that is transparent
if (ppixel[3]==0 && ppixel[0]==GetBValue(searchcolor) && ppixel[1]==GetGValue(searchcolor) && ppixel[2]==GetRValue(searchcolor)) {
// set new color
ppixel[0]=GetBValue(desiredcolor);
ppixel[1]=GetGValue(desiredcolor);
ppixel[2]=GetRValue(desiredcolor);
ppixel[3]=desiredalpha;
}
ppixel+=4;
}
}
}
}
}
Upvotes: -2
Views: 93