我正在使用代码编辑器(WinForms),我想知道如何执行 { 和 } 的功能,特别是使用括号(打开和关闭)的自动缩进,就像在实际代码编辑器中一样。
---|> { 和 }
像这样 1:
编辑器是一个名为 rtb 的富文本框。
我正在使用代码编辑器(WinForms),我想知道如何执行 { 和 } 的功能,特别是使用括号(打开和关闭)的自动缩进,就像在实际代码编辑器中一样。
---|> { 和 }
像这样 1:
编辑器是一个名为 rtb 的富文本框。
好的,我的解决方案有问题,但足以让您了解它的工作原理
我的结果:
{
{
{
}
}
}
这里是我的代码
public partial class Form1 : Form
{
private bool FLAG_Selftimer = false;
private bool FLAG_KeyPressed = false;
private int pos = 0;
public Form1()
{
InitializeComponent();
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
var rtb = sender as RichTextBox;
var point = rtb.SelectionStart;
if (!FLAG_Selftimer)
{
rtb.Text = ReGenerateRTBText(rtb.Text);
FLAG_KeyPressed = false;
}
else
{
point ++;
FLAG_Selftimer = false;
}
rtb.SelectionStart = point;
}
private string ReGenerateRTBText(string Text)
{
string[] text = Regex.Split(Text,"\n");
int lvl = 0;
string newString = "";
foreach (string line in text)
{
line.TrimStart(' ');
newString += indentation(lvl) + line.TrimStart(' ') + "\n";
if (line.Contains("{"))
lvl++;
if (line.Contains("}"))
lvl--;
}
FLAG_Selftimer = true;
return (!FLAG_KeyPressed) ? newString : newString.TrimEnd('\n');
}
private string indentation(int IndentLevel)
{
string space = "";
if(IndentLevel>0)
for (int lvl = 0; lvl < IndentLevel; lvl++)
{
space += " ".PadLeft(8);
}
return space;
}
private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
FLAG_KeyPressed = true;
}
}
我希望这能帮到您
在阅读和使用代码之前,请阅读以下文本:
我应该说一些使用代码的提示:
您可以从以下地址下载示例项目:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class frmCodeEditor : Form
{
char[] chrTracingKeyChars = new char[] { ';', '}', '\n' };
char[] chrCheckingKeyChars = new char[] { '{', '(' };
Point ptCurrentCharPosition;
bool bolCheckCalling = false;
int intInitialCursorPosition = 0;
int intRemainingCharsOfInitialText = 0;
int intNextCharIndex = 0;
int intPrevCharIndex = 0;
public frmCodeEditor()
{
InitializeComponent();
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
AutoIndention(rtbCodes);
}
/// <summary>
/// Implements Auto-Indention.
/// </summary>
/// <param name="rtb">A RichTextBox control</param>
private void AutoIndention(RichTextBox rtb)
{
char chrLastChar = GetChar(rtb);
if (chrLastChar == chrTracingKeyChars[0])
{
intRemainingCharsOfInitialText = rtb.TextLength - rtb.SelectionStart;
intInitialCursorPosition = rtb.SelectionStart;
ImplementIndentionForSemicolon(rtb);
}
else if (chrLastChar == chrTracingKeyChars[1])
{
ImplementIndentionForRightCurlyBracket(rtb);
}
else if (chrLastChar == chrTracingKeyChars[2])
{
ImplementIndentionForNewLineCharacter(rtb);
}
}
/// <summary>
/// Specifies current char based on the cursor position.
/// </summary>
/// <param name="rtb">A RichTextBox control</param>
/// <returns>Returns a char.</returns>
private char GetChar(RichTextBox rtb)
{
return GetChar(rtb.SelectionStart, rtb);
}
/// <summary>
/// Specifies a char based on the specified index.
/// </summary>
/// <param name="intCharIndex">A char index</param>
/// <param name="rtb">A RichTextBox control</param>
/// <returns>Returns a char.</returns>
private char GetChar(int intCharIndex, RichTextBox rtb)
{
if (intCharIndex != rtb.TextLength)
{
ptCurrentCharPosition = rtb.GetPositionFromCharIndex(intCharIndex - 1);
}
else
{
ptCurrentCharPosition = rtb.GetPositionFromCharIndex(intCharIndex);
}
return rtb.GetCharFromPosition(ptCurrentCharPosition);
}
/// <summary>
/// Specifies current line number based on the cursor position.
/// </summary>
/// <param name="rtb">A RichTextBox control</param>
/// <returns>Returns the line number.</returns>
private int GetLineNumber(RichTextBox rtb)
{
return GetLineNumber(rtb.GetFirstCharIndexOfCurrentLine(), rtb);
}
/// <summary>
/// Specifies the line number based on the specified index.
/// </summary>
/// <param name="intCharIndex">A char index</param>
/// <param name="rtb">A RichTextBox control</param>
/// <returns>Returns the line number.</returns>
private int GetLineNumber(int intCharIndex, RichTextBox rtb)
{
return rtb.GetLineFromCharIndex(intCharIndex);
}
/// <summary>
/// Implements indention for semicolon ";" character.
/// </summary>
/// <param name="rtb">A RichTextBox control</param>
private void ImplementIndentionForSemicolon(RichTextBox rtb)
{
Dictionary<char, int> dicResult = IsExistCheckingKeyChars(rtb);
if (dicResult[chrCheckingKeyChars[0]] != -1)
{
int intIndentionLevel = CheckingIndentionLevel(dicResult[chrCheckingKeyChars[0]], rtb);
ImplementIndention(dicResult[chrCheckingKeyChars[0]], intIndentionLevel, rtb);
}
}
private void ImplementIndentionForRightCurlyBracket(RichTextBox rtb)
{
}
private void ImplementIndentionForNewLineCharacter(RichTextBox rtb)
{
}
/// <summary>
/// Checks current and previous lines for finding key-chars.
/// </summary>
/// <param name="rtb">A RichTextBox control</param>
/// <param name="bolSearchCurrentLine">The search state</param>
/// <returns>Returns first occurrences of key-chars before current char.</returns>
private Dictionary<char, int> IsExistCheckingKeyChars(RichTextBox rtb, bool bolSearchCurrentLine = false)
{
GetChar(rtb);
Dictionary<char, int> dicCheckingKeyCharsIndexes = new Dictionary<char, int>();
for (int intCntr = 0; intCntr < chrCheckingKeyChars.Length; intCntr++)
{
dicCheckingKeyCharsIndexes.Add(chrCheckingKeyChars[intCntr], 0);
}
for (int intCntr = 0; intCntr < chrCheckingKeyChars.Length; intCntr++)
{
int intFirstIndexForChecking = 0;
int intLastIndexForChecking = 0;
for (int intLineCounter = GetLineNumber(rtb); intLineCounter >= 0; intLineCounter--)
{
if (intLineCounter == GetLineNumber(rtb))
{
intLastIndexForChecking = rtb.GetCharIndexFromPosition(ptCurrentCharPosition);
}
else
{
intLastIndexForChecking = intFirstIndexForChecking - 1;
}
intFirstIndexForChecking = rtb.GetFirstCharIndexFromLine(intLineCounter);
try
{
dicCheckingKeyCharsIndexes[chrCheckingKeyChars[intCntr]] = rtb.Find(chrCheckingKeyChars[intCntr].ToString(), intFirstIndexForChecking,
rtb.GetCharIndexFromPosition(ptCurrentCharPosition), RichTextBoxFinds.NoHighlight | RichTextBoxFinds.None);
if (dicCheckingKeyCharsIndexes[chrCheckingKeyChars[intCntr]] != -1)
{
do
{
if (rtb.Find(chrCheckingKeyChars[intCntr].ToString(), intFirstIndexForChecking, rtb.GetCharIndexFromPosition(ptCurrentCharPosition),
RichTextBoxFinds.NoHighlight | RichTextBoxFinds.None) != -1)
{
dicCheckingKeyCharsIndexes[chrCheckingKeyChars[intCntr]] = rtb.Find(chrCheckingKeyChars[intCntr].ToString(), intFirstIndexForChecking,
rtb.GetCharIndexFromPosition(ptCurrentCharPosition), RichTextBoxFinds.NoHighlight | RichTextBoxFinds.None);
}
intFirstIndexForChecking++;
} while (intFirstIndexForChecking != rtb.GetCharIndexFromPosition(ptCurrentCharPosition));
break;
}
}
catch
{
dicCheckingKeyCharsIndexes[chrCheckingKeyChars[intCntr]] = -1;
break;
}
if (bolSearchCurrentLine)
{
break;
}
}
}
return dicCheckingKeyCharsIndexes;
}
/// <summary>
/// Checks a line for calculating its indention level.
/// </summary>
/// <param name="intCharIndex">A char index</param>
/// <param name="rtb">A RichTextBox control</param>
/// <returns>Returns indention level of the line.</returns>
private int CheckingIndentionLevel(int intCharIndex, RichTextBox rtb)
{
int intLineNumber = GetLineNumber(intCharIndex, rtb);
int intIndentionLevelNumber = 0;
intCharIndex = rtb.GetFirstCharIndexFromLine(intLineNumber);
char chrChar = GetChar(intCharIndex, rtb);
if (chrChar == '\n')
{
chrChar = GetChar(++intCharIndex, rtb);
}
if (chrChar != ' ')
{
return 0;
}
else
{
int intSpaceCntr = 0;
while(chrChar == ' ')
{
chrChar = GetChar(++intCharIndex, rtb);
if (chrChar == ' ')
{
intSpaceCntr++;
}
if (intSpaceCntr % 4 == 0 && intSpaceCntr != 0)
{
intIndentionLevelNumber++;
intSpaceCntr = 0;
}
}
if (intSpaceCntr % 4 != 0)
{
intIndentionLevelNumber++;
}
}
return intIndentionLevelNumber;
}
/// <summary>
/// Implements Indention to the codes
/// </summary>
/// <param name="intCharIndex">A char index</param>
/// <param name="intIndentionLevel">The number of indention level</param>
/// <param name="rtb">A RichTextBox control</param>
private void ImplementIndention(int intCharIndex, int intIndentionLevel, RichTextBox rtb)
{
intNextCharIndex = intCharIndex;
intPrevCharIndex = intCharIndex;
int intKeyCharsNumberInLine = 1;
int intCurrentLineNumber = GetLineNumber(rtb);
int intKeyCharLineNumber = GetLineNumber(intNextCharIndex, rtb);
string[] strLinesTexts;
Dictionary<char, int> dicResult;
do
{
rtb.SelectionStart = intPrevCharIndex;
dicResult = IsExistCheckingKeyChars(rtb);
if (dicResult[chrCheckingKeyChars[0]] != -1)
{
intKeyCharsNumberInLine++;
intPrevCharIndex = dicResult[chrCheckingKeyChars[0]];
}
} while (dicResult[chrCheckingKeyChars[0]] != -1);
if (!bolCheckCalling)
{
if (intCurrentLineNumber == intKeyCharLineNumber)
{
for (int intCntr = 1; intCntr <= intKeyCharsNumberInLine; intCntr++)
{
do
{
rtb.SelectionStart = intPrevCharIndex;
dicResult = IsExistCheckingKeyChars(rtb, true);
if (dicResult[chrCheckingKeyChars[0]] != -1)
{
intPrevCharIndex = dicResult[chrCheckingKeyChars[0]];
}
} while (dicResult[chrCheckingKeyChars[0]] != -1);
bolCheckCalling = true;
ImplementIndention(intPrevCharIndex, rtb);
}
return;
}
}
bolCheckCalling = false;
rtb.SelectionStart = intNextCharIndex;
rtb.SelectionLength = 1;
rtb.SelectedText = "\n" + rtb.SelectedText;
intCurrentLineNumber = GetLineNumber(rtb);
strLinesTexts = rtb.Lines;
strLinesTexts[intCurrentLineNumber] = strLinesTexts[intCurrentLineNumber].Trim();
for (int intIndentionCntr = 1; intIndentionCntr <= intIndentionLevel; intIndentionCntr++)
{
for (int intSpaceCntr = 1; intSpaceCntr <= 4; intSpaceCntr++)
{
strLinesTexts[intCurrentLineNumber] = ' ' + strLinesTexts[intCurrentLineNumber];
}
}
rtb.Lines = strLinesTexts;
rtb.SelectionStart = intNextCharIndex + ((intIndentionLevel * 4) + 1);
intNextCharIndex = rtb.SelectionStart;
rtb.SelectionLength = 1;
rtb.SelectedText = rtb.SelectedText + "\n";
intCurrentLineNumber = GetLineNumber(rtb);
strLinesTexts = rtb.Lines;
strLinesTexts[intCurrentLineNumber] = strLinesTexts[intCurrentLineNumber].Trim();
for (int intIndentionCntr = 1; intIndentionCntr <= intIndentionLevel + 1; intIndentionCntr++)
{
for (int intSpaceCntr = 1; intSpaceCntr <= 4; intSpaceCntr++)
{
strLinesTexts[intCurrentLineNumber] = ' ' + strLinesTexts[intCurrentLineNumber];
}
}
rtb.Lines = strLinesTexts;
rtb.SelectionStart = intInitialCursorPosition + ((rtb.TextLength - intInitialCursorPosition) - intRemainingCharsOfInitialText);
intNextCharIndex = rtb.SelectionStart;
intPrevCharIndex = intNextCharIndex;
}
/// <summary>
/// Implements Indention to the codes
/// </summary>
/// <param name="intCharIndex">A char index</param>
/// <param name="rtb">A RichTextBox control</param>
private void ImplementIndention(int intCharIndex, RichTextBox rtb)
{
int intIndentionLevel = CheckingIndentionLevel(intCharIndex, rtb);
ImplementIndention(intCharIndex, intIndentionLevel, rtb);
}
}
}
我希望这个示例代码可以帮助你。
如果您改进它们,请更新和共享代码。