3

At first, I used drawString and GraphicsPath.AddString to draw outlined/solid text in the pictureBox. I can change it's font size, style and font-family but I realized that I won't be able to resized/stretch the text since the font size is proportionally distributed to the string. So the solution I was told was this:

I have been advised that in order to scale a Text (from a Draw String), I need to use a rectangle on which the text will depend on. In that way, I can resize the whole text (width, height, both). But I have no idea how to do it.

PS. If there are other ways, you can tell me. Thanks all.

Here's my TextDrawing Method:

public void DrawRects(Font f, string text, Graphics g, RectangleF rect)
    {
        List<RectangleF> list = new List<RectangleF>();
        using (StringFormat format = new StringFormat())
        {
            int i; 
            format.Alignment = StringAlignment.Near;
            format.LineAlignment = StringAlignment.Center;
            format.Trimming = StringTrimming.None;
            format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
            CharacterRange[] ranges = new CharacterRange[text.Length];
            for (i = 0; i < text.Length; i++)
            {
                ranges[i] = new CharacterRange(i, 1);
            }
            format.SetMeasurableCharacterRanges(ranges);
            Region[] regionArray = g.MeasureCharacterRanges(text, f, rect, format);
            for (i = 0; i < regionArray.Length; i++)
            {
                list.Add(regionArray[i].GetBounds(g));
            }
            foreach (RectangleF r in list)
            {
                //g.SmoothingMode = SmoothingMode.AntiAlias;
                //g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
                //g.InterpolationMode = InterpolationMode.High;
                g.DrawRectangle(Pens.LightBlue, Rectangle.Round(r));
            }
            using (GraphicsPath path = new GraphicsPath())
            {
                path.AddString(text, f.FontFamily, Convert.ToInt32(f.Style), g.DpiY * rect.Height/72f, rect.Location, format);
                RectangleF text_rectf = path.GetBounds();
                PointF[] target_pts = {
                        new PointF(rect.Left, rect.Top),
                        new PointF(rect.Right, rect.Top),
                        new PointF(rect.Left, rect.Bottom)};
                g.Transform = new Matrix(text_rectf, target_pts);

                g.FillPath(Brushes.Red, path);
                g.DrawPath(Pens.Red, path);
                g.ResetTransform();
            }
            //g.SmoothingMode = SmoothingMode.AntiAlias;
            //g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
            //g.InterpolationMode = InterpolationMode.High;
            //g.DrawString(text, f, Brushes.Red, rect, format);

        }
    }

And my UI for your reference:

enter image description here

Result I need:

enter image description here

Edit: I changed the code on my text drawing, what I still can't do is to create different rectangles on each letters that is able o be resized using trackbar.

TerribleDog
  • 1,237
  • 1
  • 8
  • 31
  • Some images showing what you expect the output to look like (at different sizes) would be appreciated. – mjwills Nov 05 '18 at 03:49
  • The first thing to note is that the `isOutlined` check does not produce any different result. It's the `(int)_fontStyle.Style` that determines the Font.Style. You could DRY up your code a bit. To stretch the string, you just need to add a transformation matrix or use `e.Graphics.TranslateTransform(scaleX, scaleY)`, where `scaleX` and `scaleY` are given by the relation between the text measure (Width, Height) and the container Rectangle (Width, Height). Nothing else. `Graphics.DrawString()` will scale/stretch the text accordingly. – Jimi Nov 05 '18 at 04:55
  • @Jimi the function for isOutlined booelan value is in another form (radio button event) – TerribleDog Nov 05 '18 at 05:08
  • I'll try @Jimi. – TerribleDog Nov 05 '18 at 05:09
  • @Jimi I think, I really need to create rectangle each letter, the small letter stretches at first unless a capital letter is typed. – TerribleDog Nov 05 '18 at 06:55
  • @Jimi when period [.] is typed, it stretches until another character is typed – TerribleDog Nov 05 '18 at 07:04
  • It stretches where? Did you measure the text width beforehand? You need to begin stretching the text when it's wider then the bounding rectangle. – Jimi Nov 05 '18 at 08:00
  • It stretches it's height. It adapts with the rectangle height that adapts to the string height. – TerribleDog Nov 05 '18 at 08:11
  • The same concept applies to the height. If the text height is lower than the Rectangle height, don't stretch it (don't apply the transformation). – Jimi Nov 05 '18 at 08:17
  • But the rectangle height depends on the character's height. – TerribleDog Nov 05 '18 at 08:42
  • Also, the picturebox shows an X when the textbox has no characters on it. – TerribleDog Nov 05 '18 at 08:51
  • Maybe we don't understand each other here. If the measure of the rectangle is given by the text measure, when do you stretch the text? On these conditions, never, since the text determines its own bounds. You might want to explain the situation more in depth, updating the question with details on what you want to achive, on which conditions on how this all operates. – Jimi Nov 05 '18 at 08:55
  • I'm sorry if we're not on the same page as of now. – TerribleDog Nov 05 '18 at 08:56
  • @Jimi I updated the question. – TerribleDog Nov 05 '18 at 08:57
  • @Jimi What I need to do is to scale the text drawn in the picturebox (Both, Width, and Height), and also other modifications as seen in my UI. – TerribleDog Nov 05 '18 at 09:01
  • Then you need to start from scale 0, which is given by the text.Size using a specific Font Size and Weight. That's your bounding rectangle. When you apply a scale, you apply it to this reference Rectangle. Measure the text, scale it in relation to the bounding rectangle, apply a transformation in any of the possible ways, then draw the text in the scaled Device context. If you modify the Font, re-measure the text, setting the bounding rectangle again, then re-apply the transformation, draw the text. It will scale as you set it to be. – Jimi Nov 05 '18 at 09:23
  • That's a long way, but I'll try to understand it. @Jimi – TerribleDog Nov 05 '18 at 09:32
  • @TerribleDog So you want to form a rectangle that can be dragged to resize.? – SH7 Nov 08 '18 at 04:52

1 Answers1

1

I had a go and I couldn't work out the rectangles relationship to the letters...

enter image description here


Never the less I propose a more elegant, time-tested and mathematically correct solution.

Alex Fr provided an excellent set of drawing tools in his DrawTools article and this project serves as a basis for Draw Tool Redux.

The original project by Alex Fr was based on a Microsoft C++ MFC sample project which developers may learn from DRAWCLI. The DrawTools C# program reproduces some of DRAWCLI functionality and uses some design decisions from this sample. These days the only way to see it is via WayBack machine link: https://web.archive.org/web/20120814082327/https://www.codeproject.com/Articles/8494/DrawTools

I'd recommend you swap drawing libraries and start off with a really well designed solution. The Draw Tool Redux has most of the functionality I see you need. With the exception of the Rotation Offset which I believe I've seen an example of in Rod Stephens book, here it is on WayBack Machine again: Interactively rotate images by an arbitrary angle in C#.

Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
  • 1
    No worries, I've used this in a commercial solution - it even comes with Undo/Redo.. https://stackoverflow.com/questions/17182062/trouble-getting-system-drawing-graphics-to-work-in-form – Jeremy Thompson Nov 12 '18 at 03:13
  • 1
    Issue with the rotation offset article by Rod Stephens, again I had to use the WayBack Machine to see it: https://web.archive.org/web/20150302104614/http://csharphelper.com/blog/2015/02/interactively-rotate-images-by-an-arbitrary-angle-in-c/ – Jeremy Thompson Nov 12 '18 at 03:25