Delphi - ListView或类似的所有者绘制按钮

时间:2010-04-20 12:36:57

标签: delphi virtualtreeview

如何使用每行上的按钮创建列表视图(或类似视图)?按钮需要能够根据需要在每一行上具有不同的文本/颜色。

我确信Virtual Treeview对此非常完美,但我有点迷失它。

由于

-Brad

1 个答案:

答案 0 :(得分:5)

使用virtualtreeview ......将vstButton添加到您的用途并在对象检查器中选择您的Virtualtreeview并为您的树设置以下事件:

procedure TForm1.VSTCreateEditor(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; out EditLink: IVTEditLink);
begin
  EditLink:=TStringEditLink.Create;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  VST.NodeDataSize := SizeOf(TTreeData);
  AddRandomNodesToTree(Vst);
end;

procedure TForm1.VSTFreeNode(Sender: TBaseVirtualTree;
  Node: PVirtualNode);
var
 Data: PTreeData;
begin
 Data:=VST.GetNodeData(Node);
 if Assigned(Data) then begin
   Data^.Column0 := '';
   Data^.Column1 := '';
   Data^.Column2 := '';
 end;
end;

procedure TForm1.VSTGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: string);
var
  Data: PTreeData;
begin
  Data := VST.GetNodeData(Node);
  case Column of
    0: CellText := Data^.Column0;
    1: CellText := Data^.Column1;
    2: CellText := Data^.Column2;
  end;
end;

procedure TForm1.VSTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; NewText: string);
Var
  Data: PTreeData;
begin
  Data := VST.GetNodeData(Node);
  Case Column of
     0: Data^.Column0:= NewText;
     1: Data^.Column1:= NewText;
     2: Data^.Column2:= NewText;
  End;
end;

procedure TForm1.VSTPaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);
Var
 Data: PTreeData;
begin
  if Odd(Node.Index) then 
    TargetCanvas.Font.Color:= clRed;
end;

......这假设记录是:

type
  PTreeData = ^TTreeData;
  TTreeData = record
    Column0: String;
    Column1: String;
    Column2: String;
  end;

...添加以下单位:

unit vstButton;


interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, VirtualTrees,
  messages, windows, StdCtrls, ShlObj;

type
  TStringEditLink = class(TInterfacedObject, IVTEditLink)
  private
    FEdit: TWinControl;
    FTree: TVirtualStringTree;
    FNode: PVirtualNode;
    FColumn: Integer;
    FSelectedFolder: string;
  protected
    procedure ButtonClick(Sender: TObject);
  public
    destructor Destroy; override;
    function BeginEdit: Boolean; stdcall;
    function CancelEdit: Boolean; stdcall;
    function EndEdit: Boolean; stdcall;
    function GetBounds: TRect; stdcall;
    function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall;
    procedure ProcessMessage(var Message: TMessage); stdcall;
    procedure SetBounds(R: TRect); stdcall;
  end;

  function GetFolderDialog(Handle: Integer; Caption: string; var strFolder: string): Boolean;

implementation

destructor TStringEditLink.Destroy;
begin
  FEdit.Free;
  inherited;
end;

procedure TStringEditLink.ButtonClick(Sender: TObject);
var
  s: string;
begin
  s := 'c:\';
  if GetFolderDialog(Application.Handle, 'Select a folder', s) then
    FSelectedFolder := s;

  FTree.EndEditNode;
  FTree.setfocus;
end;

function TStringEditLink.BeginEdit: Boolean;
begin
  Result := True;
  FSelectedFolder := FTree.Text[FNode, FColumn];
  TButton(FEdit).CAption := FTree.Text[FNode, FColumn];
  FEdit.Show;
  FEdit.SetFocus;
end;

function TStringEditLink.CancelEdit: Boolean;
begin
  Result := True;
  FEdit.Hide;
  FTree.EndEditNode;
  FTree.setfocus;
end;

