Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> VT - помогите с собственными редакторами данных 
V
    Опции темы
ВиТеК
Дата 11.9.2009, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 27.4.2008
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Вопрос скорее к Quadr0, но если кто знает - милости прошу.

В этой статье описывает пример использования в VT собственных редакторов данных (fig 1.4).

Так вот при компиляции этого примера все происходит так, как и задумал автор:
user posted image
Если же перенести код в другой проект, то такого результата уже не увидем:
user posted image
Я уже и свойства компонента скопировал  вручную из dfm-файла.

Может кто помочь?
PM MAIL ICQ   Вверх
kami
Дата 11.9.2009, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(ВиТеК @  11.9.2009,  12:03 Найти цитируемый пост)
при компиляции этого примера все происходит так, как и задумал автор:

На скриншоте не видно использования редактора, а вопрос поставлен именно про него. Вообще, из скриншотов понятно только одно - не отображаются данные.

Цитата(ВиТеК @  11.9.2009,  12:03 Найти цитируемый пост)
Если же перенести код в другой проект, то такого результата уже не увидем:

События для VT назначены? Первое, что приходит в голову - нет OnGetText. Или оно есть, но в инспекторе объектов на этом событии ничего нет.
Проект с минимальным кодом - в студию.

Это сообщение отредактировал(а) kami - 11.9.2009, 12:18
PM MAIL WWW   Вверх
ВиТеК
Дата 11.9.2009, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 27.4.2008
Где: Санкт-Петербург

Репутация: нет
Всего: нет



В приложении форма проекта содержащая VT.
Тут все повторяется как и в примере от Quadr0.

Код

nit ClimatEditor;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, XPMan, StdCtrls, VirtualTrees, ExtCtrls, Mask, ComCtrls, Buttons;

type
  TVTEditorKind = (
    ekString, // TEdit
    ekMemo, // TMemo
    ekComboBox, // TComboBox
    ekColor, // TColorBox
    ekDate, // TDateTimePicker
    ekMask, // TMaskedEdit
    ekProgress // TProgressBar
  );

  PVTEditNode = ^TVTEditNode;

  TVTEditNode = record
    Kind: TVTEditorKind;
    Value: String;
    Changed: Boolean;
  end;

  TVTCustomEditor = class(TInterfacedObject, IVTEditLink)
  private
    FEdit: TWinControl;        // Базовый класс для каждого типа редактора
    FTree: TVirtualStringTree; // Ссылка на дерево, вызвавшее редактирование
    FNode: PVirtualNode;       // Редактируемый узел
    FColumn: Integer;          // Его колонка, в которой оно происходит
  protected
    procedure EditKeyDown(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;

  TfrmClimatEditor = class(TForm)
    VT: TVirtualStringTree;
    btn1: TBitBtn;
    btn2: TBitBtn;
    pgc1: TPageControl;
    ts1: TTabSheet;
    ts2: TTabSheet;
    pgc2: TPageControl;
    ts5: TTabSheet;
    ts6: TTabSheet;
    ts7: TTabSheet;
    ts8: TTabSheet;
    ts9: TTabSheet;
    lbledt1: TLabeledEdit;
    btn3: TBitBtn;
    btn4: TBitBtn;
    procedure VTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; NewText: WideString);
    procedure VTChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
    procedure VTPaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas;
      Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType);
    procedure VTCreateEditor(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; out EditLink: IVTEditLink);
    procedure VTEditing(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; var Allowed: Boolean);
    procedure VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  const
  ValueTypes: array[0..6] of TVTEditorKind = (
    ekString, // Имя
    ekMemo, // Описание
    ekComboBox, // Тип
    ekColor, // Цвет
    ekDate, // Дата
    ekMask, // Маска
    ekProgress // Процесс
  );
  // Значения по умолчанию
  DefaultValues: array[0..6] of String = (
    'Свитер',
    'Мягкий и тёплый.',
    'Шерсть',
    'clRed',
    '24.06.2006',
    '798-77-66',
    '70 %'
  );
  // Имена параметров
  ValueNames: array[0..6] of String = (
    'Имя изделия',
    'Комментарий',
    'Материал',
    'Цвет изделия',
    'Дата изготовления',
    'Телефон склада',
    'Процесс доставки'
  );

var
  frmClimatEditor: TfrmClimatEditor;

implementation

