2016-12-01 15 views
1

私は文字列のヒットテストをしようとしています(xオフセットからcharインデックスを取得したい)が、メジャー文字列で問題を起こしています。MeasureStringは常に空白が収まると考えています

これは、基本的に私はcharFittedの値が(私はそれに基づいてサイズを与えている、それはサイズ内にその弾力を合うことができる文字の数に設定する必要があり

 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); 

を使用していたコードですポイント私はテストをヒットしようとしている)。

これは、領域が '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

私はそれを試みましたが、各文字に対してcharacterRangeを作成する必要があり、32文字を超える文字範囲が設定されていると、OverflowExceptionがスローされます。 – Sprotty

+0

本当にそうです! 32以上が 'OverflowException'を投げます。 –

答えて

1

"abc"と "abc"の長さが同じであるという問題があります。末尾のスペースを印刷しないので、グラフィック表現は同じです。 最後に文字を追加して文字列を測定し、追加された文字の長さを削除します。

これまであなたのOnPaint急が

、動作しているようです:

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のソリューションに基づいていますが、同じStringFormatを渡しても、Graphics.MeasureString & Graphics.DrawStringの結果がドリフトしていることがわかりました。

TextFormatFlags.TextBoxControlフラグがセットされた状態でTextRendererを使用することで、一貫した測定ができました。

これは、結果を狩ることによって少し改善することができた厄介な解決策です。つまり、文字列の真ん中で開始します。結果が出るまで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); 
    } 
関連する問題