Iceman
Iceman

Reputation: 397

DrawText with outline using GDI (C++)

I'm using this code to sign a frame from webcam:

Font = CreateFont(18, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, VARIABLE_PITCH, "times");

...

HDC hDC = CreateCompatibleDC(NULL);
unsigned char * img = 0;
HBITMAP hBitmap = CreateDIBSection(hDC, &BMI, DIB_RGB_COLORS, (void**)&img, NULL, 0);
memcpy(img, CameraFrame.data, CameraFrame.size());
free(CameraFrame.data);
CameraFrame.data = img;
SelectObject(hDC, hBitmap);
SelectObject(hDC, Font);
SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, RGB(255,255,255));
string Text = "Test";
DrawTextA(hDC, Text.c_str(), Text.size(), &rect, DT_CENTER | DT_WORDBREAK);
DeleteDC(hDC);

Of course the color scale of frames will differ, and I need the text to be visible anyway.

How to DrawText with outline? For example, white text with black outline.

Upvotes: 2

Views: 4445

Answers (3)

Adam Gross
Adam Gross

Reputation: 56

Here is what I would recommend:

  1. Create a custom pen with a dashed style using CreatePen or ExtCreatePen with PS_DASH.
  2. DrawText using DT_CALCRECT and your desired styles to see where the text will actually go.
  3. SelectObject the HPEN from #1 into your HDC
  4. Use MoveToEx and LineTo to draw the 4 edges of your frame based on the rectangle retrieved in #2 (adding some padding as needed). Sample code here: https://msdn.microsoft.com/en-us/library/windows/desktop/dd145182(v=vs.85).aspx

Step 1 happens when initializing. Steps 2-4 happen each time you paint.

Upvotes: 0

Adrian McCarthy
Adrian McCarthy

Reputation: 48038

With GDI, you can use BeginPath, DrawText, EndPath, and then StrokeAndFillPath, as long as you're using an "outline" font (like TrueType or OpenType).

  ::BeginPath(ps.hdc);
  RECT rc;
  GetClientRect(&rc);
  ::DrawTextW(ps.hdc, L"Hello", 5, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
  ::EndPath(ps.hdc);
  ::StrokeAndFillPath(ps.hdc);

The StrokeAndFillPath will use the currently selected pen for the outline and the currently selected brush to fill it in. You can use TextOut or other GDI calls inside the BeginPath/EndPath.

You won't get any anti-aliasing like you'd have with regular text output, so it won't be as crisp as your regular ClearType text. At larger sizes, this isn't a big issue.

Upvotes: 2

James Poag
James Poag

Reputation: 2380

Two approaches:

  • Draw the Text in black, but scaled slightly larger by 2 pixels (good luck) and offset by (-1,-1) then normally in white in the center.

  • Draw the Text in black, but offset { (-1,-1), (1,1), (-1,1), (1,-1) } and then in white in the center.

Upvotes: 3

Related Questions