function TStringEditLink.EndEdit: Boolean;
var
  S: WideString;
begin
  Result := True;
  FTree.Text[FNode, FColumn] := FSelectedFolder;

  FTree.InvalidateNode(FNode);
  FEdit.Hide;
  FTree.SetFocus;
end;

function TStringEditLink.GetBounds: TRect;
begin
  Result := FEdit.BoundsRect;
end;

function TStringEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean;
begin
  Result := True;
  FTree := Tree as TVirtualStringTree;
  FNode := Node;
  FColumn := Column;

  FEdit.Free;
  FEdit := nil;

  FEdit := TButton.Create(nil);
   with FEdit as TButton do
     begin
          Visible := False;
          Parent := Tree;
          Font.Color := FTree.Colors.HeaderHotColor;
          OnClick := ButtonClick;
      end;
end;

procedure TStringEditLink.ProcessMessage(var Message: TMessage);
begin
  FEdit.WindowProc(Message);
end;

procedure TStringEditLink.SetBounds(R: TRect);
var
  Dummy: Integer;
begin
  FTree.Header.Columns.GetColumnBounds(FColumn, Dummy, R.Right);
  FEdit.BoundsRect := R;
end;

//------------------------------------------------------------------------------\\

function BrowseCallbackProc(hwnd: HWND; uMsg: UINT; lParam: LPARAM; lpData: LPARAM): Integer; stdcall;
begin
  if (uMsg = BFFM_INITIALIZED) then
    SendMessage(hwnd, BFFM_SETSELECTION, 1, lpData);
  BrowseCallbackProc := 0;
end;

function GetFolderDialog(Handle: Integer; Caption: string; var strFolder: string): Boolean;
const
  BIF_STATUSTEXT           = $0004;
  BIF_NEWDIALOGSTYLE       = $0040;
  BIF_RETURNONLYFSDIRS     = $0080;
  BIF_SHAREABLE            = $0100;
  BIF_USENEWUI             = BIF_EDITBOX or BIF_NEWDIALOGSTYLE;

var
  BrowseInfo: TBrowseInfo;
  ItemIDList: PItemIDList;
  JtemIDList: PItemIDList;
  Path: PChar;
begin
  Result := False;
  Path := StrAlloc(MAX_PATH);
  SHGetSpecialFolderLocation(Handle, CSIDL_DRIVES, JtemIDList);
  with BrowseInfo do
  begin
    hwndOwner := GetActiveWindow;
    pidlRoot := JtemIDList;
    SHGetSpecialFolderLocation(hwndOwner, CSIDL_DRIVES, JtemIDList);

    { return display name of item selected }
    pszDisplayName := StrAlloc(MAX_PATH);

    { set the title of dialog }
    lpszTitle := PChar(Caption);//'Select the folder';
    { flags that control the return stuff }
    lpfn := @BrowseCallbackProc;
    { extra info that's passed back in callbacks }
    lParam := LongInt(PChar(strFolder));
  end;

  ItemIDList := SHBrowseForFolder(BrowseInfo);

  if (ItemIDList <> nil) then
    if SHGetPathFromIDList(ItemIDList, Path) then
    begin
      strFolder := Path;
      Result := True
    end;
end;

End.

以上代码基于本网站的代码: http://wiki.freepascal.org/VirtualTreeview_Example_for_Lazarus 如果你看单位vstButton,得到一个TEdit,或TCombo ......等......只需用TEdit或TCombo等替换任何TButton参考...为它调整事件等...上面的链接代码实际上使用了TCombo

该网站帮助我学习如何使用virtualtreeview 上面的代码将在每个单元格中插入一个Tbutton,当您单击该按钮时,它将打开一个BrowseForFolder对话框并将结果插回到virtualtreeview单元格中 希望这有帮助

您是否希望始终在单元格列中显示按钮?可以用图像模拟按钮......就像单元格一侧的下拉标记