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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> редактор в VirtualTreeView заместо стандартного, появляется ошибка при выходе из редактор 
V
    Опции темы
Чoо
Дата 13.12.2009, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Здравствуйте. Совсем замучался. Проблема заключается в том, что код после компиляции то работает как надо без ошибок, то при следующей компиляции появляются ошибки при выходе из редактора (по esc или enter). 
Если программу не править, вроде бы ошибка не появляется, если начать добавлять формы, процедуры и прочее, то ошибка может опять появится, но может и не появиться. 
user posted image
вот код (лишнее убрал):
Код

unit BaseEditor1;

interface

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

type
  {редактор для VT}
  PRegexNode = ^TRegexNode;
  TRegexNode = record
    color,
    typeDtrmn,
    regular,
    extansion,
    groups,
    SimbolsCount,
    depth,
    nodeId: wideString;
    brashcolor:integer;
  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;


  TBaseEditor = class(TForm)
    GroupBox1: TGroupBox;
    GroupBox2: TGroupBox;
    Button3: TButton;
    Button2: TButton;
    OpenDialog1: TOpenDialog;
    VT: TVirtualStringTree;
    Button1: TButton;
    ColorDialog1: TColorDialog;
    procedure Button1Click(Sender: TObject);
    procedure VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType;
      var CellText: WideString);
    procedure FormCreate(Sender: TObject);
    procedure VTCompareNodes(Sender: TBaseVirtualTree; Node1,
      Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
    procedure VTHeaderClick(Sender: TVTHeader; HitInfo: TVTHeaderHitInfo);
    procedure VTIncrementalSearch(Sender: TBaseVirtualTree;
      Node: PVirtualNode; const SearchText: WideString;
      var Result: Integer);
    procedure VTPaintText(Sender: TBaseVirtualTree;
      const TargetCanvas: TCanvas; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType);
    procedure VTBeforeCellPaint(Sender: TBaseVirtualTree;
      TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
      CellPaintMode: TVTCellPaintMode; CellRect: TRect;
      var ContentRect: TRect);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure VTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; NewText: WideString);
    procedure VTCreateEditor(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; out EditLink: IVTEditLink);
    procedure VTEditing(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; var Allowed: Boolean);
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  var
  BaseEditor: TBaseEditor;
  VBrashColor:Integer; //цвет фона
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.Destroy;
  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 := TColorBox(FEdit).Items[TColorBox(FEdit).ItemIndex]
  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;
  rn:PRegexNode;
begin
  Result := True;
  FTree := Tree as TVirtualStringTree;
  FNode := Node;
  FColumn := Column;
  FreeAndNil(FEdit);
  rn:=FTree.GetNodeData(Node);
  case column of
    0:
    begin
      FEdit := TColorBox.Create(nil);
      with FEdit as TColorBox do
      begin
        Visible := False;
        Parent := Tree;
        Clear;
        OnKeyDown := EditKeyDown;
      end;
    end;
    1:
    begin
      FEdit := TEdit.Create(nil);
      with FEdit as TEdit do
      begin
        AutoSize := False;
        Visible := False;
        Parent := Tree;
        Text := rn^.typeDtrmn;
        OnKeyDown := EditKeyDown;
      end;
    end;
    2:
    begin
      FEdit := TMemo.Create(nil);
      with FEdit as TMemo do
      begin
        Visible := False;
        Parent := Tree;
        ScrollBars := ssVertical;
        Text := rn.regular;
        OnKeyDown := EditKeyDown;
      end;
    end;
    3:
    begin
      FEdit := TEdit.Create(nil);
      with FEdit as TEdit do
      begin
        AutoSize := False;
        Visible := False;
        Parent := Tree;
        Text := rn^.extansion;
        OnKeyDown := EditKeyDown;
      end;
    end;
    4:
    begin
      FEdit := TComboBox.Create(nil);
      with FEdit as TComboBox do
      begin
        Visible := False;
        Parent := Tree;
        Text := rn^.groups;
        OnKeyDown := EditKeyDown;
      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;
