diff options
Diffstat (limited to 'apps/X11/VCL/TCustomTreeView.cpp')
-rw-r--r-- | apps/X11/VCL/TCustomTreeView.cpp | 1169 |
1 files changed, 1169 insertions, 0 deletions
diff --git a/apps/X11/VCL/TCustomTreeView.cpp b/apps/X11/VCL/TCustomTreeView.cpp new file mode 100644 index 0000000..18e4c29 --- /dev/null +++ b/apps/X11/VCL/TCustomTreeView.cpp @@ -0,0 +1,1169 @@ +#include <TCustomTreeView.h> +#include <TTreeNodes.h> + +TCustomTreeView::TCustomTreeView(TComponent *AOwner) : + TWinControl(AOwner), + Items(this, &TCustomTreeView::getItems, &TCustomTreeView::SetTreeNodes), + Images(this, &TCustomTreeView::getImages, &TCustomTreeView::SetImages), + StateImages(this, &TCustomTreeView::getStateImages, &TCustomTreeView::SetStateImages), + Selected(this, &TCustomTreeView::GetSelection, &TCustomTreeView::SetSelection) { + init(AOwner); +} + + +TCustomTreeView::TCustomTreeView(GtkWidget *parent) : + TWinControl(parent), + Items(this, &TCustomTreeView::getItems, &TCustomTreeView::SetTreeNodes), + Images(this, &TCustomTreeView::getImages, &TCustomTreeView::SetImages), + StateImages(this, &TCustomTreeView::getStateImages, &TCustomTreeView::SetStateImages), + Selected(this, &TCustomTreeView::GetSelection, &TCustomTreeView::SetSelection) { + nativeControl = gtk_tree_new(); +/* + gtk_widget_ref (nativeControl); + gtk_object_set_data_full (GTK_OBJECT (InstallMgrApp), "LocalTree", LocalTree, + (GtkDestroyNotify) gtk_widget_unref); +*/ + gtk_widget_show (nativeControl); + gtk_container_add (GTK_CONTAINER (parent), nativeControl); + init(0); +} + +TCustomTreeView::~TCustomTreeView() { +} + +void TCustomTreeView::init(TComponent *AOwner) { +/* + ControlStyle := ControlStyle - [csCaptureMouse] + [csDisplayDragImage, csReflector]; + Width := 121; + Height := 97; + TabStop := True; + ParentColor := False; + FCanvas := TControlCanvas.Create; + TControlCanvas(FCanvas).Control := Self; +*/ +// FTreeNodes := TTreeNodes.Create(Self); + FTreeNodes = new TTreeNodes(this); +/* + FBorderStyle := bsSingle; + FShowButtons := True; + FShowRoot := True; + FShowLines := True; + FHideSelection := True; + FDragImage := TDragImageList.CreateSize(32, 32); + FSaveIndent := -1; + FChangeTimer := TTimer.Create(Self); + FChangeTimer.Enabled := False; + FChangeTimer.Interval := 0; + FChangeTimer.OnTimer := OnChangeTimer; + FToolTips := True; + FEditInstance := MakeObjectInstance(EditWndProc); + FImageChangeLink := TChangeLink.Create; + FImageChangeLink.OnChange := ImageListChange; + FStateChangeLink := TChangeLink.Create; + FStateChangeLink.OnChange := ImageListChange; +*/ +} + + +/* +procedure TCustomTreeView.SetTreeNodes(Value: TTreeNodes); +begin + Items.Assign(Value); +end; +*/ + +void TCustomTreeView::SetTreeNodes(TTreeNodes* Value) { +// Items->Assign(Value); +} + +/* +procedure TCustomTreeView.GetSelectedIndex(Node: TTreeNode); +begin + if Assigned(FOnGetSelectedIndex) then FOnGetSelectedIndex(Self, Node); +end; + +TTreeNode *TCustomTreeView::GetSelected() { +} + +*/ + +/* +function TCustomTreeView.GetSelection: TTreeNode; +begin + if HandleAllocated then + begin + if FRightClickSelect and Assigned(FRClickNode) then + Result := FRClickNode + else + Result := Items.GetNode(TreeView_GetSelection(Handle)); + end + else Result := nil; +end; + +procedure TCustomTreeView.SetSelection(Value: TTreeNode); +begin + if Value <> nil then Value.Selected := True + else TreeView_SelectItem(Handle, nil); +end; +*/ + +TTreeNode *TCustomTreeView::GetSelection() { + GList *selected_nodes = GTK_TREE_SELECTION (nativeControl); + selected_nodes = g_list_first(selected_nodes); + return (selected_nodes) ? Items->GetNode(GTK_TREE_ITEM(selected_nodes->data)) : 0; +} + +void TCustomTreeView::SetSelection(TTreeNode *node) { +} + + +/* +procedure TCustomTreeView.SetImages(Value: TCustomImageList); +begin + if Images <> nil then + Images.UnRegisterChanges(FImageChangeLink); + FImages := Value; + if Images <> nil then + begin + Images.RegisterChanges(FImageChangeLink); + Images.FreeNotification(Self); + SetImageList(Images.Handle, TVSIL_NORMAL) + end + else SetImageList(0, TVSIL_NORMAL); +end; + +procedure TCustomTreeView.SetStateImages(Value: TCustomImageList); +begin + if StateImages <> nil then + StateImages.UnRegisterChanges(FStateChangeLink); + FStateImages := Value; + if StateImages <> nil then + begin + StateImages.RegisterChanges(FStateChangeLink); + StateImages.FreeNotification(Self); + SetImageList(StateImages.Handle, TVSIL_STATE) + end + else SetImageList(0, TVSIL_STATE); +end; +*/ + +void TCustomTreeView::SetImages(TCustomImageList *images) { + FImages = images; +} + +void TCustomTreeView::SetStateImages(TCustomImageList *images) { + FStateImages = images; +} + + +/* +{ TCustomTreeView } +destructor TCustomTreeView.Destroy; +begin + Items.Free; + FChangeTimer.Free; + FSaveItems.Free; + FDragImage.Free; + FMemStream.Free; + FreeObjectInstance(FEditInstance); + FImageChangeLink.Free; + FStateChangeLink.Free; + FCanvas.Free; + inherited Destroy; +end; + +procedure TCustomTreeView.CreateParams(var Params: TCreateParams); +const + BorderStyles: array[TBorderStyle] of DWORD = (0, WS_BORDER); + LineStyles: array[Boolean] of DWORD = (0, TVS_HASLINES); + RootStyles: array[Boolean] of DWORD = (0, TVS_LINESATROOT); + ButtonStyles: array[Boolean] of DWORD = (0, TVS_HASBUTTONS); + EditStyles: array[Boolean] of DWORD = (TVS_EDITLABELS, 0); + HideSelections: array[Boolean] of DWORD = (TVS_SHOWSELALWAYS, 0); + DragStyles: array[TDragMode] of DWORD = (TVS_DISABLEDRAGDROP, 0); + RTLStyles: array[Boolean] of DWORD = (0, TVS_RTLREADING); + ToolTipStyles: array[Boolean] of DWORD = (TVS_NOTOOLTIPS, 0); + AutoExpandStyles: array[Boolean] of DWORD = (0, TVS_SINGLEEXPAND); + HotTrackStyles: array[Boolean] of DWORD = (0, TVS_TRACKSELECT); + RowSelectStyles: array[Boolean] of DWORD = (0, TVS_FULLROWSELECT); +begin + InitCommonControl(ICC_TREEVIEW_CLASSES); + inherited CreateParams(Params); + CreateSubClass(Params, WC_TREEVIEW); + with Params do + begin + Style := Style or LineStyles[FShowLines] or BorderStyles[FBorderStyle] or + RootStyles[FShowRoot] or ButtonStyles[FShowButtons] or + EditStyles[FReadOnly] or HideSelections[FHideSelection] or + DragStyles[DragMode] or RTLStyles[UseRightToLeftReading] or + ToolTipStyles[FToolTips] or AutoExpandStyles[FAutoExpand] or + HotTrackStyles[FHotTrack] or RowSelectStyles[FRowSelect]; + if Ctl3D and NewStyleControls and (FBorderStyle = bsSingle) then + begin + Style := Style and not WS_BORDER; + ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE; + end; + WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW); + end; +end; + +procedure TCustomTreeView.CreateWnd; +begin + FStateChanging := False; + inherited CreateWnd; + TreeView_SetBkColor(Handle, ColorToRGB(Color)); + TreeView_SetTextColor(Handle, ColorToRGB(Font.Color)); + if FMemStream <> nil then + begin + Items.ReadData(FMemStream); + FMemStream.Destroy; + FMemStream := nil; + SetTopItem(Items.GetNodeFromIndex(FSaveTopIndex)); + FSaveTopIndex := 0; + SetSelection(Items.GetNodeFromIndex(FSaveIndex)); + FSaveIndex := 0; + end; + if FSaveIndent <> -1 then Indent := FSaveIndent; + if (Images <> nil) and Images.HandleAllocated then + SetImageList(Images.Handle, TVSIL_NORMAL); + if (StateImages <> nil) and StateImages.HandleAllocated then + SetImageList(StateImages.Handle, TVSIL_STATE); +end; + +procedure TCustomTreeView.DestroyWnd; +var + Node: TTreeNode; +begin + FStateChanging := True; + if Items.Count > 0 then + begin + FMemStream := TMemoryStream.Create; + Items.WriteData(FMemStream); + FMemStream.Position := 0; + Node := GetTopItem; + if Node <> nil then FSaveTopIndex := Node.AbsoluteIndex; + Node := Selected; + if Node <> nil then FSaveIndex := Node.AbsoluteIndex; + end; + FSaveIndent := Indent; + inherited DestroyWnd; +end; + +procedure TCustomTreeView.EditWndProc(var Message: TMessage); +begin + try + with Message do + begin + case Msg of + WM_KEYDOWN, + WM_SYSKEYDOWN: if DoKeyDown(TWMKey(Message)) then Exit; + WM_CHAR: if DoKeyPress(TWMKey(Message)) then Exit; + WM_KEYUP, + WM_SYSKEYUP: if DoKeyUp(TWMKey(Message)) then Exit; + CN_KEYDOWN, + CN_CHAR, CN_SYSKEYDOWN, + CN_SYSCHAR: + begin + WndProc(Message); + Exit; + end; + end; + Result := CallWindowProc(FDefEditProc, FEditHandle, Msg, WParam, LParam); + end; + except + Application.HandleException(Self); + end; +end; + +procedure TCustomTreeView.CMColorChanged(var Message: TMessage); +begin + inherited; + RecreateWnd; +end; + +procedure TCustomTreeView.CMCtl3DChanged(var Message: TMessage); +begin + inherited; + if FBorderStyle = bsSingle then RecreateWnd; +end; + +procedure TCustomTreeView.CMFontChanged(var Message: TMessage); +begin + inherited; + TreeView_SetTextColor(Handle, ColorToRGB(Font.Color)); +end; + +procedure TCustomTreeView.CMSysColorChange(var Message: TMessage); +begin + inherited; + if not (csLoading in ComponentState) then + begin + Message.Msg := WM_SYSCOLORCHANGE; + DefaultHandler(Message); + end; +end; + +function TCustomTreeView.AlphaSort: Boolean; +var + Node: TTreeNode; +begin + if HandleAllocated then + begin + Result := CustomSort(nil, 0); + Node := FTreeNodes.GetFirstNode; + while Node <> nil do + begin + if Node.HasChildren then Node.AlphaSort; + Node := Node.GetNext; + end; + end + else + Result := False; +end; + +function TCustomTreeView.CustomSort(SortProc: TTVCompare; Data: Longint): Boolean; +var + SortCB: TTVSortCB; + Node: TTreeNode; +begin + Result := False; + if HandleAllocated then + begin + with SortCB do + begin + if not Assigned(SortProc) then lpfnCompare := @DefaultTreeViewSort + else lpfnCompare := SortProc; + hParent := TVI_ROOT; + lParam := Data; + Result := TreeView_SortChildrenCB(Handle, SortCB, 0); + end; + Node := FTreeNodes.GetFirstNode; + while Node <> nil do + begin + if Node.HasChildren then Node.CustomSort(SortProc, Data); + Node := Node.GetNext; + end; + Items.ClearCache; + end; +end; + +procedure TCustomTreeView.SetAutoExpand(Value: Boolean); +begin + if FAutoExpand <> Value then + begin + FAutoExpand := Value; + SetComCtlStyle(Self, TVS_SINGLEEXPAND, Value); + end; +end; + +procedure TCustomTreeView.SetHotTrack(Value: Boolean); +begin + if FHotTrack <> Value then + begin + FHotTrack := Value; + SetComCtlStyle(Self, TVS_TRACKSELECT, Value); + end; +end; + +procedure TCustomTreeView.SetRowSelect(Value: Boolean); +begin + if FRowSelect <> Value then + begin + FRowSelect := Value; + SetComCtlStyle(Self, TVS_FULLROWSELECT, Value); + end; +end; + +procedure TCustomTreeView.SetToolTips(Value: Boolean); +begin + if FToolTips <> Value then + begin + FToolTips := Value; + SetComCtlStyle(Self, TVS_NOTOOLTIPS, not Value); + end; +end; + +procedure TCustomTreeView.SetSortType(Value: TSortType); +begin + if SortType <> Value then + begin + FSortType := Value; + if ((SortType in [stData, stBoth]) and Assigned(OnCompare)) or + (SortType in [stText, stBoth]) then + AlphaSort; + end; +end; + +procedure TCustomTreeView.SetBorderStyle(Value: TBorderStyle); +begin + if BorderStyle <> Value then + begin + FBorderStyle := Value; + RecreateWnd; + end; +end; + +procedure TCustomTreeView.SetDragMode(Value: TDragMode); +begin + if Value <> DragMode then + SetComCtlStyle(Self, TVS_DISABLEDRAGDROP, Value = dmManual); + inherited; +end; + +procedure TCustomTreeView.SetButtonStyle(Value: Boolean); +begin + if ShowButtons <> Value then + begin + FShowButtons := Value; + SetComCtlStyle(Self, TVS_HASBUTTONS, Value); + end; +end; + +procedure TCustomTreeView.SetLineStyle(Value: Boolean); +begin + if ShowLines <> Value then + begin + FShowLines := Value; + SetComCtlStyle(Self, TVS_HASLINES, Value); + end; +end; + +procedure TCustomTreeView.SetRootStyle(Value: Boolean); +begin + if ShowRoot <> Value then + begin + FShowRoot := Value; + SetComCtlStyle(Self, TVS_LINESATROOT, Value); + end; +end; + +procedure TCustomTreeView.SetReadOnly(Value: Boolean); +begin + if ReadOnly <> Value then + begin + FReadOnly := Value; + SetComCtlStyle(Self, TVS_EDITLABELS, not Value); + end; +end; + +procedure TCustomTreeView.SetHideSelection(Value: Boolean); +begin + if HideSelection <> Value then + begin + FHideSelection := Value; + SetComCtlStyle(Self, TVS_SHOWSELALWAYS, not Value); + Invalidate; + end; +end; + +function TCustomTreeView.GetNodeAt(X, Y: Integer): TTreeNode; +var + HitTest: TTVHitTestInfo; +begin + with HitTest do + begin + pt.X := X; + pt.Y := Y; + if TreeView_HitTest(Handle, HitTest) <> nil then + Result := Items.GetNode(HitTest.hItem) + else Result := nil; + end; +end; + +function TCustomTreeView.GetHitTestInfoAt(X, Y: Integer): THitTests; +var + HitTest: TTVHitTestInfo; +begin + Result := []; + with HitTest do + begin + pt.X := X; + pt.Y := Y; + TreeView_HitTest(Handle, HitTest); + if (flags and TVHT_ABOVE) <> 0 then Include(Result, htAbove); + if (flags and TVHT_BELOW) <> 0 then Include(Result, htBelow); + if (flags and TVHT_NOWHERE) <> 0 then Include(Result, htNowhere); + if (flags and TVHT_ONITEM) = TVHT_ONITEM then + Include(Result, htOnItem) + else + begin + if (flags and TVHT_ONITEM) <> 0 then Include(Result, htOnItem); + if (flags and TVHT_ONITEMICON) <> 0 then Include(Result, htOnIcon); + if (flags and TVHT_ONITEMLABEL) <> 0 then Include(Result, htOnLabel); + if (flags and TVHT_ONITEMSTATEICON) <> 0 then Include(Result, htOnStateIcon); + end; + if (flags and TVHT_ONITEMBUTTON) <> 0 then Include(Result, htOnButton); + if (flags and TVHT_ONITEMINDENT) <> 0 then Include(Result, htOnIndent); + if (flags and TVHT_ONITEMRIGHT) <> 0 then Include(Result, htOnRight); + if (flags and TVHT_TOLEFT) <> 0 then Include(Result, htToLeft); + if (flags and TVHT_TORIGHT) <> 0 then Include(Result, htToRight); + end; +end; + +procedure TCustomTreeView.SetIndent(Value: Integer); +begin + if Value <> Indent then TreeView_SetIndent(Handle, Value); +end; + +function TCustomTreeView.GetIndent: Integer; +begin + Result := TreeView_GetIndent(Handle) +end; + +procedure TCustomTreeView.FullExpand; +var + Node: TTreeNode; +begin + Node := Items.GetFirstNode; + while Node <> nil do + begin + Node.Expand(True); + Node := Node.GetNextSibling; + end; +end; + +procedure TCustomTreeView.FullCollapse; +var + Node: TTreeNode; +begin + Node := Items.GetFirstNode; + while Node <> nil do + begin + Node.Collapse(True); + Node := Node.GetNextSibling; + end; +end; + +procedure TCustomTreeView.Loaded; +begin + inherited Loaded; + if csDesigning in ComponentState then FullExpand; +end; + +function TCustomTreeView.GetTopItem: TTreeNode; +begin + if HandleAllocated then + Result := Items.GetNode(TreeView_GetFirstVisible(Handle)) + else Result := nil; +end; + +procedure TCustomTreeView.SetTopItem(Value: TTreeNode); +begin + if HandleAllocated and (Value <> nil) then + TreeView_SelectSetFirstVisible(Handle, Value.ItemId); +end; + +procedure TCustomTreeView.OnChangeTimer(Sender: TObject); +begin + FChangeTimer.Enabled := False; + Change(TTreeNode(FChangeTimer.Tag)); +end; + +procedure TCustomTreeView.SetChangeDelay(Value: Integer); +begin + FChangeTimer.Interval := Value; +end; + +function TCustomTreeView.GetChangeDelay: Integer; +begin + Result := FChangeTimer.Interval; +end; + +function TCustomTreeView.GetDropTarget: TTreeNode; +begin + if HandleAllocated then + begin + Result := Items.GetNode(TreeView_GetDropHilite(Handle)); + if Result = nil then Result := FLastDropTarget; + end + else Result := nil; +end; + +procedure TCustomTreeView.SetDropTarget(Value: TTreeNode); +begin + if HandleAllocated then + if Value <> nil then Value.DropTarget := True + else TreeView_SelectDropTarget(Handle, nil); +end; + +function TCustomTreeView.GetNodeFromItem(const Item: TTVItem): TTreeNode; +begin + with Item do + if (state and TVIF_PARAM) <> 0 then Result := Pointer(lParam) + else Result := Items.GetNode(hItem); +end; + +function TCustomTreeView.IsEditing: Boolean; +var + ControlHand: HWnd; +begin + ControlHand := TreeView_GetEditControl(Handle); + Result := (ControlHand <> 0) and IsWindowVisible(ControlHand); +end; + +procedure TCustomTreeView.CNNotify(var Message: TWMNotify); +var + Node: TTreeNode; + MousePos: TPoint; + R: TRect; + DefaultDraw: Boolean; + TmpItem: TTVItem; +begin + with Message do + case NMHdr^.code of + NM_CUSTOMDRAW: + with PNMCustomDraw(NMHdr)^ do + begin + Result := CDRF_DODEFAULT; + if dwDrawStage = CDDS_PREPAINT then + begin + if IsCustomDrawn(dtControl, cdPrePaint) then + begin + FCanvas.Handle := hdc; + FCanvas.Font := Font; + FCanvas.Brush := Brush; + R := ClientRect; + DefaultDraw := CustomDraw(R, cdPrePaint); + FCanvas.Handle := 0; + if not DefaultDraw then + begin + Result := CDRF_SKIPDEFAULT; + Exit; + end; + end; + if IsCustomDrawn(dtControl, cdPostPaint) then + Result := CDRF_NOTIFYPOSTPAINT; + if IsCustomDrawn(dtItem, cdPrePaint) then + Result := Result or CDRF_NOTIFYITEMDRAW else + Result := Result or CDRF_DODEFAULT; + end + else if dwDrawStage = CDDS_ITEMPREPAINT then + begin + FillChar(TmpItem, SizeOf(TmpItem), 0); + TmpItem.hItem := HTREEITEM(dwItemSpec); + Node := GetNodeFromItem(TmpItem); + if Node <> nil then + begin + FCanvas.Handle := hdc; + FCanvas.Font := Font; + FCanvas.Brush := Brush; + { Unlike the list view, the tree view doesn't override the text + foreground and background colors of selected items. } + if uItemState and CDIS_SELECTED <> 0 then + begin + FCanvas.Font.Color := clHighlightText; + FCanvas.Brush.Color := clHighlight; + end; + FCanvas.Font.OnChange := CanvasChanged; + FCanvas.Brush.OnChange := CanvasChanged; + DefaultDraw := CustomDrawItem(Node, + TCustomDrawState(Word(uItemState)), cdPrePaint); + if not DefaultDraw then + Result := Result or CDRF_SKIPDEFAULT + else if FCanvasChanged then + begin + FCanvasChanged := False; + FCanvas.Font.OnChange := nil; + FCanvas.Brush.OnChange := nil; + with PNMTVCustomDraw(NMHdr)^ do + begin + clrText := ColorToRGB(FCanvas.Font.Color); + clrTextBk := ColorToRGB(FCanvas.Brush.Color); + SelectObject(hdc, FCanvas.Font.Handle); + Result := Result or CDRF_NEWFONT; + end; + end; + FCanvas.Handle := 0; + if IsCustomDrawn(dtItem, cdPostPaint) then + Result := Result or CDRF_NOTIFYPOSTPAINT; + end; + end; + end; + TVN_BEGINDRAG: + begin + FDragged := True; + with PNMTreeView(NMHdr)^ do + FDragNode := GetNodeFromItem(ItemNew); + end; + TVN_BEGINLABELEDIT: + begin + with PTVDispInfo(NMHdr)^ do + if Dragging or not CanEdit(GetNodeFromItem(item)) then + Result := 1; + if Result = 0 then + begin + FEditHandle := TreeView_GetEditControl(Handle); + FDefEditProc := Pointer(GetWindowLong(FEditHandle, GWL_WNDPROC)); + SetWindowLong(FEditHandle, GWL_WNDPROC, LongInt(FEditInstance)); + end; + end; + TVN_ENDLABELEDIT: Edit(PTVDispInfo(NMHdr)^.item); + TVN_ITEMEXPANDING: + if not FManualNotify then + begin + with PNMTreeView(NMHdr)^ do + begin + Node := GetNodeFromItem(ItemNew); + if (action = TVE_EXPAND) and not CanExpand(Node) then + Result := 1 + else if (action = TVE_COLLAPSE) and + not CanCollapse(Node) then Result := 1; + end; + end; + TVN_ITEMEXPANDED: + if not FManualNotify then + begin + with PNMTreeView(NMHdr)^ do + begin + Node := GetNodeFromItem(itemNew); + if (action = TVE_EXPAND) then Expand(Node) + else if (action = TVE_COLLAPSE) then Collapse(Node); + end; + end; + TVN_SELCHANGINGA, TVN_SELCHANGINGW: + if not CanChange(GetNodeFromItem(PNMTreeView(NMHdr)^.itemNew)) then + Result := 1; + TVN_SELCHANGEDA, TVN_SELCHANGEDW: + with PNMTreeView(NMHdr)^ do + if FChangeTimer.Interval > 0 then + with FChangeTimer do + begin + Enabled := False; + Tag := Integer(GetNodeFromItem(itemNew)); + Enabled := True; + end + else + Change(GetNodeFromItem(itemNew)); + TVN_DELETEITEM: + begin + Node := GetNodeFromItem(PNMTreeView(NMHdr)^.itemOld); + if Node <> nil then + begin + Node.FItemId := nil; + FChangeTimer.Enabled := False; + if FStateChanging then Node.Delete + else Items.Delete(Node); + end; + end; + TVN_SETDISPINFO: + with PTVDispInfo(NMHdr)^ do + begin + Node := GetNodeFromItem(item); + if (Node <> nil) and ((item.mask and TVIF_TEXT) <> 0) then + Node.Text := item.pszText; + end; + TVN_GETDISPINFO: + with PTVDispInfo(NMHdr)^ do + begin + Node := GetNodeFromItem(item); + if Node <> nil then + begin + if (item.mask and TVIF_TEXT) <> 0 then + StrLCopy(item.pszText, PChar(Node.Text), item.cchTextMax); + if (item.mask and TVIF_IMAGE) <> 0 then + begin + GetImageIndex(Node); + item.iImage := Node.ImageIndex; + end; + if (item.mask and TVIF_SELECTEDIMAGE) <> 0 then + begin + GetSelectedIndex(Node); + item.iSelectedImage := Node.SelectedIndex; + end; + end; + end; + NM_RCLICK: + begin + if RightClickSelect then + begin + GetCursorPos(MousePos); + with PointToSmallPoint(ScreenToClient(MousePos)) do + begin + FRClickNode := GetNodeAt(X, Y); + Perform(WM_RBUTTONUP, 0, MakeLong(X, Y)); + end; + end + else FRClickNode := Pointer(1); + end; + end; +end; + +function TCustomTreeView.GetDragImages: TDragImageList; +begin + if FDragImage.Count > 0 then + Result := FDragImage else + Result := nil; +end; + +procedure TCustomTreeView.WndProc(var Message: TMessage); +begin + if not (csDesigning in ComponentState) and ((Message.Msg = WM_LBUTTONDOWN) or + (Message.Msg = WM_LBUTTONDBLCLK)) and not Dragging and + (DragMode = dmAutomatic) and (DragKind = dkDrag) then + begin + if not IsControlMouseMsg(TWMMouse(Message)) then + begin + ControlState := ControlState + [csLButtonDown]; + Dispatch(Message); + end; + end + else inherited WndProc(Message); +end; + +procedure TCustomTreeView.DoStartDrag(var DragObject: TDragObject); +var + ImageHandle: HImageList; + DragNode: TTreeNode; + P: TPoint; +begin + inherited DoStartDrag(DragObject); + DragNode := FDragNode; + FLastDropTarget := nil; + FDragNode := nil; + if DragNode = nil then + begin + GetCursorPos(P); + with ScreenToClient(P) do DragNode := GetNodeAt(X, Y); + end; + if DragNode <> nil then + begin + ImageHandle := TreeView_CreateDragImage(Handle, DragNode.ItemId); + if ImageHandle <> 0 then + with FDragImage do + begin + Handle := ImageHandle; + SetDragImage(0, 2, 2); + end; + end; +end; + +procedure TCustomTreeView.DoEndDrag(Target: TObject; X, Y: Integer); +begin + inherited DoEndDrag(Target, X, Y); + FLastDropTarget := nil; +end; + +procedure TCustomTreeView.CMDrag(var Message: TCMDrag); +begin + inherited; + with Message, DragRec^ do + case DragMessage of + dmDragMove: + with ScreenToClient(Pos) do + DoDragOver(Source, X, Y, Message.Result <> 0); + dmDragLeave: + begin + TDragObject(Source).HideDragImage; + FLastDropTarget := DropTarget; + DropTarget := nil; + TDragObject(Source).ShowDragImage; + end; + dmDragDrop: FLastDropTarget := nil; + end; +end; + +procedure TCustomTreeView.DoDragOver(Source: TDragObject; X, Y: Integer; CanDrop: Boolean); +var + Node: TTreeNode; +begin + Node := GetNodeAt(X, Y); + if (Node <> nil) and + ((Node <> DropTarget) or (Node = FLastDropTarget)) then + begin + FLastDropTarget := nil; + TDragObject(Source).HideDragImage; + Node.DropTarget := True; + TDragObject(Source).ShowDragImage; + end; +end; + +procedure TCustomTreeView.GetImageIndex(Node: TTreeNode); +begin + if Assigned(FOnGetImageIndex) then FOnGetImageIndex(Self, Node); +end; + +function TCustomTreeView.CanChange(Node: TTreeNode): Boolean; +begin + Result := True; + if Assigned(FOnChanging) then FOnChanging(Self, Node, Result); +end; + +procedure TCustomTreeView.Change(Node: TTreeNode); +begin + if Assigned(FOnChange) then FOnChange(Self, Node); +end; + +procedure TCustomTreeView.Delete(Node: TTreeNode); +begin + if Assigned(FOnDeletion) then FOnDeletion(Self, Node); +end; + +procedure TCustomTreeView.Expand(Node: TTreeNode); +begin + if Assigned(FOnExpanded) then FOnExpanded(Self, Node); +end; + +function TCustomTreeView.CanExpand(Node: TTreeNode): Boolean; +begin + Result := True; + if Assigned(FOnExpanding) then FOnExpanding(Self, Node, Result); +end; + +procedure TCustomTreeView.Collapse(Node: TTreeNode); +begin + if Assigned(FOnCollapsed) then FOnCollapsed(Self, Node); +end; + +function TCustomTreeView.CanCollapse(Node: TTreeNode): Boolean; +begin + Result := True; + if Assigned(FOnCollapsing) then FOnCollapsing(Self, Node, Result); +end; + +function TCustomTreeView.CanEdit(Node: TTreeNode): Boolean; +begin + Result := True; + if Assigned(FOnEditing) then FOnEditing(Self, Node, Result); +end; + +procedure TCustomTreeView.Edit(const Item: TTVItem); +var + S: string; + Node: TTreeNode; +begin + with Item do + if pszText <> nil then + begin + S := pszText; + Node := GetNodeFromItem(Item); + if Assigned(FOnEdited) then FOnEdited(Self, Node, S); + if Node <> nil then Node.Text := S; + end; +end; + +function TCustomTreeView.CreateNode: TTreeNode; +begin + Result := TTreeNode.Create(Items); +end; + +procedure TCustomTreeView.SetImageList(Value: HImageList; Flags: Integer); +begin + if HandleAllocated then TreeView_SetImageList(Handle, Value, Flags); +end; + +procedure TCustomTreeView.ImageListChange(Sender: TObject); +var + ImageHandle: HImageList; +begin + if HandleAllocated then + begin + if TCustomImageList(Sender).HandleAllocated then + ImageHandle := TCustomImageList(Sender).Handle + else + ImageHandle := 0; + if Sender = Images then + SetImageList(ImageHandle, TVSIL_NORMAL) + else if Sender = StateImages then + SetImageList(ImageHandle, TVSIL_STATE); + end; +end; + +procedure TCustomTreeView.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then + begin + if AComponent = Images then Images := nil; + if AComponent = StateImages then StateImages := nil; + end; +end; + +procedure TCustomTreeView.LoadFromFile(const FileName: string); +var + Stream: TStream; +begin + Stream := TFileStream.Create(FileName, fmOpenRead); + try + LoadFromStream(Stream); + finally + Stream.Free; + end; +end; + +procedure TCustomTreeView.LoadFromStream(Stream: TStream); +begin + with TTreeStrings.Create(Items) do + try + LoadTreeFromStream(Stream); + finally + Free; + end; +end; + +procedure TCustomTreeView.SaveToFile(const FileName: string); +var + Stream: TStream; +begin + Stream := TFileStream.Create(FileName, fmCreate); + try + SaveToStream(Stream); + finally + Stream.Free; + end; +end; + +procedure TCustomTreeView.SaveToStream(Stream: TStream); +begin + with TTreeStrings.Create(Items) do + try + SaveTreeToStream(Stream); + finally + Free; + end; +end; + +procedure TCustomTreeView.WMRButtonDown(var Message: TWMRButtonDown); +var + MousePos: TPoint; +begin + FRClickNode := nil; + try + if not RightClickSelect then + begin + inherited; + if FRClickNode <> nil then + begin + GetCursorPos(MousePos); + with PointToSmallPoint(ScreenToClient(MousePos)) do + Perform(WM_RBUTTONUP, 0, MakeLong(X, Y)); + end; + end + else DefaultHandler(Message); + finally + FRClickNode := nil; + + end; +end; + +procedure TCustomTreeView.WMRButtonUp(var Message: TWMRButtonUp); + + procedure DoMouseDown(var Message: TWMMouse; Button: TMouseButton; + Shift: TShiftState); + begin + if not (csNoStdEvents in ControlStyle) then + with Message do + MouseDown(Button, KeysToShiftState(Keys) + Shift, XPos, YPos); + end; + +begin + if RightClickSelect then DoMouseDown(Message, mbRight, []); + inherited; +end; + +procedure TCustomTreeView.WMLButtonDown(var Message: TWMLButtonDown); +var + Node: TTreeNode; + MousePos: TPoint; +begin + FDragged := False; + FDragNode := nil; + try + inherited; + if (DragMode = dmAutomatic) and (DragKind = dkDrag) then + begin + SetFocus; + if not FDragged then + begin + GetCursorPos(MousePos); + with PointToSmallPoint(ScreenToClient(MousePos)) do + Perform(WM_LBUTTONUP, 0, MakeLong(X, Y)); + end + else begin + Node := GetNodeAt(Message.XPos, Message.YPos); + if Node <> nil then + begin + Node.Focused := True; + Node.Selected := True; + BeginDrag(False); + end; + end; + end; + finally + FDragNode := nil; + end; +end; + +procedure TCustomTreeView.WMNotify(var Message: TWMNotify); +var + Node: TTreeNode; + MaxTextLen: Integer; + Pt: TPoint; +begin + with Message do + if NMHdr^.code = TTN_NEEDTEXTW then + begin + // Work around NT COMCTL32 problem with tool tips >= 80 characters + GetCursorPos(Pt); + Pt := ScreenToClient(Pt); + Node := GetNodeAt(Pt.X, Pt.Y); + if (Node = nil) or (Node.Text = '') or + (PToolTipTextW(NMHdr)^.uFlags and TTF_IDISHWND = 0) then Exit; + if (GetComCtlVersion >= ComCtlVersionIE4) and (Length(Node.Text) < 80) then + begin + inherited; + Exit; + end; + FWideText := Node.Text; + MaxTextLen := SizeOf(PToolTipTextW(NMHdr)^.szText) div SizeOf(WideChar); + if Length(FWideText) >= MaxTextLen then + SetLength(FWideText, MaxTextLen - 1); + PToolTipTextW(NMHdr)^.lpszText := PWideChar(FWideText); + FillChar(PToolTipTextW(NMHdr)^.szText, MaxTextLen, 0); + Move(Pointer(FWideText)^, PToolTipTextW(NMHdr)^.szText, Length(FWideText) * SizeOf(WideChar)); + PToolTipTextW(NMHdr)^.hInst := 0; + SetWindowPos(NMHdr^.hwndFrom, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE or + SWP_NOSIZE or SWP_NOMOVE or SWP_NOOWNERZORDER); + Result := 1; + end + else inherited; +end; + +{ CustomDraw support } + +procedure TCustomTreeView.CanvasChanged; +begin + FCanvasChanged := True; +end; + +function TCustomTreeView.IsCustomDrawn(Target: TCustomDrawTarget; + Stage: TCustomDrawStage): Boolean; +begin + { Tree view doesn't support erase notifications } + if Stage = cdPrePaint then + begin + if Target = dtItem then + Result := Assigned(FOnCustomDrawItem) + else if Target = dtControl then + Result := Assigned(FOnCustomDraw) + else + Result := False; + end + else + Result := False; +end; + +function TCustomTreeView.CustomDraw(const ARect: TRect; Stage: TCustomDrawStage): Boolean; +begin + Result := True; + if Assigned(FOnCustomDraw) then FOnCustomDraw(Self, ARect, Result); +end; + +function TCustomTreeView.CustomDrawItem(Node: TTreeNode; State: TCustomDrawState; + Stage: TCustomDrawStage): Boolean; +begin + Result := True; + if Assigned(FOnCustomDrawItem) then FOnCustomDrawItem(Self, Node, State, Result); +end; + +*/ |