请问我想单击treeview里的一项,把它的text取出来,应该在哪个事件里写代码?
我用click事件试过,可不管单击哪里都会执行相同代码,我在change事件中也试了,可以是可以,不过在change里写代码就不能区分单击和双击操作了
因此我想请问,如果在click事件中写代码,如何防止单击不相干的地方也同时执行相同代码,谢谢,很急!
哦,我想知道treeview中的各数据项是如何编码的,比如如何区分点击的是同级树的第几项!
还有,感问那位兄台有treeview的资料,包括属性、事件、函数等,感激不尽!
我用click事件试过,可不管单击哪里都会执行相同代码,我在change事件中也试了,可以是可以,不过在change里写代码就不能区分单击和双击操作了
因此我想请问,如果在click事件中写代码,如何防止单击不相干的地方也同时执行相同代码,谢谢,很急!
哦,我想知道treeview中的各数据项是如何编码的,比如如何区分点击的是同级树的第几项!
还有,感问那位兄台有treeview的资料,包括属性、事件、函数等,感激不尽!
解决方案 »
- wsdl 不能装载dll
- 一个关于数据库的控件问题!? 请各位帮忙
- 请哪位大侠提供一个免费下载DELPHI第三方控件的网址啊!
- 窗体设计
- 我想用通过消息把一个字符串传递到另外一个窗口,该怎么做?
- 如何将DBGrid中显示的内容转为txt类型的文件?
- 請教各位達人﹐我想寫一個函數﹐傳進去未知個參數(N1,N2,N3.....)﹐不知該如何寫啊?
- 高难问题
- 如何实现类似Delphi的属性窗体似的窗体
- 前阵听各位说,电子工业出版社的<<DELPHI5从入门到精通>>有某些错误,今天我买了这本书,所以想请哥哥姐姐们帮我
- 我用SQL把一个字段的东西放在了COMBOBOX上,但运行的时候下来才看到拿些数据,怎么把那些数据的第一个提取上COMBOBOX上
- 如何解决速度慢的问题
ListItem: TListItem;
begin
ListItem:=ListView1.Items.Add;
ListItem.Caption := FlatEdit1.text;
ListItem.SubItems.Add(FlatEdit3.Text);
ListItem.SubItems.Add( FlatEdit2.Text);
ListItem.SubItems.Add( FlatEdit5.Text);
ListItem.SubItems.Add(FlatEdit4.Text);
ListItem.SubItems.Add(FlatEdit6.Text);
看看这样吧!
也许对你有一点点用!
procedure TForm1.TreeView1Click(Sender:TObject);
begin
with TreeView1 do
if Selected<>Nil then
ShowMessage(Selected.Text);
end;至于你说的如何判断当前Click的是TreeView1的第几项,你可以这样判断:
if TreeView1.Selected<>Nil then
ShowMessage(IntToStr(TreeView1.Selected.AbsoluteIndex-TreeView1.Selected.Parent.AbsoluteIndex)); //这里显示多少,就说明是同级中的第几项目。
另外,至于你说TreeView中是如何编码的,以及它的相关的属性,方法等信息,你完全可以直接看D的帮助,那是最权威的东西!
begin
showmessage(TreeView1.selected.text);
end
begin
showmessage(TreeView1.selected.text);
end
TreeView有Images属性不是吗?自己做三张小图片:全选中、部分选中、不选状态(直接拍下CheckBox三种状态的图片在加工一下就可以了),然后在点击事件中根据具体情况设置TTreeNodes的ImageIndex就OK了。
如果嫌麻烦的话就去Down一个控件,其实有些控件也是这样做的,界面上你是看不出来的. :)
**************
Manan Patel <[email protected]>
重载TreeView的CreateParams:
type
TCheckBoxTreeView = class(TTreeView)
protected
procedure CreateParams(var Params: TCreateParams); override;
end;procedure TCheckBoxTreeView.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.Style:=Params.Style or TVS_CHECKBOXES;
{ TVS_CHECKBOXES declared in CommCtrl }
end;如果要Check这个CheckBox,可以用下面的代码:
function IsNodeChecked(Node :TTreeNode) :Boolean;
const
TVIS_CHECKED = $2000;
var
TvItem :TTVItem;
begin
TvItem.Mask := TVIF_STATE;
TvItem.hItem := Node.ItemId;
TreeView_GetItem(Node.TreeView.Handle, TvItem);
Result := (TvItem.State and TVIS_CHECKED) = TVIS_CHECKED;
end;procedure SetNodeChecked(Node :TTreeNode; Checked :Boolean);
const
TVIS_CHECKED = $2000;
var
TvItem :TTVItem;
begin
FillChar(TvItem, SizeOf(TvItem), 0);
with TvItem do begin
hItem := Node.ItemId;
Mask := TVIF_STATE;
StateMask := TVIS_STATEIMAGEMASK;
if Checked then
TvItem.State :=TVIS_CHECKED
else
TvItem.State :=TVIS_CHECKED shr 1;
TreeView_SetItem(Node.TreeView.Handle, TvItem);
end;
end;
可以做成事件和封装成一个类:
private OldState :Boolean;procedure Change(Node: TTreeNode); override;
begin
inherited Change(Node);
OldState := IsNodeChecked(Node);
end;procedure Click; override;
var
NewState :Boolean;
begin
inherited Click;
NewState := IsNodeChecked(Self.Selected);
if NewState = OldState then Exit;
if (NewState) and Assigned(OnNodeChecked) then OnNodeChecked()
else if (not NewState) and Assigned(OnNodeUnChecked) then
OnNodeUnChecked()// OnNodeChecked & OnNodeUnchecked will be events that you declare
end;
弄一个窗口,放上一个TreeView和一个Button,分别取名为TV1和Btn1。如果需要
在每个节点前有个图,请在窗口上放上一个ImageList,取名为ImageList1,双击
它,加入六个图标。还要记得记得将TV1的Images属性改为ImageList1噢。双击按
钮Btn1,在里面填入以下代码,然后按F9运行,点击Btn1就可以看到效果了。
procedure TForm1.Btn1Click(Sender: TObject);
Const
MyDocDir = 'C:\My Documents';
PersonDir = '3hSoft';
Var
Var
I : Word;
SubNodeName : array [1..5] of ShortString;
RootNode, SubNode : TTreeNode;
P : PString;
begin
SubNodeName[1] := '便笺';
SubNodeName[2] := '发件箱';
SubNodeName[3] := '联系人';
SubNodeName[4] := '任务';
SubNodeName[5] := '日记';
TV1.Items.Clear;
TV1.Items.BeginUpdate;
New(P);
P^ := MyDocDir + '\' + PersonDir;
RootNode := TV1.Items.AddObject(Nil, '个人文件夹', P);
// 此 Node 的图标已对 Images 属性中取第 0 个了。
For I := 1 to 5 do
begin
New(P);
P^ := MyDocDir + '\' + PersonDir + '\' + SubNodeName[I];
SubNode := TV1.Items.AddChildObject(RootNode, SubNodeName[I], P)
;
;
// 如果不想使用图标的话请删除以下两行
SubNode.ImageIndex := I;
SubNode.SelectedIndex := I;
end;
TV1.Items.EndUpdate;
end;
二.在TreeView中如何设置选中结点
var
i:integer; {i为设置的选中结点的索引值}
begin
if i>treeview1.items.count then
treeview1.items[i].selected:=true;
或
treeview1.selected:=treeview1.items[i];
三。设置TreeView结点的图形
1. 设置TreeView的images属性为已存在的images对象
treeview1.images:=imagelist1;
2. 在加入结点后执行:
var
anode:TTreeNode;
begein
anode:=Treeview1.add(nil,'item1');
anode.imageindex:=0; {结点未选中时显示的图标}
anode.selectedindex:=1; {结点选中时显示的图标}
end
3. 如果结点图形在改变后未发生变化,可以执行:
treeview1.refresh;
四。如何批量处理TreeView结点
使用TreeView的items属性的BeginUpdate和EndUpdate方法,例:
TreeView1.items.BeginUpdate;
for i:=0 to TreeView1.items.count-1 do
begin
//将每个结点的文字改成为小写字母
TreeView1.items[i].text:=lowercase(TreeView1.items[i].text);
end;
TreeView1.items.EndUpdate; 五。实现TreeView结点拖拽的实例
下面的程序片段演示了如何实现拖拽treeview构件结点的例子
{鼠标按下时执行的语句}
procedure TForm1.Treeview1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
{判断左键按下并且鼠标点在一个结点上开始实现拖拽}
if ( Button = mbLeft ) and
( htOnItem in Treeview1.GetHitTestInfoAt( X, Y ) ) then
begin
Treeview1.BeginDrag( False );
end;
end;
{鼠标拖动执行语句}
procedure TForm1.Treeview1DragOver( Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean);
var
Node : TTreeNode;
begin
if Source = Treeview1 then
begin
Node := Treeview1.GetNodeAt( X, Y ); {取当前结点}
if Node <> nil then {当前结点不为空才能实现拖拽,accept:=true}
Accept := true;
end;
end;
{鼠标释放时执行的语句}
procedure TForm1.Treeview1DragDrop( Sender, Source: TObject;
X, Y : Integer );
var
TempNode : TTreeNode;
AttachMode : TNodeAttachMode;
begin
if Treeview1.Selected = nil then
Exit;
AttachMode := naAddChild; {设置结点移动模式,设移动结点为子结点}
{ 注意在这里存在一个bug,当移动结点时,如果目标结点没有子结点,}
{ 则加入的新的子结点会失败,所以先在当前目标结点的下面 }
{ 加入一个临时子结点,移动完毕后,再将临时结点删除 }
Treeview1.Items.BeginUpdate;
try
TempNode := Treeview1.Items.AddChild( Treeview1.DropTarget,
'Temp' );
try
{ 移动选中的结点到目标结点 }
Treeview1.Selected.MoveTo( Treeview1.DropTarget, AttachMode );
finally
TempNode.Free; { 不要忘了释放临时结点 }
end;
finally
Treeview1.Items.EndUpdate;
end;
end;
{
MS did not see fit to send a notification to the listview when the user
Double - clicks on the header. But the header control class does have the
CS_DBLCLKS Style, so it does get WM_LBUTTONDBLCLK messages, it just does
not do anything with them. To get at these messages requires API - Style
subclassing of the header control.
} uses commctrl;
function HeaderProc(wnd: HWND; Msg: Cardinal; wParam: wParam; lParam: lParam): Longint;
stdcall;
var
hti: THDHitTestInfo;
begin
Result := CallWindowProc(Pointer(GetWindowLong(wnd, GWL_USERDATA)),
wnd, Msg, wParam, lParam);
if Msg = WM_LBUTTONDBLCLK then
begin
FillChar(hti, SizeOf(hti), 0);
hti.Point := SmallPointToPoint(TSmallPoint(lParam));
if SendMessage(wnd, HDM_HITTEST, 0, Longint(@hti)) >= 0 then
if hti.Flags = HHT_ONHEADER then
// would usually send a custom notification to GetParent(wnd) here
Form1.Memo1.Lines.Add(Format('doubleclick on header item %d', [hti.Item]));
end;
end; procedure TForm1.Button1Click(Sender: TObject);
var
wnd: HWND;
buffer: array [0..80] of Char;
oldProc: Integer;
begin
wnd := GetWindow(Listview1.Handle, GW_CHILD);
if wnd <> 0 then
begin
Windows.GetClassname(wnd, buffer, SizeOf(buffer));
memo1.Text := buffer;
if (GetClassLong(wnd, GCL_STYLE) and CS_DBLCLKS) <> 0 then
begin
Memo1.Lines.Add('Has doubleclicks style');
oldproc := GetWIndowLong(wnd, GWL_WNDPROC);
if GetWindowLong(wnd, GWL_USERDATA) <> 0 then
raise Exception.Create('Cannot sublcass header, USERDATA already in use');
SetWIndowLong(wnd, GWL_USERDATA, oldproc);
SetWindowLong(wnd, GWL_WNDPROC, Integer(@HeaderProc));
end;
end
else
Memo1.Text := 'No child';
end;
procedure TForm1.TreeView1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
Node: TTreeNode;
begin
Node := TreeView.GetNodeAt(x, y);
if node <> nil then
msgbox(node.text)
end;