private
pRootNode: ^XRootNode;procedure TfrmDesignerGeneral.ManageAllProject;
var
s:String;
root:TTreeNode;
begin
tvwProject.Items.Clear;
root:= tvwProject.Items.Add(tvwProject.Selected,'aaa'); New(pRootNode); pRootNode^.id:= '';
pRootNode^.name:= 'aaa'; root.Data:= pRootNode; tvwProject.Items.AddChild(root,'tmp');
end;程序编译没问题。运行后出现:access violation at address 00404518 in module 'MyApp.exe'.read of address 00000004
project MyApp raisei exception class EInvalidPointer with message 'Invalid pointer operation'.为什么出现这样的问题?我照着帮助写的。
pRootNode: ^XRootNode;procedure TfrmDesignerGeneral.ManageAllProject;
var
s:String;
root:TTreeNode;
begin
tvwProject.Items.Clear;
root:= tvwProject.Items.Add(tvwProject.Selected,'aaa'); New(pRootNode); pRootNode^.id:= '';
pRootNode^.name:= 'aaa'; root.Data:= pRootNode; tvwProject.Items.AddChild(root,'tmp');
end;程序编译没问题。运行后出现:access violation at address 00404518 in module 'MyApp.exe'.read of address 00000004
project MyApp raisei exception class EInvalidPointer with message 'Invalid pointer operation'.为什么出现这样的问题?我照着帮助写的。
解决方案 »
- 超难问题!!保存数据时,ADOQuery的SQL改变事件严重超时,困扰我多时!解决或给些有用的线索奉送上100
- 用一表记录自动更新另一表记录内容
- openpicturedialog1 出错
- 天方夜谈,能子类化QQ吗?
- ◎◎◎◎◎◎##SQL语句,着急,高分酬谢!※※※
- 程序连接失败,出现错误!
- 送分 一个简单问题!!!!!!!!!可以加分
- 关于delphi的调试时程序出错了,任务拦的程序用蓝色在闪,怎样停止它使delphi 进入设计状态的问题?
- 那位大哥幫我解決SQL問題,謝謝!
- 请问,在Delphi中调用flash怎样才能将flash的背景设为透明。
- QuickReport问题
- 各位兄弟们我是新来的以后大家多关照啊!(散分!)可记住了我叫小人!!!哦哦哦哦!
pRootNode: ^XRootNode;
XRootNode = Record
id:string;
name:string;
......
end;//end of record
XTreeNode = class(TObject)
private
protected
public
name:String;
id:String;
nodeType: integer;
end; PxRootNode = ^XRootNode;
XRootNode = class(XTreeNode)
public
subtype: integer;
value: string;
end;
pRootNode^.id:= '';
^.name:= 'aaa';
root:= tvwProject.Items.AddObject(tvwProject.Selected,'aaa',pRootNode);
var
s:String;
root:TTreeNode;
begin
tvwProject.Items.Clear; New(pRootNode); pRootNode^.id:= '';
pRootNode^.name:= 'aaa';
pRootNode^.nodeType:= 1;
pRootNode^.subtype:= 0;
pRootNode^.value:= ''; root:= tvwProject.Items.AddObject(tvwProject.Selected,'aaa',pRootNode); tvwProject.Items.AddChild(root,'tmp');
end;可是当我把pRootNode^.*** 之类的注释掉就好了。类的定义在前面,为什么?我第一次用Delphi定义类
var
s:String;
root:TTreeNode;
begin
tvwProject.Items.Clear;
New(pRootNode);
pRootNode^.id:= '';
pRootNode^.name:= 'aaa';
pRootNode^.nodeType:= 1;
pRootNode^.subtype:= 0;
pRootNode^.value:= '';
root:= tvwProject.Items.AddChildObject(tvwProject.Selected,'tmp',pRootNode);
Dispose(pRootNode);
end;
类是create的,不是new的
pRootNode^.id:= '';
时发现错误 。id成员是父类的成员。在向父类成员赋值时出现错误。如果执行
pRootNode^.subtype:= 0;
则不会发生错误。后来定义了一个
rootNode: XRootNode;执行rootNode:= XRootNode.create;
pRootNode:= @rootNode
pRootNode^.id:= '';就好用了。那么,诸如
New(pRootNode);
getmem(pRootNode,sizeof(XRootNode));
pRootNode:= @XRootNode.Create;
这样的语句为什么不能起到为XRootNode的父类成员分配内存的效果?
TuserNode=class(Tobject)
firstname:string;
lastName:string;
UserID:string;
end;aUser:=TuserNode.Create();
aUser.firstName='xxx';
aUser.lastName='xxx';
aUser.UserID='xxx';TreeView.Items.item[0].Data:=aUser;
TuserNode(TreeView.Items.item[0].Data).firstName;
TuserNode(TreeView.Items.item[0].Data).UserID;呵呵,感觉不到指针
谢谢提出来,一时弄错了
对了,差点忘了最重要的一点:删除节点之前,一定要把Node.Data指向的
变量(内存)释放了!否则会造成内存泄漏的。
function funFreeTreeViewNodeData(aNode: TTreeNode): integer;
var
p: Pointer;
begin
Result := -1;
if Assigned(aNode.Data) then
begin
try
p := aNode.Data;
Dispose(p);
aNode.Data := nil;
except
on E: Exception do
Application.MessageBox(PChar(E.Message),
'释放树型节点指针(Data)时发生错误', 0);
end;
end;
Result := 1;
end;// 删除节点时释放内存
procedure TGZLLLBMainFrm.trvGZLLreplyDeletion(Sender: TObject;
Node: TTreeNode);
begin
wintelconst.funFreeTreeViewNodeData(Node);
end;
{展开TreeView节点}procedure TGZLLLBMainFrm.trvGZLLreplyExpanding(Sender: TObject; Node:
TTreeNode;
var AllowExpansion: Boolean);
begin
if Node.Level <> 0 then
funGetNodeChildren(1, Node);
end;{刷新TreeView节点,传递"层"参数,
aLevel=0:根节点;aLevel为其它值,非根节点}function TGZLLLBMainFrm.funGetNodeChildren(aLevel: Byte; aNode: TTreeNode):
Byte;
var
I, j: integer;
NodeData: PGZLLNodeData;
trvNode, curNode: TTreeNode;
begin
Result := 0; {失败}
try
trvGZLLreply.Items.BeginUpdate; {更改节点期间禁止刷新}
case aLevel of
{第一层不再使用!!!}
0: {根节点, 一次取两层的数据}
begin
{释放占用内存, 清除所有原来的节点}
vChooseIndexL2 := -1;
if trvGZLLreply.Items.Count > 0 then
begin
{for i := 0 to trvGZLLreply.Items.Count-1 do
wintelconst.prcFreeNodeData(trvGZLLreply.Items[i],False);}
for I := trvGZLLreply.Items.Count - 1 downto 0 do
trvGZLLreply.Items[I].Delete;
end;
with adoqryGZLLL21 do {取第一层节点数据}
begin
Active := False;
Filter := '';
Filtered := False;
SQL.Clear;
SQL.Append(wintelconst.cSQLGZLLLevel1); //cSQLLevel1 Format(,[0])
Active := True;
if not IsEmpty then
begin
for I := 0 to RecordCount - 1 do
begin
new(NodeData);
NodeData^.ID := FieldByName('id').AsInteger;
NodeData^.fjr := FieldByName('fjr').AsString;
curNode := trvGZLLreply.Items.AddObject(nil,
FieldValues['llzt'], NodeData);
{取第二层节点}
with adoqryGZLLL22 do
begin
Active := False;
//SQL.Clear;
//SQL.Append(Format(cSQLLevel2,[PGZLLNodeData(curNode.Data)^.id]));
Parameters.ParamValues['ID'] :=
PGZLLNodeData(curNode.Data)^.ID;
Active := True;
if not IsEmpty then
begin
for j := 0 to RecordCount - 1 do
begin
new(NodeData);
NodeData^.ID := FieldValues['id'];
NodeData^.fjr := FieldValues['fjr'];
trvGZLLreply.Items.AddChildObject(curNode,
FieldValues['llzt'], NodeData); //curCNode :=
Next;
end; {end for(j)}
end;
Active := False;
end; {end with adoqryGZLL2}
Next;
end; {end for(i)}
end;
Active := False;
//EmptyRec := IsEmpty;
end; {end with adoqryGZLL}
Result := 1;
end; {end case(0)}
1: {非根节点,取本层的子节点以及孙节点,相当于刷新}
begin
trvNode := aNode;
{如果有子节点,先把所有的删除}
if trvNode.HasChildren then
begin
{for i := 0 to trvNode.Count-1 do
wintelconst.prcFreeNodeData(trvNode.Item[i],False); }
trvNode.DeleteChildren;
end;
with adoqryGZLLL21 do {子节点}
begin
Active := False;
Filter := '';
Filtered := False;
SQL.Clear;
SQL.Append(Format(wintelconst.cSQLGZLLLevel2,
[PGZLLNodeData(trvNode.Data)^.ID]));
//SQL.Append(fun
Active := True;
Sort := 'id DESC';
for I := 0 to RecordCount - 1 do
begin
new(NodeData);
NodeData^.ID := FieldValues['id'];
NodeData^.fjr := FieldValues['fjr'];
curNode := trvGZLLreply.Items.AddChildObject(trvNode,
FieldValues['llzt'], NodeData); //curCNode :=
{取第二层节点}
with adoqryGZLLL22 do
begin
Active := False;
//SQL.Clear;
//SQL.Append(Format(cSQLLevel2,[PGZLLNodeData(curNode.Data)^.id]));
Parameters.ParamValues['ID'] :=
PGZLLNodeData(curNode.Data)^.ID;
Active := True;
Sort := 'id DESC';
if not IsEmpty then
begin
for j := 0 to RecordCount - 1 do
begin
new(NodeData);
NodeData^.ID := FieldValues['id'];
NodeData^.fjr := FieldValues['fjr'];
trvGZLLreply.Items.AddChildObject(curNode,
FieldValues['llzt'], NodeData); //curCNode :=
Next;
end; {end for(j)}
end;
Active := False;
end; {end with adoqryGZLL2}
Next;
end;
Active := False;
end; {end with adoqryGZLL}
Result := 1;
end; {end case(1)}
end; {end case}
finally
trvGZLLreply.Items.EndUpdate; {开始刷新}
end;
end;
对了,差点忘了最重要的一点:删除节点之前,一定要把Node.Data指向的
变量(内存)释放了!否则会造成内存泄漏的。
function funFreeTreeViewNodeData(aNode: TTreeNode): integer;
var
p: Pointer;
begin
Result := -1;
if Assigned(aNode.Data) then
begin
try
p := aNode.Data;
Dispose(p);
aNode.Data := nil;
except
on E: Exception do
Application.MessageBox(PChar(E.Message),
'释放树型节点指针(Data)时发生错误', 0);
end;
end;
Result := 1;
end;// 删除节点时释放内存
procedure TGZLLLBMainFrm.trvGZLLreplyDeletion(Sender: TObject;
Node: TTreeNode);
begin
wintelconst.funFreeTreeViewNodeData(Node);
end;
{展开TreeView节点}procedure TGZLLLBMainFrm.trvGZLLreplyExpanding(Sender: TObject; Node:
TTreeNode;
var AllowExpansion: Boolean);
begin
if Node.Level <> 0 then
funGetNodeChildren(1, Node);
end;{刷新TreeView节点,传递"层"参数,
aLevel=0:根节点;aLevel为其它值,非根节点}function TGZLLLBMainFrm.funGetNodeChildren(aLevel: Byte; aNode: TTreeNode):
Byte;
var
I, j: integer;
NodeData: PGZLLNodeData;
trvNode, curNode: TTreeNode;
begin
Result := 0; {失败}
try
trvGZLLreply.Items.BeginUpdate; {更改节点期间禁止刷新}
case aLevel of
{第一层不再使用!!!}
0: {根节点, 一次取两层的数据}
begin
{释放占用内存, 清除所有原来的节点}
vChooseIndexL2 := -1;
if trvGZLLreply.Items.Count > 0 then
begin
{for i := 0 to trvGZLLreply.Items.Count-1 do
wintelconst.prcFreeNodeData(trvGZLLreply.Items[i],False);}
for I := trvGZLLreply.Items.Count - 1 downto 0 do
trvGZLLreply.Items[I].Delete;
end;
with adoqryGZLLL21 do {取第一层节点数据}
begin
Active := False;
Filter := '';
Filtered := False;
SQL.Clear;
SQL.Append(wintelconst.cSQLGZLLLevel1); //cSQLLevel1 Format(,[0])
Active := True;
if not IsEmpty then
begin
for I := 0 to RecordCount - 1 do
begin
new(NodeData);
NodeData^.ID := FieldByName('id').AsInteger;
NodeData^.fjr := FieldByName('fjr').AsString;
curNode := trvGZLLreply.Items.AddObject(nil,
FieldValues['llzt'], NodeData);
{取第二层节点}
with adoqryGZLLL22 do
begin
Active := False;
//SQL.Clear;
//SQL.Append(Format(cSQLLevel2,[PGZLLNodeData(curNode.Data)^.id]));
Parameters.ParamValues['ID'] :=
PGZLLNodeData(curNode.Data)^.ID;
Active := True;
if not IsEmpty then
begin
for j := 0 to RecordCount - 1 do
begin
new(NodeData);
NodeData^.ID := FieldValues['id'];
NodeData^.fjr := FieldValues['fjr'];
trvGZLLreply.Items.AddChildObject(curNode,
FieldValues['llzt'], NodeData); //curCNode :=
Next;
end; {end for(j)}
end;
Active := False;
end; {end with adoqryGZLL2}
Next;
end; {end for(i)}
end;
Active := False;
//EmptyRec := IsEmpty;
end; {end with adoqryGZLL}
Result := 1;
end; {end case(0)}
1: {非根节点,取本层的子节点以及孙节点,相当于刷新}
begin
trvNode := aNode;
{如果有子节点,先把所有的删除}
if trvNode.HasChildren then
begin
{for i := 0 to trvNode.Count-1 do
wintelconst.prcFreeNodeData(trvNode.Item[i],False); }
trvNode.DeleteChildren;
end;
with adoqryGZLLL21 do {子节点}
begin
Active := False;
Filter := '';
Filtered := False;
SQL.Clear;
SQL.Append(Format(wintelconst.cSQLGZLLLevel2,
[PGZLLNodeData(trvNode.Data)^.ID]));
//SQL.Append(fun
Active := True;
Sort := 'id DESC';
for I := 0 to RecordCount - 1 do
begin
new(NodeData);
NodeData^.ID := FieldValues['id'];
NodeData^.fjr := FieldValues['fjr'];
curNode := trvGZLLreply.Items.AddChildObject(trvNode,
FieldValues['llzt'], NodeData); //curCNode :=
{取第二层节点}
with adoqryGZLLL22 do
begin
Active := False;
//SQL.Clear;
//SQL.Append(Format(cSQLLevel2,[PGZLLNodeData(curNode.Data)^.id]));
Parameters.ParamValues['ID'] :=
PGZLLNodeData(curNode.Data)^.ID;
Active := True;
Sort := 'id DESC';
if not IsEmpty then
begin
for j := 0 to RecordCount - 1 do
begin
new(NodeData);
NodeData^.ID := FieldValues['id'];
NodeData^.fjr := FieldValues['fjr'];
trvGZLLreply.Items.AddChildObject(curNode,
FieldValues['llzt'], NodeData); //curCNode :=
Next;
end; {end for(j)}
end;
Active := False;
end; {end with adoqryGZLL2}
Next;
end;
Active := False;
end; {end with adoqryGZLL}
Result := 1;
end; {end case(1)}
end; {end case}
finally
trvGZLLreply.Items.EndUpdate; {开始刷新}
end;
end;