Keep in mind that the code that I added was for testing, flexibility, and also to use as much code already available as possible. Also, my testing has only been on one AcroForm template. I am also sure that you are working on these areas, so it may be useless to mention:
<package id="PDFsharp-MigraDoc-gdi" version="1.50.4000-beta3b" targetFramework="net45" />
Currently, pdfsharp sets a default of XStringFormat.TopLeft. This was causing issues in textboxes, where the positioning was off between onfocus and non-focus of text because PDFSharp does not take into account of pre-existing alignment, and the margining/padding is different from the adobe. It was also not taking into account word-wrap in a multiline for TopLeft. The below code does not take into account multiline for other alignments, since you currently have it throw an exception, but I may come back with a fix for that as well.
What I ended up doing was adding a property for alignment that looks like this:
Code:
//PdfTextField.cs
public XStringFormat Alignment
{
get {
XStringFormat _alignment;
if (MultiLine)
{
_alignment = XStringFormats.TopLeft;
switch (Elements.GetInteger(Keys.Q))
{
case 0:
_alignment = XStringFormats.TopLeft;
break;
case 1:
_alignment = XStringFormats.TopCenter;
break;
case 2:
_alignment = XStringFormats.TopRight;
break;
default:
break;
}
}
else
{
_alignment = XStringFormats.CenterLeft;
switch (Elements.GetInteger(Keys.Q))
{
case 0:
_alignment = XStringFormats.CenterLeft;
break;
case 1:
_alignment = XStringFormats.Center;
break;
case 2:
_alignment = XStringFormats.CenterRight;
break;
default:
break;
}
}
return _alignment;
}
set {
if (XStringFormats.Equals(value, XStringFormats.CenterLeft) || XStringFormats.Equals(value, XStringFormats.BottomLeft) || XStringFormats.Equals(value, XStringFormats.TopLeft))
{
Elements.SetInteger(Keys.Q, 0);
}
else if (XStringFormats.Equals(value, XStringFormats.Center) || XStringFormats.Equals(value, XStringFormats.TopCenter) || XStringFormats.Equals(value, XStringFormats.BottomCenter))
{
Elements.SetInteger(Keys.Q, 1);
}
else if (XStringFormats.Equals(value, XStringFormats.CenterRight) || XStringFormats.Equals(value, XStringFormats.TopRight) || XStringFormats.Equals(value, XStringFormats.BottomRight))
{
Elements.SetInteger(Keys.Q, 2);
}
}
}
public double TopMargin
{
get { return _topMargin; }
set { _topMargin = value; }
}
double _topMargin = 0;
public double BottomMargin
{
get { return _bottomMargin; }
set { _bottomMargin = value; }
}
double _bottomMargin = 0;
public double LeftMargin
{
get { return _leftMargin; }
set { _leftMargin = value; }
}
double _leftMargin = 0;
public double RightMargin
{
get { return _rightMargin; }
set { _rightMargin = value; }
}
double _rightMargin = 0;
I changed the RenderAppearance to the below. This one and the following could be added together so the margin properties would not be needed:
Code:
//PdfTextField->RenderAppearance
PdfRectangle rect = Elements.GetRectangle(PdfAnnotation.Keys.Rect);
XForm form = new XForm(_document, rect.Size);
XGraphics gfx = XGraphics.FromForm(form);
XRect xrect = (rect.ToXRect() - rect.Location);
if (_backColor != XColor.Empty)
gfx.DrawRectangle(new XSolidBrush(BackColor), xrect);
string text = Text;
if (text.Length > 0)
{
xrect.Y = xrect.Y + TopMargin;
xrect.X = xrect.X + LeftMargin;
xrect.Width = xrect.Width + RightMargin;
xrect.Height = xrect.Height + BottomMargin;
if (this.MultiLine)
{
XTextFormatter formatter = new XTextFormatter(gfx);
formatter.Text = text;
formatter.DrawString(Text, Font, new XSolidBrush(ForeColor),
xrect, Alignment);
}
else
{
gfx.DrawString(Text, Font, new XSolidBrush(ForeColor),
xrect, Alignment);
}
}
Where I am using PdfSharp, I added:
Code:
if (textbox.MultiLine)
{
if (XStringFormats.Equals(textbox.Alignment, XStringFormats.TopLeft))
{
textbox.LeftMargin = 2;
textbox.TopMargin = -6;
textbox.RightMargin = 0;
textbox.BottomMargin = 0;
}
else if (XStringFormats.Equals(textbox.Alignment, XStringFormats.TopCenter))
{
}
else if (XStringFormats.Equals(textbox.Alignment, XStringFormats.TopRight))
{
}
}
else
{
if (XStringFormats.Equals(textbox.Alignment, XStringFormats.CenterLeft))
{
textbox.LeftMargin = 2;
textbox.TopMargin = .25;
textbox.RightMargin = 0;
textbox.BottomMargin = 0;
}
else if (XStringFormats.Equals(textbox.Alignment, XStringFormats.Center))
{
textbox.TopMargin = .25;
}
else if (XStringFormats.Equals(textbox.Alignment, XStringFormats.CenterRight))
{
textbox.LeftMargin = 0;
textbox.TopMargin = .25;
textbox.RightMargin = -2;
textbox.BottomMargin = 0;
}
}
I also changed XStringFormats to have an Equals method:
Code:
public static bool Equals(XStringFormat format1, XStringFormat format2)
{
if((format1 == null && format2 == null))
{
return true;
}
else if((format1 != null && format2 == null) || (format2 != null && format1 == null))
{
return false;
}
return (format1.Alignment == format2.Alignment && format1.LineAlignment == format2.LineAlignment);
}