Can't select HBRUSH into device context
-
Hello, Stuck on a Microsoft drawing problem: The brush I'm using to draw text is being ignored, and SelectObject () returns NULL when I try to select it into a device context:
HFONT hFont = CreateFontIndirect(& logFont); HFONT oldFont = (HFONT) SelectObject (hDc, hFont); HBRUSH oldBrush = (HBRUSH) SelectObject (hDc, hbrush); TextOut (hDc, 0, 0, fontName, wcslen (fontName));
The brush comes from the nativeBrush member of a .NET System.Drawing.Brush, which works correctly both before and after this. I've tried using DrawText () instead, with the same result. Can anyone point out what I'm doing wrong? Thanks!
"Microsoft -- Adding unnecessary complexity to your work since 1987!"
-
Hello, Stuck on a Microsoft drawing problem: The brush I'm using to draw text is being ignored, and SelectObject () returns NULL when I try to select it into a device context:
HFONT hFont = CreateFontIndirect(& logFont); HFONT oldFont = (HFONT) SelectObject (hDc, hFont); HBRUSH oldBrush = (HBRUSH) SelectObject (hDc, hbrush); TextOut (hDc, 0, 0, fontName, wcslen (fontName));
The brush comes from the nativeBrush member of a .NET System.Drawing.Brush, which works correctly both before and after this. I've tried using DrawText () instead, with the same result. Can anyone point out what I'm doing wrong? Thanks!
"Microsoft -- Adding unnecessary complexity to your work since 1987!"
Brushes are used to fill the interior of filled shapes. They are not used to draw text.
TextOut()
andDrawText()
use the text and background colors currently selected by the device context. These can be set usingSetTextColor()
andSetBkColor()
.SelectObject()
returns the object that is going to be replaced. This may beNULL
if there is actually no such object selected into the device context. It is not an error condition. The return value is usally used to restore the old state after drawing has been done. -
Brushes are used to fill the interior of filled shapes. They are not used to draw text.
TextOut()
andDrawText()
use the text and background colors currently selected by the device context. These can be set usingSetTextColor()
andSetBkColor()
.SelectObject()
returns the object that is going to be replaced. This may beNULL
if there is actually no such object selected into the device context. It is not an error condition. The return value is usally used to restore the old state after drawing has been done.Hmm... I'm using the same brush to draw text in the .NET half of the application. These are complex patterns (linear gradient and hatch brushes), and the text correctly appears with these textures in GDI+/.NET. I'm using GDI (no plus) in this part because GDI+ doesn't support OpenType or PostScript fonts (only TrueType). So how can these patterns be used in text under GDI?
"Microsoft -- Adding unnecessary complexity to your work since 1987!"
-
Hmm... I'm using the same brush to draw text in the .NET half of the application. These are complex patterns (linear gradient and hatch brushes), and the text correctly appears with these textures in GDI+/.NET. I'm using GDI (no plus) in this part because GDI+ doesn't support OpenType or PostScript fonts (only TrueType). So how can these patterns be used in text under GDI?
"Microsoft -- Adding unnecessary complexity to your work since 1987!"
I'm sorry, I don't think that there is a solution with GDI.
-
I'm sorry, I don't think that there is a solution with GDI.
Thanks for the input!
"Microsoft -- Adding unnecessary complexity to your work since 1987!"
-
Hello, Stuck on a Microsoft drawing problem: The brush I'm using to draw text is being ignored, and SelectObject () returns NULL when I try to select it into a device context:
HFONT hFont = CreateFontIndirect(& logFont); HFONT oldFont = (HFONT) SelectObject (hDc, hFont); HBRUSH oldBrush = (HBRUSH) SelectObject (hDc, hbrush); TextOut (hDc, 0, 0, fontName, wcslen (fontName));
The brush comes from the nativeBrush member of a .NET System.Drawing.Brush, which works correctly both before and after this. I've tried using DrawText () instead, with the same result. Can anyone point out what I'm doing wrong? Thanks!
"Microsoft -- Adding unnecessary complexity to your work since 1987!"
Yeah, it shouldn't be a problem to do what you're asking for. You need to make use of _both_ TextOut and Paths. Basically, the process goes like this (sorry code is in a PDF ebook that prevents copy and paste) 1. Create your font 2. Select it into your hdc 3. Call BeginPath(hdc) 4. Call TextOut 5. Call EndPath 6. Use StrokePath for the outline, FillPath for the interior. 7. Select the old font back into the hdc 8. delete your font from #1 Ah! found a CHM version of the same book. Here's the code given there: (I'll leave it as, unedited, for completeness)
void PaintRoutine (HWND hwnd, HDC hdc, int cxArea, int cyArea)
{
static TCHAR szString [] = TEXT ("Filling") ;
HFONT hFont ;
SIZE size ;hFont = EzCreateFont (hdc, TEXT ("Times New Roman"), 1440, 0, 0, TRUE) ; SelectObject (hdc, hFont) ; SetBkMode (hdc, TRANSPARENT) ; GetTextExtentPoint32 (hdc, szString, lstrlen (szString), &size) ; BeginPath (hdc) ; TextOut (hdc, (cxArea - size.cx) / 2, (cyArea - size.cy) / 2, szString, lstrlen (szString)) ; EndPath (hdc) ; SelectObject (hdc, CreateHatchBrush (HS\_DIAGCROSS, RGB (255, 0, 0))) ; SetBkColor (hdc, RGB (0, 0, 255)) ; SetBkMode (hdc, OPAQUE) ; StrokeAndFillPath (hdc) ; DeleteObject (SelectObject (hdc, GetStockObject (WHITE\_BRUSH))) ; SelectObject (hdc, GetStockObject (SYSTEM\_FONT)) ; DeleteObject (hFont) ;
}
Make it work. Then do it better - Andrei Straut
-
Yeah, it shouldn't be a problem to do what you're asking for. You need to make use of _both_ TextOut and Paths. Basically, the process goes like this (sorry code is in a PDF ebook that prevents copy and paste) 1. Create your font 2. Select it into your hdc 3. Call BeginPath(hdc) 4. Call TextOut 5. Call EndPath 6. Use StrokePath for the outline, FillPath for the interior. 7. Select the old font back into the hdc 8. delete your font from #1 Ah! found a CHM version of the same book. Here's the code given there: (I'll leave it as, unedited, for completeness)
void PaintRoutine (HWND hwnd, HDC hdc, int cxArea, int cyArea)
{
static TCHAR szString [] = TEXT ("Filling") ;
HFONT hFont ;
SIZE size ;hFont = EzCreateFont (hdc, TEXT ("Times New Roman"), 1440, 0, 0, TRUE) ; SelectObject (hdc, hFont) ; SetBkMode (hdc, TRANSPARENT) ; GetTextExtentPoint32 (hdc, szString, lstrlen (szString), &size) ; BeginPath (hdc) ; TextOut (hdc, (cxArea - size.cx) / 2, (cyArea - size.cy) / 2, szString, lstrlen (szString)) ; EndPath (hdc) ; SelectObject (hdc, CreateHatchBrush (HS\_DIAGCROSS, RGB (255, 0, 0))) ; SetBkColor (hdc, RGB (0, 0, 255)) ; SetBkMode (hdc, OPAQUE) ; StrokeAndFillPath (hdc) ; DeleteObject (SelectObject (hdc, GetStockObject (WHITE\_BRUSH))) ; SelectObject (hdc, GetStockObject (SYSTEM\_FONT)) ; DeleteObject (hFont) ;
}
Make it work. Then do it better - Andrei Straut
Wow, that's some fancy coding! People elsewhere are saying it's impossible. Thanks enhzflep!
"Microsoft -- Adding unnecessary complexity to your work since 1987!"
-
Wow, that's some fancy coding! People elsewhere are saying it's impossible. Thanks enhzflep!
"Microsoft -- Adding unnecessary complexity to your work since 1987!"
-
You're welcome :) Yeah, Charles Pretzold always was a smart cookie. I'm so glad that I remembered having read a section in his books about the topic.
Make it work. Then do it better - Andrei Straut
Hi enhzflep, I incorporated code from your example into my function, and it works with the CreateHatchBrush call to create a new brush. Unfortunately, when I substitute my already-created brush, it doesn't work; I just get solid white filling the text outlines. I've verified the brush handle is the same as the nativeBrush member of my .NET Brush, which draws correctly both before and after. Can you see anything I'm doing wrong?
DLLEXPORT void drawWithGdiFont (HBITMAP hBitmap, HBRUSH hbrush, LPCWSTR fontName,
LPCWSTR text, int sizeToUse, bool bold, bool italic, int br, int bg, int bb)
{
HDC hDc = CreateCompatibleDC (NULL);
HGDIOBJ oldObj = SelectObject (hDc, hBitmap);
SIZE size ;LOGFONT logFont; ::ZeroMemory(& logFont, sizeof(LOGFONT)); wcscpy ((&logFont)->lfFaceName, fontName); logFont.lfHeight = sizeToUse; if (bold) logFont.lfWeight = 800; else logFont.lfWeight = 500; logFont.lfItalic = italic; HFONT hFont = CreateFontIndirect(& logFont); HFONT oldFont = (HFONT) SelectObject (hDc, hFont); SetBkMode (hDc, TRANSPARENT) ; BeginPath (hDc) ; TextOut (hDc, 0, 0, fontName, wcslen (fontName)); EndPath (hDc) ;
**// MY BRUSH FROM .NET (DOESN'T WORK):
HBRUSH oldBrush = (HBRUSH) SelectObject (hDc, hbrush);// FROM EXAMPLE (WORKS): HBRUSH oldBrush = (HBRUSH) SelectObject (hDc, CreateHatchBrush (HS_DIAGCROSS, RGB (255, 0, 0))) ;**
SetBkColor (hDc, RGB (br, bg, bb)); SetBkMode (hDc, OPAQUE) ; StrokeAndFillPath (hDc) ; DeleteObject (SelectObject (hDc, oldFont)); SelectObject (hDc, oldBrush); DeleteObject (hDc);
}
Also, it seems like the background color here is the second color of the hatch pattern. But how do I set the color between the letters (which is also called the "background color"?) Thanks! Alan
"Microsoft -- Adding unnecessary complexity to your work since 1987!"