简体   繁体   English

使用GemBox.Document在所有方向绘制ShapeType.Line对象

[英]Draw ShapeType.Line objects in all directions with GemBox.Document

High Level Business Need: 高级业务需求:

1.) Grab input from user in order to create object data for constructing lines, rectangles, text and fields . 1.)抓取用户输入,以创建用于构造线条,矩形, textfields对象数据。

2.) Using input from user create doc templates via GemBox.Document (currently stuck here for lines) 3.) Ingest work object merge data to doc template (s) to populate fields, save as image. 2.)使用用户通过GemBox.Document创建的doc模板的input (当前在此处停留GemBox.Document )3.)将工作对象合并数据摄取到doc template以填充字段,另存为图像。

I believe i should be able to figure out #2 for rectangles and text as the way the objects are constructed are similar to how Shape works for GemBox.Document . 我相信我应该能够找出矩形和文本的#2,因为对象的构造方式类似于Shape对GemBox.Document工作GemBox.Document However, the object for Line is not the same, providing point1 and length/width, not point1 and point2 . 但是,Line的对象不同,提供的是point1和length / width,而不是point1point2

I'm categorizing 3 types of lines... 我正在对3种类型的线进行分类...

1.) Flat 2.) Positive Pitch 3.) Negative Pitch 1.)扁平2.)正螺距3.)负螺距

... I've been able to figure out flat (no horizontal or vertical delta) and positive pitch (line from top left to bottom right or its mirror bottom right to top left) but have been unable to figure out a negative pitch (line from top right to bottom left or its mirror bottom left to top right). ...我已经能够算出平坦的(没有水平或垂直的变化量)和正的螺距(从左上角到右下角的线,或者从镜子的右下角到左上角的线),但是却无法找出负的螺距(从右上角到左下角的直线或它的镜像左下角到右上角)

The Shape object will not allow a negative length or negative with attribute to have it draw the way i want. Shape对象将不允许负长度或具有负值的属性,使其以我想要的方式绘制。 I couldn't see / figure out if there was a way to mutate the line object via a rotation/flip etc. 我看不到/想不知道是否有一种方法可以通过旋转/翻转等方式改变线对象。

I'm open to different approaches but i have been told that i do have to use GemBox.Document 我对各种方法GemBox.Document开放态度,但有人告诉我必须使用GemBox.Document

namespace GemBoxDocument_LineDemo
{
    using System;
    using MyModels;
    using GemBox.Document;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using GemBox.Document.Drawing;
    using System.IO;
    using System.Reflection;

    public class Program
    {
        //inputs come from a GUI window, we're working with stub/coupon/partial-page/rectangle where w > h
        private const float GUIWIDTH = 425;
        private const float GUIHEIGHT = 200;

        public static void Main(string[] args)
        {
            ComponentInfo.SetLicense("FREE-LIMITED-KEY");

            var gemDoc = new DocumentModel();

            var firstSection = new Section(gemDoc);
            gemDoc.Sections.Add(firstSection);

            var firstParagraph = new Paragraph(gemDoc);
            firstSection.Blocks.Add(firstParagraph);

            var workableWidth = firstSection.PageSetup.PageWidth - (firstSection.PageSetup.PageMargins.Left + firstSection.PageSetup.PageMargins.Right);
            //i think this needs to be -something, or * % of total page since we're partial page
            var workableHeight = firstSection.PageSetup.PageHeight - (firstSection.PageSetup.PageMargins.Top + firstSection.PageSetup.PageMargins.Bottom);

            var widthMultiplier = workableWidth / GUIWIDTH;
            //for now this has been working just fine...
            var heightMultiplier = widthMultiplier;

            //offset of 0 is whole available workable width from GUI, simulating the offset at 50 for instance will show dynamic input shrinks towards center as this increases
            //don't change it too high as it'd create dynamic negative input which isn't possible fron an input perspective. (negative width and/or height)
            var offset = 0;

            var flatOnHorizontalTOPLine = new TemplateItem()
            {
                X = 0 + offset,
                Y = 0 + offset,
                X2 = GUIWIDTH - offset,
                Y2 = 0 + offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Black, 1),
                TemplateItemType = TemplateItemType.Line
            };

