TTreeView Delphi组件(位于“Win32”组件选项板选项卡上)表示一个窗口,显示项目的层次列表,例如文档中的标题、索引中的条目或磁盘上的文件和目录。
Delphi的TTreeview本机不支持复选框,但底层的WC_TREEVIEW控件支持复选框。通过覆盖TTreeView的CreateParams过程,指定控件的TVS_复选框样式,可以将复选框添加到treeview。结果是树视图中的所有节点都将附加复选框。此外,stateMages属性不能再使用,因为WC_TREEVIEW在内部使用此imagelist来实现复选框。如果要切换复选框,则必须使用SendMessage或CommCtrl.pas中的TreeView_SetItem/TreeView_GetItem宏进行切换。WC_TREEVIEW仅支持复选框,不支持单选按钮。
在本文中,您将发现的方法更加灵活:您可以将复选框和单选按钮以任何方式与其他节点混合,而无需更改TTreeview或从中创建新类来实现这一点。此外,您只需将适当的图像添加到StateImages imagelist中,即可决定复选框/单选按钮使用哪些图像。
与您可能相信的相反,这在Delphi中很容易实现。以下是使其工作的步骤:
为了使您的treeview更加专业,您应该在切换stateimages之前检查节点被单击的位置:通过仅在实际图像被单击时切换节点,您的用户仍然可以选择节点而不更改其状态。
此外,如果不希望用户展开/折叠treeview,请在forms OnShow事件中调用FullExpand过程,并在treeview的OnCollapsing事件中将AllowCollapse设置为false。
以下是ToggleTreeViewCheckBox过程的实现:
procedure ToggleTreeViewCheckBoxes( Node :TTreeNode; cUnChecked, cChecked, cRadioUnchecked, cRadioChecked :integer);var tmp:TTreeNode;beginif Assigned(Node) thenbeginif Node.StateIndex = cUnChecked then Node.StateIndex := cChecked else if Node.StateIndex = cChecked then Node.StateIndex := cUnChecked else if Node.StateIndex = cRadioUnChecked thenbegin tmp := Node.Parent; if not Assigned(tmp) then tmp := TTreeView(Node.TreeView).Items.getFirstNode else tmp := tmp.getFirstChild; while Assigned(tmp) dobeginif (tmp.StateIndex in [cRadioUnChecked,cRadioChecked]) then tmp.StateIndex := cRadioUnChecked; tmp := tmp.getNextSibling; end; Node.StateIndex := cRadioChecked; end; // if StateIndex = cRadioUnCheckedend; // if Assigned(Node)end; (*ToggleTreeViewCheckBoxes*)从上面的代码中可以看到,该过程首先查找任何复选框节点,然后将其打开或关闭。接下来,如果节点是未选中的单选按钮,则过程将移动到当前标高上的第一个节点,将该标高上的所有节点设置为“cRadioUnchecked”(如果它们是cRadioUnchecked或cRadioChecked节点),最后将节点切换为“cRadioChecked”。
请注意,如何忽略任何已选中的单选按钮。显然,这是因为已选中的单选按钮将切换为未选中,使节点处于未定义状态。几乎不是你大多数时候想要的。
下面是如何使代码更加专业:在Treeview的OnClick事件中,编写以下代码,仅在单击stateimage时切换复选框(cFlatUnCheck、cFlatChecked等常量在StateImages图像列表的其他位置定义为索引):
procedure TForm1.TreeView1Click(Sender: TObject);var P:TPoint;begin GetCursorPos(P); P := TreeView1.ScreenToClient(P); if (htOnStateIcon in TreeView1.GetHitTestInfoAt(P.X,P.Y)) then ToggleTreeViewCheckBoxes( TreeView1.Selected, cFlatUnCheck, cFlatChecked, cFlatRadioUnCheck, cFlatRadioChecked);end; (*TreeView1Click*)代码获取当前鼠标位置,转换为treeview坐标,并通过调用GetHitTestInfo函数检查是否单击了StateIcon。如果是,则调用切换过程。
大多数情况下,您希望空格键切换复选框或单选按钮,因此下面介绍如何使用该标准编写TreeView OnKeyDown事件:
procedure TForm1.TreeView1KeyDown( Sender: TObject; var Key: Word; Shift: TShiftState);beginif (Key = VK_SPACE) and Assigned(TreeView1.Selected) then ToggleTreeViewCheckBoxes( TreeView1.Selected, cFlatUnCheck, cFlatChecked, cFlatRadioUnCheck, cFlatRadioChecked);end; (*TreeView1KeyDown*)最后,如果您想防止Treeview节点崩溃,那么表单的OnShow和Treeview的onChange事件可能是这样的:
procedure TForm1.FormCreate(Sender: TObject);begin TreeView1.FullExpand;end; (*FormCreate*)procedure TForm1.TreeView1Collapsing( Sender: TObject; Node: TTreeNode; var AllowCollapse: Boolean);begin AllowCollapse := false;end; (*TreeView1Collapsing*)最后,要检查是否检查了节点,只需进行以下比较(例如,在按钮的OnClick事件处理程序中):
procedure TForm1.Button1Click(Sender: TObject);var BoolResult:boolean; tn : TTreeNode;beginif Assigned(TreeView1.Selected) thenbegin tn := TreeView1.Selected; BoolResult := tn.StateIndex in [cFlatChecked,cFlatRadioChecked]; Memo1.Text := tn.Text + #13#10 + 'Selected: ' + BoolToStr(BoolResult, True); end;end; (*Button1Click*)尽管这种类型的编码不能被视为任务关键型,但它可以让您的应用程序看起来更专业、更流畅。此外,通过明智地使用复选框和单选按钮,它们可以使应用程序更易于使用。它们一定会好看的!
下图是使用本文描述的代码从测试应用程序中获取的。如您所见,您可以自由地将具有复选框或单选按钮的节点与没有复选框或单选按钮的节点混合,尽管您不应该将“空”节点与“复选框”节点混合(查看图像中的单选按钮),因为这使得很难看到哪些节点是相关的。
...密码来加密这些数据,这样Google就不能读取了。 相关:如何在Chrome中打开或关闭同步 同步密码短语可以通过Chrome在windows10或Mac桌面、iPhone、iPad或Android上设置。我们从桌面开始。 Warning: You will have to reset Chrome Sync if you ever choose t...
...ash脚本中使用GUI窗口、滑块、单选按钮、进度条等。学习如何使用zenity工具箱,并对Bash脚本进行整容。我们会教你怎么做。 Bash脚本是一种功能强大的编程语言,由于它内置在Bash shell中,因此每个人都可以随时使用它。这是一...
...”部分有时会显示“高级”按钮,但有时会显示“存档”复选框。为什么会这样来回切换?今天的超级用户问答帖子回答了一位好奇的读者的问题。 今天的问答环节是由SuperUser提供的,SuperUser是Stack Exchange的一个分支,是一个由...
...候,这就像找到一个眼睛的背景色一样简单。让我们看看如何在Windows8中轻松更改背景/强调文字颜色。 Dear How-To Geek, It’s ridiculous, but I can’t tell you how much the default purple color in Windows 8 really bothers me. It’s so loud it hurts my face. I wan...
...户)提供的屏幕截图。 问题 超级用户读者Joseph想知道如何阻止每次访问谷歌时出现谷歌隐私提醒信息: This is incredibly annoying. When I edit all the opti***, set them all to Off (although I doubt this makes any difference!), and accept the review, the same pri...
...个程序在登录到Windows后立即以提升的权限自动运行,但如何设置这样的程序?今天的超级用户问答帖子对一个沮丧的读者有一些有用的建议。 今天的问答环节是由SuperUser提供的,SuperUser是Stack Exchange的一个分支,是一个由社区...
...表单,而是选择“我的模板” 现在您需要单击“模板”复选框,然后按“确定”创建一个空白模板。最后,按“Ctrl+S”保存文档。我们称之为“表单模板1”。 填充表单 现在您有了一个空白模板,就可以开始向表单添加信...
...eeds部分,选中synchronizerssfeedstothecommonfeedlist(CFL)inwindows复选框,这样框中就会有一个复选标记。 单击“确定”接受更改并关闭“选项”对话框。 Now, we will add the RSS feed for How-To Geek to the Common Feed List in Internet Explorer. To do this, ...
Automatic syncing between browsers is handy but if it lets you down (or you prefer not to use it) you can still manually copy extensi*** between Chrome installati***. Read on to see how. 今天的问答环节是由SuperUser提供的,SuperUser是Stack Exchange的一个分支,是一个由社区...
...项卡,然后在“高级设置”列表中选中“始终显示菜单”复选框,以便在该框中有一个复选标记。单击“确定”。 现在,标准菜单栏将始终在Windows资源管理器中可用。 在资源管理器中显示/隐藏驱动器号 默认情况下,显示Wind...