///////////////////
//////////////////
///////////////////// Редактор закончился
//////////////////////
///////////////////
////////////////


procedure TBaseEditor.VTHeaderClick(Sender: TVTHeader;
  HitInfo: TVTHeaderHitInfo);
begin
  if HitInfo.Button = mbLeft then
  begin
    // Меняем индекс сортирующей колонки на индекс колонки,
    // которая была нажата.
    VT.Header.SortColumn := HitInfo.Column;
    // Сортируем всё дерево относительно этой колонки
    // и изменяем порядок сортировки на противополжный
    if VT.Header.SortDirection = sdAscending then
    begin
      VT.Header.SortDirection := sdDescending;
      VT.SortTree(HitInfo.Column, VT.Header.SortDirection);
    end
    else begin
      VT.Header.SortDirection := sdAscending;
      VT.SortTree(HitInfo.Column, VT.Header.SortDirection);
    end;
  end;
end;

procedure TBaseEditor.Button1Click(Sender: TObject);
begin
 showmessage('смайл');
end;

procedure TBaseEditor.VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
  VTEditNode: PRegexNode;
begin
  case Column of
    0:
    begin
      VTEditNode := Sender.GetNodeData(Node);
      CellText := VTEditNode^.color;
    end;
    1:
    begin
      VTEditNode := Sender.GetNodeData(Node);
      CellText := VTEditNode^.typeDtrmn;
    end;
    2:
    begin
      VTEditNode := Sender.GetNodeData(Node);
      CellText := VTEditNode^.regular;
    end;
    3:
    begin
      VTEditNode := Sender.GetNodeData(Node);
      CellText := VTEditNode^.extansion;
    end;
    4:
    begin
      VTEditNode := Sender.GetNodeData(Node);
      CellText := VTEditNode^.groups;
    end;
    5:
    begin
      VTEditNode := Sender.GetNodeData(Node);
      CellText := VTEditNode^.SimbolsCount;
    end;
    6:
    begin
      VTEditNode := Sender.GetNodeData(Node);
      CellText := VTEditNode^.depth;
    end;
    7:
    begin
      VTEditNode := Sender.GetNodeData(Node);
      CellText := VTEditNode^.nodeId;
    end;

  end;
end;

procedure TBaseEditor.FormCreate(Sender: TObject);
begin
  VT.NodeDataSize := SizeOf(TRegexNode);
end;

