Jump to content
Sign in to follow this  
rexx

How to make this TreeView drag drop work in x64?

Recommended Posts

rexx

http://www.autoitscript.com/forum/index.php?showtopic=56411

It works fine in x86, but in x64, I got some problem in DLL calls.

First, in the WM_NOTIFY function,

Local $tNMHDR = DllStructCreate("hwnd hTree;int_ptr;int_ptr code", $lParam)
        Local $code = DllStructGetData($tNMHDR, "code")

I use int_ptr in the struct to get the correct 64-bit int, but it becomes unsigned int.

The help file says that int_ptr is signed int.

Is that a bug or I'm doing something wrong?

I convert both $code and the $TVN_ constants to HEX to make it work, but I think it's not a good solution.

And the second problem, in the SysEvents() function.

Case $GUI_EVENT_MOUSEMOVE
            If $bTreeDrag = False Then ContinueCase
            $aHwnd = DllCall("user32.dll", "hwnd", "WindowFromPoint", "uint", MouseGetPos(0), "uint", MouseGetPos(1))
            ;cancel drag in progress and cleanup if moved outside treeview:
            If ($aHwnd[0] <> $hTree) Then
                $bTreeDrag = False
                _WinAPI_InvalidateRect($hTree)
                _GUIImageList_Destroy($hTreeDragImage) ;delete drag image
                _SendMessage($hTree, $TVM_SELECTITEM, $TVGN_DROPHILITE, 0) ;remove DropTarget
                _SendMessage($hTree, $TVM_SETINSERTMARK, 0, 0) ;remove InsertMark
                ContinueCase
            EndIf

The $aHwnd[0] is always a strange number, so it always stop dragging here.

I've tried use "uint_ptr" for mouse position, but not works.

Anyone helps? Thanks in advance.

Here's the full code.

#include <GuiTreeView.au3>
#Include <WindowsConstants.au3>
#Include <GUIConstantsEx.au3>

;Opt("GUICloseOnESC", 0)
Opt("GUIOnEventMode", 1)

$sTitle = "Treeview Drag & Drop Editing"
;Required global constants:
Global $bTreeDrag = False, $bTreeEdit = False, $hDragItem, $hTreeDragImage, $fWhere

$hGui = GUICreate($sTitle, 400, 300, -1, -1, -1, -1)

$label = GUICtrlCreateLabel("Drag and drop separate items or branches to move them." & _
                        @LF & "To start edit selected item, LMB on item or press Enter." & _
                        @LF & "To end editing, LMB outside item (apply) or Esc (cancel) / Enter (apply)." & _
                        @LF & "To insert new item press Insert, to delete existing item press Delete.", 30, 10, 340, 60)
$cTree = GUICtrlCreateTreeView(50,75,300,200,$TVS_HASBUTTONS+$TVS_HASLINES+$TVS_LINESATROOT+$TVS_EDITLABELS+$TVS_CHECKBOXES)
GUICtrlSetState(-1, $GUI_DROPACCEPTED)
$cTreeItemsStart = GUICtrlCreateDummy()
$cTreeItem_1 = GUICtrlCreateTreeViewItem("item 1", $cTree)
$cTreeItem_1a = GUICtrlCreateTreeViewItem("item 1a", $cTreeItem_1)
$cTreeItem_1b = GUICtrlCreateTreeViewItem("item 1b", $cTreeItem_1)
$cTreeItem_2 = GUICtrlCreateTreeViewItem("item 2", $cTree)
$cTreeItem_2a = GUICtrlCreateTreeViewItem("item 2a", $cTreeItem_2)
$cTreeItem_3 = GUICtrlCreateTreeViewItem("item 3", $cTree)
$cTreeItem_3a = GUICtrlCreateTreeViewItem("item 3a", $cTreeItem_3)
$cTreeItem_3a1 = GUICtrlCreateTreeViewItem("item 3a1", $cTreeItem_3a)
$cTreeItem_4 = GUICtrlCreateTreeViewItem("item 4", $cTree)
$cTreeItemsEnd = GUICtrlCreateDummy()
;Treeview with images test:
;~  $hImgList = _GUIImageList_Create (16, 16)
;~  For $ii = 1 To $cTreeItemsEnd-$cTreeItemsStart
;~      _GUIImageList_AddIcon ($hImgList, "shell32.dll", 60+$ii*2)
;~  Next
;~  _GUICtrlTreeView_SetNormalImageList(GUICtrlGetHandle($cTree), $hImgList)
;~  $a = 0
;~  For $i = $cTreeItemsStart+1 To $cTreeItemsEnd-1
;~      _GUICtrlTreeView_SetImageIndex($cTree, _GUICtrlTreeView_GetItemHandle($cTree, $i), $a)
;~      _GUICtrlTreeView_SetSelectedImageIndex($cTree, _GUICtrlTreeView_GetItemHandle($cTree, $i), $a)
;~      $a += 1
;~  Next

