5

ユーザーが上矢印と下矢印を押したときと同じように、 DataGridView 内のテキストボックス編集コントロールでキャレットを1行上と1行下に移動するのに苦労しています。

したがって、改行文字の間にあるものとして行を意味するのではなく、テキストボックスの左側と右側の間にあるものとして行を意味します.

すべてのテキストがテキスト ボックスの表示領域に常に表示されるわけではないため、GetCharIndexFromPosition と GetPositionFromCharIndex を使用できません。

編集: DataGridView 内のテキスト ボックス セルを扱っているため、KeyPress をシミュレートできません。私の目的は、実際には、行から行にジャンプするのではなく、通常のテキストボックスで行うことを矢印キーで行うことです。

4

3 に答える 3

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 のプロパティ/キー処理を調べる必要があります。

于 2012-06-20T16:59:03.383 に答える
1

メソッドGetPositionFromCharIndex()と には、次のGetCharIndexFromPosition()2 つの制限があります。

  1. テキストボックスの境界を超えるテキストでは機能しません
  2. の文字インデックスはTextBox.SelectionStart、行末のキャレットと次の行の先頭のキャレットで同じです。

これを修正するには、次のことができます。

  1. 上記のメソッドを使用する前に、テキストボックスをスクロールして関連する行を表示します。
  2. user32.dll の GetCaretPos 関数を使用して、SelectionStart の位置と比較します。それらが等しくない場合、キャレットが行末にあることを意味します。
  3. 行末にキャレットを配置する {END} キーの押下をシミュレートします。

私が遭遇したもう1つの問題は、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}");
                }
            }
        }
    }
}

アイデアの功績はこの回答にあり、 GetCaretPosおよびその他の Caret 関数に関する MSDN リファレンスも参照してください。

于 2012-06-22T16:19:41.837 に答える
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;
    }
于 2013-08-15T18:15:23.847 に答える