delphi7通过treeview增加个性化增加checkbox功能

hills95 2015-06-29 08:49:55
DELPHI7 环境下,treeview通过语句实现增加checkbox功能,但现场需要的是不是所有分支都出现checkbox框,具体是分类支不出现,没有下级分类的才出现。好比是文件夹与文件,文件夹前没有选择框,文件名前才有选择框。如附图,只需要方案前出现复选框,一级分类与二级分类前不出现分类框(不想使用第三方控件)。


SetWindowLong(tvDemo.Handle, GWL_STYLE, GetWindowLong(tvDemo.Handle,
GWL_STYLE) or $0000100); //使树形控件具有复选框功能


unit TVDemo;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, CommCtrl, StdCtrls;

type
TfrmtvDemo = class(TForm)
tvDemo: TTreeView;
Memo1: TMemo;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure tvDemoKeyPress(Sender: TObject; var Key: Char);
procedure tvDemoClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
function IsChecked(Node: TTreeNode): Boolean;
procedure SetChecked(Node: TTreeNode; Checked: Boolean);
procedure Checkbox(TreeView: TTreeView; Node: TTreeNode; isclick:
boolean = false);
end;

var
frmtvDemo: TfrmtvDemo;

implementation

{$R *.dfm}

const
TVIS_CHECKED = $2000; //节点是否被选中

procedure TfrmtvDemo.FormCreate(Sender: TObject);
var
Node1A, NodeB:TTreeNode;
begin
SetWindowLong(tvDemo.Handle, GWL_STYLE, GetWindowLong(tvDemo.Handle,
GWL_STYLE) or $0000100); //使树形控件具有复选框功能
self.tvDemo.Items.Clear;
Node1A := self.tvDemo.Items.AddFirst(nil, '一级分类1A');
NodeB := self.tvDemo.Items.AddChildFirst(Node1A,'二级分类1A_2A');
self.tvDemo.Items.AddChildFirst(NodeB,'方案一');
self.tvDemo.Items.AddChild(NodeB,'方案二');
self.tvDemo.Items.AddChild(NodeB,'方案三');
NodeB := self.tvDemo.Items.AddChild(Node1A,'二级分类1A_2B');
self.tvDemo.Items.AddChildFirst(NodeB,'方案一');
self.tvDemo.Items.AddChild(NodeB,'方案二');
self.tvDemo.Items.AddChild(NodeB,'方案三');
Node1A := self.tvDemo.Items.Add(nil, '一级分类1B');
NodeB := self.tvDemo.Items.AddChildFirst(Node1A,'二级分类1B_2A');
self.tvDemo.Items.AddChildFirst(NodeB,'方案一');
self.tvDemo.Items.AddChild(NodeB,'方案二');
self.tvDemo.Items.AddChild(NodeB,'方案三');
NodeB := self.tvDemo.Items.AddChild(Node1A,'二级分类1B_2B');
self.tvDemo.Items.AddChildFirst(NodeB,'方案一');
self.tvDemo.Items.AddChild(NodeB,'方案二');
self.tvDemo.Items.AddChild(NodeB,'方案三');
end;

function TfrmtvDemo.IsChecked(Node: TTreeNode): Boolean;
//节点是否被选中
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 TfrmtvDemo.SetChecked(Node: TTreeNode; Checked: Boolean);
//让某个节点被选中
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;