procedure TBaseEditor.VTCompareNodes(Sender: TBaseVirtualTree; Node1,
  Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
var
  Data1, Data2: PRegexNode; //для сортировку по числам
begin
  case column of
  1,2,3,4:
  {сортировка по алфавиту}
  Result := WideCompareStr(VT.Text[Node1, Column], VT.Text[Node2, Column]);
  0:
  begin
  {cортировка по числам}
    Data1 := Sender.GetNodeData(Node1);
    Data2 := Sender.GetNodeData(Node2);
    if StrToInt('$0'+Data1^.color) > StrToInt('$0'+Data2^.color) then
      Result := 1
    else if StrToInt('$0'+Data1^.color) < StrToInt('$0'+Data2^.color) then
      Result := -1
    else if StrToInt('$0'+Data1^.color) = StrToInt('$0'+Data2^.color) then
      Result := 0;
  end;
  5:
  begin
  {cортировка по числам}
    Data1 := Sender.GetNodeData(Node1);
    Data2 := Sender.GetNodeData(Node2);
    if StrToInt(Data1^.SimbolsCount) > StrToInt(Data2^.SimbolsCount) then
      Result := 1
    else if StrToInt(Data1^.SimbolsCount) < StrToInt(Data2^.SimbolsCount) then
      Result := -1
    else if StrToInt(Data1^.SimbolsCount) = StrToInt(Data2^.SimbolsCount) then
      Result := 0;
  end;
  6:  ;
  7:
  begin
  {cортировка по числам}
    Data1 := Sender.GetNodeData(Node1);
    Data2 := Sender.GetNodeData(Node2);
    if StrToInt(Data1^.nodeId) > StrToInt(Data2^.nodeId) then
      Result := 1
    else if StrToInt(Data1^.nodeId) < StrToInt(Data2^.nodeId) then
      Result := -1
    else if StrToInt(Data1^.nodeId) = StrToInt(Data2^.nodeId) then
      Result := 0;
  end;
  end;

end;

procedure TBaseEditor.VTIncrementalSearch(Sender: TBaseVirtualTree;
  Node: PVirtualNode; const SearchText: WideString; var Result: Integer);
var
  RegexNode: PRegexNode;
begin
  Result := 0;
  RegexNode := VT.GetNodeData(Node);
  if Assigned(RegexNode) then
  begin
    // Используя StrLIComp, мы можем указать длину сравнения.
    // Таким образом, мы сможем найти узлы, совпадающие частично.
    Result := StrLIComp(PAnsiChar(AnsiString(SearchText)),
      PAnsiChar(AnsiString(RegexNode^.groups)),
       Min(Length(SearchText), Length(RegexNode^.groups)));
  end;
end;
procedure TBaseEditor.VTPaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);
var
  RegexNode: PRegexNode;
begin
  {RegexNode := VT.GetNodeData(Node);
  if Assigned(RegexNode) then
    TargetCanvas.Font.Color := StrToInt('$0'+RevRGB(RegexNode^.Color));
  if (vsSelected in Node.States) and (Sender.Focused) then
    TargetCanvas.Font.Color := clHighlightText;   }
end;

{окрашивает фон таблицы (построчно)}
procedure TBaseEditor.VTBeforeCellPaint(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  CellPaintMode: TVTCellPaintMode; CellRect: TRect;
  var ContentRect: TRect);
var
  RegexNode: PRegexNode;
begin
  {RegexNode := VT.GetNodeData(Node);
  if Assigned(RegexNode) then
    with TargetCanvas do
    begin
      Brush.Color := strToInt(RegexNode^.brashcolor);
      FillRect(CellRect);
    end;    }
end;

{удаление текущей строки}
{При удалении надо запоминать ID удаляемых элементов}
procedure TBaseEditor.Button2Click(Sender: TObject);
var
  rNode:PregexNode;
begin
  rNode:=VT.GetNodeData(VT.FocusedNode);
  if rNode<>nil then begin
    //showmessage('смайл');
    VT.DeleteNode(VT.FocusedNode);
  end;
end;

procedure TBaseEditor.Button3Click(Sender: TObject);

begin
  //OpenDialog1.Filter:='Base.d*';
  if OpenDialog1.Execute then begin
    showmessage('смайл');
  end;
end;

procedure TBaseEditor.VTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; NewText: WideString);
var
  regexNode: PRegexNode;
