@狂给分了@ 难!--RichEdit编写XML编辑器--!难(200分)

  • 主题发起人 主题发起人 心碎了才懂
  • 开始时间 开始时间

心碎了才懂

Unregistered / Unconfirmed
GUEST, unregistred user!
正在写一个XML编辑器,用的是Delphi7的RichEdit和TreeView控件,有好多问题难以解决,比如说:
·语法高亮
·自动格式化
·结点定位
哪位高手能回答我下面的几个问题:
1、回车换行的时候,自动缩进和上一行对齐。怎样实现?
2、当点击结点树(TreeView)的时候,RichEdit光标自动定位到相应的结点。怎样实现?
3、在编辑文本的时候,怎么实时的保持语法着色?
或者谁有RichEdit的文档,希望给我一份。delphi的帮助实在是太少了!RichEdit单元定义的那些消息都不知道是干什么的!
 
分不够可以再加!!![:(!]
 
希望有人和我讨论一下!大家一起来解决!
 
是不是可以加一个字符串主动匹配的函数啊?
好久没有编程了,手生了,精神上支持你~!不要心碎,呵呵
 
不要让我的贴沉了!
 
·语法高亮
·自动格式化
以上旧贴子中有人讨论过 你可以查一下

其他未作过。。。
 
我也想知道哈,能不能交流一下?
 
回答1、回车换行的时候,自动缩进和上一行对齐。怎样实现?
Richedit1.Paragraph.Alignment:=taLeftJustify;
//属性可以设置段落的 居左(taLeftJustify),居右(taRightJustify)、居中(taCenter);
Richedit1.Paragraph.FirstIndent:=30; //段落首行缩进
Richedit1.Paragraph.LeftIndent:=-20; //段落左缩进
Richedit1.Paragraph.RightIndent:=-20; //段落右缩

当你设置好了,回车换行的时候和上一行自动缩进一致,如果你上一行如果用手工设置的你就做过判断然后在给该行进行设置,你看这样行吗?我已经试过了!
 
我也做过xml编辑器,不过使用一个类似 dbtree的控件,象使用RichEdit 和treeview
搂主可以看看delphi的 xml mapping
 
回答2、当点击结点树(TreeView)的时候,RichEdit光标自动定位到相应的结点。怎样实现?
用TreeView相应的标志,在RichEdit中搜索相应的标志结点,
(最好不要直接在RichEdit中搜索,标志不要重复)
光标自动定位是: RichEdit1.SelStart(在RichEdit中搜索相应的结点的位置);
RichEdit1.SelLength(RichEdit中相应的标志的长度);

你看行了吗?
 
1、回车换行的时候,自动缩进和上一行对齐。怎样实现?
-- 所谓“行”,不过是多个用#13#10分开的字符串。“自动缩进和上一行对齐”应该是在新回车(#13#10)前面插入n个空格,至于n等于几?只需计算一下向前数第2个回车(#13#10)后面带了几个空格就行了。

2、当点击结点树(TreeView)的时候,RichEdit光标自动定位到相应的结点。怎样实现?
-- 这似乎应该建立TreeView和RichEdit中内容的联系,不妨考虑让每个TreeView的节点TTreeNode的Data指向一个自定义的数据结构,在数据结构中记录RichEdit中相关内容,比如位置,颜色,字体等等。

3、在编辑文本的时候,怎么实时的保持语法着色?
--没看懂想干什么。大概是想完成一个单词的录入后再根据单词内容设置字体颜色吧?
 
回答 3、在编辑文本的时候,怎么实时的保持语法着色?
可以拦截输入内容;
用线程来给编辑的一行着色,比如发现空格回车点等你觉得需要时
 
我是用先序遍历XMLDocument控件建立结点树和输出文本的,代码:
procedure TForm1.VisitChild(aNode: IXMLNode;level:Integer); //先序遍历出入文本
var
i:Integer;
begin
if aNode<>nil then
begin
myOutputNode(aNode,level);
for i := 0 to aNode.ChildNodes.Count-1 do
begin
VisitChild(aNode.ChildNodes,level+1);
end;
myOutputEnd(aNode,level);
end;
end;

procedure TForm1.BuildTree(aChild: IXMLNode; Parent: TTreeNode);//先序建立结点树
var
aTreeNode:TTreeNode;
i:Integer;
begin
if aChild<>nil then
begin
aTreeNode:=TreeView1.Items.AddChild(Parent,myOutPutTreeNode(aChild));
aTreeNode.ImageIndex:=myCheckNodeType(aChild.NodeType);
aTreeNode.SelectedIndex:=myCheckNodeType(aChild.NodeType);
if myCheckNodeType(aChild.NodeType)=1 then
begin
aTreeNode.SelectedIndex:=13;
end;
aTreeNode.Data:=@aChild;
for i := 0 to aChild.ChildNodes.Count-1 do
begin
BuildTree(aChild.ChildNodes,aTreeNode);
end;
end;
end;
 
这是具体判断结点类型,并输出:
procedure tform1.myOutputNode(aChildNode:IXMLNode;level:Integer);
function indent(level:Integer):Integer;
begin
Result:=level*20;
end;
var
i:Integer;
CDATAList:TStringList;
//CharFmt:TCharFormat2;
begin
RichEdit1.Paragraph.Alignment:=taLeftJustify;
RichEdit1.Paragraph.FirstIndent:=indent(level);
RichEdit1.Paragraph.LeftIndent:=indent(level);
case myCheckNodeType(aChildNode.NodeType) of
0:;//do nothing
1:begin
RichEdit1.SelAttributes.Color:=clRed;
RichEdit1.SelAttributes.Style:=[fsBold];
RichEdit1.Lines.Add({indent(level)+}'<'+aChildNode.NodeName);
if aChildNode.AttributeNodes.Count>0 then
begin
for i := 0 to aChildNode.AttributeNodes.Count-1 do
begin
RichEdit1.Lines.Strings[RichEdit1.Lines.Count-1]:=
RichEdit1.Lines.Strings[RichEdit1.Lines.Count-1]
+' '
+aChildNode.AttributeNodes.NodeName+'=&quot;'
+VarToStr(aChildNode.AttributeNodes.NodeValue+'&quot;');
end;
end;
RichEdit1.Lines.Strings[RichEdit1.Lines.Count-1]:=
RichEdit1.Lines.Strings[RichEdit1.Lines.Count-1]+'>';
end;
2:;//do nothing
3:begin
RichEdit1.SelAttributes.Color:=clBlack;
RichEdit1.SelAttributes.Style:=[fsBold];
RichEdit1.Lines.Add({indent(level)+}aChildNode.Text);
end;
4:begin
CDATAList:=TStringList.Create;
//CDATAList.Assign()
//
CDATAList.Text:='<![CDATA['+VarToStr(aChildNode.NodeValue)+']]>';
for i := 0 to CDATAList.Count-1 do
begin
if i=0 then
begin
RichEdit1.SelAttributes.Color:=clBlue;
RichEdit1.SelAttributes.Style:=[fsBold];
RichEdit1.Lines.Add({indent(level)+}CDATAList.Strings);
end
else if i=CDATAList.Count-1 then
begin
RichEdit1.SelAttributes.Color:=clBlue;
RichEdit1.SelAttributes.Style:=[fsBold];
RichEdit1.Lines.Add({indent(level)+' '+}CDATAList.Strings);
end
else
begin
RichEdit1.SelAttributes.Color:=clBlack;
RichEdit1.SelAttributes.Style:=[];
RichEdit1.Lines.Add({indent(level)+' '+}CDATAList.Strings);
end;
end;
CDATAList.Free;
end;
5:;//do nothing
6:;//do nothing
7:begin
RichEdit1.SelAttributes.Color:=clBlue;
RichEdit1.Lines.Add({indent(level)+}'<?xml '+VarToStr(aChildNode.NodeValue)+'?>');
end;
8:begin
RichEdit1.SelAttributes.Color:=clGrayText;
RichEdit1.Lines.Add({indent(level)+}'<!--'+VarToStr(aChildNode.NodeValue)+
'-->');
end;
9:;
10:;
11:;
12:;
end;
end;
 
问题是输出以后,有的结点颜色不对,我开始的时候没有设置段落格式,就是用空格缩进的,格式没问题,但是回车换行不对。现在改成设置段落格式缩进,回车对了但是输出以后的格式乱七八糟!
[:(][:(][:(]
 
全部代码:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, xmldom, XMLIntf, msxmldom, XMLDoc, ComCtrls, ToolWin, StdCtrls,
ExtCtrls,RichEdit, ImgList;

{Types,RichEdit,u_keywords;}
type
TForm1 = class(TForm)
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
TreeView1: TTreeView;
Splitter1: TSplitter;
RichEdit1: TRichEdit;
StatusBar1: TStatusBar;
ToolBar1: TToolBar;
LoadToolBtn: TToolButton;
XMLDocument1: TXMLDocument;
CancelToolBtn: TToolButton;
SaveAllToolBtn: TToolButton;
ImageList1: TImageList;
procedure LoadToolBtnClick(Sender: TObject);
procedure RichEdit1KeyPress(Sender: TObject; var Key: Char);
procedure SaveAllToolBtnClick(Sender: TObject);
procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
procedure RichEdit1Enter(Sender: TObject);
procedure RichEdit1Change(Sender: TObject);
procedure RichEdit1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure CancelToolBtnClick(Sender: TObject);

private
{ Private declarations }
//function getXY:TPoint;
public
{ Public declarations }
function myCheckNodeType(aNodeType:TNodeType):Integer;
procedure myOutputNode(aChildNode:IXMLNode;level:Integer);
procedure myOutputEnd(aChildNode:IXMLNode;level:Integer);
procedure VisitChild(aNode:IXMLNode;level:Integer);
function myOutPutTreeNode(aXMLNode:IXMLNode):string;
procedure BuildTree(aChild:IXMLNode;Parent:TTreeNode);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure tform1.myOutputNode(aChildNode:IXMLNode;level:Integer);
function indent(level:Integer):Integer;
var
//s:string;
i:Integer;
begin
{s:='';
for i := 0 to level do
begin
s:=s+' ';
end;
Result:=Copy(s,0,Length(s)-4); }
Result:=level*20;
end;
var
i:Integer;
CDATAList:TStringList;
//CharFmt:TCharFormat2;
begin
RichEdit1.Paragraph.Alignment:=taLeftJustify;
RichEdit1.Paragraph.FirstIndent:=indent(level);
RichEdit1.Paragraph.LeftIndent:=indent(level);
case myCheckNodeType(aChildNode.NodeType) of
0:;//do nothing
1:begin
RichEdit1.SelAttributes.Color:=clRed;
RichEdit1.SelAttributes.Style:=[fsBold];
RichEdit1.Lines.Add({indent(level)+}'<'+aChildNode.NodeName);
if aChildNode.AttributeNodes.Count>0 then
begin
for i := 0 to aChildNode.AttributeNodes.Count-1 do
begin
RichEdit1.Lines.Strings[RichEdit1.Lines.Count-1]:=
RichEdit1.Lines.Strings[RichEdit1.Lines.Count-1]
+' '
+aChildNode.AttributeNodes.NodeName+'=&quot;'
+VarToStr(aChildNode.AttributeNodes.NodeValue+'&quot;');
end;
end;
RichEdit1.Lines.Strings[RichEdit1.Lines.Count-1]:=
RichEdit1.Lines.Strings[RichEdit1.Lines.Count-1]+'>';
end;
2:;//do nothing
3:begin
RichEdit1.SelAttributes.Color:=clBlack;
RichEdit1.SelAttributes.Style:=[fsBold];
RichEdit1.Lines.Add({indent(level)+}aChildNode.Text);
end;
4:begin
CDATAList:=TStringList.Create;
//CDATAList.Assign()
//
CDATAList.Text:='<![CDATA['+VarToStr(aChildNode.NodeValue)+']]>';
for i := 0 to CDATAList.Count-1 do
begin
if i=0 then
begin
RichEdit1.SelAttributes.Color:=clBlue;
RichEdit1.SelAttributes.Style:=[fsBold];
RichEdit1.Lines.Add({indent(level)+}CDATAList.Strings);
end
else if i=CDATAList.Count-1 then
begin
RichEdit1.SelAttributes.Color:=clBlue;
RichEdit1.SelAttributes.Style:=[fsBold];
RichEdit1.Lines.Add({indent(level)+' '+}CDATAList.Strings);
end
else
begin
RichEdit1.SelAttributes.Color:=clBlack;
RichEdit1.SelAttributes.Style:=[];
RichEdit1.Lines.Add({indent(level)+' '+}CDATAList.Strings);
end;
end;
CDATAList.Free;
end;
5:;//do nothing
6:;//do nothing
7:begin
RichEdit1.SelAttributes.Color:=clBlue;
RichEdit1.Lines.Add({indent(level)+}'<?xml '+VarToStr(aChildNode.NodeValue)+'?>');
end;
8:begin
RichEdit1.SelAttributes.Color:=clGrayText;
RichEdit1.Lines.Add({indent(level)+}'<!--'+VarToStr(aChildNode.NodeValue)+
'-->');
end;
9:;
10:;
11:;
12:;
end;
end;

function tform1.myCheckNodeType(aNodeType:TNodeType):Integer;
begin
if aNodeType=ntReserved then Result:=0;
if aNodeType=ntElement then Result:=1;
if aNodeType=ntAttribute then Result:=2;
if aNodeType=ntText then Result:=3;
if aNodeType=ntCData then Result:=4;
if aNodeType=ntEntityRef then Result:=5;
if aNodeType=ntEntity then Result:=6;
if aNodeType=ntProcessingInstr then Result:=7;
if aNodeType=ntComment then Result:=8;
if aNodeType=ntDocument then Result:=9;
if aNodeType=ntDocType then Result:=10;
if aNodeType=ntDocFragment then Result:=11;
if aNodeType=ntNotation then Result:=12;
end;

procedure TForm1.LoadToolBtnClick(Sender: TObject);
begin
XMLDocument1.LoadFromFile('C:/Documents and Settings/Admin/桌面/a.xml');
XMLDocument1.Active:=True;
if XMLDocument1.IsEmptyDoc then Exit;
if not XMLDocument1.Active then Exit;
RichEdit1.Lines.Clear;
TreeView1.Items.Clear;
BuildTree(XMLDocument1.DocumentElement.ParentNode,nil);
VisitChild(XMLDocument1.DocumentElement.ParentNode,0);
SaveAllToolBtn.Enabled:=False;
CancelToolBtn.Enabled:=False;
StatusBar1.Panels[2].Text:='字节数:'+IntToStr(Length(RichEdit1.Text));
end;

procedure TForm1.VisitChild(aNode: IXMLNode;level:Integer); //先序遍历
var
i:Integer;
begin
if aNode<>nil then
begin
myOutputNode(aNode,level);
for i := 0 to aNode.ChildNodes.Count-1 do
begin
VisitChild(aNode.ChildNodes,level+1);
end;
myOutputEnd(aNode,level);
end;
end;

procedure TForm1.myOutputEnd(aChildNode: IXMLNode; level: Integer);
function indent(level:Integer):Integer;
var
//s:string;
i:Integer;
begin
{s:='';
for i := 0 to level do
begin
s:=s+' ';
end;
Result:=Copy(s,0,Length(s)-4); }
Result:=level*20;
end;
begin
case myCheckNodeType(aChildNode.NodeType) of
0:;
1:begin
RichEdit1.Paragraph.Alignment:=taLeftJustify;
RichEdit1.Paragraph.FirstIndent:=indent(level);
RichEdit1.Paragraph.LeftIndent:=indent(level);
RichEdit1.SelAttributes.Color:=clRed;
RichEdit1.SelAttributes.Style:=[fsBold];
RichEdit1.Lines.Add({indent(level)+}'</'+aChildNode.NodeName+'>');
end;
2:;
3:;
4:;
5:;
6:;
7:;
8:;
9:;
10:;
11:;
12:;
end;
end;

{function TForm1.getXY: TPoint;
begin
//result.Y:=SendMessage(Handle, EM_EXLINEFROMCHAR, 0,SelStart);
//result.X:=(SelStart - SendMessage(Handle, EM_LINEINDEX, result.Y, 0));
end; }



procedure TForm1.RichEdit1KeyPress(Sender: TObject; var Key: Char);
var
x,y:Integer;
begin
Y:=RichEdit1.Perform(EM_EXLINEFROMCHAR, 0,richedit1.SelStart);
X:=(RichEdit1.SelStart - RichEdit1.Perform(EM_LINEINDEX, Y, 0));
StatusBar1.Panels[1].Text:='行:'+IntToStr(y)+',列:'+IntToStr(x);
if Key=#13 then
begin
{j:=0;
repeat
if s[j]<>' ' then
begin
Break;
end;
j:=j+1;
until i>Length(s);
for c := 1 to j do
begin
RichEdit1.Lines.Strings[i+1]:=' '+RichEdit1.Lines.Strings[i+1];
end;}
end;
end;


procedure TForm1.BuildTree(aChild: IXMLNode; Parent: TTreeNode);//先序建立结点树
var
aTreeNode:TTreeNode;
i:Integer;
begin
if aChild<>nil then
begin
aTreeNode:=TreeView1.Items.AddChild(Parent,myOutPutTreeNode(aChild));
aTreeNode.ImageIndex:=myCheckNodeType(aChild.NodeType);
aTreeNode.SelectedIndex:=myCheckNodeType(aChild.NodeType);
if myCheckNodeType(aChild.NodeType)=1 then
begin
aTreeNode.SelectedIndex:=13;
end;
aTreeNode.Data:=@aChild;
for i := 0 to aChild.ChildNodes.Count-1 do
begin
BuildTree(aChild.ChildNodes,aTreeNode);
end;
end;
end;


function TForm1.myOutPutTreeNode(aXMLNode: IXMLNode):string;
begin
case myCheckNodeType(aXMLNode.NodeType) of
0:Result:=aXMLNode.NodeName;
1:Result:='<'+aXMLNode.NodeName+'>';
2:Result:=aXMLNode.NodeName;
3:Result:=aXMLNode.NodeName;
4:Result:=aXMLNode.NodeName;
5:Result:=aXMLNode.NodeName;
6:Result:=aXMLNode.NodeName;
7:Result:='<?'+aXMLNode.NodeName+'...?>';
8:Result:='<!-- '+aXMLNode.NodeName+'...-->';
9:Result:=aXMLNode.NodeName;
10:Result:=aXMLNode.NodeName;
11:Result:=aXMLNode.NodeName;
12:Result:=aXMLNode.NodeName;
end;
end;

procedure TForm1.SaveAllToolBtnClick(Sender: TObject);
var
i:Integer;
begin
XMLDocument1.XML.Clear;
for i := 0 to RichEdit1.Lines.Count-1 do
begin
XMLDocument1.XML.Add(Trim(RichEdit1.Lines.Strings));
end;
//XMLDocument1.XML.Append('<!--北京瑞德高科技术有限公司 www.x-sql.com-->');
XMLDocument1.Active:=True;
RichEdit1.Lines.Clear;
TreeView1.Items.Clear;
if XMLDocument1.IsEmptyDoc then Exit;
if not XMLDocument1.Active then Exit;
BuildTree(XMLDocument1.DocumentElement.ParentNode,nil);
VisitChild(XMLDocument1.DocumentElement.ParentNode,0);
XMLDocument1.XML.SaveToFile('C:/Documents and Settings/Admin/桌面/w.xml');
CancelToolBtn.Enabled:=False;
SaveAllToolBtn.Enabled:=False;
end;

procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
var
i:Integer;
//search:string;
//aNode:TTreeNode;
begin
case TreeView1.Selected.ImageIndex of
0:;
1:begin
for i := 0 to TreeView1.Selected.Level do
begin
;
end;
end;
2:;
3:;
end;
end;

procedure TForm1.RichEdit1Enter(Sender: TObject);
var
x,y:Integer;
begin
Y:=RichEdit1.Perform(EM_EXLINEFROMCHAR, 0,richedit1.SelStart);
X:=(RichEdit1.SelStart - RichEdit1.Perform(EM_LINEINDEX, Y, 0));
StatusBar1.Panels[1].Text:='行:'+IntToStr(y)+',列:'+IntToStr(x);

end;

procedure TForm1.RichEdit1Change(Sender: TObject);
var
x,y:Integer;
begin
CancelToolBtn.Enabled:=True;
SaveAllToolBtn.Enabled:=True;
Y:=RichEdit1.Perform(EM_EXLINEFROMCHAR, 0,richedit1.SelStart);
X:=(RichEdit1.SelStart - RichEdit1.Perform(EM_LINEINDEX, Y, 0));
StatusBar1.Panels[1].Text:='行:'+IntToStr(y)+',列:'+IntToStr(x);
StatusBar1.Panels[2].Text:='字节数:'+IntToStr(Length(RichEdit1.Text));
end;

procedure TForm1.RichEdit1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
x1,y1:Integer;
begin
Y1:=RichEdit1.Perform(EM_EXLINEFROMCHAR, 0,richedit1.SelStart);
X1:=(RichEdit1.SelStart - RichEdit1.Perform(EM_LINEINDEX, Y1, 0));
StatusBar1.Panels[1].Text:='行:'+IntToStr(y1)+',列:'+IntToStr(x1);
end;

procedure TForm1.CancelToolBtnClick(Sender: TObject);
begin
LoadToolBtn.Click;
SaveAllToolBtn.Enabled:=False;
CancelToolBtn.Enabled:=False;
end;

end.
 
楼主可以从网上下载 inno setup的源码看看
里面的编辑器有楼主需要的全部功能,包括关键字高亮,自动缩进等等。
 
我也看过别的编辑器的代码,它们好像都是在载入文本的时候先把文本整个扫描一边,再输出,而且关键字是事先定义好的,可是我的难题是XML文档允许用户自定义结点名称、属性和内容,不一定有<,<!,</,<!--等等字符就是结点,比如<![CDATA[结点的内容里面什么字符都可能有,还要考虑到换行。我知道和注释的处理方法类似,但是我终究还是要借助XMLDocument控件,毕竟它可以给我文档出错信息,要是我自己处理出错信息并且定位,太难了!目前我的水平还做不到,怪我当年没好好看《编译原理》。[:(]
 
各位高手,给点儿建议,给点儿想法![xx(]
 
我最近也在研究XML的解析器。我的目的是将RxRichEdit中的文字(内容和文字属性)、图片、表格等信息保存成XML文件,请问大侠们都现成的控件或源码么?我的QQ:316251557。
 
后退
顶部