            var flatOnHorizontalBOTTOMLine = new TemplateItem()
            {
                X = 0 + offset,
                Y = GUIHEIGHT - offset,
                X2 = GUIWIDTH - offset,
                Y2 = GUIHEIGHT - offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Black, 1),
                TemplateItemType = TemplateItemType.Line
            };

            var flatOnVerticalLEFTLine = new TemplateItem()
            {
                X = 0 + offset,
                Y = 0 + offset,
                X2 = 0 + offset,
                Y2 = GUIHEIGHT - offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Black, 1),
                TemplateItemType = TemplateItemType.Line
            };

            var flatOnVerticalRIGHTLine = new TemplateItem()
            {
                X = GUIWIDTH - offset,
                Y = 0 + offset,
                X2 = GUIWIDTH - offset,
                Y2 = GUIHEIGHT - offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Black, 1),
                TemplateItemType = TemplateItemType.Line
            };

            var positivePitchPoint1LessThanPoint2 = new TemplateItem()
            {
                X = 0 + offset,
                Y = 0 + offset,
                X2 = GUIWIDTH - offset,
                Y2 = GUIHEIGHT - offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Black, 1),
                TemplateItemType = TemplateItemType.Line
            };

            var positivePitchPoint1GreaterThanPoint2 = new TemplateItem()
            {
                X = 0 + offset,
                Y = 0 + offset,
                X2 = GUIWIDTH - offset,
                Y2 = GUIHEIGHT - offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Blue, 1),
                TemplateItemType = TemplateItemType.Line
            };

            //else if (templateItem.X < templateItem.X2 && templateItem.Y > templateItem.Y2)//negative pitch, point 1 below/ToLeft point 2
            var negativePitchPoint1BelowAndToLeftOfPoint2 = new TemplateItem()
            {
                X = 0 + offset,
                Y = GUIHEIGHT - offset,
                X2 = GUIWIDTH - offset,
                Y2 = 0 + offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Red, 1),
                TemplateItemType = TemplateItemType.Line
            };

            //else if (templateItem.X > templateItem.X2 && templateItem.Y < templateItem.Y2)//negative pitch, point 1 above/ToRight point 2
            var negativePitchPoint1AboveAndToRightOfPoint2 = new TemplateItem()
            {
                X = GUIWIDTH - offset,
                Y = 0 + offset,
                X2 = 0 + offset,
                Y2 = GUIHEIGHT - offset,
                Pen = new System.Drawing.Pen(System.Drawing.Color.Green, 1),
                TemplateItemType = TemplateItemType.Line
            };

            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, flatOnHorizontalTOPLine, heightMultiplier, widthMultiplier));
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, flatOnHorizontalBOTTOMLine, heightMultiplier, widthMultiplier));
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, flatOnVerticalLEFTLine, heightMultiplier, widthMultiplier));
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, flatOnVerticalRIGHTLine, heightMultiplier, widthMultiplier));
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, positivePitchPoint1LessThanPoint2, heightMultiplier, widthMultiplier));
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, positivePitchPoint1GreaterThanPoint2, heightMultiplier, widthMultiplier));

            //cannot figure out these two 'negative pitch' instances...
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, negativePitchPoint1BelowAndToLeftOfPoint2, heightMultiplier, widthMultiplier));
            firstParagraph.Inlines.Add(GetGemboxLineShape(gemDoc, firstSection, negativePitchPoint1AboveAndToRightOfPoint2, heightMultiplier, widthMultiplier));

            gemDoc.Save(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), $"{Assembly.GetExecutingAssembly().GetName().Name}-{DateTime.Now.ToString("yyyy-MM-dd hhmmss")}.docx"));

            Console.WriteLine("DONE");
            Console.ReadKey();
        }

        public static Shape GetGemboxLineShape(DocumentModel document, Section section, TemplateItem templateItem, double heightMultiplier, double widthMultiplier)
        {
            var verticalTranslation = Math.Abs(templateItem.Y2 - templateItem.Y) * heightMultiplier;
            var horizontalTranslation = Math.Abs(templateItem.X2 - templateItem.X) * widthMultiplier;
            var horizontalAbsolutePosition = 0.0;
            var verticalAbsolutePosition = 0.0;

            if ((templateItem.X < templateItem.X2 && templateItem.Y < templateItem.Y2) ||//positive pitch, point1 < point2
                (templateItem.X == templateItem.X2) || (templateItem.Y == templateItem.Y2))//flat on the horizontal or vertical
            {
                horizontalAbsolutePosition = templateItem.X * widthMultiplier;
                verticalAbsolutePosition = templateItem.Y * heightMultiplier;

                var gemboxLineShape = new Shape(document, ShapeType.Line, GemBox.Document.Layout.Floating(new HorizontalPosition(section.PageSetup.PageMargins.Left + horizontalAbsolutePosition, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin),
                                                                                                          new VerticalPosition(section.PageSetup.PageMargins.Top + verticalAbsolutePosition, LengthUnit.Point, VerticalPositionAnchor.TopMargin),
                                                                                                          new GemBox.Document.Size(horizontalTranslation, verticalTranslation, LengthUnit.Point)));

                gemboxLineShape.Outline.Fill.SetSolid(new GemBox.Document.Color(templateItem.Pen.Color.R, templateItem.Pen.Color.G, templateItem.Pen.Color.B));
                gemboxLineShape.Outline.Width = templateItem.Pen.Width;

                return gemboxLineShape;
            }
            else if (templateItem.X > templateItem.X2 && templateItem.Y > templateItem.Y2)//positive pitch, point1 > point2
            {
                //quickly found out i cannot give a negative width or height to GemBox.Document.Size
                //to account for the mirror of the above condition, AKA drawing the same object but in mirror
                //we just flip-flop the starting point / absolute position and create the shape the same way
                horizontalAbsolutePosition = templateItem.X2 * widthMultiplier;
                verticalAbsolutePosition = templateItem.Y2 * heightMultiplier;

                var gemboxLineShape = new Shape(document, ShapeType.Line, GemBox.Document.Layout.Floating(new HorizontalPosition(section.PageSetup.PageMargins.Left + horizontalAbsolutePosition, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin),
                                                                                                          new VerticalPosition(section.PageSetup.PageMargins.Top + verticalAbsolutePosition, LengthUnit.Point, VerticalPositionAnchor.TopMargin),
                                                                                                          new GemBox.Document.Size(horizontalTranslation, verticalTranslation, LengthUnit.Point)));

                gemboxLineShape.Outline.Fill.SetSolid(new GemBox.Document.Color(templateItem.Pen.Color.R, templateItem.Pen.Color.G, templateItem.Pen.Color.B));
                gemboxLineShape.Outline.Width = templateItem.Pen.Width;

                return gemboxLineShape;
            }
            else if (templateItem.X < templateItem.X2 && templateItem.Y > templateItem.Y2)//negative pitch, point 1 below/ToLeft point 2
            {
                horizontalAbsolutePosition = templateItem.X * widthMultiplier;
                verticalAbsolutePosition = templateItem.Y * heightMultiplier;

                //cannot set negative height for size for it to draw up
                var badLineShape = new Shape(document, ShapeType.Line, GemBox.Document.Layout.Floating(new HorizontalPosition(section.PageSetup.PageMargins.Left + horizontalAbsolutePosition, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin),
                                                                                                       new VerticalPosition(section.PageSetup.PageMargins.Top + verticalAbsolutePosition, LengthUnit.Point, VerticalPositionAnchor.TopMargin),
                                                                                                       new GemBox.Document.Size(horizontalTranslation, verticalTranslation, LengthUnit.Point)));

                badLineShape.Outline.Fill.SetSolid(new GemBox.Document.Color(templateItem.Pen.Color.R, templateItem.Pen.Color.G, templateItem.Pen.Color.B));
                badLineShape.Outline.Width = templateItem.Pen.Width;

                return badLineShape;
            }
            else if (templateItem.X > templateItem.X2 && templateItem.Y < templateItem.Y2)//negative pitch, point 1 above/ToRight point 2
            {
                horizontalAbsolutePosition = templateItem.X * widthMultiplier;
                verticalAbsolutePosition = templateItem.Y * heightMultiplier;

                //cannot set negative width for size for it to draw left
                var badLineShape = new Shape(document, ShapeType.Line, GemBox.Document.Layout.Floating(new HorizontalPosition(section.PageSetup.PageMargins.Left + horizontalAbsolutePosition, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin),
                                                                                                       new VerticalPosition(section.PageSetup.PageMargins.Top + verticalAbsolutePosition, LengthUnit.Point, VerticalPositionAnchor.TopMargin),
                                                                                                       new GemBox.Document.Size(horizontalTranslation, verticalTranslation, LengthUnit.Point)));

                badLineShape.Outline.Fill.SetSolid(new GemBox.Document.Color(templateItem.Pen.Color.R, templateItem.Pen.Color.G, templateItem.Pen.Color.B));
                badLineShape.Outline.Width = templateItem.Pen.Width;

                return badLineShape;
            }
            else
                return null;
        }
    }
}

