2012-06-20 13 views
3

我很努力地在一個DataGridView內移動一個文本框編輯控件中的插入符,一行一行一行,正如用戶在按下時獲得的向下箭頭。以編程方式在文本框中移動插入符號,排隊並排隊

所以我不是說換行符就是換行符,換句話說,就是文本框左右兩邊之間的內容。

我無法使用GetCharIndexFromPosition和GetPositionFromCharIndex,因爲並非所有文本都會始終顯示在文本框顯示區域中。

編輯: 我無法模擬KeyPress,因爲我正在處理DataGridView中的文本框單元格。我的目標實際上是讓箭頭鍵在普通文本框中執行,而不是逐行跳轉。

+1

模擬'KeyPress'。 –

+0

請指定您是否使用Windows窗體,WPF或其他。如果一切都失敗了,就像Kendall所說的那樣,根據情況爲上下箭頭生成一個KeyPress事件。 –

+0

Winforms和模擬KeyPress在這種情況下將不起作用,因爲我試圖模擬DataGridView中的文本框單元格中的正常文本框行爲 - 請參閱[this](http://stackoverflow.com/questions/11108791/edit- a-textbox-cell-in-datagridview-as-if-it-a-normal-textbox-no-jumping-o) – Dil

回答

1

這應該起作用。

Point pOld = textBox1.GetPositionFromCharIndex(textBox1.SelectionStart); 
Point pNew = new Point(pOld.X, pOld.Y + textBox1.Font.Height) 
int charIndex = textBox1.GetCharIndexFromPosition(pNew); 
textBox1.SelectionStart = charIndex; 

雖然我不認爲這是最乾淨的解決方案。也許你應該看看DataGridView屬性/鍵處理。

+0

只要沒有隱藏文本(即文本框顯示區域不顯示所有文本),此功能就可以工作。如果沒有其他解決方案,我可能不得不先滾動文本框然後使用它。謝謝。 – Dil

+0

這種方法的另一個問題是,當caret在行尾時,selectionStart獲取下一行的第一個字符,所以結果不符合預期。當然,它可以用更多的代碼行來糾正,但我認爲可能有更好的方法來移動插入符號,可能是通過Windows API或其他方式。 – Dil

+0

雖然有一些更正,但它應該可以工作。謝謝。 – Dil

1

的方法GetPositionFromCharIndex()GetCharIndexFromPosition()有兩個限制:

  1. 他們不超出文本框
  2. 的邊框文字工作的TextBox.SelectionStart的字符索引是在結束一個插入符號相同在下一行開始處插入一行字符和一個插入符號。

要解決這個問題,您可以:

  1. 滾動文本框使用方法說之前顯示相關行。
  2. 使用user32.dll中的GetCaretPos函數將其與SelectionStart的位置進行比較。如果它們不相等,則意味着脫字符號在行尾。
  3. 模擬{END}鍵將光標定位在行尾。

我遇到的另一個問題是,TextBox.Lines指的是由新行字符分隔邏輯線路,而功能TextBox.GetLineFromCharIndex()TextBox.GetFirstCharIndexFromLine()指視線,因爲它們被顯示在文本框(即,從一邊到文本框的側,而不必有新行字符)。不要混淆。

生成的代碼(醜,你可以要求,但工作)如下:

class Utils 
{ 
    [DllImport("user32.dll")] 
    static extern bool GetCaretPos(out System.Drawing.Point lpPoint); 

    public static void LineUp(TextBox tb) 
    { 
     int oldCharIndex = tb.SelectionStart; 
     int oldLineNo = tb.GetLineFromCharIndex(oldCharIndex); 
     System.Drawing.Point oldCharPos = tb.GetPositionFromCharIndex(oldCharIndex); 
     System.Drawing.Point oldCaretPos; 
     if (GetCaretPos(out oldCaretPos)) 
     { 
      if (oldCharPos == oldCaretPos) 
      { 
       if (oldLineNo > 0) 
       { 
        tb.SelectionStart = tb.GetFirstCharIndexFromLine(oldLineNo - 1); 
        tb.ScrollToCaret(); 
        System.Drawing.Point newPos = new System.Drawing.Point(oldCaretPos.X, oldCaretPos.Y - tb.Font.Height); 
        int newCharIndex = tb.GetCharIndexFromPosition(newPos); 
        if (tb.GetPositionFromCharIndex(newCharIndex).Y == newPos.Y) 
        { 
         tb.SelectionStart = newCharIndex; 
        } 
        else 
        { 
         tb.SelectionStart = tb.GetFirstCharIndexFromLine(oldLineNo - 1); 
         System.Windows.Forms.SendKeys.Send("{END}"); 
        } 
       } 
      } 
      else 
      { 
       if (oldLineNo > 1) 
       { 
        tb.SelectionStart = tb.GetFirstCharIndexFromLine(oldLineNo - 2); 
        tb.ScrollToCaret(); 
        System.Drawing.Point newPos = new System.Drawing.Point(oldCaretPos.X, oldCaretPos.Y - tb.Font.Height); 
        int newCharIndex = tb.GetCharIndexFromPosition(newPos); 
        if (tb.GetPositionFromCharIndex(newCharIndex).Y == newPos.Y) 
        { 
         tb.SelectionStart = newCharIndex; 
        } 
        else 
        { 
         tb.SelectionStart = tb.GetFirstCharIndexFromLine(oldLineNo - 2); 
         System.Windows.Forms.SendKeys.Send("{END}"); 
        } 
       } 
      } 
     } 
    } 

    public static void LineDown(TextBox tb) 
    { 
     int oldCharIndex = tb.SelectionStart; 
     int oldLineNo = tb.GetLineFromCharIndex(oldCharIndex); 
     System.Drawing.Point oldCharPos = tb.GetPositionFromCharIndex(oldCharIndex); 
     System.Drawing.Point oldCaretPos; 
     if (GetCaretPos(out oldCaretPos)) 
     { 
      if (oldCharPos == oldCaretPos) 
      { 
       if (oldLineNo < tb.GetLineFromCharIndex(tb.Text.Length - 1)) 
       { 
        tb.SelectionStart = tb.GetFirstCharIndexFromLine(oldLineNo + 1); 
        tb.ScrollToCaret(); 
        System.Drawing.Point newPos = new System.Drawing.Point(oldCaretPos.X, oldCaretPos.Y + tb.Font.Height); 
        int newCharIndex = tb.GetCharIndexFromPosition(newPos); 
        if (tb.GetPositionFromCharIndex(newCharIndex).Y == newPos.Y) 
        { 
         tb.SelectionStart = newCharIndex; 
        } 
        else 
        { 
         tb.SelectionStart = tb.GetFirstCharIndexFromLine(oldLineNo + 1); 
         System.Windows.Forms.SendKeys.Send("{END}"); 
        } 
       } 
      } 
      else 
      { 
       System.Drawing.Point newPos = new System.Drawing.Point(oldCaretPos.X, oldCaretPos.Y + tb.Font.Height); 
       int newCharIndex = tb.GetCharIndexFromPosition(newPos); 
       if (tb.GetPositionFromCharIndex(newCharIndex).Y == newPos.Y) 
       { 
        tb.SelectionStart = newCharIndex; 
       } 
       else 
       { 
        tb.SelectionStart = tb.GetFirstCharIndexFromLine(oldLineNo); 
        System.Windows.Forms.SendKeys.Send("{END}"); 
       } 
      } 
     } 
    } 
} 

信用爲理念去this answer,你也可能想看看MSDN reference on GetCaretPosother Caret functions

+0

請注意,如果它不是DataGridView中的文本框,可以像Kendall Frey所建議的那樣簡單地模擬KeyPress,並避免所有這些。 – Dil

0
/// ------------------------------------------------------------------------------------ 
    /// <summary> 
    /// Processes up key when a grid cell is in the edit mode. This overrides the default 
    /// behavior in a grid cell when it's being edited so using the up arrow will move the 
    /// IP up one line rather than moving to the previous row. 
    /// </summary> 
    /// ------------------------------------------------------------------------------------ 
    protected virtual bool ProcessUpKey(TextBox txtBox) 
    { 
     // Don't override the default behavior if all the text is selected or not multi-line. 
     if (txtBox.SelectedText == txtBox.Text || !txtBox.Multiline) 
      return false; 

     int selectionPosition = txtBox.SelectionStart; 
     // Getting the position after the very last character doesn't work. 
     if (selectionPosition == txtBox.Text.Length && selectionPosition > 0) 
      selectionPosition--; 
     Point pt = txtBox.GetPositionFromCharIndex(selectionPosition); 

     if (pt.Y == 0) 
      return false; 

     pt.Y -= TextRenderer.MeasureText("x", txtBox.Font).Height; 
     txtBox.SelectionStart = txtBox.GetCharIndexFromPosition(pt); 
     return true; 
    } 

    /// ------------------------------------------------------------------------------------ 
    /// <summary> 
    /// Processes down key when a grid cell is in the edit mode. This overrides the default 
    /// behavior in a grid cell when it's being edited so using the down arrow will move the 
    /// IP down one line rather than moving to the next row. 
    /// </summary> 
    /// ------------------------------------------------------------------------------------ 
    protected virtual bool ProcessDownKey(TextBox txtBox) 
    { 
     // Don't override the default behavior if all the text is selected or not multi-line. 
     if (txtBox.SelectedText == txtBox.Text || !txtBox.Multiline) 
      return false; 

     int chrIndex = txtBox.SelectionStart; 
     Point pt = txtBox.GetPositionFromCharIndex(chrIndex); 
     pt.Y += TextRenderer.MeasureText("x", txtBox.Font).Height; 
     var proposedNewSelection = txtBox.GetCharIndexFromPosition(pt); 
     if (proposedNewSelection <= chrIndex) 
      return false; // Don't let "down" take you *up*. 
     txtBox.SelectionStart = proposedNewSelection; 
     return true; 
    }