Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Создание редактора для VirtualTreeView


Автор: aktuba 27.12.2006, 06:13
Люди, возникла проблема при создании своего редактора для VT.
Вот что есть:
Код

type
  PHKNode = ^THKNode;
  THKNode = record
    Caption: string;
    Key: TShortCut;
    Modify: Boolean;
  end;

  TVTCustomEditor = class(TInterfacedObject, IVTEditLink)
  private
    FEdit: TEdit;
    FTree: TVirtualStringTree;
    FNode: PVirtualNode;
    FColumn: Integer;
  protected
    procedure EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure EditKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
  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 TVTCustomEditor.BeginEdit: Boolean;
begin
    Result := True;
  with FEdit do
    begin
      Show;
      SetFocus;
    end;
end;

function TVTCustomEditor.CancelEdit: Boolean;
begin
    Result := True;
  FEdit.Hide;
  FTree.SetFocus;
end;

destructor TVTCustomEditor.Destroy;
begin
    FreeAndNil(FEdit);
  inherited;
end;

procedure TVTCustomEditor.EditKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
const
    keys: set of Byte = [8, 9, 13, 32];
var
    str: string;
begin
    str := '';
  if Key = VK_ESCAPE then
    begin
      FTree.CancelEditNode;
     Key := 0;
      Exit;
    end;
  if ssCtrl in Shift then str := str + 'Ctrl+';
  if ssAlt in Shift then str := str + 'Alt+';
  if ssShift in Shift then str := str + 'Shift+';
  if Key in keys then
    begin
      case Key of
       VK_RETURN: str := str + 'Enter';
        VK_TAB: str := str + 'TAB';
        VK_BACK: str := str + 'Backspace';
        VK_SPACE: str := str + 'Space';
      end;
    end;
  if Key > 32 then str := str + Chr(Key);
  FEdit.Text := str;
  if (Key >= 32) or (Key in keys) then EndEdit;//FTree.EndEditNode;
end;

procedure TVTCustomEditor.EditKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
    Key := 0;
    EditKeyDown(Sender, Key, Shift);
end;

function TVTCustomEditor.EndEdit: Boolean;
var
    lData: PHKNode;
begin
    Result := False;
  lData := FTree.GetNodeData(FNode);
  if not Assigned(lData) then Exit;
  lData^.Key := TextToShortCut(FEdit.Text);
  lData^.Modify := True;
  FEdit.Hide;
  FTree.SetFocus;
  Result := True;
end;

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

function TVTCustomEditor.PrepareEdit(Tree: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex): Boolean;
var
  VTEditNode: PHKNode;
begin
  Result := True;
  FTree := Tree as TVirtualStringTree;
  FNode := Node;
  FColumn := Column;
  FreeAndNil(FEdit);
  VTEditNode := FTree.GetNodeData(Node);
  FEdit := TEdit.Create(FTree);
  with FEdit as TEdit do
    begin
      AutoSize := False;
      Visible := False;
      Parent := Tree;
      Text := ShortCutToText(VTEditNode^.Key);
      OnKeyDown := EditKeyDown;
      OnKeyUp := EditKeyUp;
    end;
end;

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

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


Так все работает, но после окончания работы с редактором не происходит перерисовка (Repaint). 
А если в функции EditKeyDown заменить строку
Код

if (Key >= 32) or (Key in keys) then EndEdit;

на строку
Код

if (Key >= 32) or (Key in keys) then FTree.EndEditNode;

то получаю AV. Помогите разобраться plz... smile 

Автор: Bose 27.12.2006, 18:53
в PrepareEdit НЕ присваивай обработчик для OnKeyDown. Обрабатывай всё это в OnKeyUp! smile

Добавлено @ 18:55 
изменённая PrepareEdit будeт выглядеть так:

Код

function TVTCustomEditor.PrepareEdit(Tree: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex): Boolean;
var
  VTEditNode: PHKNode;
begin
  Result := True;
  FTree := Tree as TVirtualStringTree;
  FNode := Node;
  FColumn := Column;
  FreeAndNil(FEdit);
  VTEditNode := FTree.GetNodeData(Node);
  FEdit := TEdit.Create(FTree);
  with FEdit as TEdit do
    begin
      AutoSize := False;
      Visible := False;
      Parent := Tree;
      Text := ShortCutToText(VTEditNode^.Key);
      OnKeyDown := nil;
      OnKeyUp := EditKeyDown;
    end;
end;

Автор: aktuba 31.12.2006, 03:59
Проблему решил иначе. Убрал 
Код

FEdit.Hide;
 в CancelEdit и в EndEdit.

Может кому пригодится...

Автор: Bose 2.1.2007, 16:34
aktuba, тебе мой совет не помог что ли? smile  smile  smile 

Автор: aktuba 2.1.2007, 17:20
Bose - я не мог использовать твой совет, т.к. основной код у меня как-раз в OnKeyDown. Если нажата Shift или Ctrl или Alt и удерживается, то выводится название иначе не выводится... Поэтому пришлось искать обходные пути...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)