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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> TVirtualTreeView проблема с отрисовкой контролов 
:(
    Опции темы
DreamHunter
Дата 1.7.2014, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Добрый день коллеги.
Столкнулся с проблемой, использую внутренний редактор TVirtualTreeView для добавления TbitBtn в одну из колонок(например в 3-ю).
Так вот проблема в следующем если нодов не много (в смысле помещаются в 1 экран то все нормально рисуется)
как только появляется скролл то у первой ноды появляется BitBtn в первой колонке :(.
Если проскролить список вниз а потом вернутся назад в начало списка все отрисовывается корректно.
Может кто сталкивался с таким помогите.
PM MAIL   Вверх
Poseidon
Дата 1.7.2014, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

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



Ну а код где?

BeginUpdate используете?


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
DreamHunter
Дата 1.7.2014, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



вот код базового класса
Код

unit VTCustomEditorUnit;

interface

uses
  Classes, Windows, SysUtils, Messages, Controls, StdCtrls, ComCtrls,
  ExtCtrls, Graphics, Mask, Variants, CommCtrl, Buttons, VirtualTrees,
  TypesUnit, DateWithTimePickerUnit;

type
  // Наш класс, реализующий интерфейс IVTEditLink.
  // Он будет базовым для всех типов редакторов. Тип создаваемого редактора
  // для каждого узла будет определять по значению поля Kind у записи данных
  // узла (TVTEditNode).
  // Этот вариант более рационален, так как не придётся для каждого типа данных
  // создавать разные классы, релаизующие один и тот же интерфейс по почти
  // идентичной схеме.
  TVTCustomEditor = class(TInterfacedObject, IVTEditLink)
  private
    FEdit: TWinControl;        // Базовый класс для каждого типа редактора
    FTree: TVirtualStringTree; // Ссылка на дерево, вызвавшее редактирование
    FNode: PVirtualNode;       // Редактируемый узел
    FColumn: Integer;          // Его колонка, в которой оно происходит
    FControlValues: TStringList;
  protected
    procedure EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    function GetControlValue: string;
    procedure SetControlValue(AControlValue: string);
    property Edit: TWinControl read FEdit write FEdit;
    property Tree: TVirtualStringTree read FTree write FTree;
    property Node: PVirtualNode read FNode write FNode;
    property Column: Integer read FColumn write FColumn;
    property ControlValue: string read GetControlValue write SetControlValue;
    property ControlValueList: TStringList read FControlValues write FControlValues;
  public
    constructor Create;
    destructor Destroy; override;
    function BeginEdit: Boolean; stdcall;
    function CancelEdit: Boolean; stdcall;
    function EndEdit: Boolean; stdcall;
    function GetBounds: TRect; stdcall;
    function PrepareEdit(ATree: TBaseVirtualTree; ANode: PVirtualNode;
      AColumn: TColumnIndex): Boolean; virtual; stdcall;
    function DefaultPrepareControl(EditorKind: TVTEditorKind): Boolean;
    procedure ProcessMessage(var Message: TMessage); stdcall;
    procedure SetBounds(R: TRect); stdcall;
    procedure DateWithTimePickerChange(Sender: TObject);
  end;

implementation

{ TVTCustomEditor }

function TVTCustomEditor.BeginEdit: Boolean;
begin
  Result := True;
  with FEdit do
    begin
      Show;
      if not (FEdit is TCustomButton) then
        SetFocus;
    end;
end;

function TVTCustomEditor.CancelEdit: Boolean;
begin
  if FEdit is TCustomButton then
    begin
      Result := False;
      FTree.FocusedNode := FNode;
      FTree.OnFocusChanged(FTree, FTree.FocusedNode, FTree.FocusedColumn);
      Exit;
    end;
  Result := True;
  FEdit.Hide;
  if FTree.CanFocus then
    FTree.SetFocus;
end;

constructor TVTCustomEditor.Create;
begin
  inherited;
  FControlValues := TStringList.Create;
end;

procedure TVTCustomEditor.DateWithTimePickerChange(Sender: TObject);
begin
  if not (Sender is TDateWithTimePicker) then
    Exit;
  if TDateWithTimePicker(Sender).Checked then
    begin
      //SendMessage(TDateWithTimePicker(Sender).Handle, DTM_SETSYSTEMTIME, GDT_VALID, Longint(@SysTime));
      //DateTime_SetSystemTime(TDateWithTimePicker(Sender).Handle, GDT_VALID, SysTime);
      //TDateWithTimePicker(Sender).Perform(DTM_SETSYSTEMTIME, GDT_VALID, Longint(@SysTime));
      //PostMessage(TDateWithTimePicker(Sender).Handle, WM_KEYDOWN, VK_RIGHT, 0);
      //PostMessage(TDateWithTimePicker(Sender).Handle, WM_KEYUP, VK_RIGHT, 0);

      //if TDateWithTimePicker(Sender).ForceDateWithTimeChange then //вызов данного метода перенесен в переопределенный метод TDateWithTimePicker.Change
        FTree.Text[FNode, FColumn] := DateTimeToStr(TDateWithTimePicker(Sender).DateTime);
    end;
end;

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

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.EndEdit: Boolean;
var
  Txt: String;
begin
  Result := True;
  Txt := '';
  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
    and TDateTimePicker(FEdit).Checked then
      Txt := DateTimeToStr(TDateTimePicker(FEdit).DateTime)
  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;
  if FTree.CanFocus then
    FTree.SetFocus;
end;

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

function TVTCustomEditor.PrepareEdit(ATree: TBaseVirtualTree; ANode: PVirtualNode;
  AColumn: TColumnIndex): Boolean;
//var
//  VTEditNode: PObjectAddInfoRec;
//  AttrValue: string;
begin
  Result := True;
  FTree := ATree as TVirtualStringTree;
  FNode := ANode;
  FColumn := AColumn;
  FreeAndNil(FEdit);
  //VTEditNode := FTree.GetNodeData(Node);
  //AttrValue := VarToStr(VTEditNode.AttrVal); перенести в класс наследник
  //PrepareControl(VTEditNode.AttrEditorKind, AttrValue);
end;

function TVTCustomEditor.DefaultPrepareControl(
  EditorKind: TVTEditorKind): Boolean;
begin
  Result := True;
  case EditorKind of
    ekString:
      begin
        FEdit := TEdit.Create(nil);
        with FEdit as TEdit do
        begin
          AutoSize := False;
          Visible := False;
          Parent := Tree;
          Text := ControlValue;
          OnKeyDown := EditKeyDown;
        end;
      end;
    ekMemo:
      begin
        FEdit := TMemo.Create(nil);
        with FEdit as TMemo do
        begin
          Visible := False;
          Parent := Tree;
          ScrollBars := ssVertical;
          Text := ControlValue;
          OnKeyDown := EditKeyDown;
        end;
      end;
    ekComboBox, ekComboBoxFixed:
      begin
        FEdit := TComboBox.Create(nil);
        with FEdit as TComboBox do
        begin
          Visible := False;
          Parent := Tree;
          //FNode.NodeHeight := Height + Margins.Top + Margins.Bottom;
          if Assigned(ControlValueList) then
            Items.AddStrings(ControlValueList);
          if EditorKind = ekComboBox then
            begin
              Style := csDropDown;
              Text := ControlValue;
            end
          else if EditorKind = ekComboBoxFixed then
            begin
              Style := csDropDownList;
              ItemIndex := Items.IndexOf(ControlValue);
            end;
          OnKeyDown := EditKeyDown;
        end;
      end;
    ekColor:
      begin
        FEdit := TColorBox.Create(nil);
        with FEdit as TColorBox do
        begin
          Visible := False;
          Parent := Tree;
          Selected := StringToColor(ControlValue);
          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'; //NB! -> can define in descendant class
          Text := ControlValue;
          OnKeyDown := EditKeyDown;
        end;
      end;
    ekDate, ekDateTime:
      begin
        FEdit := TDateWithTimePicker.Create(nil);
        with FEdit as TDateWithTimePicker do
        begin
          Visible := False;
          Parent := Tree;
          if EditorKind = ekDate then
            begin
              DateMode := dmComboBox;
              Kind := dtkDate;
              Format := 'dd.MM.yyyy';
              DateTime := StrToDateTimeDef(ControlValue, SysUtils.Date);
            end
          else if EditorKind = ekDateTime then
            begin
              DateMode := dmUpDown;
              Kind := dtkTime;
              Format := 'dd.MM.yyyy HH:mm:ss';
              DateTime := StrToDateTimeDef(ControlValue, SysUtils.Now);
              OnChange := DateWithTimePickerChange;
            end;
          ShowCheckbox := True;
          Checked := ControlValue <> '';
          OnKeyDown := EditKeyDown;
        end;
    end;
    ekProgress:
      begin
        FEdit := TProgressBar.Create(nil);
        with FEdit as TProgressBar do
        begin
          Visible := False;
          Parent := Tree;
          Position := StrToIntDef(ControlValue, 0);
        end;
      end;
    ekButton:
      begin
        FEdit := TBitBtn.Create(nil);
        with FEdit as TBitBtn do
          begin
            Visible := False;
            Parent := Tree;
            Caption := ControlValue;
            OnKeyDown := EditKeyDown;
          end;
      end
  else
    Result := False;
  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 := R;
  if FEdit is TMemo then
    FEdit.Height := 80;
end;

function TVTCustomEditor.GetControlValue: string;
begin
  if FControlValues.Count > 0 then
    Result := FControlValues.Strings[0]
  else
    Result := '';
end;

procedure TVTCustomEditor.SetControlValue(AControlValue: string);
begin
  FControlValues.Text := AControlValue;
end;

end.

а вот его наследник
Код

TVTResponsibleEditor = class(TVTCustomEditor)
  private
    FOnCallToResponsible: TNotifyEvent;
    FButtonGlyph: TBitmap;
  public
    constructor Create;
    function PrepareEdit(ATree: TBaseVirtualTree; ANode: PVirtualNode;
      AColumn: TColumnIndex): Boolean; override; stdcall;
    destructor Destroy; override;
    property OnCallToResponsible: TNotifyEvent read FOnCallToResponsible write FOnCallToResponsible;
    property ButtonGlyph: TBitmap read FButtonGlyph write FButtonGlyph;
  end;
{ TVTResponsibleEditor }

constructor TVTResponsibleEditor.Create;
begin
  inherited;
  FButtonGlyph := TBitmap.Create;
end;

destructor TVTResponsibleEditor.Destroy;
begin
  FreeAndNil(FButtonGlyph);
  inherited;
end;

function TVTResponsibleEditor.PrepareEdit(ATree: TBaseVirtualTree;
  ANode: PVirtualNode; AColumn: TColumnIndex): Boolean;
begin
  Result := inherited;
  if not Result then
    Exit;
  ControlValue := TVirtualStringTree(ATree).Header.Columns[AColumn].Text;
  Result := DefaultPrepareControl(ekButton);
  (Edit as TBitBtn).OnClick := FOnCallToResponsible;
  (Edit as TBitBtn).Glyph := FButtonGlyph;
end;

BeginUpdate не использую

Добавлено через 4 минуты и 44 секунды
еще несколько финтов для скрола 
Код

procedure TKeyRespSendEventsFrame.VSTListScroll(Sender: TBaseVirtualTree;
  DeltaX, DeltaY: Integer);
var
  Node : PVirtualNode;
  rec : PResponsible;
  DY : integer;
begin
  if (TVirtualStringTree(Sender).Tag = RESPONSIBLES) then
    begin
      if DeltaY <> 0 then begin
        DY := TVirtualStringTree(Sender).DefaultNodeHeight;
        Sender.OffsetY := Round(Sender.OffsetY / DY) * DY;
      end;

      Node := VSTList.GetFirst;
      if Assigned(Node) then
        repeat
          rec := Sender.GetNodeData(Node);
          if rec.btn_Call=nil then
            Exit;

          if  vsVisible in Node.States then
            begin
              with rec^ do
                begin
                  btn_Call.Visible := true;

                end;
            end
          else
            with rec^ do
              begin

                btn_Call.Visible := false;

              end;
          Node := Node.NextSibling;
        until Node = nil;
    end;

end;

и еще AfterCellPaint
Код

procedure TKeyRespSendEventsFrame.VSTListAfterCellPaint(
  Sender: TBaseVirtualTree; TargetCanvas: TCanvas; Node: PVirtualNode;
  Column: TColumnIndex; CellRect: TRect);
var
  rec : PResponsible;
  R : TRect;
begin
  try
    Sender.BeginSynch;
    rec := Sender.GetNodeData(Node);
    R := VSTList.GetDisplayRect(Node,Column,false);

    with rec^ do
      case Column of
        3:  begin
              btn_Call.Left := CellRect.Left;
              btn_Call.Top := R.Top;
              btn_Call.Width := CellRect.Right-CellRect.Left;
              btn_Call.Height := VSTList.DefaultNodeHeight-3;
              btn_Call.Visible := true;
            end;
      end;
  finally
    Sender.EndSynch;
  end;
end;


Это сообщение отредактировал(а) DreamHunter - 1.7.2014, 12:58
PM MAIL   Вверх
DreamHunter
Дата 2.7.2014, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



неужели никто не сталкивался с такой проблемой?
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

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

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

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

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


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

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


 




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


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

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