2016-12-01 6 views
1

문자열에 대한 적중 테스트를하려고합니다. (x 오프셋에서 char 인덱스를 가져 오려고합니다.)하지만 측정 문자열로 문제가 발생합니다. MeasureString은 항상 공백이 적합하다고 생각합니다.

은 본질적으로 내가

 StringFormat sf = new StringFormat(StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap | StringFormatFlags.LineLimit); 
    e.Graphics.MeasureString("test string", this.Font, new SizeF(xHitTestPosition, this.Font.Height), sf, out charFitted, out linesFilled); 

charFitted의 값은 그것주고 크기에 맞지 수있는 문자의 수를 설정해야합니다 사용하고있는 코드입니다 (나는에 따라 그것을 크기를주는거야 포인트 나는 시험을 치려고 노력하고있다).

'test'문자열을 포함 할만큼 큰 영역이 나올 때까지 제대로 작동합니다. 이 시점에서 charFitted는 3 ('tes')에서 8 ('test')로 점프합니다. 기본적으로 항상 주어진 공백에 관계없이 모든 공백을 포함합니다. 내가 그 울부 짖는 소리 테스트 응용 프로그램을 포함 시켰습니다

내가있는 StringFormat 설정을 장난 해봤지만 아무것도 t의 도움을 보인다는 ...이

enter image description here enter image description here

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace WindowsFormsApplication2 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      trackBar1.Maximum = this.ClientRectangle.Width; 
     } 

     protected override void OnPaint(PaintEventArgs e) 
     { 
      string sample = "abc      def"; 
      int charFitted, linesFilled; 

      e.Graphics.DrawString(sample, this.Font, Brushes.Black, PointF.Empty); 
      e.Graphics.DrawLine(Pens.Red, trackBar1.Value, 0, trackBar1.Value, 100); 

      StringFormat sf = new StringFormat(StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap | StringFormatFlags.LineLimit); 
      sf.Trimming = StringTrimming.Character; 
      e.Graphics.MeasureString(sample, this.Font, new SizeF(trackBar1.Value, this.Font.Height), sf, out charFitted, out linesFilled); 
      textBox1.Text = "[" + sample.Substring(0, charFitted) + "]"; 

      base.OnPaint(e); 
     } 

     private void trackBar1_Scroll(object sender, EventArgs e) 
     { 
      Invalidate(); 
     } 

     /// <summary> 
     /// Required designer variable. 
     /// </summary> 
     private System.ComponentModel.IContainer components = null; 

     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 

     #region Windows Form Designer generated code 

     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     private void InitializeComponent() 
     { 
      this.trackBar1 = new System.Windows.Forms.TrackBar(); 
      this.textBox1 = new System.Windows.Forms.TextBox(); 
      ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit(); 
      this.SuspendLayout(); 
      // 
      // trackBar1 
      // 
      this.trackBar1.Location = new System.Drawing.Point(13, 184); 
      this.trackBar1.Name = "trackBar1"; 
      this.trackBar1.Size = new System.Drawing.Size(259, 45); 
      this.trackBar1.TabIndex = 0; 
      this.trackBar1.Scroll += new System.EventHandler(this.trackBar1_Scroll); 
      // 
      // textBox1 
      // 
      this.textBox1.Location = new System.Drawing.Point(22, 229); 
      this.textBox1.Name = "textBox1"; 
      this.textBox1.Size = new System.Drawing.Size(237, 20); 
      this.textBox1.TabIndex = 1; 
      // 
      // Form1 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.ClientSize = new System.Drawing.Size(284, 261); 
      this.Controls.Add(this.textBox1); 
      this.Controls.Add(this.trackBar1); 
      this.Name = "Form1"; 
      this.Text = "Form1"; 
      this.Load += new System.EventHandler(this.Form1_Load); 
      ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit(); 
      this.ResumeLayout(false); 
      this.PerformLayout(); 

     } 

     #endregion 

     private System.Windows.Forms.TrackBar trackBar1; 
     private System.Windows.Forms.TextBox textBox1; 
    } 
} 
보여줍니다
+1

