以编程方式在文本框中移动插入符号,排列和向下排列

时间:2012-06-20 15:36:09

标签: c# winforms datagridview textbox caret

我正在努力将插入符号移动到DataGridView 中的文本框编辑控件中,一行向上,一行向下,就像用户在按向上和向下箭头时所得到的那样。

所以我的意思不是换行符之间的行,我的意思是文本框左右两边的行。

我无法使用GetCharIndexFromPosition和GetPositionFromCharIndex,因为并非所有文本都会始终显示在文本框显示区域中。

修改 我无法模拟KeyPress,因为我正在处理DataGridView中的文本框单元格。我的目标实际上是让箭头键在普通文本框中执行操作,而不是从一行到另一行跳转。

3 个答案:

答案 0 :(得分: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属性/键处理。

答案 1 :(得分:1)

方法GetPositionFromCharIndex()GetCharIndexFromPosition()有两个限制:

  1. 它们不适用于文本框边框以外的文本
  2. TextBox.SelectionStart的字符索引对于行尾的插入符号和下一行开头的插入符号相同。
  3. 要纠正此问题,您可以:

    1. 在使用上述方法之前滚动文本框以显示相关行。
    2. 使用user32.dll中的GetCaretPos函数将其与SelectionStart的位置进行比较。如果它们不相等,则意味着插入符号位于行尾。
    3. 模拟{END}按键,将插入符号放在一行的末尾。
    4. 我遇到的另一个问题是TextBox.Lines指的是由换行符分隔的逻辑行,而函数TextBox.GetLineFromCharIndex()TextBox.GetFirstCharIndexFromLine()指的是在文本框中显示的可视线(也就是说,从TextBox的一边到另一边,没有必须是新行字符)。不要混淆它们。

      结果代码(您可能声称的丑陋,但正在工作)如下:

      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

答案 2 :(得分: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;
    }