{$R *.dfm}

//------------------------------------------------------------------------------
{* * * * * * * * * * * * * * * * TVTCustomEditor * * * * * * * * * * * * * * * }
//------------------------------------------------------------------------------
destructor TVTCustomEditor.Destroy;
begin
  FreeAndNil(FEdit);
  inherited;
end;

//------------------------------------------------------------------------------
// Для обработки нажатий с клавиатуры.
// Отмена редактироваеия по Escape, завершение редактирования по Enter,
// и переход между узлами по Up/Down, если список элементов у комбо бокса или
// редактора даты не выпущен.
//------------------------------------------------------------------------------
procedure TVTCustomEditor.EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
  CanContinue: Boolean;
begin
  CanContinue := True;
  case Key of
    VK_ESCAPE: // Нажали Escape
      if CanContinue then
      begin
        FTree.CancelEditNode;
        Key := 0;
      end;
    VK_RETURN: // Нажали Enter
      if CanContinue then
      begin
        // Если Ctrl для TMemo не зажат, то завершаем редактирование
        // Сдеалем так, чтобы можно было по Ctrl+Enter вставлять в Memo
        // новую линию.
        if (FEdit is TMemo) and (Shift = []) then
          FTree.EndEditNode
        else if not(FEdit is TMemo) then
          FTree.EndEditNode;
        Key := 0;
      end;
    VK_UP, VK_DOWN:
      begin
        // Проверить, не идёт ли работа с редактором. Если идёт, то запретить
        // активность дерева, если нет, то передать нажатие дереву.
        CanContinue := Shift = [];
        if FEdit is TComboBox then
          CanContinue := CanContinue and not TComboBox(FEdit).DroppedDown;
        if FEdit is TDateTimePicker then
          CanContinue :=  CanContinue and not TDateTimePicker(FEdit).DroppedDown;
        if CanContinue then
        begin
          // Передача клавиши дереву
          PostMessage(FTree.Handle, WM_KEYDOWN, Key, 0);
          Key := 0;
        end;
      end;
  end;
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;
end;

//------------------------------------------------------------------------------
// Успешно завершилось, прячем редактор, обновляем данные узла и возвращаем
// фокус дереву.
//------------------------------------------------------------------------------
function TVTCustomEditor.EndEdit: Boolean;
var
  Txt: String;
begin
  Result := True;
  if FEdit is TEdit then
    Txt := TEdit(FEdit).Text
  else if FEdit is TMemo then
    Txt := TEdit(FEdit).Text
  else if FEdit is TComboBox then
    Txt := TComboBox(FEdit).Text
  else if FEdit is TColorBox then
    Txt := ColorToString(TColorBox(FEdit).Selected)
  else if FEdit is TDateTimePicker then
  begin
    Txt := DateToStr(TDateTimePicker(FEdit).DateTime);
  end
  else if FEdit is TMaskEdit then
    Txt := TMaskEdit(FEdit).Text
  else if FEdit is TProgressBar then
    Txt := IntToStr(TProgressBar(FEdit).Position) + ' %';
  // Изменяем текст узла (поле Value у TVTEditNode) через событие OnNewText
  // у дерева
  FTree.Text[FNode, FColumn] := Txt;
  FEdit.Hide;
  FTree.SetFocus;
end;

//------------------------------------------------------------------------------
// Возвращаем границы редактора.
//------------------------------------------------------------------------------
function TVTCustomEditor.GetBounds: TRect;
begin
  Result := FEdit.BoundsRect;
end;

//------------------------------------------------------------------------------
// В подготовке к редактированию мы должны создать экземпляр TWinControl
// нужного класса потомка в соответствии с полем Kind у TVTEditNode.
//------------------------------------------------------------------------------
function TVTCustomEditor.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex): Boolean;
var
  VTEditNode: PVTEditNode;
