From: Robe on
Hi there,

How can I change the space between characters to the text we render using
GDI Plus DrawString() ??

I'm trying with the win32 API SetTextCharacterExtra() and I get the
following Exception when I try to use the Graphics object “Object is
currently in use elsewhere.”

Here's the declaration of the method:

[DllImport("Gdi32.dll")]
public static extern int SetTextCharacterExtra(int hdc, int nCharExtra);

Here's the way I use it

int a = SetTextCharacterExtra(formGraphics.GetHdc().ToInt32(), 8);

If there's a way to avoid SetTextCharacterExtra() will be much better.

Thank you in advance,

Robe.
From: Peter Duniho on
Robe wrote:
> Hi there,
>
> How can I change the space between characters to the text we render using
> GDI Plus DrawString() ??
>
> I'm trying with the win32 API SetTextCharacterExtra() and I get the
> following Exception when I try to use the Graphics object “Object is
> currently in use elsewhere.”

Well, is it in use elsewhere?

> Here's the declaration of the method:
>
> [DllImport("Gdi32.dll")]
> public static extern int SetTextCharacterExtra(int hdc, int nCharExtra);
>
> Here's the way I use it
>
> int a = SetTextCharacterExtra(formGraphics.GetHdc().ToInt32(), 8);
>
> If there's a way to avoid SetTextCharacterExtra() will be much better.

One approach would be to adjust the character position explicitly,
rendering each one yourself. You can use the
Graphics.MeasureCharacterRanges() method to obtain baseline position
information and then adjust that to suit your needs. Or just measure
each character individually with the TextRenderer class and calculate
exact positions yourself.

It may be useful to render into a off-screen bitmap when doing that, and
then draw the results all at once. There's a lot of performance
overhead to the above in any case, but doing one character at a time
straight to the screen could be prohibitively expensive.

IMHO, the big issue trying to get SetTextCharacterExtra() to work is
that it's an unmanaged function, with a specific assumption about the
underlying implementation of the managed type you're using (Graphics, in
this case). Given the documentation's description of the Graphics class
as an encapsulation of GDI+ functionality, that may well be a safe
assumption to make. But if you can avoid making it, that might be better.

Alternatively, you could code the entire text rendering component of
your code using the unmanaged API (either via p/invoke or writing a
C++/CLI module), so that your only dependency is in using an HDC, rather
than assuming specific ways that the managed classes use an HDC.

Pete
From: Mihai N. on

> One approach would be to adjust the character position explicitly,
> rendering each one yourself.

This can break a lot of things: ligatures, kerning, combining characters,
scripts that require complex shaping (most Indic scripts, Arabic),
right-to-left scripts (Arabic & Hebrew).

If all you need is Latin 1 with not ligatures, then this is an option.
But somehow I think that someone who cares to control the distance
between charactes I think will also care about proper ligatures or
kerning, which are useful even for Latin 1.


--
Mihai Nita [Microsoft MVP, Visual C++]
http://www.mihai-nita.net
------------------------------------------
Replace _year_ with _ to get the real email

From: Peter Duniho on
Mihai N. wrote:
>> One approach would be to adjust the character position explicitly,
>> rendering each one yourself.
>
> This can break a lot of things: ligatures, kerning, combining characters,
> scripts that require complex shaping (most Indic scripts, Arabic),
> right-to-left scripts (Arabic & Hebrew).
>
> If all you need is Latin 1 with not ligatures, then this is an option.
> But somehow I think that someone who cares to control the distance
> between charactes I think will also care about proper ligatures or
> kerning, which are useful even for Latin 1.

Possible. But we have no idea why the OP wants to control the distance
between characters. Frankly, kerning isn't an issue at all. By
definition, if you're messing with the distance, you're going to mess
with kerning necessarily. Combining characters also shouldn't be an
issue, because those should have zero-width spacing (i.e. if you're
moving each character a specific distance according to its current
distance from the origin of the rendering, it will move the same amount
as the character it's combining with...alternatively, it's easy enough
to detect those, if one wants to just increase the delta by a fixed
amount for each character).

The other issues you point out are valid, but may or may not be relevant
to the OP, and some are not hard to address in any case. It's good he
should know about them, but it doesn't mean that an explicit adjustment
is precluded. The fact is, the OP has taken as granted he's going to
change the distance between characters, and that's going to break a lot
of visuals related to the characters no matter what technique he uses.

Pete