히트 테스트를위한 것이 아니며 대신 Graphics.MeasureCharacterRanges()를 사용하십시오. –

+1

나는 그것을 시도했지만 각각의 char에 대해 characterRange를 만들 필요가 있고, 32 개 이상의 문자 범위가 설정되면 OverflowException을 던진다. – Sprotty

+0

젠장, 정말이야! 32 개 이상이'OverflowException'을 던집니다. –

답변

1

문제는 "abc"와 "abc"의 길이가 동일하다는 것입니다. 뒤 공백을 인쇄하지 않으므로 그래픽 표현은 동일합니다. 끝에 문자를 추가 한 다음 문자열을 측정하고 추가 된 문자의 길이를 제거합니다.

이 당신의 OnPaint를 swith를

작동하는 것 같다 :

protected override void OnPaint(PaintEventArgs e) { 
     string sample = "abc      def"; 

     e.Graphics.DrawString(sample, this.Font, Brushes.Black, PointF.Empty); 
     e.Graphics.DrawLine(Pens.Red, trackBar1.Value, 0, trackBar1.Value, 100); 

     StringFormat sf = new StringFormat(StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap | StringFormatFlags.LineLimit); 
     sf.Trimming = StringTrimming.Character; 

     var underscoreWidth = e.Graphics.MeasureString("_", this.Font).Width; 

     for (int i = 0; i < sample.Length; i++) { 
      var s = sample.Substring(0, i + 1) + "_"; 
      var size = e.Graphics.MeasureString(s, this.Font).Width - underscoreWidth; 
      if (size > trackBar1.Value) { 
       if (s.Length > 0) { 
        var ok = s.Substring(0, s.Length - 2); 
        textBox1.Text = "[" + ok + "]"; 
        base.OnPaint(e); 
        return; 
       } 
      } 
     } 

     textBox1.Text = "[" + sample + "]"; 
     base.OnPaint(e); 
    } 
0

나는 정말 내가 가지고있는이 솔루션을하지만, 지금까지의 유일한 작업 솔루션을 좋아하지 않는다. 그것의 @ FSDaniel에서 솔루션을 기반으로,하지만 Graphics.MeasureString & Graphics.DrawString에서 결과가 동일한 StringFormat을 전달하더라도 표류하는 것으로 나타났습니다.

TextFormatFlags.TextBoxControl 플래그가 설정된 TextRenderer를 사용하여 일관된 측정 만이 이루어졌습니다.

이것은 결과를 찾기 위해 조금씩 (성능 현명함) 향상시킬 수있는 불쾌한 해결책입니다. 즉, 문자열의 중간에서 시작하십시오. 너무 커서 문자열의 3/4을 시도하십시오. 결과가 나올 때까지 5/8 등.

이것은 최상의 해결책과는 거리가 멀기 때문에 누구나 더 나은 점이 있다면 게시 해주세요!

protected override void OnPaint(PaintEventArgs e) 
    { 
     string sample = "abc      defXXXXXXXXXXXXiiiiiiiX"; 

     TextFormatFlags flags = TextFormatFlags.NoPadding | TextFormatFlags.TextBoxControl | TextFormatFlags.SingleLine | TextFormatFlags.NoPrefix; 

     TextRenderer.DrawText(e.Graphics, sample, this.Font, Point.Empty, Color.Black, flags); 
     e.Graphics.DrawLine(Pens.Red, trackBar1.Value, 0, trackBar1.Value, 100); 

     string measuredString = sample; 
     for (int i = 0; i < sample.Length; i++) 
     { 
      Size size = TextRenderer.MeasureText(e.Graphics, sample.Substring(0, i+1), this.Font, new Size(10000000, 1000000), flags); 
      if (size.Width > trackBar1.Value) 
      { 
       textBox1.Text = "[" + sample.Substring(0,i+1) + "]"; 
       break; 
      } 
     } 

     base.OnPaint(e); 
    }