需求:最近项目有个小功能,根据配置文件配置的个数,动态在窗体上生成指定个数的TextBox,并获取其内容用于业务需求。
无废话,直接上核心代码:
/// <summary> /// 获取所有TextBox的内容 /// </summary> private void GetAllTextBoxValue() { StringBuilder sb = new StringBuilder(); foreach (Control c in this.PanelCarton.Controls) { if (c is TextBox) { TextBox testBox = c as TextBox; sb.Append(testBox.Text+","); } } label1.Text = sb.ToString(); } /// <summary> ///根据配置的units,动态添加TextBox控件 /// </summary> /// <param name="units"></param> private void AddTextBoxControlByUnits(int units) { int loopCount = 0; int txtID = 0; int x = units, y = 5; while (x > y) { for (int j = 1; j <= y; j++) { TextBox textBox = new TextBox(); //textBox.Name = string.Format("txtSN{0}", (x-y)*j+1); textBox.Name = string.Format("txtSN{0}", txtID); textBox.Width = 200; textBox.Height = 20; textBox.BorderStyle = BorderStyle.FixedSingle; textBox.Location = new Point(10 + 250 * loopCount, 10 + (j - 1) * 65); //textBox.Text = txtID.ToString();//用于定位,下同 PanelCarton.Controls.Add(textBox); txtID++; } x -= y; ++loopCount; } int leftOffset = 10 + 250 * loopCount; for (int j = 1; j <= x; j++) { TextBox textBox = new TextBox(); //textBox.Name = string.Format("txtSN{0}", j-1); textBox.Name = string.Format("txtSN{0}",txtID); textBox.Width = 200; textBox.Height = 20; textBox.BorderStyle = BorderStyle.FixedSingle; textBox.Location = new Point(leftOffset, 10 + (j - 1) * 65); //textBox.Text = txtID.ToString(); PanelCarton.Controls.Add(textBox); txtID++; } }
以上代码比较简单,但也做个简单的介绍:
AddTextBoxControlByUnits方法:核心在于处理“被整除”和“没有被整除”。举个简单例子。比如配置文件需要显示10个TextBox, 10÷5=2能被整除,所以在while循环处循环2次,每次循环创建5个TextBox。 最下面的for循环水用于处理不能被5整除的情况。比如需要生成12给TextBox,12÷5=2 余2,所以最下面的for循环就是用来干这事的。循环余下的2次循环。
GetAllTextBoxValue()方法:用于获取上述方法动态生成的TextBox的内容。太简单,不做分析
(对于文中处理方法,如果大家有更高效,更简单的方法,希望大家不吝赐教~ 再次谢过)
具体效果如下:
通过上面的效果图,大家可以看到图片的右下角有个公用章的水印。
无废话,直接上核心代码:
/// <summary> /// Compute string total length and every char length /// </summary> /// <param name="sText"></param> /// <param name="g"></param> /// <param name="fCharWidth"></param> /// <param name="fIntervalWidth"></param> /// <returns></returns> private float ComputeStringLength(string sText, Graphics g, float[] fCharWidth, float fIntervalWidth, Char_Direction Direction) { // Init string format StringFormat sf = new StringFormat(); sf.Trimming = StringTrimming.None; sf.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap | StringFormatFlags.LineLimit; // Measure whole string length SizeF size = g.MeasureString(sText, _font, (int)_font.Style); RectangleF rect = new RectangleF(0f, 0f, size.Width, size.Height); // Measure every character size CharacterRange[] crs = new CharacterRange[sText.Length]; for (int i = 0; i < sText.Length; i++) crs[i] = new CharacterRange(i, 1); // Reset string format sf.FormatFlags = StringFormatFlags.NoClip; sf.SetMeasurableCharacterRanges(crs); sf.Alignment = StringAlignment.Near; // Get every character size Region[] regs = g.MeasureCharacterRanges(sText, _font, rect, sf); // Re-compute whole string length with space interval width float fTotalWidth = 0f; for (int i = 0; i < regs.Length; i++) { if (Direction == Char_Direction.Center || Direction == Char_Direction.OutSide) fCharWidth[i] = regs[i].GetBounds(g).Width; else fCharWidth[i] = regs[i].GetBounds(g).Height; fTotalWidth += fCharWidth[i] + fIntervalWidth; } fTotalWidth -= fIntervalWidth;//Remove the last interval width return fTotalWidth; } /// <summary> /// Compute every char position /// </summary> /// <param name="CharWidth"></param> /// <param name="recChars"></param> /// <param name="CharAngle"></param> /// <param name="StartAngle"></param> private void ComputeCharPos( float[] CharWidth, PointF[] recChars, double[] CharAngle, double StartAngle) { double fSweepAngle, fCircleLength; //Compute the circumference fCircleLength = _rectcircle.Width * Math.PI; for (int i = 0; i < CharWidth.Length; i++) { //Get char sweep angle fSweepAngle = CharWidth[i] * 360 / fCircleLength; //Set point angle CharAngle[i] = StartAngle + fSweepAngle / 2; //Get char position if (CharAngle[i] < 270f) recChars[i] = new PointF( _rectcircle.X + _rectcircle.Width / 2 - (float)(_rectcircle.Width / 2 * Math.Sin(Math.Abs(CharAngle[i] - 270) * Math.PI / 180)), _rectcircle.Y + _rectcircle.Width / 2 - (float)(_rectcircle.Width / 2 * Math.Cos( Math.Abs(CharAngle[i] - 270) * Math.PI / 180))); else recChars[i] = new PointF( _rectcircle.X + _rectcircle.Width / 2 + (float)(_rectcircle.Width / 2 * Math.Sin(Math.Abs(CharAngle[i] - 270) * Math.PI / 180)), _rectcircle.Y + _rectcircle.Width / 2 - (float)(_rectcircle.Width / 2 * Math.Cos( Math.Abs(CharAngle[i] - 270) * Math.PI / 180))); //Get total sweep angle with interval space fSweepAngle = (CharWidth[i] + _letterspace) * 360 / fCircleLength; StartAngle += fSweepAngle; } } /// <summary> /// Generate seal bitmap /// </summary> /// <returns></returns> public Bitmap TextOnPathBitmap() { // Create bitmap and graphics Bitmap bit = new Bitmap(_rect.Width, _rect.Height); Graphics g = Graphics.FromImage(bit); // Compute string length in graphics float[] fCharWidth = new float[_text.Length]; float fTotalWidth = ComputeStringLength(_text, g, fCharWidth, _letterspace, _chardirect); // Compute arc's start-angle and end-angle double fStartAngle, fSweepAngle; fSweepAngle = fTotalWidth * 360 / (_rectcircle.Width * Math.PI); fStartAngle = 270 - fSweepAngle / 2; // Compute every character's position and angle PointF[] pntChars = new PointF[_text.Length]; double[] fCharAngle = new double[_text.Length]; ComputeCharPos(fCharWidth, pntChars, fCharAngle, fStartAngle); g.SmoothingMode = SmoothingMode.HighQuality; g.CompositingQuality = CompositingQuality.HighQuality; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; DrawSealBase(g); // Draw every character for (int i = 0; i < _text.Length; i++) DrawRotatedText(g, _text[i].ToString(), (float)(fCharAngle[i] + _degree), pntChars[i]); g.Dispose(); // Return bitmap return bit; } /// <summary> /// Draw seal base /// </summary> /// <param name="g"></param> private void DrawSealBase(Graphics g) { // Draw background g.FillRectangle(Brushes.Transparent, _rect); #region 填充圆内部颜色 //g.FillEllipse(new SolidBrush(_fillcolor), // new Rectangle(1, 1, _rect.Width - 2, _rect.Height - 2)); //g.FillEllipse(Brushes.Black, // new Rectangle(4, 4, _rect.Width - 8, _rect.Height - 8)); #endregion //画个空心圆(自我感觉这样效果比较好,如果想用喜欢的颜色填充可以用上面屏蔽掉的代码) g.DrawEllipse(new Pen(Brushes.Red,3), new Rectangle(4, 4, _rect.Width - 8, _rect.Height - 8)); // Draw start signal StringFormat sf = new StringFormat(); string strStar = "★"; Font fnt = new Font(_font.FontFamily, _font.Size * 3); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; SizeF siz = g.MeasureString(strStar, fnt); g.DrawString(strStar, fnt, new SolidBrush(_fillcolor), new RectangleF(_rect.Width / 2 - siz.Width / 2, _rect.Height / 2 - siz.Height / 2, siz.Width, siz.Height), sf); // Draw base string float[] fCharWidth = new float[_basestring.Length]; float fTotalWidths = ComputeStringLength(_basestring, g, fCharWidth, 0, Char_Direction.Center); float fLeftPos = (_rect.Width - fTotalWidths) / 2; PointF pt; for (int i = 0; i < _basestring.Length; i++) { pt = new PointF(fLeftPos + fCharWidth[i] / 2, _rect.Height / 2 + siz.Height / 2 + 10); DrawRotatedText(g, _basestring[i].ToString(), 0, pt); fLeftPos += fCharWidth[i]; } } /// <summary> /// Draw every rotated character /// </summary> /// <param name="g"></param> /// <param name="_text"></param> /// <param name="_angle"></param> /// <param name="_PointCenter"></param> private void DrawRotatedText(Graphics g, string _text, float _angle, PointF _PointCenter) { // Init format StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; // Create graphics path GraphicsPath gp = new GraphicsPath(System.Drawing.Drawing2D.FillMode.Winding); int x = (int)_PointCenter.X; int y = (int)_PointCenter.Y; // Add string gp.AddString(_text, _font.FontFamily, (int)_font.Style, _font.Size, new Point(x, y), sf); // Rotate string and draw it Matrix m = new Matrix(); m.RotateAt(_angle, new PointF(x, y)); g.Transform = m; g.DrawPath(new Pen(_color), gp); g.FillPath(new SolidBrush(_fillcolor), gp); } }
代码比较简单,注释也比较详细。就不逐一分析了。
虽然水印效果在第一个工具上已经实现,不过在发放一张福利照片,给深夜忙碌的码农们提提神。(真正的效果在右下角的水印,请注意力集中。谢谢)
如果大家觉得这两个小东西对自己有点用处或者觉得上图妹纸能提升的话,麻烦点击推荐!您的支持就是俺无限的动力。
最后附上文中示例代码下载(https://files.cnblogs.com/axing/TEST.rar),代码仅供参考.
最后谢谢大家。