procedure TfrmtvDemo.Checkbox(TreeView: TTreeView;
Node: TTreeNode; isclick: boolean = false); //节点选择后子节点状态处理
var
CurNode, ParentNode, GrandSonNode, sonNode: TTreeNode;
flag: boolean;
begin
CurNode := node;
with TreeView do
begin
if IsChecked(CurNode) then
begin
sonNode := CurNode.GetFirstChild;
while sonNode <> nil do
begin
SetChecked(sonNode, true);
Checkbox(TreeView, sonNode, true);
sonNode := sonNode.GetNextSibling;
end;
ParentNode := CurNode.Parent;
if ParentNode <> nil then
begin
if not isChecked(parentNode) then
begin
GrandSonNode := ParentNode.GetFirstChild;
flag := false;
while GrandSonNode <> nil do
begin
if (not IsChecked(GrandSonNode)) then
flag := true;
if flag then
GrandSonNode := nil
else
GrandSonNode := GrandSonNode.GetNextSibling;
end;
SetChecked(ParentNode, not flag);
Checkbox(TreeView, ParentNode, false);
end;
end;
end
else if not IsChecked(CurNode) then
begin
ParentNode := CurNode.Parent;
if ParentNode <> nil then
begin
if isChecked(parentNode) then
begin
SetChecked(ParentNode, false);
Checkbox(TreeView, ParentNode);
end;
end;
if (isclick) then
begin
sonNode := CurNode.GetFirstChild;
while sonNode <> nil do
begin
SetChecked(sonNode, false);
Checkbox(TreeView, sonNode, true);
sonNode := sonNode.GetNextSibling;
end;
end;
end;
end;
end;

procedure TfrmtvDemo.tvDemoClick(Sender: TObject); //鼠标单击时选择
var
P: TPoint;
treenode: TTreeNode;
begin
GetCursorPos(P);
P := tvDemo.ScreenToClient(P);
if (htOnStateIcon in tvDemo.GetHitTestInfoAt(P.X, P.Y)) then
begin
treenode := tvDemo.GetNodeAt(P.X, P.Y);
Checkbox(tvDemo, treenode, true);
end;
end;

procedure TfrmtvDemo.tvDemoKeyPress(Sender: TObject; var Key: Char);
//键盘空格时选择
begin
if (Key = #32) and Assigned(tvDemo.Selected) then
Checkbox(tvDemo, tvDemo.Selected, true);
end;

procedure TfrmtvDemo.Button1Click(Sender: TObject);
var
i:integer;
node:TTreeNode;
s:String;
begin
for i:=0 to tvDemo.Items.Count -1 do
begin
node := tvDemo.Items[i];
if IsChecked(node) and (self.tvDemo.Items[i].Level = 2) then
begin
s := s + tvDemo.Items[i].Text + #13 +#10;
end;
end;
self.memo1.text := s;

end;

end.

...全文
1218 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
小小爬虾 2017-01-09
  • 打赏
  • 举报
回复
感谢,正好有用!
HedgeWirter 2016-04-22
  • 打赏
  • 举报
回复
这种半选中状态是怎么做的呢
hills95 2015-07-07
  • 打赏
  • 举报
回复
引用 14 楼 lyhoo163的回复:
你是通过画图,模拟Checkbox?
不是。是API函数
lyhoo163 2015-07-07
  • 打赏
  • 举报
回复
你是通过画图,模拟Checkbox?
hills95 2015-07-07
  • 打赏
  • 举报
回复
已完美解决,使不显示图标的节点的stateindex为0即可。谢谢各位回贴。
hills95 2015-07-06
  • 打赏
  • 举报
回复
引用 11 楼 lyhoo163 的回复:
叶节点带Check,需要有条件地带Check。那么自己继承一个TreeView,当节点是叶节点时,带上TCheckbox。自己编写一个控件代码较多,他人是不好为你花时间写代码的。 但是我建议你使用 istClass中的TfcTreeView。效果图: 与你的要求一致,自己弄吧。1
谢谢。要的就是这个效果。但又不想用第三方控件。有空了再慢慢研究吧
lyhoo163 2015-07-04
  • 打赏
  • 举报
回复
叶节点带Check,需要有条件地带Check。那么自己继承一个TreeView,当节点是叶节点时,带上TCheckbox。自己编写一个控件代码较多,他人是不好为你花时间写代码的。

但是我建议你使用 istClass中的TfcTreeView。效果图:



与你的要求一致,自己弄吧。1
hills95 2015-07-04
  • 打赏
  • 举报
回复
引用 9 楼 lyhoo163 的回复:
楼主的办法,设置TreeView附带Check功能,所有的节点,都带上Check。它与第三方RzCheckTree功能是一致的。 如果非得要,只有叶节点带Check,需要有条件地带Check。那么自己继承一个TreeView,当节点是叶节点时,带上TCheckbox。
谢谢。思路明白。 if node.havechild then 节点带TCheckbox; 麻烦能不能给出代码。谢谢。本人刚入门。
lyhoo163 2015-07-03
  • 打赏
  • 举报
回复
楼主的办法,设置TreeView附带Check功能,所有的节点,都带上Check。它与第三方RzCheckTree功能是一致的。 如果非得要,只有叶节点带Check,需要有条件地带Check。那么自己继承一个TreeView,当节点是叶节点时,带上TCheckbox。
lyhoo163 2015-07-02
  • 打赏
  • 举报
回复
试试在叶结点,挂上一个Tcheckbox。
Mr Dang 2015-07-01
  • 打赏
  • 举报
回复
引用 6楼Bzdr 的回复:
在树控件的draw事件里判断节点有没有子节点,如果没有子节点就使树有复选框,代码是你formcreate的第一句
大概就是这个意思
Mr Dang 2015-07-01
  • 打赏
  • 举报
回复
在树控件的draw事件里判断节点有没有子节点,如果没有子节点就使树有复选框,代码是你formcreate的第一句
hills95 2015-07-01
  • 打赏
  • 举报
回复
引用 4 楼 Bzdr的回复:
引用 3楼Bzdr 的回复:
判断节点有没有子节点
if node.haschild = true then set…
对,就是这个思路。Set后设置不显示复选框的代码是什么?分类什么图标(图片)都不要显示的。本人小白……
Mr Dang 2015-06-30
  • 打赏
  • 举报
回复
引用 3楼Bzdr 的回复:
判断节点有没有子节点
if node.haschild = true then set…
Mr Dang 2015-06-30
  • 打赏
  • 举报
回复
判断节点有没有子节点
李_军 2015-06-30
  • 打赏
  • 举报
回复
一般都是用imagelist实现复选框,功能,即你将treeview的stateindex,点击事件后更换stateindex为复选的图标。不需要的设置的stateindex不一样好了
lyhoo163 2015-06-29
  • 打赏
  • 举报
回复
支持源码共享。TreeView的脚法很多的。
一、简介 通过这个课程带大家从零开发一款功能全面的后台管理系统,包括项目搭建、功能实现到最后的Linux系统部署全过程。本课程使用SpringMVC + Spring + Mybatis作为主体框架,使用AdminLTE作为前端框架,使用主流关系型数据库Mysql作为存储数据库,使用非关系型数据库Redis作为缓存数据库,并集成SpringSecuriy安全框架做权限的动态管理,集成Swagger2自动生成接口文档,集成Druid连接池进行SQL性能监控,集成ActiveMQ消息中间件进行异步解耦,提高性能。最后使用linux系统进行服务部署,并搭建nginx反向代理服务器提高网站性能。 二、学习目标 通过本课程的学习带大家掌握SSM框架的开发流程,并熟练使用SpringSecurity做为安全框架进行权限管理,整合相关优秀的开源框架进行功能开发。还在项目中带大家学习前端相关的Jquery、Bootstrap等知识。课程结束之后希望大家能做到独立进行开发项目的目的,增强解决问题的能力,具备功能落地实现的能力。 三、课程涉及知识点 SpringMVC源码分析Mybatis源码分析通用MapperMysql数据库Redis缓存实现ActiveMQ消息中间件SpringSecurity鉴权Swagger2接口文档生成自定义注解AOP切面编程自定义过滤器Logback日志整合Druid性能监控Linux系统Nginx反向代理Ajax异步请求技术Jquery基本使用AdminLTE前端框架Chart图表-线状图和饼状图百度地图定位城市BootStrap前端框架BootStrap-Table插件BootStrap-Treeview插件Markdown编辑器403、404、500错误页面配置数据库事务消息提示插件toastr.js图片上传插件bootstrap fileinput数字滚动效果pv/uv流量统计...四、课程部分内容截图如下 1、首页 2、菜单管理 3、图床管理 4、图标管理 5、留言反馈管理 6、druid监控 7、登录日志

5,392

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