要实现的功能是这样的
treeview树点击一个节点Node,从网上下载子节点的数据并加载(子节点数据是XML压缩文档)用户有可能连着点多个节点Node,比如点了节点没等子节点数据下载完,又点另一个Node。
所以下载、压缩是放在线程中,下载完成后SendMessage给主窗体,然后执行解压线程
解压线程完成后SendMessage给主窗体,对选中节点添加子节点每点击一个节点,就启动一个线程,进行下载、解压操作,
现在问题是:
解压完成后怎么知道是点击的哪个Node? 以便对这个Node添加子节点?
我想给解压线程传进去进中节点的指针,解压操作完成后,SendMessage给主窗体,
1、不知道怎么传节点指针给解压线程?
2、在解压线程完成后,不知道怎么将节点指传给主窗体?

解决方案 »

  1.   

    1  在线程创建的时候当参数传进去  constructor  Create(FrmHandle:Thandle;NodePoint:Pointer);
    2  解压结束后  PostMessage(FrmHandle,WM_ZipNode,Integer(NodePoint),0);
       接收时候用  Msg.WParam  就ok 
      

  2.   

    想用SendMessage
    小弟对指针一知半角,帖出代码,帮我加上传节点指针,和接收节点指针的代码吧unit UnzipThread;interfaceuses
      SysUtils, Classes,VCLUnZip,Messages,Windows;type
      TUnzipThread = class(TThread)
      private
        { Private declarations }
        m_strSrc: string;
        m_strDest: string;
        m_cdMsgID: Cardinal;
        m_hParentHwnd:HWND;
      protected
        { Protected declarations }
        procedure Execute; override;
        procedure UnzipFinished;
      public
        { Public declarations }
        constructor Create(parentWND:HWND;strSrc: string; strDest: string; cdMsgID: Cardinal); virtual;
      published
        { Published declarations }
      end;implementationconstructor TUnzipThread.Create(parentWND:HWND;strSrc: string; strDest: string; cdMsgID: Cardinal);
    begin
      inherited
        Create(True);
        m_hParentHwnd:=parentWND;
      m_strSrc := strSrc;
      m_strDest := strDest;
      m_cdMsgID := cdMsgID;
      Resume;
    end;procedure TUnzipThread.Execute;
    var
      myZip: TVCLUnZip;
    begin
      if not FileExists(m_strSrc) then exit;
      myZip := TVCLUnZip.Create(nil);
     //解压缩
      try
        with myZip do                                 //解压zip
        begin
          ZipName := m_strSrc;
          DestDir := m_strDest;
          Doall := true;
          overwriteMode := Always;
          DoProcessMessages := false;
          Password:= 'zlb7695111';
          UnZip;
        end;
      finally
        myZip.Free;
      end;
      Synchronize(UnzipFinished);
    end;//unzip finishedprocedure TUnzipThread.UnzipFinished;
    var
      M: TMessage;
      B: DWord;
    begin
      M.Msg := m_cdMsgID;
      B := BSM_ALLCOMPONENTS;
      M.WParam := 4;
      M.LParam := 1;
      SendMessage(m_hParentHwnd,M.Msg,M.WParam,M.LParam);
    end;end. 
      

  3.   

    还是回到你的问题上吧,你要实现的功能无非就是用户点击哪个节点,就处理哪个节点。首先,用户点击的节点可以在TreeView的OnClick或者OnDblClick事件上获得,代码如下:
    var
      SelNode: TTreeNode;
    begin
      if TreeView1.Selected <> nil then
      begin
        SelNode := TreeView1.Selected;
        ......
      end;
    end;
    (当然,如果允许多选那就需要遍历树了)好了,节点得到了,然后就是根据这个节点的操作,LZ说要通过线程下载并且解压缩,然后再把信息加入到这个节点上。因为你觉得这很耗时,要用线程,那好吧,就用线程(其实,你用线程反而把你的程序弄复杂了,要是用户频繁点击节点,你该如何控制不能让用户点击还没有完成下载的那些节点?也就是用户点选过的、还没有处理完的节点不能被选中。或者即使被重复点击了也不再次开启下载的工作?)
    就问他说问他,你采用线程的方式:
    可以把选中节点作为参数传入到线程中去,然后在线程中下载、解压缩,完成之后,直接通过线程同步函数操作这个传入的节点就是了,没有必要使用消息的。type
      TUnzipThread = class(TThread)
      private
        { Private declarations }
        FNode: TTreeNode;
      protected
        { Protected declarations }
        procedure Execute; override;
        procedure UnzipFinished;
      public
        { Public declarations }
        constructor Create(Node: TTreeNode); virtual;
      published
        { Published declarations }
      end;implementationconstructor TUnzipThread.Create(Node: TTreeNode);
    begin
      inherited Create(True);
      FNode := Node;
      Resume;
    end;procedure TUnzipThread.Execute;
    begin
      //在这里下载就可以不必要再开个线程  //在这里解压缩  //解压缩完事后,采用同步函数的方式向主界面中的树种添加数据
      Synchronize(UnzipFinished);
    end;//unzip finishedprocedure TUnzipThread.UnzipFinished;
    begin
      //FNode.Owner.AddChild(FNode, '')
    end;
      

  4.   

    楼上朋友建议:
      //解压缩完事后,采用同步函数的方式向主界面中的树种添加数据
      Synchronize(UnzipFinished);
    ---------
    说得很对,我已经采用这种方式,在压缩完成后对树添加子节点,但遇到一个小问题
    如果下载的是根节点,在添加根节点时要引用树,要这样:Form1.TreeView1.Items.AddChild(nil,'44444'),
    要在解压线程里引用主窗体的树,这样合适吗?或者是否有更好的方法? 
      

  5.   

    这个其实也好办,一个办法是:你在树上弄个根节点,这个节点什么都不干,就是为了添加子节点的,呵呵。这样如果觉得不合适,那就把TreeItem1.Items传入到你的线程中去type
      TUnzipThread = class(TThread)
      private
        { Private declarations }
        FNode: TTreeNode;
        FNodes: TTreeNodes;
      protected
        { Protected declarations }
        procedure Execute; override;
        procedure UnzipFinished;
      public
        { Public declarations }
        constructor Create(Nodes: TTreeNodes; Node: TTreeNode); virtual;
      published
        { Published declarations }
      end;implementationconstructor TUnzipThread.Create(Nodes: TTreeNodes; Node: TTreeNode);
    begin
      inherited Create(True);
      FNodes := Nodes;
      FNode := Node;
      Resume;
    end;procedure TUnzipThread.Execute;
    begin
      //在这里下载就可以不必要再开个线程  //在这里解压缩  //解压缩完事后,采用同步函数的方式向主界面中的树种添加数据
      Synchronize(UnzipFinished);
    end;//unzip finishedprocedure TUnzipThread.UnzipFinished;
    begin
      FNodes.AddChild(FNode, '');
    end;调用部分这样
      TUnzipThread.Create(TreeView1.Items, TreeView1.Selected);
      

  6.   

    传数字子针给窗体:unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls,Registry;
    //定义消息索引号
    const
      WM_mymessage=WM_USER+$133;type
      TForm1 = class(TForm)
        Edit1: TEdit;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      Procedure  myownermessage(var Msg: TMessage);message WM_mymessage;//stdcall;  end;
    var
      Form1: TForm1;implementation{$R *.dfm}procedure Tform1.myownermessage(var Msg: TMessage);
    var s : array[0..100] of char;
    begin
     edit1.Text:=inttostr(PInteger(msg.LParam)^);
    end;procedure TForm1.Button1Click(Sender: TObject);
    var i :integer;
    begin
     i:=100555;
     SendMessage(form1.Handle,WM_mymessage,0,DWORD(@i));
    end;end.
      

  7.   

    mwy654321正解,就是发送前把地址转为Cardinal,然后接收后转换为指针。