GDI+ DrawString with \n new lines

It appears the \n character is treated as a space when drawing text instead of
applying a Y shift. Is there any way around this? I would hate to have to do
separate DrawString calls every time I use a new line in a single character
buffer. In addition, I notice the length parameter of the DrawString call is
not respected. It seems to render the entire string till null termination no
matter what I put in the length parameter. This hinders applications where I
want to use custom spacing between each character.

I know it may sound stupid but did you try \r\n?

No joy. Just a double space

@EPellissier any ideas?

I don’t think DrawString has ever supported hard-coded line breaks. You might
be able to fake it by adding enough spaces where you want the newline so it
wraps, but that’s a bit of a hack (and might not work). I think multiple calls
are probably the safest way.

If you mean DrawString in MSFS yeah I can see this bug slipping through,
although if you mean DrawString in GDI+ in native C++ environment I know that
is not the case as this is display code I ported from a P3D project. And wrap
isn’t working either. So I would like Asobo to look deeper at fixing this
(it’s not hard to do, my own proprietary DX based 2D graphics engine that I
use in P3D does it nicely).

You can use nvgTextBox instead of DrawString. I know, it’s not \n but you can
define a “breakRowWidth” and use this to create a multi-line text output. MSFS
GDI+ and nanovg can be used concurrently without any problems.

Thanks. I would hope Asobo fixes this though as it is far more convenient from
a programming perspective to simply use \n for newlines in strings.

@HansHartmann last I tried to load fonts
things didn’t go all that well. Can you show an example of loading fonts and
combining GDI+ and nvg?

I don’t see a problem with fonts. However, I recommend to load fonts first and
only start drawing after the NVG_FONT.face_id change from -1 to something
useful. In the following example, I skip the draw function until
fontsInitialized is true.

      1. if (!fontsInitialized)
  2. {
  3. if (this->nvgctx == nullptr)
  4. return;
  6. this->fonts[0] = NVG_FONT(this->nvgctx, "ARIAL", "./SimObjects/Airplanes/Common/fonts/arial.ttf", 36.0f);
  7. this->fonts[1] = NVG_FONT(this->nvgctx, "ARIAL", "./SimObjects/Airplanes/Common/fonts/arial.ttf", 42.0f);
  8. this->fonts[2] = NVG_FONT(this->nvgctx, "ARIAL", "./SimObjects/Airplanes/Common/fonts/arial.ttf", 32.0f);
  10. for (auto & font : this->fonts)
  11. {
  12. if (font.faceId == -1)
  13. fontsInitialized = false;
  14. }
  16. fontsInitialized = true;
  17. }

Hope this helps.

Perfect. Thanks. Next question, can nvgBeginFrame/EndFrame be called from
inside the Graphics::StartFrame block? Or must they be kept separate?