begin
  regexNode := VT.GetNodeData(Node);
  if Assigned(regexNode) then
  begin
    case Column of
      0:
      begin
        regexNode^.color := NewText;
      end;
      1:
      begin
        regexNode^.typeDtrmn := NewText;
      end;
      2:
      begin
        fillChar(regexNode^.regular,SizeOf(regexNode^.regular),#0);
        RegexNode^.regular:=NewText;
        {необходимо вызвать процедуру подсчета длины строки}
        fillChar(regexNode^.SimbolsCount,SizeOf(regexNode^.SimbolsCount),#0);
        //GetLengthRegularInNode(regexNode); - процедура в мое   библе
      end;
      3:
      begin
        fillChar(regexNode^.extansion,SizeOf(regexNode^.extansion),#0);
        RegexNode^.extansion:=NewText;
      end;
      4:
      begin
        fillChar(regexNode^.groups,SizeOf(regexNode^.groups),#0);
        RegexNode^.groups:=NewText;
      end;
    end;
  end;
end;

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

{ПРОЦЕДУРА РАЗРЕШАЕТ РЕДАКТИРОВАНИЕ VT}
procedure TBaseEditor.VTEditing(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; var Allowed: Boolean);
begin
  Allowed := TRUE;
end;

procedure TBaseEditor.FormActivate(Sender: TObject);
var
  NewNode: PVirtualNode;
  NewRegex: PRegexNode;
  i:integer;
begin
  vbrashColor:=clWhite;


  {заполним VT}
  for i:=0 to 3 do begin
    NewNode := VT.AddChild(nil);
    NewRegex := VT.GetNodeData(NewNode);
    if Assigned(NewRegex) then
      with NewRegex^ do
      begin
        color:='00ff00';
        typeDtrmn:='b';
        regular:='sdfsdfsdfsdfsdf';
        extansion:='sdf';
        groups:='ccvv';
        SimbolsCount:='20';
        //Depth:='1024';
        nodeId:='1';
        //brashcolor:=vbrashcolor;
      end;
  end;
end;

end.



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

  PRegexNode = ^TRegexNode;
  TRegexNode = record
    color,
    typeDtrmn,
    regular,
    extansion,
    groups,
    SimbolsCount,
    depth,
    nodeId: wideString;
    brashcolor:integer;
  end;

добавил строчку 
Код

brashcolor:integer;

даже если к этому полю записи не обращаться, появлялись ошибки. 
Потом я решил все поля записи сделать фиксированными, тоесть сделал так:
Код

PRegexNode = ^TRegexNode;
  TRegexNode = record
    color:string[6];
    typeDtrmn:string[1];
    regular:widestring;
    extansion:string[100];
    groups:string[100]; 
    SimbolsCount:string[11]; 
    depth:string[4];   
    nodeId: String[11];
    brashcolor:integer;
  end; 

все заработало как надо. Ошибок не наблюдалось. Скорее всего совпадения, потому что сегодня продолжил работать над программой (то что в архиве - маленький кусочек) опять появились эти ошибки. 
Вернул как было:
Код

  PRegexNode = ^TRegexNode;
  TRegexNode = record
    color,
    typeDtrmn,
    regular,
    extansion,
    groups,
    SimbolsCount,
    depth,
    nodeId: wideString;
    brashcolor:integer;
  end;

(если у вас ошибка не вылетает, попробуйте раскоментируйте эту запись, соотв. старую закоментируйте)
ошибка не появляется.  Начал окрашивать строки таблицы в соотв полю  brashcolor:integer; , опять появилась ошибка. Вобщем похоже на танцы с бубном.
Что это может быть? Криво написал код? (да он тут голый, но тоже пока экспериентировал над ним, ошибка то появлялась, то исчезала). Среда разработки выбрасывает фокусы?
Рад любому совету, спасибо.

Добавлено через 5 минут и 42 секунды
да, это программа ни чего не делает, потому что я ее выдернул из той, которая делает smile. Суть этого окошка в том, что в него загружаются данные из базы данных, цвет текста в строке окрашивается во соответствии с содержимым первой колонки этой строки, фон определяется пользователем. Изменение любой строки в таблице по enter так же вносится в базу данных. По esc все отменяется. 
странность еще и в том, что даже если ошибка появляется, то все работает: редактирование отменятся, если мы отменяем, если мы сохраняем изменения, то они вносятся в таблицу и в базу данных.

Добавлено через 9 минут и 3 секунды
вложение:

Присоединённый файл ( Кол-во скачиваний: 24 )
Присоединённый файл  2.ZIP 6,81 Kb


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
Rrader
  Дата 14.12.2009, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Inspired =)
***


Профиль
Группа: Экс. модератор
Сообщений: 1535
Регистрация: 7.5.2005

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





--------------------
Let's do this quickly!
Rest in peace, Vit!
PM MAIL Skype   Вверх
Чoо
Дата 14.12.2009, 18:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Rrader, посмотрел, спасибо. Решение вопроса сводится к убиранию:
Код

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


вот только не знаю как это скажется на работоспособности программы в целом (программу пишу не только для себя). Саму форму я создаю при вызове этого редктора (в котором использую компонент VTView), после закрытия формы ее уничтожаю.


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
Rrader
  Дата 14.12.2009, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Inspired =)
***


Профиль
Группа: Экс. модератор
Сообщений: 1535
Регистрация: 7.5.2005

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



Чoо, лучше возьмите оттуда мой редактор. Он является наследником TEdit и лишен этой проблемы вылета.

Правда там SetBounds нужно переопределить по-нормальному, а не через reintroduce, но это пустяки


--------------------
Let's do this quickly!
Rest in peace, Vit!
PM MAIL Skype   Вверх
Чoо
Дата 14.12.2009, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Rrader, ну если работает без ошибок, воспользуюсь им, пасиб.  С SetBounds разберусь.
а природа ошибки все же интересна, в той теме ее тоже не открыли (смайл). Разве что намекнули, что возможно происходит обращение к уничтоженому или скрытому редактору 


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
RomanEEP
Дата 14.12.2009, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Природа ошибки очень проста - в вызове FTree.EndEditNode() и FTree.CancelEditNode в обработчике редактора OnKeyDown. Дерево спокойно убивает редактор, а потом возвращается в процедуру обработки события компонента, которого давно нет. В этом лекго убедиться поставив точку останова на TVTCustomEditor.Destroy;
Выход - завершать редактировать узел асинхронно, например, с помощью PostMessage()

ЗЫ: Поскольку редактор является интерфейсом, то можно хранить ссылочку на него где-нибудь, деструктор вызываться не будет и тогда можно даже без PostMessage() обойтись.

Это сообщение отредактировал(а) RomanEEP - 14.12.2009, 20:20
PM MAIL   Вверх
Чoо
Дата 14.12.2009, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



RomanEEP, ну да, процедура OnKeyDown выполняется, доходит до FTree.EndEditNode(), после уничтожается редактор и происходит возврат в OnKeyDown, после окончания которой вылетает ошибка.
пункт "ЗЫ" пока для меня сложен, даже не представляю что сделать, хотя как завершить редактирование ассинхронно, тоже не понятно 


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
RomanEEP
Дата 15.12.2009, 09:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



асинхронно означает отправить PostMessage(WM_USER + xxx); например форме где стоит дерево а вобработчике сообщения WM_USER + xxx вызывать EndEdit()
Второй вариант еще проще - обьяви, например в главной форме ссылку на редактор и сохраняй в неё созданый редактор
Код

private
  FEditor: IVTEditLink;

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

PM MAIL   Вверх
Чoо
Дата 15.12.2009, 21:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



RomanEEP, сделал так, как вы написали. Вобщем что получается, все работает, а вот деструктор вызывается после второго создания редкатора. Тоесть:
1. Создался редактор, сохранили ссылку.
2. Закончили редактировать, деструктор не вызвался.
3. Начали редактировать новый узел, создался редактор, вызвался деструктор, который уничтожил предыдущий редактор. 

Так и должно быть? smile

Добавлено @ 21:19
кстати, обязательно FEditor: IVTEditLink; объявлять как поле, соответственно надо создавать методы, что бы работать с ним? Я просто в раздел объявления переменных первой формы запихнул это  smile

Добавлено через 5 минут и 54 секунды
а не, в раздел переменных нельзя, вылетает ошибка при закрытии программы smile..  Так что писать конструктор, деструктор и методы для поля FEditor ? Если да, то напишу, вроде умею smile 

Это сообщение отредактировал(а) Чoо - 15.12.2009, 21:20


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
Чoо
Дата 15.12.2009, 21:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



а... вываливается ошибка, потому что при закрытии программы вызывается все тот же деструктор, в то время как ссылка Fedit указывает на NIL
Код

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

вобщем все-равно  вызывается деструктор


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
Чoо
Дата 20.12.2009, 21:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



что бы не засорять статью по VT, спрошу тут. назрел еше один вопрос. уже второй день бьюсь и не пойму, как с помощью Drag&Drop перетащить строчку из одного VT в другой? в статье расписано, как это сделать, если у нас одна колонка. Не вопрос, если строка состояит из одной колонки все номрально переносится. Более того, если несколько колонок, но строку переносим в пределах одного компонента VT, переносится содержимое всех столбцов. Однако, если попытаться из одного VT перетащить строку в другой VT, то строка перетащится, но в другом VT (в который мы перетащили строку) отобразится только содержимое первого столбца, содержимое остальных столбцов будет потеряно. Буду рад любому своету. 
структура данных в обоих VT идентична

Это сообщение отредактировал(а) Чoо - 20.12.2009, 21:06


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
kami
Дата 20.12.2009, 23:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Чoо @  20.12.2009,  21:03 Найти цитируемый пост)
в другом VT (в который мы перетащили строку) отобразится только содержимое первого столбца, содержимое остальных столбцов будет потеряно.

Скорее всего, у Вас активна опция TreeOptions>StringOptions>SaveCaptions. Из-за этого в любом случае происходит загрузка и сохранение строки из первого столбца. В том числе и при Drag&Drop, где вызывается ProcessOLEData (само собой, если не используется VCL Drag&Drop). Так вот, в этом ProcessOleData загрузка брошенного нода производится из IStream.
Вам нужно реализовать события OnLoadNode и OnSaveNode, в которых сохранять в поток (и загружать, соответственно) все данные из NodeData.

Кстати, в этом случае будет совсем не лишним отключить опцию SaveCaptions.

Это сообщение отредактировал(а) kami - 20.12.2009, 23:20
PM MAIL WWW   Вверх
Чoо
Дата 20.12.2009, 23:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Спасибо за ответ. звучит сложно. Да, указанная вами опция включена.
Остальное пробую осмыслить.

Добавлено через 4 минуты и 24 секунды
у меня еще такой момент.
  VT.NodeDataSize := SizeOf(TRNode);

в самом VT 2 колонки, однако в записи TRNode больше 2 х полей. Содержимое "скрытых" полей так же важно сохранить.


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
Чoо
Дата 21.12.2009, 00:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



разобрался.. Убил время, нет что бы проверить после реализации указанных вами двух событий, искал как инициализировать эти события  smile  user posted image Вроде все просто и работает smile .


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
kami
Дата 21.12.2009, 01:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Чoо @  20.12.2009,  23:24 Найти цитируемый пост)
Спасибо за ответ. звучит сложно.

Ну, первая часть ответа была на "копание" в исходниках TBaseVirtualTree, если нужно понять, как это вообще работает. Потому что связь Drag&Drop с OnSave/OnLoadNode совсем не очевидна smile
Ну, а потом уже был непосредственно совет - сделать обработчики этих событий...

Цитата(Чoо @  21.12.2009,  00:37 Найти цитируемый пост)
 Вроде все просто и работает

Вот и славно  smile 

Последнее предложение (про убирание опции SaveCaptions, если объявлены OnLoad|SaveNode) остается в силе - эта опция не только добавляет лишние данные к потоку, но и вызывает OnNewText и т.п для каждого загружаемого нода, что при указанных обработчиках не только не полезно, но я бы сказал даже вредно, особенно при большом дереве...

Теперь, кстати, можете очень легко и просто сохранять и загружать все дерево, просто сказав vt.SaveToStream|LoadFromStream - сохранится и загрузится в точности как и было.
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

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

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

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

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


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

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


 




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


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

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