delphi里面Treeview这个控件里面的TreeNode列表是怎么在VCL里面绘制的?我想重新写一个这样的控件,把后面的文字变成二行,然后进行一些别的操作。这个问题我在网上找了他妈的N久都没有找到?

解决方案 »

  1.   

    楼主讲话不文明啊。
    你可以定义节点的 OnCustomDrawItem 事件,实现节点绘制方面的特殊要求。
      

  2.   

    其实这个过程是Windows作的和Delphi没有太大关系,可以看一下VCL代码
      

  3.   

    shiyj兄:如果用OnCustomDrawItem能绘制出一些特殊的效果,那我就不用看VCL了。你呀……blazingfire兄:你说的也有道理,我看了VCL源码,那如果我要绘制一个跟QQ好友列表一样的控件出来,不得自己绘制呀。这方面我不懂的,愿听指点。谢谢
      

  4.   

    其实也没有什么指点的,我在VCL里也没有找到代码,呵呵!
    看看TCustomTreeView的CreateParam方法如何作的就知道了
    VCL代码
    procedure TCustomTreeView.CreateParams(var Params: TCreateParams);
    const
      BorderStyles: array[TBorderStyle] of DWORD = (0, WS_BORDER);
      LineStyles: array[Boolean] of DWORD = (0, TVS_HASLINES);
      RootStyles: array[Boolean] of DWORD = (0, TVS_LINESATROOT);
      ButtonStyles: array[Boolean] of DWORD = (0, TVS_HASBUTTONS);
      EditStyles: array[Boolean] of DWORD = (TVS_EDITLABELS, 0);
      HideSelections: array[Boolean] of DWORD = (TVS_SHOWSELALWAYS, 0);
      DragStyles: array[TDragMode] of DWORD = (TVS_DISABLEDRAGDROP, 0);
      RTLStyles: array[Boolean] of DWORD = (0, TVS_RTLREADING);
      ToolTipStyles: array[Boolean] of DWORD = (TVS_NOTOOLTIPS, 0);
      AutoExpandStyles: array[Boolean] of DWORD = (0, TVS_SINGLEEXPAND);
      HotTrackStyles: array[Boolean] of DWORD = (0, TVS_TRACKSELECT);
      RowSelectStyles: array[Boolean] of DWORD = (0, TVS_FULLROWSELECT);
    begin
      //调用Windows方法来创建一个TreeView组件,其它的绘制动作其实也是Windows实现的
      InitCommonControl(ICC_TREEVIEW_CLASSES);  
      inherited CreateParams(Params);
      CreateSubClass(Params, WC_TREEVIEW);
      with Params do
      begin
        Style := Style or LineStyles[FShowLines] or BorderStyles[FBorderStyle] or
          RootStyles[FShowRoot] or ButtonStyles[FShowButtons] or
          EditStyles[FReadOnly] or HideSelections[FHideSelection] or
          DragStyles[DragMode] or RTLStyles[UseRightToLeftReading] or
          ToolTipStyles[FToolTips] or AutoExpandStyles[FAutoExpand] or
          HotTrackStyles[FHotTrack] or RowSelectStyles[FRowSelect];
        if Ctl3D and NewStyleControls and (FBorderStyle = bsSingle) then
        begin
          Style := Style and not WS_BORDER;
          ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE;
        end;
        WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
      end;
    end;其实TButton,TEdit也是这样实现的,Delphi没有绘制过程
      

  5.   

    如果要改变绘制的样子要拦截WM_PAINT, WM_NCPAINT....消息去处理
      

  6.   

    blazingfire 兄弟,你的回答对我很有用,虽然资料太少,但最起码知道该控件不是Delphi自己绘制。呵。
      

  7.   

    为了赚点粉,这里再粘一次,写这些代码不容易呀?!用TListBox呀
    procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    //ListBox.OnDrawItem事件
    var
      ImgRect, MemoRect: TRect;
      Cnvs: TCanvas;
      B: TBitmap;
      S, Memo: string;
      iPos: Integer;
    begin
      Cnvs := ListBox1.Canvas;
      ImgRect := Rect;
      ImgRect.Right := ImgRect.Left + (ImgRect.Bottom - ImgRect.Top); //画图区域  if odSelected in State then
      begin
        Cnvs.Brush.Color := clSkyBlue;
        Cnvs.Pen.Color := clNavy;
      end
      else
      begin
        Cnvs.Brush.Color := ListBox1.Color;
        Cnvs.Pen.Color := ListBox1.Color;
      end;
      Cnvs.Brush.Style := bsSolid;
      Cnvs.Rectangle(Rect);  Cnvs.Brush.Style := bsClear;
      if ImageList.Count > 0 then
      begin
        B := TBitmap.Create;
        try
          ImageList.GetBitmap(0, B);
          B.PixelFormat := pf24bit;
          B.Transparent := True;
          InflateRect(ImgRect, -2, -2);
          Cnvs.StretchDraw(ImgRect, B);
        finally
          B.Free;
        end;
      end;  Rect.Left := ImgRect.Right;
      MemoRect := Rect;
      MemoRect.Top := (Rect.Top + Rect.Bottom) div 2;
      Rect.Bottom := MemoRect.Top;
      S := ListBox1.Items[Index];  iPos := Pos(#9, S);
      Memo := Copy(S, iPos + 1, Length(S)); //提取备注
      S := Copy(S, 1, iPos - 1); //提取名称
      Cnvs.Font.Assign(ListBox1.Font);
      DrawText(Cnvs.Handle, PChar(S), -1,
        Rect, DT_SingleLine or DT_VCENTER); //垂直、水平居中 画名字  Cnvs.Font.Color := clGrayText;
      DrawText(Cnvs.Handle, PChar(Memo), -1,
        MemoRect, DT_SingleLine or DT_VCENTER); //垂直、水平居中 画名字
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      ListBox1.Style := lbOwnerDrawVariable; //自己画每一项,项高度可调
      ListBox1.ItemHeight := 30;
      ListBox1.Clear;
      //名称+#9+备注
      ListBox1.Items.Add('yao518'#9 + '一剑飘雪');
      ListBox1.Items.Add('blazingfire'#9 + '...该充电了...');
      ListBox1.Items.Add('yao518'#9 + '一剑飘雪');
      ListBox1.Items.Add('blazingfire'#9 + '...该充电了...');
    end;
      

  8.   

    我最近在研究TreeView里面的东西,看了很久都没有发现他在那里绘制的,呵。你写的Listbox绘制代码对我的帮助不是很大。不过我也看了,非常不错你的QQ是?
      

  9.   

    我把你的代码放在delphi里面运行了试一下看~!