begin
  Result := True;
  FTree := Tree as TVirtualStringTree;
  FNode := Node;
  FColumn := Column;
  FreeAndNil(FEdit);
  VTEditNode := FTree.GetNodeData(Node);
  case VTEditNode.Kind of
    ekString:
    begin
      FEdit := TEdit.Create(nil);
      with FEdit as TEdit do
      begin
        AutoSize := False;
        Visible := False;
        Parent := Tree;
        Text := VTEditNode.Value;
        OnKeyDown := EditKeyDown;
      end;
    end;
    ekMemo:
    begin
      FEdit := TMemo.Create(nil);
      with FEdit as TMemo do
      begin
        Visible := False;
        Parent := Tree;
        ScrollBars := ssVertical;
        Text := VTEditNode.Value;
        OnKeyDown := EditKeyDown;
      end;
    end;
    ekComboBox:
    begin
      FEdit := TComboBox.Create(nil);
      with FEdit as TComboBox do
      begin
        Visible := False;
        Parent := Tree;
        Text := VTEditNode.Value;
        Items.Add('Шерсть');
        Items.Add('Хлопок');
        Items.Add('Шёлк');
        Items.Add('Кожа');
        Items.Add('Велюр');
        OnKeyDown := EditKeyDown;
      end;
    end;
    ekColor:
    begin
      FEdit := TColorBox.Create(nil);
      with FEdit as TColorBox do
      begin
        Visible := False;
        Parent := Tree;
        Selected := StringToColor(VTEditNode.Value);
        Style := Style + [cbPrettyNames];
        OnKeyDown := EditKeyDown;
      end;
    end;
    ekMask:
    begin
      FEdit := TMaskEdit.Create(nil);
      with FEdit as TMaskEdit do
      begin
        AutoSize := False;
        Visible := False;
        Parent := Tree;
        EditMask := '999-99-99';
        Text := VTEditNode.Value;
        OnKeyDown := EditKeyDown;
      end;
    end;
    ekDate:
    begin
      FEdit := TDateTimePicker.Create(nil);
      with FEdit as TDateTimePicker do
      begin
        Visible := False;
        Parent := Tree;
        Date := StrToDate(VTEditNode.Value);
        OnKeyDown := EditKeyDown;
      end;
    end;
    ekProgress:
    begin
      FEdit := TProgressBar.Create(nil);
      with FEdit as TProgressBar do
      begin
        Visible := False;
        Parent := Tree;
        Position := StrToIntDef(VTEditNode.Value, 70);
      end;
    end
  else
    Result := False;
  end;
end;

//------------------------------------------------------------------------------
// Обработка сообщений Windows для редактора.
//------------------------------------------------------------------------------
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 := R;
  if FEdit is TMemo then
    FEdit.Height := 80;
end;

//------------------------------------------------------------------------------
{* * * * * * * * * * * * * * * * * * * TfrmMain * * * * * * * * * * * * * * * *}
//------------------------------------------------------------------------------
procedure TfrmClimatEditor.FormCreate(Sender: TObject);
var
  i: Integer;
  NewNode: PVirtualNode;
  VTEditNode: PVTEditNode;
begin
  VT.NodeDataSize := SizeOf(TVTEditNode);
  for i := 0 to 6 do
  begin
    NewNode := VT.AddChild(nil);
    VTEditNode := VT.GetNodeData(NewNode);
    with VTEditNode^ do
    begin
      Kind := ValueTypes[i];
      Value := DefaultValues[i];
      Changed := False;
    end;
  end;
  VT.AddChild (nil);
end;

//------------------------------------------------------------------------------

procedure TfrmClimatEditor.VTChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
begin
  with Sender do
  begin
    if Assigned(Node) then
    begin
      // Убираем паузу перед редактированием узла. Что бы ни случилось с узлом,
      // (кликнули, выделили) сразу начётся редактирование колонки.
      VT.EditNode(Node, 1);
    end;
  end;
end;

//------------------------------------------------------------------------------

procedure TfrmClimatEditor.VTCreateEditor(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; out EditLink: IVTEditLink);
begin
  EditLink := TVTCustomEditor.Create;
end;

//------------------------------------------------------------------------------
// Разрешаем редактировать только второую колонку.
//------------------------------------------------------------------------------
procedure TfrmClimatEditor.VTEditing(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; var Allowed: Boolean);
begin
  Allowed := Column > 0;
end;

//------------------------------------------------------------------------------

procedure TfrmClimatEditor.VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
  VTEditNode: PVTEditNode;
begin
  case Column of
    0: CellText := ValueNames[Node.Index];
    1:
    begin
      VTEditNode := Sender.GetNodeData(Node);
      CellText := VTEditNode^.Value;
    end;
  end;
end;

