Новичок
Профиль
Группа: Участник
Сообщений: 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
|