$label2 = GUICtrlCreateLabel("", 50, 280, 300, 15)

GUISetOnEvent($GUI_EVENT_CLOSE, "SysEvents")
GUISetOnEvent($GUI_EVENT_MOUSEMOVE, "SysEvents")
GUISetOnEvent($GUI_EVENT_PRIMARYUP, "SysEvents")
GUIRegisterMsg($WM_NOTIFY, "On_WM_NOTIFY")

GUISetState()

While 1
    Sleep(200)
    ;add Enter, Esc, Delete and Insert key functionality to treeview edit:
;   TreeKeyboardFunc($cTree)
WEnd

Func SysEvents()
    Local $hTree = GUICtrlGetHandle($cTree)
    Switch @GUI_CtrlId
        Case $GUI_EVENT_CLOSE
            Exit
        Case $GUI_EVENT_PRIMARYUP
            If $bTreeDrag Then
                _WinAPI_InvalidateRect($hTree)
                $bTreeDrag = False
                _GUIImageList_Destroy($hTreeDragImage) ;delete drag image
                _SendMessage($hTree, $TVM_SELECTITEM, $TVGN_DROPHILITE, 0) ;remove DropTarget
                _SendMessage($hTree, $TVM_SETINSERTMARK, 0, 0) ;remove InsertMark
                If (TreeItemFromPoint($hTree) = $hDragItem) Then ContinueCase
                ;move item:
                $hItem = TreeItemCopy($hTree, $hDragItem, TreeItemFromPoint($hTree), $fWhere)
                If $hItem <> 0 Then
                    _GUICtrlTreeView_SelectItem($hTree, $hItem)
                    _GUICtrlTreeView_Delete($hTree, $hDragItem)
                EndIf
            EndIf
        Case $GUI_EVENT_MOUSEMOVE
            If $bTreeDrag = False Then ContinueCase
            $aHwnd = DllCall("user32.dll", "hwnd", "WindowFromPoint", "uint", MouseGetPos(0), "uint", MouseGetPos(1))
            ;cancel drag in progress and cleanup if moved outside treeview:
            If ($aHwnd[0] <> $hTree) Then
                $bTreeDrag = False
                _WinAPI_InvalidateRect($hTree)
                _GUIImageList_Destroy($hTreeDragImage) ;delete drag image
                _SendMessage($hTree, $TVM_SELECTITEM, $TVGN_DROPHILITE, 0) ;remove DropTarget
                _SendMessage($hTree, $TVM_SETINSERTMARK, 0, 0) ;remove InsertMark
                ContinueCase
            EndIf
            $hItemHover = TreeItemFromPoint($hTree)
            If $hItemHover = 0 Then
                ;meh
            Else
                $aRect = _GUICtrlTreeView_DisplayRect($hTree, $hItemHover)
                $iTreeY = _WinAPI_GetMousePosY(True, $hTree)
                Switch $iTreeY
                    Case $aRect[1] To $aRect[1]+Int(($aRect[3]-$aRect[1])/4)
                        _SendMessage($hTree, $TVM_SELECTITEM, $TVGN_DROPHILITE, 0) ;remove DropTarget
                        _SendMessage($hTree, $TVM_SETINSERTMARK, 0, $hItemHover) ;add InsertMark before item
                        $fWhere = -1
                    Case 1+$aRect[1]+Int(($aRect[3]-$aRect[1])/3) To $aRect[1]+Int(($aRect[3]-$aRect[1])*2/3)
                        _SendMessage($hTree, $TVM_SETINSERTMARK, 0, 0) ;remove InsertMark
                        _SendMessage($hTree, $TVM_SELECTITEM, $TVGN_DROPHILITE, $hItemHover) ;add DropTarget
                        $fWhere = 0
                    Case 1+$aRect[1]+Int(($aRect[3]-$aRect[1])*2/3) To $aRect[3]
                        _SendMessage($hTree, $TVM_SELECTITEM, $TVGN_DROPHILITE, 0) ;remove DropTarget
                        _SendMessage($hTree, $TVM_SETINSERTMARK, 1, $hItemHover) ;add InsertMark after item
                        $fWhere = 1
                EndSwitch
            EndIf
            DrawDragImage($hTree, $hTreeDragImage)
    EndSwitch