//------------------------------------------------------------------------------
// Обновляем виртуальные данные после редактирования.
//------------------------------------------------------------------------------
procedure TfrmClimatEditor.VTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; NewText: WideString);
var
  VTEditNode: PVTEditNode;
begin
  VTEditNode := Sender.GetNodeData(Node);
  with VTEditNode^ do
  begin
    if not Changed then
      Changed := Value <> NewText;
    Value := StringReplace(NewText, #13#10, ' ', [rfReplaceAll]);
  end;
end;

//------------------------------------------------------------------------------

procedure TfrmClimatEditor.VTPaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);
var
  VTEditNode: PVTEditNode;
begin
  VTEditNode := Sender.GetNodeData(Node);
  if VTEditNode.Changed then
    TargetCanvas.Font.Style := [fsBold]
  else
    TargetCanvas.Font.Style := [];
end;

end.


Это сообщение отредактировал(а) ВиТеК - 11.9.2009, 16:01

Присоединённый файл ( Кол-во скачиваний: 17 )
Присоединённый файл  climateditor.zip 13,66 Kb
PM MAIL ICQ   Вверх
kami
Дата 11.9.2009, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



В выложенном файле отсутствует обработчик события OnCreate для формы.
Это - единственная проблема. Надеюсь, почему в результате не было отображено ни одного нода, пояснять не нужно?

Добавлено через 35 секунд
Вернее, обработчик присутствует, но не назначен для формы.
PM MAIL WWW   Вверх
ВиТеК
Дата 13.9.2009, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 27.4.2008
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Спасибо это поправил, но теперь при отображении формы выскакивает ошибка:

First chance exception at $7C81EB33. Exception class EAccessViolation with message 'Access violation at address 0040560A in module 'Energopas.exe'. Read of address FFFFFFFF'. Process Energopas.exe (1496)
Thread Exit: Thread ID: 1296. Process Energopas.exe (1496)

ведущая к:

Код

procedure TCustomVirtualStringTree.DoGetText(Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var Text: UnicodeString);

begin
  if Assigned(FOnGetText) then
    FOnGetText(Self, Node, Column, TextType, Text);
end;


Это сообщение отредактировал(а) ВиТеК - 13.9.2009, 11:58
PM MAIL ICQ   Вверх
kami
Дата 13.9.2009, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Ставь брейкпоинт на первую строку в процедуре
Код

procedure TfrmClimatEditor.VTGetText

И смотри, где и что.
Если до нее отладчик не доберется - дело скрылось где-то раньше.
Хотя у меня ничего такого не выдало. (выложенный код я не правил, за исключением назначения OnFormCreate)

Это сообщение отредактировал(а) kami - 13.9.2009, 16:31
PM MAIL WWW   Вверх
ВиТеК
Дата 21.9.2009, 02:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 27.4.2008
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Если кому интересно окончание истории.

Сначала вылезала ошибка:
Код

procedure TfrmClimatEditor.VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
  VTEditNode: PVTEditNode;
begin
  case Column of
    0: CellText := ValueNames[Node.Index];
    1:
    begin
      VTEditNode := Sender.GetNodeData(Node);
      CellText := VTEditNode^.Value;
    end;
  end;
end;

То получаем картину:
user posted image

Когда установил комментарий:
Код

procedure TfrmClimatEditor.VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
  VTEditNode: PVTEditNode;
begin
  case Column of
    //0: CellText := ValueNames[Node.Index];
    1:
    begin
      VTEditNode := Sender.GetNodeData(Node);
      CellText := VTEditNode^.Value;
    end;
  end;
end;

Получилось:
user posted image

Тогда стало понятно, что добавляется лишний узел и он был найден тут:
Код

procedure TfrmClimatEditor.FormCreate(Sender: TObject);
var
  i: Integer;
  NewNode: PVirtualNode;
  VTEditNode: PVTEditNode;
begin
  VT.NodeDataSize := SizeOf(TVTEditNode);
  for i := 0 to 6 do
  begin
    NewNode := VT.AddChild(nil);
    VTEditNode := VT.GetNodeData(NewNode);
    with VTEditNode^ do
    begin
      Kind := ValueTypes[i];
      Value := DefaultValues[i];
      Changed := False;
    end;
  end;
  //VT.AddChild (nil);
end;


Спасибо всем, кто помог.

Это сообщение отредактировал(а) ВиТеК - 21.9.2009, 02:19
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0513 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.