main.pas
来自「本系统前端界面采用WINDOWS 窗口风格」· PAS 代码 · 共 662 行 · 第 1/2 页
PAS
662 行
SetString(Data.Caption, Head, Tail - Head);
end;
// skip line separators
if Tail^ = #13 then
Inc(Tail);
if Tail^ = #10 then
Inc(Tail);
Head := Tail;
end;
finally
Target.EndUpdate;
end;
end;
end;
//----------------------------------------------------------------------------------------------------------------------
function TMainForm.FindCPFormatDescription(CPFormat: Word): string;
var
Buffer: array[0..2048] of Char;
begin
// Try the formats support the by Virtual Treeview first.
Result := GetVTClipboardFormatDescription(CPFormat);
// Retrieve additional formats from system.
if Length(Result) = 0 then
begin
if GetClipboardFormatName(CPFormat, @Buffer, 2048) > 0 then
Result := ' - ' + Buffer
else
Result := Format(' - unknown format (%d)', [CPFormat]);
end
else
Result := ' - ' + Result;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TMainForm.TreeDragDrop(Sender: TBaseVirtualTree; Source: TObject; DataObject: IDataObject;
Formats: TFormatArray; Shift: TShiftState; Pt: TPoint; var Effect: Integer; Mode: TDropMode);
//--------------- local function --------------------------------------------
procedure DetermineEffect;
// Determine the drop effect to use if the source is a Virtual Treeview.
begin
// In the case the source is a Virtual Treeview we know 'move' is the default if dragging within
// the same tree and copy if dragging to another tree. Set Effect accordingly.
if Shift = [] then
begin
// No modifier key, so use standard action.
if Source = Sender then
Effect := DROPEFFECT_MOVE
else
Effect := DROPEFFECT_COPY;
end
else
begin
// A modifier key is pressed, hence use this to determine action.
if (Shift = [ssAlt]) or (Shift = [ssCtrl, ssAlt]) then
Effect := DROPEFFECT_LINK
else
if Shift = [ssCtrl] then
Effect := DROPEFFECT_COPY
else
Effect := DROPEFFECT_MOVE;
end;
end;
//--------------- end local function ----------------------------------------
var
S: string;
Attachmode: TVTNodeAttachMode;
Nodes: TNodeArray;
I: Integer;
begin
Nodes := nil;
if LogListBox.Items.Count > 0 then
LogListBox.Items.Add('');
if Sender = Tree1 then
LogListBox.Items.Add('----- Tree 1')
else
LogListBox.Items.Add('----- Tree 2');
if DataObject = nil then
LogListBox.Items.Add('VCL drop arrived')
else
LogListBox.Items.Add('OLE drop arrived');
S := 'Drop actions allowed:';
if Boolean(DROPEFFECT_COPY and Effect) then
S := S + ' copy';
if Boolean(DROPEFFECT_MOVE and Effect) then
S := S + ' move';
if Boolean(DROPEFFECT_LINK and Effect) then
S := S + ' link';
LogListBox.Items.Add(S);
S := 'Drop mode: ' + GetEnumName(TypeInfo(TDropMode), Ord(Mode));
LogListBox.Items.Add(S);
// Translate the drop position into an node attach mode.
case Mode of
dmAbove:
AttachMode := amInsertBefore;
dmOnNode:
AttachMode := amAddChildLast;
dmBelow:
AttachMode := amInsertAfter;
else
AttachMode := amNowhere;
end;
if DataObject = nil then
begin
// VCL drag'n drop. Handling this requires detailed knowledge about the sender and its data. This is one reason
// why it was a bad decision by Borland to implement something own instead using the system's way.
// In this demo we have two known sources of VCL dd data: Tree2 and LogListBox.
if Source = Tree2 then
begin
// Since we know this is a Virtual Treeview we can ignore the drop event entirely and use VT mechanisms.
DetermineEffect;
Nodes := Tree2.GetSortedSelection(True);
if Effect = DROPEFFECT_COPY then
begin
for I := 0 to High(Nodes) do
Tree2.CopyTo(Nodes[I], Sender.DropTargetNode, AttachMode, False);
end
else
for I := 0 to High(Nodes) do
Tree2.MoveTo(Nodes[I], Sender.DropTargetNode, AttachMode, False);
end
else
begin
// One long string (one node) is added, containing all text currently in the list box.
AddVCLText(Sender as TVirtualStringTree, LogListBox.Items.CommaText, AttachMode);
LogListBox.Items.Add('List box data accepted as string.');
end;
end
else
begin
// OLE drag'n drop. Perform full processing.
LogListBox.Items.Add('There are ' + IntToStr(Length(Formats)) + ' formats available:');
// Determine action in advance even if we don't use the dropped data.
// Note: The Effect parameter is a variable which must be set to the action we
// will actually take, to notify the sender of the drag operation about remaining actions.
// This value determines what the caller will do after the method returns,
// e.g. if DROPEFFECT_MOVE is returned then the source data will be deleted.
if Source is TBaseVirtualTree then
begin
DetermineEffect;
end
else
// Prefer copy if allowed for every other drag source. Alone from Effect you cannot determine the standard action
// of the sender, but we assume if copy is allowed then it is also the standard action
// (e.g. as in TRichEdit).
if Boolean(Effect and DROPEFFECT_COPY) then
Effect := DROPEFFECT_COPY
else
Effect := DROPEFFECT_MOVE;
InsertData(Sender as TVirtualStringTree, DataObject, Formats, Effect, AttachMode);
end;
// scroll last added entry into view
LogListBox.ItemIndex := LogListBox.Items.Count - 1;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TMainForm.Button2Click(Sender: TObject);
begin
LogListBox.Clear;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TMainForm.TreeInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode;
var InitialStates: TVirtualNodeInitStates);
var
Data: PNodeData;
begin
Data := Sender.GetNodeData(Node);
// set a generic caption only if there is not already one (e.g. from drag operations)
if Length(Data.Caption) = 0 then
Data.Caption := Format('Node Index %d', [Node.Index]);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TMainForm.Tree1NewText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; Text: WideString);
var
Data: PNodeData;
// Tree1 as well as Tree2 use the soSaveCaptions StringOption which enables automatic caption store action
// when tree data is serialized into memory (e.g. for drag'n drop). Restoring the caption is done by triggering
// this event for each loaded node.
// This mechanism frees us from implementing a SaveNode and LoadNode event since we have only the caption to store.
begin
Data := Sender.GetNodeData(Node);
Data.Caption := Text;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TMainForm.Button3Click(Sender: TObject);
begin
with FontDialog do
begin
Font := Tree1.Font;
if Execute then
begin
Tree1.Font := Font;
Tree2.Font := Font;
end;
end;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TMainForm.Tree2DragAllowed(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean);
// Tree 2 uses manual drag start to tell which node might be dragged.
begin
Allowed := Odd(Node.Index);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TMainForm.TreeDragOver(Sender: TBaseVirtualTree; Source: TObject; Shift: TShiftState; State: TDragState;
Pt: TPoint; Mode: TDropMode; var Effect: Integer; var Accept: Boolean);
begin
Accept := True;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TMainForm.Tree2BeforeItemErase(Sender: TBaseVirtualTree; Canvas: TCanvas; Node: PVirtualNode; ItemRect: TRect;
var ItemColor: TColor; var EraseAction: TItemEraseAction);
// The second tree uses manual drag and we want to show the lines which are allowed to start a drag operation by
// a colored background.
begin
if Odd(Node.Index) then
begin
ItemColor := $FFEEEE;
EraseAction := eaColor;
end;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TMainForm.InsertData(Sender: TVirtualStringTree; DataObject: IDataObject; Formats: TFormatArray;
Effect: Integer; Mode: TVTNodeAttachMode);
var
FormatAccepted: Boolean;
I: Integer;
begin
// Go through each available format and see if we can make sense of it.
FormatAccepted := False;
for I := 0 to High(Formats) do
begin
case Formats[I] of
// standard clipboard formats
CF_UNICODETEXT:
begin
LogListBox.Items.Add(' - Unicode text');
// As demonstration for non-tree data here an implementation for Unicode text.
// Formats are placed in preferred order in the formats parameter. Hence if
// there is native tree data involved in this drop operation then it has been
// caught earlier in the loop and FormatAccepted is already True.
if not FormatAccepted then
begin
// Unicode text data was dropped (e.g. from RichEdit1) add this line by line
// as new nodes.
AddUnicodeText(DataObject, Sender as TVirtualStringTree, Mode);
LogListBox.Items.Add('+ Unicode accepted');
FormatAccepted := True;
end;
end;
else
if Formats[I] = CF_VIRTUALTREE then
begin
// this is our native tree format
LogListBox.Items.Add(' - native Virtual Treeview data');
if not FormatAccepted then
begin
Sender.ProcessDrop(DataObject, Sender.DropTargetNode, Effect, Mode);
LogListBox.Items.Add('+ native Virtual Treeview data accepted');
// Indicate that we found a format we accepted so the data is not used twice.
FormatAccepted := True;
end;
end
else
if Formats[I] = CF_VTREFERENCE then
LogListBox.Items.Add(' - Virtual Treeview reference')
else
begin
// Predefined, shell specific, MIME specific or application specific clipboard data.
LogListBox.Items.Add(FindCPFormatDescription(Formats[I]));
end;
end;
end;
end;
//----------------------------------------------------------------------------------------------------------------------
end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?