namespace MyModels
{
    using System.Drawing;

    public enum TemplateItemType { Default, Box, Line, Text, Field }
    public class TemplateItem
    {
        public TemplateItemType TemplateItemType { get; set; }
        public Font Font { get; set; }
        public Pen Pen { get; set; }
        public float X { get; set; }
        public float Y { get; set; }
        public float X2 { get; set; }
        public float Y2 { get; set; }
        public float Width { get; set; }
        public float Height { get; set; }
        public string Text { get; set; }

        public override string ToString()
        {
            switch (this.TemplateItemType)
            {
                case TemplateItemType.Box:
                    return $"<{this.TemplateItemType.ToString("G")}Item> X<{this.X}> Y<{this.Y}> W<{this.Width}> H<{this.Height}>";
                case TemplateItemType.Line:
                    return $"<{this.TemplateItemType.ToString("G")}Item> X1<{this.X}> Y1<{this.Y}> X2<{this.X2}> Y2<{this.Y2}>";
                case TemplateItemType.Text:
                case TemplateItemType.Field:
                    return $"<{this.TemplateItemType.ToString("G")}Item> X<{this.X}> Y<{this.Y}> W<{this.Width}> H<{this.Height}> T<{this.Text}>";
            }

            return string.Empty;
        }
    }
}

