Drag'nDrop manual sort for TreeGadget

Windows specific forum
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Drag'nDrop manual sort for TreeGadget

Post by zapman* »

Code: Select all

; Drag'nDrop manual sort for TreeGadget
; By Zapman
;
; This demo code shows how to implemente a drag'n drop ability for TreeGadget
; in order to allow the user to sort manually the gadget content by draging
; it elements.
;
Procedure GetFolderIconHandle()
  *sfi.SHFILEINFO = AllocateMemory(SizeOf(SHFILEINFO))
  If SHGetFileInfo_("aa.txt",#FILE_ATTRIBUTE_DIRECTORY,*sfi, SizeOf(SHFILEINFO), #SHGFI_ICON| #SHGFI_SMALLICON | #SHGFI_USEFILEATTRIBUTES)
    hFolderIcon = *sfi\hIcon
  EndIf
  FreeMemory(*sfi)
  ProcedureReturn hFolderIcon
EndProcedure

Procedure GetTreeItemIndexFromHandle(IHandle,TreeGadgetID)
;   By Timo 'fr34k' Harter and Zapman
  dItem = 0
  hItem = SendMessage_(TreeGadgetID, #TVM_GETNEXTITEM, #TVGN_ROOT, 0)
  While IHandle And hItem And hItem <> IHandle
    hItem2 = SendMessage_(TreeGadgetID, #TVM_GETNEXTITEM, #TVGN_CHILD, hItem)
    Repeat
      If hItem2 = #Null: hItem2 = SendMessage_(TreeGadgetID, #TVM_GETNEXTITEM, #TVGN_NEXT, hItem): EndIf
      If hItem2 = #Null: hItem = SendMessage_(TreeGadgetID, #TVM_GETNEXTITEM, #TVGN_PARENT, hItem): EndIf
    Until hItem2 <> #Null
    hItem = hItem2
    dItem + 1
  Wend
  ProcedureReturn dItem
EndProcedure
;
Procedure HighLightTreeItem(TreeGadgetID,hItem,HighLight)
;   By Timo 'fr34k' Harter and Zapman
  If HighLight : HighLight = #TVIS_DROPHILITED : EndIf ; to be sure that te right value is used
  ; We'll send a #TVM_SETITEM message. We only need to change the
  ; item state, so #TVIF_STATE is enough for the mask.          
  pitem.TV_ITEM
  pitem\mask = #TVIF_STATE
  pitem\hItem = hItem
  
  ; 'stateMask' determines, what will be changed, and 'state' sets the actual value,
  ; so here, we set the TVIS_DROPHILITED state flag to HighLight.
  pitem\state = HighLight
  pitem\stateMask = #TVIS_DROPHILITED
  Result = SendMessage_(TreeGadgetID, #TVM_SETITEM, 0, @pitem)
  
  ; a redraw is neccesary here to avoid problems.
  RedrawWindow_(TreeGadgetID, 0, 0, #RDW_UPDATENOW)
  ProcedureReturn Result
EndProcedure
;
Procedure GetTreeItemIconIndex(TreeGadget,hitem)
  ; by Zapman
  tvitem.TV_ITEM\mask=#TVIF_IMAGE
  tvitem\hitem=hitem
  If SendMessage_(GadgetID(TreeGadget), #TVM_GETITEM,0,@tvitem) ; get the icon index from the item
    ProcedureReturn tvitem\iImage
  Else
    ProcedureReturn -1
  EndIf
EndProcedure
;
Procedure SetTreeItemIconIndex(TreeGadget,hitem,iconeIndex)
  ; by Zapman
  tvitem.TV_ITEM\mask=#TVIF_IMAGE|#TVIF_SELECTEDIMAGE 
  tvitem\hitem=hitem
  tvitem\iImage= iconeIndex
  tvitem\iSelectedImage = iconeIndex
  result = SendMessage_(GadgetID(TreeGadget), #TVM_SETITEM,0,@tvitem) ; set the icon index from the item
  ProcedureReturn result
EndProcedure
;
Procedure InvertTreeGadgetItems(TreeGadget,p1,p2)
  t1$=GetGadgetItemText(TreeGadget,p1)
  t2$=GetGadgetItemText(TreeGadget,p2)
  SetGadgetItemText(TreeGadget,p1,t2$)
  SetGadgetItemText(TreeGadget,p2,t1$)
  iconindex1 = GetTreeItemIconIndex(TreeGadget,GadgetItemID(TreeGadget,p1)); get the icon from the first item
  iconindex2 = GetTreeItemIconIndex(TreeGadget,GadgetItemID(TreeGadget,p2)); get the icon from the second item
  SetTreeItemIconIndex(TreeGadget,GadgetItemID(TreeGadget,p1),iconindex2); set the icon for the first item
  SetTreeItemIconIndex(TreeGadget,GadgetItemID(TreeGadget,p2),iconindex1); set the icon for the second item
EndProcedure
;
;
Global DD_TreeGadget
Procedure DD_TreeCallback(Window, Message, wParam, lParam)
;   By Timo 'fr34k' Harter for ListView Gadget
;   Adapted to TreeView by Zapman
  Shared OldTreeItem,TreeIsDraging,DraggedItemsList$,DragImageList
  result = #PB_ProcessPureBasicEvents

  ; The first message we need is #TVN_BEGINDRAG. This is a so called
  ; Notification message. This means, that you don't get a message called
  ; #TVN_BEGINDRAG, but you get a #WM_NOTIFY message, with further information, 
  ; that tells you, that it is #TVN_BEGINDRAG
  
  If Message = #WM_NOTIFY
    ; The lparam paramenter contains a pointer to a NMHDR structure. There is
    ; the information about the Message    
    *nmhdr.NMHDR = lParam

    ; The 'hwndfrom' member tells you, which Gadget actually sent the message
    ; This must be always checked to be sure, it is the right gadget.
    ; We allow only our own Gadgets:
    If *nmhdr\hwndfrom = GadgetID(DD_TreeGadget)
        
      ; The 'code' member contains the real message, in our case #TVN_BEGINDRAG
      If *nmhdr\code = #TVN_BEGINDRAG
        ; Ok, for the #TVN_BEGINDRAG notification message, lParam is a pointer to a
        ; NMTREEVIEW Structure. You might think that this can't be, as lParam allready
        ; pointed to a NMHDR structure, but this is correct, as NMTREEVIEW has a
        ; NMHDR structure inside, it only adds more members to it.
    
        *nmv.NMTREEVIEW = lParam
        
        ; The 'hItem' member contains the index of the source item, which we will need
        ; later.        
        TreeItemSource = *nmv\itemNew\hItem
        OldTreeItem = TreeItemSource ; will be used to unhilite the item which was hilited
        
        ; By sending a #TVM_CREATEDRAGIMAGE message to the gadget, we create an ImageList
        ; that contains just one image, the drag&drop image. We will need the Imagelist WinAPI
        ; commands to work with that one later.            
        HighLightTreeItem(GadgetID(DD_TreeGadget),TreeItemSource,0)
        HighLightTreeItem(GadgetID(DD_TreeGadget),GadgetItemID(DD_TreeGadget,GetGadgetState(DD_TreeGadget)),0)
        DragImageList = SendMessage_(GadgetID(DD_TreeGadget), #TVM_CREATEDRAGIMAGE, 0,TreeItemSource)
        ;
        ; If the user is draging a node,
        ; we'll modify the image by adding all the items contained by the node
        LImage = 400
        HImage = 600
        Pb_Image = CreateImage(#PB_Any,LImage,HImage)
        Font1 = LoadFont(#PB_Any, "Tahoma"  ,  8) 
        StartDrawing(ImageOutput(Pb_Image))
        DrawingFont(FontID(Font1))
        Box(0, 0, LImage, HImage ,RGB(255,255,255))
        ItemIndex = GetTreeItemIndexFromHandle(TreeItemSource,GadgetID(DD_TreeGadget))
        ItemText$ = GetGadgetItemText(DD_TreeGadget,ItemIndex,0)
        DraggedItemsList$ = Str(ItemIndex)+Chr(13)+ReplaceString(ItemText$,Chr(13),"")+Chr(13)+"0"+Chr(13)
        DrawText(0,0,ItemText$,0,RGB(255,255,255))
        dep = TextWidth(ItemText$)
        posvert=0
        hcar = 14
        hItem = SendMessage_(GadgetID(DD_TreeGadget), #TVM_GETNEXTITEM, #TVGN_CHILD, TreeItemSource)
        If hItem
          level = 1
          Repeat
            posvert + hcar
            ItemIndex = GetTreeItemIndexFromHandle(hItem,GadgetID(DD_TreeGadget))
            ItemText$ = GetGadgetItemText(DD_TreeGadget,ItemIndex,0)
            DraggedItemsList$ + Str(ItemIndex)+Chr(13)+ReplaceString(ItemText$,Chr(13),"")+Chr(13)+Str(level)+Chr(13)
            DrawText(level*20,posvert,ItemText$,0,RGB(255,255,255))
            nWidth = TextWidth(ItemText$)+(level*20)
            If nWidth>dep ; calculate max text width for our draging image
              dep = nWidth
            EndIf
            hItem2 = SendMessage_(GadgetID(DD_TreeGadget), #TVM_GETNEXTITEM, #TVGN_CHILD, hItem) ; is the next item a child ?
            If hItem2
              level + 1
              hItem = hItem2
            Else
              hItem2 = SendMessage_(GadgetID(DD_TreeGadget), #TVM_GETNEXTITEM, #TVGN_NEXT, hItem) ; is it a same level item ?
              If hItem2
                hItem = hItem2
              Else
                hItem = SendMessage_(GadgetID(DD_TreeGadget), #TVM_GETNEXTITEM,#TVGN_PARENT, hItem) ; get the parent of our item
                hItem = SendMessage_(GadgetID(DD_TreeGadget), #TVM_GETNEXTITEM, #TVGN_NEXT, hItem) ; and go to the next
                level - 1
              EndIf             
            EndIf
          Until level = 0 Or hItem = 0
        EndIf
        DraggedItemsList$ + "Store_end" + Chr(13)
        
        StopDrawing()
        FreeFont(Font1)
        
        ImageList_SetIconSize_(DragImageList,dep+5,posvert+hcar)
        ImageList_AddMasked_(DragImageList,ImageID(Pb_Image),RGB(255,255,255))
        FreeImage(Pb_Image)

        If DragImageList 
          ; This begins the drag&drop operation by displaying the image
          If ImageList_BeginDrag_(DragImageList , 0, 0, 0)

            ; this command shows or hides the drag&drop image. Or course,
            ; we want to see it now :)
            ImageList_DragShowNolock_(#True)
            
            ; this causes windows to send all mouse messages to our window,
            ; even if the mouse is outside of our window. This is neccesary,
            ; because we need to detect the mouseup event to abort the
            ; operation, even if the mouse is outside our window.
            SetCapture_(GetParent_(GadgetID(DD_TreeGadget)))
            
            ; hide the standard cursor
            ShowCursor_(#False)
            
            ; When processing the other events, we need to know whether something
            ; is being draged or not.
            TreeIsDraging = #True
   
          EndIf ; check for ImageList_BeginDrag_()       
        
        EndIf ; check for DragImageList
        
      EndIf ; check for #TVN_BEGINDRAG
          
    EndIf ; check for right gadget
    
  
  ; The next message we need is #WM_MOUSEMOVE, to update the mouse.
  ; But only if TreeIsDraging is #TRUE.  
  ElseIf Message = #WM_MOUSEMOVE And TreeIsDraging
    
    
    ; now we hide the image to avoid redrawn problems.
    ImageList_DragShowNolock_(#False)
    
    ; the next thing we do is hilighting the target item in the target gadget.
    GetWindowRect_(GadgetID(DD_TreeGadget),re.RECT) 
    GetCursorPos_(pt.POINT)  
    If PtInRect_(@re, pt\x | (pt\y<<32))

      ; What we need next is the Item, that is currently under the mouse cursor.
      ; the #TVM_HITTEST message does that test for us.
    
      ; here, we need coordinates relative to the top/left corner of our target
      ; Gadget, so we substract the Gadget position from our window coordinates
      ;  When #EM_MOUSEMOVE is sent, the lParam parameter contains
      ; the x coordinate in the low-word and the y coordinate in the high-word, so we
      ; just use them here:
      MouseX = lParam & $FFFF
      MouseY = lParam >> 16
      hittestinfo.TV_HITTESTINFO
      hittestinfo\pt\x = MouseX - GadgetX(DD_TreeGadget)
      hittestinfo\pt\y = MouseY - GadgetY(DD_TreeGadget)
      
      ; find the item, if none is under the cursor, we get -1, and the next
      ; SendMessage won't work, and nothing is hilighted.
      TargetItem = SendMessage_(GadgetID(DD_TreeGadget), #TVM_HITTEST, 0, @hittestinfo)
      If TargetItem<>-1 And TargetItem<>OldTreeItem
        If OldTreeItem
          HighLightTreeItem(GadgetID(DD_TreeGadget),OldTreeItem,0) ; Unhilighte the precedent hilighted item
        EndIf
        OldTreeItem = TargetItem
        HighLightTreeItem(GadgetID(DD_TreeGadget),OldTreeItem,1)
      EndIf
    Else ; scroll treegadget if mouse is upper or lower than it
      GetWindowRect_(GadgetID(DD_TreeGadget),re.RECT) 
      GetCursorPos_(@MP.POINT) 
      If MP\y < re\top
        SendMessage_(GadgetID(DD_TreeGadget), #WM_VSCROLL, #SB_LINEUP, 0);
      EndIf
      If MP\y > re\bottom
        SendMessage_(GadgetID(DD_TreeGadget), #WM_VSCROLL, #SB_LINEDOWN, 0);
      EndIf
    EndIf
    
    ; now we can show the drag image again:        
    ImageList_DragShowNolock_(#True)

        ; this moves the drag Image.
    GetCursorPos_(@MP.Point)
    ImageList_DragMove_(MP\x, MP\y-7)
    
    ; that's all to do while moving the mouse. Of course, there can be more checks added,
    ; and for example, a different cursor displayed, if you don't want the source to
    ; be draged to the current target and so on, but i think this is enough for a basic
    ; example.
  
  
  ; next is the end of the drag&drop operation... when the user releases the mouse.           
  ElseIf Message = #WM_LBUTTONUP And TreeIsDraging
    ; first, we release all we did, to unlock the mouse. 
    
    ; mouse messages will be sent to other windows again    
    ReleaseCapture_()
    
    ; and drag&drop (remove the image)
    ImageList_EndDrag_()
    
    ; free the image list
    ImageList_Destroy_(DragImageList)
    
    ; show cursor again
    ShowCursor_(#True)
    
    ; no draging in progress now.
    TreeIsDraging = #False
    
    
    ; next, we unhilight the last target item        
    If OldTreeItem
      HighLightTreeItem(GadgetID(DD_TreeGadget),OldTreeItem,0)
    EndIf
    
    GetWindowRect_(GadgetID(DD_TreeGadget),re.RECT) 
    GetCursorPos_(pt.POINT)  
    If PtInRect_(@re, pt\x | (pt\y<<32))
      ; now, move the items as demanded by the user:
      ;
      ; examine items at old positions
      ;
      nbitems = 0
      FIndex = -1
      ct = 0
      Repeat
        ct + 1
        LValue$ = StringField(DraggedItemsList$,ct,Chr(13))
        If LValue$ <> "Store_end"
          ItemIndex = Val(LValue$)
          If FIndex = -1 : FIndex = ItemIndex: EndIf
          ct + 2
          nbitems + 1
        EndIf
      Until LValue$ = "Store_end"
      ;
      ; add items at new position
      ;
      nPosition = GetTreeItemIndexFromHandle(OldTreeItem,GadgetID(DD_TreeGadget))+1
      If nPosition>FIndex And nPosition<(FIndex+nbitems+1)
        Debug "Trying to put a node inside its own content !!!!"
      Else
        mnPosition = nPosition
        nLevel = GetGadgetItemAttribute(DD_TreeGadget,nPosition-1,#PB_Tree_SubLevel)
        iconindex = GetTreeItemIconIndex(DD_TreeGadget,GadgetItemID(DD_TreeGadget,nPosition-1))
        If iconindex And iconindex<>-1 ; get the icon from the target item
          Debug "target is a folder"   ; if there is one, we suppose that the item is a folder (a potential node)
          nLevel + 1
        EndIf
        ct = 0
        Repeat
          ct + 1
          LValue$ = StringField(DraggedItemsList$,ct,Chr(13))
          If LValue$ <> "Store_end"
            ItemIndex = Val(LValue$)
            ct + 1
            ItemText$ = StringField(DraggedItemsList$,ct,Chr(13))
            ct + 1
            level = Val(StringField(DraggedItemsList$,ct,Chr(13)))
            If FIndex>= mnPosition
              ItemIndex + nPosition - mnPosition
            EndIf
            iconindex = GetTreeItemIconIndex(DD_TreeGadget,GadgetItemID(DD_TreeGadget,ItemIndex)); get the icon from the old item
            AddGadgetItem(DD_TreeGadget, nPosition, ItemText$,0,level+nLevel)
            SetTreeItemIconIndex(DD_TreeGadget,GadgetItemID(DD_TreeGadget,nPosition),iconindex); set the icon for the new item
            nPosition + 1
          EndIf
        Until LValue$ = "Store_end"
        
        If FIndex>= mnPosition ; position has to be adjusted if items to delete are after added items
          FIndex + nbitems
          nPosition = mnPosition
        Else
          nPosition = mnPosition-nbitems
        EndIf
        RemoveGadgetItem(DD_TreeGadget,FIndex)
  
        SetGadgetState(DD_TreeGadget,nPosition)
        SetActiveGadget(DD_TreeGadget)
      EndIf ; IsMouseOver(GadgetID(DD_TreeGadget))
    EndIf ; If Message = #WM_LBUTTONUP And TreeIsDraging
    
  EndIf ; check Message

  ProcedureReturn Result
EndProcedure
;
Global hFolderIcon
Procedure Enable_DragnDrop_On_TreeGadget(Window,TreeGadget)
  DD_TreeGadget = TreeGadget
  hWndTV = GadgetID(TreeGadget)
  Style = GetWindowLong_(hWndTV, #GWL_STYLE)
  Style = Style & (~#TVS_DISABLEDRAGDROP) 
  SetWindowLong_(hWndTV, #GWL_STYLE, Style) ; enable drag'n drop for the gadget
  ;
  hFolderIcon = GetFolderIconHandle() ; get a folder icon to use later in our list
  ;
  SendMessage_(hWndTV, #TVM_GETIMAGELIST,#TVSIL_NORMAL,imageList)
  If imageList = 0 ; The TreeGadget has no image list!! We need one, so we'll create one.
    AddGadgetItem(TreeGadget, -1, "ToDelete", hFolderIcon,0) ; PB will automatically create an image list if we add an item with an icon
    RemoveGadgetItem(TreeGadget, CountGadgetItems(TreeGadget)-1) ; OK, we can now delete this item
  EndIf
  ;
  SetWindowCallback(@DD_TreeCallback(),Window)
EndProcedure

; Window und Gadget...
winMain = OpenWindow(#PB_Any, 0, 0, 350, 260, "Drag'n Drop sorting with a TreeView", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

TreeGadget = TreeGadget(#PB_Any, 5, 5, 200, 250,#PB_Tree_AlwaysShowSelection)
Enable_DragnDrop_On_TreeGadget(winMain,TreeGadget)

ItemString = StringGadget(#PB_Any,220,5,120,20,"")

TextGadget = TextGadget(#PB_Any, 220, 50, 120, 250,"You can sort this treeview manually by draging items from one position to another one.")

PosVert = 160
BNewFolder = ButtonGadget(#PB_Any,220,PosVert,120,20,"New Folder")
PosVert + 25
BNewItem = ButtonGadget(#PB_Any,220,PosVert,120,20,"New Item")
PosVert + 25
BDelete = ButtonGadget(#PB_Any,220,PosVert,120,20,"Delete")
PosVert + 25
BSort = ButtonGadget(#PB_Any,220,PosVert,120,20,"Alphabetical Sort")

AddGadgetItem(TreeGadget, -1, "Item1"+Chr(13), 0,0)
AddGadgetItem(TreeGadget, -1, "Folder#1", hFolderIcon,0)
  AddGadgetItem(TreeGadget, -1, "Item11",0,1)
  AddGadgetItem(TreeGadget, -1, "Item12",0,1)
  AddGadgetItem(TreeGadget, -1, "Folder#12",hFolderIcon,1)
    AddGadgetItem(TreeGadget, -1, "Item121",0,2)
    AddGadgetItem(TreeGadget, -1, "Item122",0,2)
AddGadgetItem(TreeGadget, -1, "Folder#2", hFolderIcon,0)
  AddGadgetItem(TreeGadget, -1, "Itemz11",0,1)
  AddGadgetItem(TreeGadget, -1, "zItem1a",0,1)

For ct = 1 To 20
  AddGadgetItem(TreeGadget, -1, "Item"+Str(ct+1),0,0)
Next
SetGadgetState(TreeGadget,0)
SetGadgetText(ItemString,GetGadgetText(TreeGadget))
SendMessage_(GadgetID(ItemString), #EM_SETSEL, 0, Len(GetGadgetText(TreeGadget)))
SetActiveGadget(ItemString)


Repeat
  Event = WaitWindowEvent()
  If Event = #PB_Event_Gadget
    If EventGadget() = TreeGadget
      ItemText$ = GetGadgetItemText(TreeGadget,GetGadgetState(TreeGadget))
      SetGadgetText(ItemString,ItemText$)
      SendMessage_(GadgetID(ItemString), #EM_SETSEL, 0, Len(ItemText$))
    EndIf
    If EventGadget() = ItemString And EventType() = #PB_EventType_Change
      SetGadgetItemText(TreeGadget,GetGadgetState(TreeGadget),GetGadgetText(ItemString))
    ElseIf EventGadget() = BNewFolder Or EventGadget() = BNewItem
      IIndex = GetGadgetState(TreeGadget)+1
      If EventGadget() = BNewFolder 
        AddGadgetItem(TreeGadget,IIndex,"New folder",hFolderIcon)
      Else
        AddGadgetItem(TreeGadget,IIndex,"New item")
      EndIf
      SetGadgetState(TreeGadget,IIndex)
      ItemText$ = GetGadgetItemText(TreeGadget,IIndex)
      SetGadgetText(ItemString,ItemText$)
      SendMessage_(GadgetID(ItemString), #EM_SETSEL, 0, Len(ItemText$))
      SetActiveGadget(ItemString)
    ElseIf EventGadget() = BDelete
      IIndex = GetGadgetState(TreeGadget)
      RemoveGadgetItem(TreeGadget, IIndex)
      SetGadgetState(TreeGadget,IIndex)
      SetGadgetText(ItemString,ItemText$)
      SendMessage_(GadgetID(ItemString), #EM_SETSEL, 0, Len(ItemText$))
      SetActiveGadget(TreeGadget)
    ElseIf EventGadget() = BSort
      ; Windows API has a sort function for treeview (#TVM_SORTCHILDREN message)
      ; but we can't use it because the PureBasic element index is not sorted with the elements.
      ; So, we recreate a complete sort function for PB treegadget.
      lastitem = CountGadgetItems(TreeGadget)-1
      maxlevel = 0
      For clevel = 0 To maxlevel
        For i=0 To lastitem-1
          nlevel = GetGadgetItemAttribute(TreeGadget,i,#PB_Tree_SubLevel)
          If nlevel>maxlevel : maxlevel = nlevel : EndIf
          If nlevel = clevel
            min=i
            For j=i+1 To lastitem 
              If GetGadgetItemText(TreeGadget,j)<GetGadgetItemText(TreeGadget,min) And GetGadgetItemAttribute(TreeGadget,j,#PB_Tree_SubLevel)=clevel
                min=j 
              EndIf
              If GetGadgetItemAttribute(TreeGadget,j,#PB_Tree_SubLevel)<nlevel
                j = lastitem
              EndIf
            Next
            If min<>i
              For b = 1 To 2
                storeitems$ = ""
                If b = 1
                  posd = i
                Else
                  posd = min
                EndIf
                ; Store the node content
                ct = 1
                While GetGadgetItemAttribute(TreeGadget,posd+ct,#PB_Tree_SubLevel)>clevel
                  storeitems$ + GetGadgetItemText(TreeGadget,posd+ct)+Chr(13)+Str(GetGadgetItemAttribute(TreeGadget,posd+ct,#PB_Tree_SubLevel))+Chr(13)+Str(GetTreeItemIconIndex(TreeGadget,GadgetItemID(TreeGadget,posd+ct)))+Chr(13)
                  ct + 1
                  If b = 1 And min>i
                    min - 1
                  EndIf
                  If b = 2 And i>min
                    i - 1
                  EndIf
                Wend
                If b = 1
                  storeitems_i$ = storeitems$
                Else
                  storeitems_min$ = storeitems$
                EndIf
                ; Delete the node content
                While GetGadgetItemAttribute(TreeGadget,posd+1,#PB_Tree_SubLevel)>clevel
                  RemoveGadgetItem(TreeGadget,posd+1)
                Wend
              Next
              ; recreate the node content at the right place
              For b = 1 To 2
                If b = 1
                  posi = min
                  storeitems$ = storeitems_i$
                Else
                  posi = i
                  storeitems$ = storeitems_min$
                EndIf
                ct = 0
                Repeat
                  ct + 1
                  itemtext$ = StringField(storeitems$,ct,Chr(13))
                  If itemtext$
                    ct + 1
                    level = Val(StringField(storeitems$,ct,Chr(13)))
                    ct + 1
                    iconindex = Val(StringField(storeitems$,ct,Chr(13)))
                    posi + 1
                    AddGadgetItem(TreeGadget,posi,itemtext$,0,level)
                    SetTreeItemIconIndex(TreeGadget,GadgetItemID(TreeGadget,posi),iconindex)
                    If b = 1 And i>min
                      i + 1
                    EndIf
                    If b = 2 And min>i
                      min + 1
                    EndIf
                  EndIf
                Until itemtext$ = ""
              Next
              InvertTreeGadgetItems(TreeGadget,i,min)
            EndIf         
          EndIf
        Next 
      Next
      SetGadgetState(TreeGadget,0)
      SetGadgetText(ItemString,GetGadgetText(TreeGadget))
      SendMessage_(GadgetID(ItemString), #EM_SETSEL, 0, Len(GetGadgetText(TreeGadget)))
      SetActiveGadget(ItemString)
    EndIf
  EndIf
Until Event = #PB_Event_CloseWindow
End

; -------------------------------------------------------------------------

Don't try - DO it !
freak
PureBasic Team
PureBasic Team
Posts: 5948
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Drag'nDrop manual sort for TreeGadget

Post by freak »

quidquid Latine dictum sit altum videtur
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Re: Drag'nDrop manual sort for TreeGadget

Post by zapman* »

Thanks Freak. I did'nt found your version before.

I add many features like icon compatibility, draging image, alpha sorting and automatic scrolling, so I hope my version can be usefull for windows programmers.
Don't try - DO it !
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: Drag'nDrop manual sort for TreeGadget

Post by c4s »

I can't get your code to work. At line 377 (SetWindowLong_(hWndTV, ...) seem to be an IMA.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Re: Drag'nDrop manual sort for TreeGadget

Post by zapman* »

Thanks to test, SeaForce.

What"s your PB version and what message do you get, please?

What's an IMA? :oops:
Don't try - DO it !
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: Drag'nDrop manual sort for TreeGadget

Post by c4s »

I'm using PB 4.50 on Windows XP x86.
The debugger says: "Line 377: Invalid memory access [that's an IMA ;)] at address 12"

Installing PB 4.51 rc2 right now to test it as well...
Edit: Ok, exactly the same error!
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Re: Drag'nDrop manual sort for TreeGadget

Post by zapman* »

That's amazing. Did you make any change to the code or is it unchanged ?

Could you please add some "Debug" to know the value of hWndTV and Style just before the error occure?

Thanks again for your help. :)
Don't try - DO it !
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: Drag'nDrop manual sort for TreeGadget

Post by c4s »

I just realized you didn't combine the styles correctly. Instead of an AND "&" it should be an OR "|" in the line before:

Code: Select all

Style = Style | (#TVS_DISABLEDRAGDROP)
Ok, now I see the window but I can't drag & drop the items just the buttons seem to work...
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Re: Drag'nDrop manual sort for TreeGadget

Post by gnozal »

c4s:

Code: Select all

Style = Style & (~#TVS_DISABLEDRAGDROP)
is correct : we want to remove the TVS_DISABLEDRAGDROP style, not add it.
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: Drag'nDrop manual sort for TreeGadget

Post by c4s »

Yes, you're right. Somehow I always over read the "disable" in #TVS_DISABLEDRAGDROP. This also explains why it doesn't work with my fix.

So I still don't understand why this code crashes at line 377, the IMA is at address 4. hWndTV seem to be valid...
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Re: Drag'nDrop manual sort for TreeGadget

Post by zapman* »

c4s wrote:So I still don't understand why this code crashes at line 377, the IMA is at address 4. hWndTV seem to be valid...
That's weird. :(

Does anybody else has the same problem? If some of you has tested this code, please report. I would like to know if c4s has the problem because of his particular configuration or if it's a code problem.
Don't try - DO it !
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Re: Drag'nDrop manual sort for TreeGadget

Post by gnozal »

zapman* wrote:Does anybody else has the same problem? If some of you has tested this code, please report. I would like to know if c4s has the problem because of his particular configuration or if it's a code problem.
No crash here, tested with PB4.51 beta 2 (WinXP / NT4).
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: Drag'nDrop manual sort for TreeGadget

Post by c4s »

Again I played a little around with the code...Now I uncommented that line and it works. :shock: What's the error here?

By the way: Looks nice!
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Re: Drag'nDrop manual sort for TreeGadget

Post by zapman* »

Thank you very much for this feedback, SeaForce. I'm happy to learn that you found the solution.

But I'm still very puzzled by the problem that you encountered. I( would like very much to understand what happen :(
Don't try - DO it !
Post Reply