EndFunc
;   TreeItemFromPoint()
;   Returns handle of tree item under mouse:
Func TreeItemFromPoint($hWnd)
    Local $tMPos = _WinAPI_GetMousePos(True, $hWnd)
    Return _GUICtrlTreeView_HitTestItem($hWnd, DllStructGetData($tMPos, 1), DllStructGetData($tMPos, 2))
EndFunc
;   TreeItemCopy()
;   Copies tree item $hItemSource and all its children to an item $hItemTarget, depending on $fDirection
;   $fDirection:
;           -1 = before $hItemTarget
;           0 = inside $hItemTarget
;           1 = after $hItemTarget
Func TreeItemCopy($hWnd, $hItemSource, $hItemTarget, $fDirection)
    ;making sure parent can't be dropped onto one of its descendants:
    $hTest = $hItemTarget
    Do
        $hTest = _GUICtrlTreeView_GetParentHandle($hWnd, $hTest)
        If $hTest = $hItemSource Then Return 0
    Until $hTest = 0
    ;create new item at determined position
    $sText = _GUICtrlTreeView_GetText($hWnd, $hItemSource)
    $hParent = _GUICtrlTreeView_GetParentHandle($hWnd, $hItemTarget)
    Switch $fDirection
        Case -1
            $hPrev = _GUICtrlTreeView_GetPrevSibling($hWnd, $hItemTarget)
            If $hPrev = 0 Then
                $hNew = _GUICtrlTreeView_AddFirst($hWnd, $hItemTarget, $sText)
            Else
                $hNew = _GUICtrlTreeView_InsertItem($hWnd, $sText, $hParent, $hPrev)
            EndIf
        Case 0
            $hNew = _GUICtrlTreeView_InsertItem($hWnd, $sText, $hItemTarget)
        Case 1
            $hNew = _GUICtrlTreeView_InsertItem($hWnd, $sText, $hParent, $hItemTarget)
        Case Else
            Return 0
    EndSwitch
    ;save item state and checkbox image if there is such
    _GUICtrlTreeView_SetState($hWnd, $hNew, _GUICtrlTreeView_GetState($hWnd, $hItemSource))
    If _GUICtrlTreeView_GetStateImageList($hWnd) <> 0 Then
        _GUICtrlTreeView_SetStateImageIndex($hWnd, $hNew, _GUICtrlTreeView_GetStateImageIndex($hWnd, $hItemSource))
    EndIf
    ;save icon/selected image indexes
    If _GUICtrlTreeView_GetNormalImageList($hWnd) <> 0 Then
        _GUICtrlTreeView_SetImageIndex($hWnd, $hNew, _GUICtrlTreeView_GetImageIndex($hWnd, $hItemSource))
        _GUICtrlTreeView_SetSelectedImageIndex($hWnd, $hNew, _GUICtrlTreeView_GetSelectedImageIndex($hWnd, $hItemSource))
    EndIf
    ;recurse through descendants:
    $iChildCount = _GUICtrlTreeView_GetChildCount($hWnd, $hItemSource)
    If $iChildCount > 0 Then
        For $i = 0 To $iChildCount-1
            $hRecSource = _GUICtrlTreeView_GetItemByIndex($hWnd, $hItemSource, $i)
            TreeItemCopy($hWnd, $hRecSource, $hNew, 0)
        Next
    EndIf
    Return $hNew
EndFunc
Func On_WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    ;wparam = cid, lparam = pnmh
    If $wParam = $cTree Then
        Local $tNMHDR = DllStructCreate("hwnd hTree;int_ptr;int_ptr code", $lParam)
        Local $code = DllStructGetData($tNMHDR, "code")
        Local $hTree = HWnd(DllStructGetData($tNMHDR, "hTree"))
;       tooltip($code)
        Switch Hex($code)
            Case Hex($TVN_BEGINDRAGA), Hex($TVN_BEGINDRAGW)
;               msgbox(0,0,"Begin Drag",0)
                $bTreeDrag = True
                $hDragItem = TreeItemFromPoint($hTree)
;~              _GUICtrlTreeView_SelectItem($hTree, $hDragItem)
                _GUICtrlTreeView_SetSelected($hTree, _GUICtrlTreeView_GetSelection($hTree), False)
                $hTreeDragImage = TreeCreateDragImage($hTree, $hDragItem)
                DrawDragImage($hTree, $hTreeDragImage)
            Case Hex($TVN_BEGINLABELEDITA), Hex($TVN_BEGINLABELEDITW)
                $bTreeEdit = True
;~              $hTreeEdit = _SendMessage($hTree, $TVM_GETEDITCONTROL, 0, 0)
            Case Hex($TVN_ENDLABELEDITA), Hex($TVN_ENDLABELEDITW)
                $bTreeEdit = False
                Return 1
            Case Hex($TVN_SELCHANGEDA), Hex($TVN_SELCHANGEDW)
                Local $hSel = _GUICtrlTreeView_GetSelection($hTree)
;               Local $tNMTREEVIEW = DllStructCreate($tagNMTREEVIEW, $lParam)
;               Local $hSel = DllStructGetData($tNMTREEVIEW, "NewhItem")
                Local $sTxt = "Selected: " & _GUICtrlTreeView_GetText($hTree, $hSel) & " (item handle " & $hSel & ")"
                GUICtrlSetData($label2, $sTxt)
            Case Else
        EndSwitch
        ;
    EndIf
EndFunc
Func KeyPressed($iHexKey)
    Local $aRet = DllCall('user32.dll', "int", "GetAsyncKeyState", "int", $iHexKey)
;~  If BitAND($aRet[0], 0x8000) Or BitAND($aRet[0], 1) Then Return 1
    If BitAND($aRet[0], 1) Then Return 1
    Return 0
EndFunc
;Func TreeKeyboardFunc($cID)
;   Local $hWnd = GUICtrlGetHandle($cID)
;   If $bTreeDrag Then Return
;   If $bTreeEdit Then
;       If KeyPressed(0x0d) Then _SendMessage($hWnd, $TVM_ENDEDITLABELNOW, 0, 0) ;enter
;       If KeyPressed(0x1b) Then _SendMessage($hWnd, $TVM_ENDEDITLABELNOW, 1, 0) ;esc
;   EndIf
;   Local $aRet = DllCall('user32.dll', 'hwnd', 'GetFocus')
;   If $aRet[0] = $hWnd Then
;       If KeyPressed(0x2d) Then _GUICtrlTreeView_Add($hWnd, _GUICtrlTreeView_GetSelection($hWnd), "New Item") ;insert
;       If KeyPressed(0x2e) Then _GUICtrlTreeView_Delete($hWnd, _GUICtrlTreeView_GetSelection($hWnd)) ;delete
;       If KeyPressed(0x0d) Then _SendMessage($hWnd, $TVM_EDITLABEL, 0, _GUICtrlTreeView_GetSelection($hWnd)) ;enter
;   EndIf
;EndFunc
Func TreeCreateDragImage($hWnd, $hItem)
    ;if treeview has imagelist, use image from it
    If _GUICtrlTreeView_GetNormalImageList($hWnd) <> 0 Then Return _GUICtrlTreeView_CreateDragImage($hWnd, $hItem)
    ;if not, create a bitmap of dragitem's text rectangle and put it into imagelist.
    Local $aItemRect = _GUICtrlTreeView_DisplayRect($hWnd, $hItem, True)
    Local $iImgW = $aItemRect[2]-$aItemRect[0]
    Local $iImgH = $aItemRect[3]-$aItemRect[1]
    Local $hTreeDC = _WinAPI_GetDC($hWnd)
    Local $hMemDC = _WinAPI_CreateCompatibleDC($hTreeDC)
    Local $hMemBmp = _WinAPI_CreateCompatibleBitmap($hTreeDC, $iImgW, $iImgH)
    Local $hMemBmpOld = _WinAPI_SelectObject($hMemDC, $hMemBmp)
    _WinAPI_BitBlt($hMemDC, 0, 0, $iImgW, $iImgH, $hTreeDC, $aItemRect[0], $aItemRect[1], $SRCCOPY)
    _WinAPI_SelectObject($hMemDC, $hMemBmpOld)
    _WinAPI_ReleaseDC($hWnd, $hTreeDC)
    _WinAPI_DeleteDC($hMemDC)
    Local $hImgList = _GUIImageList_Create($iImgW, $iImgH, 6)
    _GUIImageList_Add($hImgList, $hMemBmp)
    _WinAPI_DeleteObject($hMemBmp)
    Return $hImgList
EndFunc
; Draw drag image
; by Gary Frost (gafrost) (?)
Func DrawDragImage(ByRef $hControl, ByRef $aDrag)
    Local $tPoint, $hDC
    $hDC = _WinAPI_GetWindowDC($hControl)
    $tPoint = _WinAPI_GetMousePos(True, $hControl)
    _WinAPI_InvalidateRect($hControl)
    _GUIImageList_Draw($aDrag, 0, $hDC, DllStructGetData($tPoint, "X")-10, DllStructGetData($tPoint, "Y")-8)
    _WinAPI_ReleaseDC($hControl, $hDC)
EndFunc   ;==>DrawDragImage

Share this post


Link to post
Share on other sites
rexx

I found the solution for WindowFromPoint

http://www.autoitscript.com/forum/index.php?showtopic=109121

But the first problem still not solved.

Share this post


Link to post
Share on other sites
rexx

OK, I solved it.

Just use the $tagNMHDR structure.

Global Const $tagNMHDR = "hwnd hWndFrom;uint_ptr IDFrom;INT Code"

"Code" is int, not int_ptr

#include <GuiTreeView.au3>
#Include <WindowsConstants.au3>
#Include <GUIConstantsEx.au3>

;Opt("GUICloseOnESC", 0)
Opt("GUIOnEventMode", 1)

$sTitle = "Treeview Drag & Drop Editing"
;Required global constants:
Global $bTreeDrag = False, $bTreeEdit = False, $hDragItem, $hTreeDragImage, $fWhere

$hGui = GUICreate($sTitle, 400, 300, -1, -1, -1, -1)

$label = GUICtrlCreateLabel("Drag and drop separate items or branches to move them." & _
                        @LF & "To start edit selected item, LMB on item or press Enter." & _
                        @LF & "To end editing, LMB outside item (apply) or Esc (cancel) / Enter (apply)." & _
                        @LF & "To insert new item press Insert, to delete existing item press Delete.", 30, 10, 340, 60)
$cTree = GUICtrlCreateTreeView(50,75,300,200,$TVS_HASBUTTONS+$TVS_HASLINES+$TVS_LINESATROOT+$TVS_EDITLABELS+$TVS_CHECKBOXES)
GUICtrlSetState(-1, $GUI_DROPACCEPTED)
$cTreeItemsStart = GUICtrlCreateDummy()
$cTreeItem_1 = GUICtrlCreateTreeViewItem("item 1", $cTree)
$cTreeItem_1a = GUICtrlCreateTreeViewItem("item 1a", $cTreeItem_1)
$cTreeItem_1b = GUICtrlCreateTreeViewItem("item 1b", $cTreeItem_1)
$cTreeItem_2 = GUICtrlCreateTreeViewItem("item 2", $cTree)
$cTreeItem_2a = GUICtrlCreateTreeViewItem("item 2a", $cTreeItem_2)
$cTreeItem_3 = GUICtrlCreateTreeViewItem("item 3", $cTree)
$cTreeItem_3a = GUICtrlCreateTreeViewItem("item 3a", $cTreeItem_3)
$cTreeItem_3a1 = GUICtrlCreateTreeViewItem("item 3a1", $cTreeItem_3a)
$cTreeItem_4 = GUICtrlCreateTreeViewItem("item 4", $cTree)
$cTreeItemsEnd = GUICtrlCreateDummy()
;Treeview with images test:
;~  $hImgList = _GUIImageList_Create (16, 16)
;~  For $ii = 1 To $cTreeItemsEnd-$cTreeItemsStart
;~      _GUIImageList_AddIcon ($hImgList, "shell32.dll", 60+$ii*2)
;~  Next
;~  _GUICtrlTreeView_SetNormalImageList(GUICtrlGetHandle($cTree), $hImgList)
;~  $a = 0
;~  For $i = $cTreeItemsStart+1 To $cTreeItemsEnd-1
;~      _GUICtrlTreeView_SetImageIndex($cTree, _GUICtrlTreeView_GetItemHandle($cTree, $i), $a)
;~      _GUICtrlTreeView_SetSelectedImageIndex($cTree, _GUICtrlTreeView_GetItemHandle($cTree, $i), $a)
;~      $a += 1
;~  Next

$label2 = GUICtrlCreateLabel("", 50, 280, 300, 15)

GUISetOnEvent($GUI_EVENT_CLOSE, "SysEvents")
GUISetOnEvent($GUI_EVENT_MOUSEMOVE, "SysEvents")
GUISetOnEvent($GUI_EVENT_PRIMARYUP, "SysEvents")
GUIRegisterMsg($WM_NOTIFY, "On_WM_NOTIFY")

GUISetState()

While 1
    Sleep(200)
    ;add Enter, Esc, Delete and Insert key functionality to treeview edit:
;   TreeKeyboardFunc($cTree)
WEnd

Func SysEvents()
    Local $hTree = GUICtrlGetHandle($cTree)
    Switch @GUI_CtrlId
        Case $GUI_EVENT_CLOSE
            Exit
        Case $GUI_EVENT_PRIMARYUP
            If $bTreeDrag Then
                _WinAPI_InvalidateRect($hTree)
                $bTreeDrag = False
                _GUIImageList_Destroy($hTreeDragImage) ;delete drag image
                _SendMessage($hTree, $TVM_SELECTITEM, $TVGN_DROPHILITE, 0) ;remove DropTarget
                _SendMessage($hTree, $TVM_SETINSERTMARK, 0, 0) ;remove InsertMark
                If (TreeItemFromPoint($hTree) = $hDragItem) Then ContinueCase
                ;move item:
                $hItem = TreeItemCopy($hTree, $hDragItem, TreeItemFromPoint($hTree), $fWhere)
                If $hItem <> 0 Then
                    _GUICtrlTreeView_SelectItem($hTree, $hItem)
                    _GUICtrlTreeView_Delete($hTree, $hDragItem)
                EndIf
            EndIf
        Case $GUI_EVENT_MOUSEMOVE
            If $bTreeDrag = False Then ContinueCase
            Local $tPoint = DllStructCreate("int;int")
            DllStructSetData($tPoint, 1, MouseGetPos(0))
            DllStructSetData($tPoint, 2, MouseGetPos(1))
            Local $hWndPoint = _WinAPI_WindowFromPoint($tPoint)
            ;cancel drag in progress and cleanup if moved outside treeview:
            if $hWndPoint <> $hTree then
                $bTreeDrag = False
                _WinAPI_InvalidateRect($hTree)
                _GUIImageList_Destroy($hTreeDragImage) ;delete drag image
                _SendMessage($hTree, $TVM_SELECTITEM, $TVGN_DROPHILITE, 0) ;remove DropTarget
                _SendMessage($hTree, $TVM_SETINSERTMARK, 0, 0) ;remove InsertMark
                ContinueCase
            EndIf
            $hItemHover = TreeItemFromPoint($hTree)
            If $hItemHover = 0 Then
                ;meh
            Else
                $aRect = _GUICtrlTreeView_DisplayRect($hTree, $hItemHover)
                $iTreeY = _WinAPI_GetMousePosY(True, $hTree)
                Switch $iTreeY
                    Case $aRect[1] To $aRect[1]+Int(($aRect[3]-$aRect[1])/4)
                        _SendMessage($hTree, $TVM_SELECTITEM, $TVGN_DROPHILITE, 0) ;remove DropTarget
                        _SendMessage($hTree, $TVM_SETINSERTMARK, 0, $hItemHover) ;add InsertMark before item
                        $fWhere = -1
                    Case 1+$aRect[1]+Int(($aRect[3]-$aRect[1])/3) To $aRect[1]+Int(($aRect[3]-$aRect[1])*2/3)
                        _SendMessage($hTree, $TVM_SETINSERTMARK, 0, 0) ;remove InsertMark
                        _SendMessage($hTree, $TVM_SELECTITEM, $TVGN_DROPHILITE, $hItemHover) ;add DropTarget
                        $fWhere = 0
                    Case 1+$aRect[1]+Int(($aRect[3]-$aRect[1])*2/3) To $aRect[3]
                        _SendMessage($hTree, $TVM_SELECTITEM, $TVGN_DROPHILITE, 0) ;remove DropTarget
                        _SendMessage($hTree, $TVM_SETINSERTMARK, 1, $hItemHover) ;add InsertMark after item
                        $fWhere = 1
                EndSwitch
            EndIf
            DrawDragImage($hTree, $hTreeDragImage)
    EndSwitch
EndFunc
;   TreeItemFromPoint()
;   Returns handle of tree item under mouse:
Func TreeItemFromPoint($hWnd)
    Local $tMPos = _WinAPI_GetMousePos(True, $hWnd)
    Return _GUICtrlTreeView_HitTestItem($hWnd, DllStructGetData($tMPos, 1), DllStructGetData($tMPos, 2))
EndFunc
;   TreeItemCopy()
;   Copies tree item $hItemSource and all its children to an item $hItemTarget, depending on $fDirection
;   $fDirection:
;           -1 = before $hItemTarget
;           0 = inside $hItemTarget
;           1 = after $hItemTarget
Func TreeItemCopy($hWnd, $hItemSource, $hItemTarget, $fDirection)
    ;making sure parent can't be dropped onto one of its descendants:
    $hTest = $hItemTarget
    Do
        $hTest = _GUICtrlTreeView_GetParentHandle($hWnd, $hTest)
        If $hTest = $hItemSource Then Return 0
    Until $hTest = 0
    ;create new item at determined position
    $sText = _GUICtrlTreeView_GetText($hWnd, $hItemSource)
    $hParent = _GUICtrlTreeView_GetParentHandle($hWnd, $hItemTarget)
    Switch $fDirection
        Case -1
            $hPrev = _GUICtrlTreeView_GetPrevSibling($hWnd, $hItemTarget)
            If $hPrev = 0 Then
                $hNew = _GUICtrlTreeView_AddFirst($hWnd, $hItemTarget, $sText)
            Else
                $hNew = _GUICtrlTreeView_InsertItem($hWnd, $sText, $hParent, $hPrev)
            EndIf
        Case 0
            $hNew = _GUICtrlTreeView_InsertItem($hWnd, $sText, $hItemTarget)
        Case 1
            $hNew = _GUICtrlTreeView_InsertItem($hWnd, $sText, $hParent, $hItemTarget)
        Case Else
            Return 0
    EndSwitch
    ;save item state and checkbox image if there is such
    _GUICtrlTreeView_SetState($hWnd, $hNew, _GUICtrlTreeView_GetState($hWnd, $hItemSource))
    If _GUICtrlTreeView_GetStateImageList($hWnd) <> 0 Then
        _GUICtrlTreeView_SetStateImageIndex($hWnd, $hNew, _GUICtrlTreeView_GetStateImageIndex($hWnd, $hItemSource))
    EndIf
    ;save icon/selected image indexes
    If _GUICtrlTreeView_GetNormalImageList($hWnd) <> 0 Then
        _GUICtrlTreeView_SetImageIndex($hWnd, $hNew, _GUICtrlTreeView_GetImageIndex($hWnd, $hItemSource))
        _GUICtrlTreeView_SetSelectedImageIndex($hWnd, $hNew, _GUICtrlTreeView_GetSelectedImageIndex($hWnd, $hItemSource))
    EndIf
    ;recurse through descendants:
    $iChildCount = _GUICtrlTreeView_GetChildCount($hWnd, $hItemSource)
    If $iChildCount > 0 Then
        For $i = 0 To $iChildCount-1
            $hRecSource = _GUICtrlTreeView_GetItemByIndex($hWnd, $hItemSource, $i)
            TreeItemCopy($hWnd, $hRecSource, $hNew, 0)
        Next
    EndIf
    Return $hNew
EndFunc
Func On_WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    ;wparam = cid, lparam = pnmh
    If $wParam = $cTree Then
        Local $tNMHDR = DllStructCreate("hwnd hTree;int_ptr;int code", $lParam)
        Local $code = DllStructGetData($tNMHDR, "code")
        Local $hTree = HWnd(DllStructGetData($tNMHDR, "hTree"))
        Switch $code
            Case $TVN_BEGINDRAGA, $TVN_BEGINDRAGW
                $bTreeDrag = True
                $hDragItem = TreeItemFromPoint($hTree)
;~              _GUICtrlTreeView_SelectItem($hTree, $hDragItem)
                _GUICtrlTreeView_SetSelected($hTree, _GUICtrlTreeView_GetSelection($hTree), False)
                $hTreeDragImage = TreeCreateDragImage($hTree, $hDragItem)
                DrawDragImage($hTree, $hTreeDragImage)
            Case $TVN_BEGINLABELEDITA, $TVN_BEGINLABELEDITW
                $bTreeEdit = True
;~              $hTreeEdit = _SendMessage($hTree, $TVM_GETEDITCONTROL, 0, 0)
            Case $TVN_ENDLABELEDITA, $TVN_ENDLABELEDITW
                $bTreeEdit = False
                Return 1
            Case $TVN_SELCHANGEDA, $TVN_SELCHANGEDW
                Local $hSel = _GUICtrlTreeView_GetSelection($hTree)
