winapi function for drawing isolated font characters - winapi

I'm working on a music notation program, and the musical symbols are provided in the form of a font. I'm using DrawTextW to render the symbols to the screen for now, but it doesn't seem very appropriate to use a function that takes a RECT parameter when I have to render the rectangle's size irrelevant by setting the background to transparent and setting the DT_NOCLIP option. Is there a way to draw a single font character that takes only an x and a y coordinate rather than a RECT?

Related

How to wrap text around images or abstract shapes in DirectWrite with Direct2D?

I couldn't find an example of a block of text not rendered to a rectangular area.
Ideally, it would be nice if ID2D1HwndRenderTarget.DrawText() would let me provide a polygon Geometry instead of a rectangle.
I've tried adding a Direct2D Layer with contentBounds, thinking it might skip rendering text within those layers. It didn't work as expected, it just blocked render to the area still emulating text underneath.
I've also tried applying a rectangular area to hwnd window itself. It too blocked render but didn't shift text.
IDWriteTextLayout only supports rectangular layouts, but DirectWrite supports any shape you can think of by using the lower level functions (text analysis, glyph measurement, glyph shaping). It's no easy task to write your own text layout from scratch, but I wrote a Windows 7 SDK sample containing a "FlowLayout" that demonstrates a circle and a few other simple shapes. It doesn't take arbitrary geometry, but you may be able to adapt it to your needs (see FlowLayoutSource::GetNextRect for computing the width of each line).
https://github.com/pauldotknopf/WindowsSDK7-Samples/tree/master/multimedia/DirectWrite/CustomLayout
DirectWrite only supports rectangular layouts, so you can't get anything more complicated automatically. You'll have to implement layout functionality yourself if you want it to work differently. Clipping arguments, like you already observed, have nothing to do with text layout.

DwmEnableBlurBehindWindow makes the entire client area transparent

Aero glass causes alot of people problems trying to draw on it. Anything with an alpha value of 255 seems to be treated as transparent with DWM using an additive blur to draw it. I want a part of client area to use Aero glass with the rest of it treated as opaque, so I don't have to deal with the headache of common controls not rendering properly.
MSDN lists a function DwmEnableBlurBehindWindow which lets you mark part of the client area as blurred by DWM. It takes a DWM_BLURBEHIND pointer which which has an HRGN handle to the region of the window. When I use this function, the entire window becomes transparent with an additive blend, but only the region of the window I passed to DwmEnableBlurBehindWindow gets blurred. Is there a way I can keep the rest of the window from becoming transparent?
What I have looks a bit like:
blur.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
blur.hRgnBlur = CreateRectRgn(0, 0, 90, 90);
blur.fEnable = true;
DwmEnableBlurBehindWindow(hwnd, &blur);
RECT rect;
GetClientArea(&rect);
FillRect(hdc, &rect, CreateSolidBrush(0));
From the MSDN Library article:
The alpha values in the window are honored and the rendering atop the blur will use these alpha values. It is the applications responsiblity for ensuring that the alpha values of all pixels in the window are correct. Some GDI operations do not perserve alpha values so care must be taken when presenting child windows as the alpha values they contribute are unpredicitable.
Make that most GDI operations, like FillRect(). The brush you created is drawn with 24-bit colors, the alpha will be 0. Which makes the window transparent. You'll need to switch to, say, GDI+. Text is particularly troublesome. As well as legacy Windows controls, like EDIT and LISTBOX which draw with GDI.

Using Win32 TextOut to draw text at an angle

I'm using GDI to draw text onto a device context, and I noticed that the kerning or character placement is different if the angle is exactly 0, 90, 180, or 270. As soon as I increase the angle by 1, the character placement differs noticeably.
Rather than creating an HFONT with the angle, I am using ModifyWorldTransform to transform the device context's world coordinates, and then I use TextOut to draw the text onto the device context.
I think that GDI is using font hints or some other special technique when the text is being drawn at exact multiples of 90 degrees, but not for any other angle.
Is there a way to disable this hinting, so that text rendered at 0 degrees does not differ significantly from text rendered at 1 degree?
Here's an example of what I mean (Monotype Corsiva font):
0 degrees:
1 degree:
For some fonts, such as Arial or Tahoma, it is not as noticeable, but I would like to get rid of the difference entirely, even if it means the text is not rendered as best it can.
I think this is due to anti-aliasing rather than font hints. You could try the following:
Disable (font) AA, but this will not yield acceptable results.
Create font handles for every possible angle and see if the problem persists. I assume it doesn't, but it's not a pretty solution.
Render the text to a bitmap (e.g. using CreateCompatibleBitmap() ) render the text to it and then render the rotated bitmap. This depends on how often you need different rotations / different text.
Play with fdwOutputPrecision and fdwQuality in CreateFont(). This could be the easiest solution, but you'd have to experiment a little bit I guess.
hth

How to get real text dimensions when ClearType is on?

I have a Win32 GUI application that uses GDI havily. It needs to draw text over a bitmap at specified coordinates and later erase it and substitute with the original bitmap.
I proceed as follows:
select font (GetStockObject( DEFAULT_GUI_FONT)), brush, other stuff into the device context
call GetTextExtentPoint32() to compute the size of the text
now having the text starting point I can compute the expected text rectangle and store it
call TextOut() for the same device context with the same starting point and the same text
and later restore the bitmap for the store rectangle.
It works fine when ClearType antialiasing is off. But with ClearType on the size returned by GetTextExtentPoint32() is slightly smaller than the size actually occupied by the text when TextOut() is called. So when I later restore the original bitmap some small stripes of the text remain in place and I have artifacts.
Is there any cure to this without disabling ClearType?
You could also try DrawText with DT_CALCRECT to compute the string size. Maybe it works better.
Also you can then write the string with DrawText inside a rectangle with the sizes equal to the one you get with DT_CALCRECT and it will clip the text in case it is a bit larger.

How to draw a selected text in win32 using only gdi call?

I tried to draw a selected text using two TextOut call and TA_UPDATECP flag but when I move the selected area, the characters are moving a bit.
Does someone know the correct way to do that ?
According to the MSDN documentation, when you have set the TA_UPDATECP flag using SetTextAlign(), TextOut() ignores its position parameters in favor of the device context's current position. Without seeing your code, I suspect that your drawing algorithm calls TextOut() with a current position that differs slightly based on the selection.
As a debugging strategy, you can call GetCurrentPositionEx() just before you call TextOut() to obtain the current position and make sure it matches your expectation for where the text should be drawn.
I believe that antialiasing and ClearType can draw text at fractional pixel positions. If you draw a string of text, and then try to redraw a portion of the middle, there might not be a way for you to draw text starting at exactly the same position as those characters in the middle. The trick seems to be to redraw the entire string, but with a clipping region for the selected text.
Chapter 4 in this tutorial on writing a Win32 text editor goes into quite some detail on how to draw selected text.

Resources