Download the current latest bug fix version from here and try using the following: 从此处下载当前最新的错误修复版本然后尝试使用以下版本:

badLineShape.Layout.Transform.FlipVertical = true;

Regarding the FlipVertical and FlipHorizontal transformations, in this case (line shape) they should be the same. 关于FlipVerticalFlipHorizontal转换,在这种情况下(线形),它们应该相同。

For example, consider the following image: 例如,考虑以下图像:

画线

Applying the vertical flip transformation on it with some photoshop application (I've used Gimp) results in: 使用某些photoshop应用程序(我使用过Gimp)在其上应用垂直翻转变换会导致:

垂直翻转线描

Applying the horizontal flip transformation on it with some photoshop application (I've used Gimp) results in: 使用某些photoshop应用程序(我使用过Gimp)在其上应用水平翻转变换会导致:

水平翻转线描

As you may notice, the resulting images are the same. 您可能会注意到,生成的图像是相同的。

Regarding the RightMargin, I'll try to investigate this further. 关于RightMargin,我将尝试进一步调查。

As Mario Z has mentioned the new big-fix version v1099 does allow the transformation of lines to create what i'm classifying as a negative pitch line... which now allows to draw lines in all directions. 正如Mario Z提到的那样,新的大修正版本v1099确实允许对线条进行转换以创建我归类为负间距线的东西...现在可以在所有方向上绘制线。

It appears to be a bit buggy as FlipVertical and FlipHorizontal appear to do the same exact transformation when they shouldn't. 似乎有些错误,因为FlipVertical和FlipHorizo​​ntal似乎在不应该进行相同的准确转换。 I also found a minor bug with setting the floating point via RightMargin, it doesn't appear to function the same way as Top/Left (i haven't tried playing with Bottom yet). 我还发现了一个通过RightMargin设置浮点的小错误,它的功能似乎与顶部/左侧的功能不同(我还没有尝试过使用底部)。

public static Shape GetGemboxLineShape(DocumentModel document, Section section, TemplateItem templateItem, double heightMultiplier, double widthMultiplier)
{
    var size = new GemBox.Document.Size(Math.Abs(templateItem.X2 - templateItem.X) * widthMultiplier, Math.Abs(templateItem.Y2 - templateItem.Y) * heightMultiplier, LengthUnit.Point);
    var horizontal = new HorizontalPosition();
    var vertical = new VerticalPosition();
    var requiresNegativeTransform = false;

    if ((templateItem.X < templateItem.X2 && templateItem.Y < templateItem.Y2) ||//positive pitch, point1 < point2
        (templateItem.X == templateItem.X2) || (templateItem.Y == templateItem.Y2))//flat on the horizontal or vertical
    {
        horizontal = new HorizontalPosition(section.PageSetup.PageMargins.Left + (templateItem.X * widthMultiplier), LengthUnit.Point, HorizontalPositionAnchor.LeftMargin);
        vertical = new VerticalPosition(section.PageSetup.PageMargins.Top + (templateItem.Y * heightMultiplier), LengthUnit.Point, VerticalPositionAnchor.TopMargin);
    }
    else if (templateItem.X > templateItem.X2 && templateItem.Y > templateItem.Y2)//positive pitch, point1 > point2
    {
        //quickly found out i cannot give a negative width or height to GemBox.Document.Size
        //to account for the mirror of the above condition, AKA drawing the same object but in mirror
        //we just flip-flop the starting point / absolute position and create the shape the same way
        horizontal = new HorizontalPosition(section.PageSetup.PageMargins.Left + (templateItem.X2 * widthMultiplier), LengthUnit.Point, HorizontalPositionAnchor.LeftMargin);
        vertical = new VerticalPosition(section.PageSetup.PageMargins.Top + (templateItem.Y2 * heightMultiplier), LengthUnit.Point, VerticalPositionAnchor.TopMargin);
    }
    else if (templateItem.X < templateItem.X2 && templateItem.Y > templateItem.Y2)//negative pitch, point 1 below/ToLeft point 2
    {
        //so for ease we're going to pick point2 at the top right and we can use Top/Right margin as our origin instead of Top/Left
        //however, this appears a bit buggy, i would assume i'd need to do -section.PageSetup.PageMargins.Right minus relative (opposite of TopLeft on the X/horizontal)
        //but it appears this wasn't accounted for on the right margin? or i'm not entirely understanding the floating/anchor functionality
        horizontal = new HorizontalPosition(-(templateItem.X2 * widthMultiplier), LengthUnit.Point, HorizontalPositionAnchor.RightMargin);
        vertical = new VerticalPosition(section.PageSetup.PageMargins.Top + (templateItem.Y2 * heightMultiplier), LengthUnit.Point, VerticalPositionAnchor.TopMargin);
        requiresNegativeTransform = true;
    }
    else if (templateItem.X > templateItem.X2 && templateItem.Y < templateItem.Y2)//negative pitch, point 1 above/ToRight point 2
    {
        //opposite of previous in that we're going to pick point1 but everything else will be the same
        horizontal = new HorizontalPosition(-(templateItem.X * widthMultiplier), LengthUnit.Point, HorizontalPositionAnchor.RightMargin);
        vertical = new VerticalPosition(section.PageSetup.PageMargins.Top + (templateItem.Y * heightMultiplier), LengthUnit.Point, VerticalPositionAnchor.TopMargin);
        requiresNegativeTransform = true;
    }
    else
    {
        throw new ArgumentException();
    }

    var gemboxLineShape = new Shape(document, ShapeType.Line, GemBox.Document.Layout.Floating(horizontal, vertical, size));

    gemboxLineShape.Outline.Fill.SetSolid(new GemBox.Document.Color(templateItem.Pen.Color.R, templateItem.Pen.Color.G, templateItem.Pen.Color.B));
    gemboxLineShape.Outline.Width = templateItem.Pen.Width;

    //this appears to solve my problem.... however, similar to right margin appears to be
    //a bit buggy... at least in the sense that FlipVertical and FlipHorizontal should do different transformations but it doesn't
    gemboxLineShape.Layout.Transform.FlipVertical = requiresNegativeTransform;

    return gemboxLineShape;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM