• Delphi树形控件(TreeView)节点间的拖动


    http://hi.baidu.com/ningj123/blog/item/040b36af4e9554f2fbed50c9.html/cmtid/892d2ea7be915298d14358dd

    Delphi树形控件(TreeView)节点间的拖动

      很久没写博客了,因为实在没什么东西可写。不过,今天以前的同事问我,关于TreeView的操作,那我就顺便写在博客里,稍微展开一下,说说TreeView吧。

      TTreeView是VCL里面一个类,也是我们经常会用到的,而且功能也是很强大的。与TreeView相关的一个极其重要的类就是TTreeNode,我们下面的操作,几乎都是在围绕着它进行的。下面直接切入正题,要实现节点间的拖动,都需要实现哪几个事件呢?

    1. 首先,要实现 OnMouseDown ,在其内要写入开启拖动的代码。
    2. 然后,要实现 OnDragOver ,其主要作用是在拖动过程中,实现对节点拖动目的(di)的控制。
    3. 最后,要实现 OnDragDrop ,其是实现拖动释放的操作。

      这三个事件,我们可以简单的理解为,拖动开始、拖动过程、拖动结束(虽然“拖动开始”和“拖动结束”都有他们各自对应的事件,但是也不妨碍我们这样的理解)。首先是 OnMouseDown 事件。

    1. procedure TfrmMain.TreeView1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    2. var
    3.     node: TTreeNode;
    4. begin
    5.     node := TreeView1.GetNodeAt(X, Y);  // 获取鼠标按下位置的节点
    6.    if (node <> nil) and (node.Level > 0) and (Button = mbLeft) then
    7.        TreeView1.BeginDrag(True);  // 启动拖动
    8. end;

      需要注意的是,TreeView 控件的 DragMode 要设置为 dmManual,才会需要执行 BeginDrag 手工启动拖动。DragMode 的缺省值就是 dmManual。

      接下来就是 OnDargOver 事件。

    1. procedure TfrmMain.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
    2. var
    3.     node: TTreeNode;
    4. begin
    5.     node := TreeView1.GetNodeAt(X, Y);
    6.    // node.Level 是节点的层级,等于0时,表示是根节点(没有上级节点了)
    7.    // 本语句控制只能将节点拖动到与父节点平级的其他节点上,Accept表示,是否可释放
    8.    if (node <> nil) and (node.Level = 0) and (TreeView1.Selected.Parent <> node) then
    9.        Accept := True
    10.    else
    11.        Accept := False;
    12. end;

      最后是实现 OnDragDrop 事件,此事件里就要写上与业务相关的代码了。

    1. procedure TfrmMain.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
    2. var
    3.     node: TTreeNode;
    4. begin
    5.     node := TreeView1.GetNodeAt(X, Y);
    6.    if (node <> nil) and (node.Level = 0) then
    7.     begin
    8.       // 此处用到了StateIndex,只是在生成TreeView的时候,将每条记录的主键值储存到了这里,并不代表StateIndex的实际意义
    9.        Query1.SQL.Text := 'update sys_config set class_id=' + IntToStr(node.StateIndex) + ' where cid=' + IntToStr(TreeView1.Selected.StateIndex);
    10.       if Query1.ExecSQL() > 0 then
    11.           TreeView1.Selected.MoveTo(node, naAddChild);  // 将节点移动到目标节点的下一级,也就是使目标节点成为被拖动节点的父节点
    12.     end;
    13. end;

      至此,整个拖动就结束了。代码是不是很简单?又回到了我刚开始说的话,整个过程,都是在围绕着TTreeNode类进行的操作。最后,说明一下,代码中我使用到了TreeNode的StateIndex属性,实际上我这样的做法是不推荐的。我们推荐使用TreeNode的Data属性来保存额外的数据,而且这也是正宗的用法。Data属性可以保存任何数据,因为它是Pointer类型(无类型指针),相当于C++里面的void*。具体Data如何使用,与本次的主题关系不大,以后有时间再来讲吧。

    来自:http://hi.baidu.com/shxwinner/blog/item/d56dab09eb541fd862d986a6.html

  • 相关阅读:
    移动端--基于Android Studio的项目文件结构(一)【转】
    java知识体系粗略梳理
    简单的使用hibernate插入数据的例子
    触发器
    存储过程和函数
    视图
    索引的设计和使用
    数据类型的选择
    表类型(存储引擎)的选择
    MySQL中的常用函数
  • 原文地址:https://www.cnblogs.com/chulia20002001/p/1913291.html
Copyright © 2020-2023  润新知