;               Local $tNMTREEVIEW = DllStructCreate($tagNMTREEVIEW, $lParam)
;               Local $hSel = DllStructGetData($tNMTREEVIEW, "NewhItem")
                Local $sTxt = "Selected: " & _GUICtrlTreeView_GetText($hTree, $hSel) & " (item handle " & $hSel & ")"
                GUICtrlSetData($label2, $sTxt)
            Case Else
        EndSwitch
        ;
    EndIf
EndFunc
Func KeyPressed($iHexKey)
    Local $aRet = DllCall('user32.dll', "int", "GetAsyncKeyState", "int", $iHexKey)
;~  If BitAND($aRet[0], 0x8000) Or BitAND($aRet[0], 1) Then Return 1
    If BitAND($aRet[0], 1) Then Return 1
    Return 0
EndFunc
;Func TreeKeyboardFunc($cID)
;   Local $hWnd = GUICtrlGetHandle($cID)
;   If $bTreeDrag Then Return
;   If $bTreeEdit Then
;       If KeyPressed(0x0d) Then _SendMessage($hWnd, $TVM_ENDEDITLABELNOW, 0, 0) ;enter
;       If KeyPressed(0x1b) Then _SendMessage($hWnd, $TVM_ENDEDITLABELNOW, 1, 0) ;esc
;   EndIf
;   Local $aRet = DllCall('user32.dll', 'hwnd', 'GetFocus')
;   If $aRet[0] = $hWnd Then
;       If KeyPressed(0x2d) Then _GUICtrlTreeView_Add($hWnd, _GUICtrlTreeView_GetSelection($hWnd), "New Item") ;insert
;       If KeyPressed(0x2e) Then _GUICtrlTreeView_Delete($hWnd, _GUICtrlTreeView_GetSelection($hWnd)) ;delete
;       If KeyPressed(0x0d) Then _SendMessage($hWnd, $TVM_EDITLABEL, 0, _GUICtrlTreeView_GetSelection($hWnd)) ;enter
;   EndIf
;EndFunc
Func TreeCreateDragImage($hWnd, $hItem)
    ;if treeview has imagelist, use image from it
    If _GUICtrlTreeView_GetNormalImageList($hWnd) <> 0 Then Return _GUICtrlTreeView_CreateDragImage($hWnd, $hItem)
    ;if not, create a bitmap of dragitem's text rectangle and put it into imagelist.
    Local $aItemRect = _GUICtrlTreeView_DisplayRect($hWnd, $hItem, True)
    Local $iImgW = $aItemRect[2]-$aItemRect[0]
    Local $iImgH = $aItemRect[3]-$aItemRect[1]
    Local $hTreeDC = _WinAPI_GetDC($hWnd)
    Local $hMemDC = _WinAPI_CreateCompatibleDC($hTreeDC)
    Local $hMemBmp = _WinAPI_CreateCompatibleBitmap($hTreeDC, $iImgW, $iImgH)
    Local $hMemBmpOld = _WinAPI_SelectObject($hMemDC, $hMemBmp)
    _WinAPI_BitBlt($hMemDC, 0, 0, $iImgW, $iImgH, $hTreeDC, $aItemRect[0], $aItemRect[1], $SRCCOPY)
    _WinAPI_SelectObject($hMemDC, $hMemBmpOld)
    _WinAPI_ReleaseDC($hWnd, $hTreeDC)
    _WinAPI_DeleteDC($hMemDC)
    Local $hImgList = _GUIImageList_Create($iImgW, $iImgH, 6)
    _GUIImageList_Add($hImgList, $hMemBmp)
    _WinAPI_DeleteObject($hMemBmp)
    Return $hImgList
EndFunc
; Draw drag image
; by Gary Frost (gafrost) (?)
Func DrawDragImage(ByRef $hControl, ByRef $aDrag)
    Local $tPoint, $hDC
    $hDC = _WinAPI_GetWindowDC($hControl)
    $tPoint = _WinAPI_GetMousePos(True, $hControl)
    _WinAPI_InvalidateRect($hControl)
    _GUIImageList_Draw($aDrag, 0, $hDC, DllStructGetData($tPoint, "X")-10, DllStructGetData($tPoint, "Y")-8)
    _WinAPI_ReleaseDC($hControl, $hDC)
EndFunc   ;==>DrawDragImage
Edited by rexx

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×