Jump to content

TreeView struct not working with x64 directive


Recommended Posts

  • Moderators

Hi all,

Please ignore this post - the problem was elsewhere - see my later post in this thread.

It appears that the rather large struct I have been using within the WM_NOTIFY handler of my ChooseFileFolder UDF  (and which took so long to design with the help of guinness) does not function correctly when the #AutoIt3Wrapper_UseX64=y directive is used within the script on x64 systems. I have only just got an x64 system to play with and so was previously unable to determine the cause of a couple of complaints about the UDF - everything works fine without the directive and on x32 systems.

Here is the struct itself and the various data elements taken from it:

; Create NMTREEVIEW structure
Local $tStruct = DllStructCreate("struct;hwnd hWndFrom;uint_ptr IDFrom;INT Code;endstruct;" & _
        "uint Action;struct;uint OldMask;handle OldhItem;uint OldState;uint OldStateMask;" & _
        "ptr OldText;int OldTextMax;int OldImage;int OldSelectedImage;int OldChildren;lparam OldParam;endstruct;" & _
        "struct;uint NewMask;handle NewhItem;uint NewState;uint NewStateMask;" & _
        "ptr NewText;int NewTextMax;int NewImage;int NewSelectedImage;int NewChildren;lparam NewParam;endstruct;" & _
        "struct;long PointX;long PointY;endstruct", $lParam)
Local $hWndFrom = DllStructGetData($tStruct, "hWndFrom")
Local $hItem = DllStructGetData($tStruct, "NewhItem")
Local $iCode = DllStructGetData($tStruct, "Code")

In particular the NewhItem element is not returning the correct value - usually returning either the handle of the top element of the TreeView or 0.

I would be most grateful if someone could point me towards how to get the !#$£*? thing working when the Autoit3Wrapper directive is set.

M23

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

I can confirm something isn't looking right 

I just did a switch from #AutoIt3Wrapper_UseX64=n to y and everything worked 

then switched back from "y" to "n" and got jinxed with the same thing as mentioned here

And cannot get it to work either ways switching, maybe something gets mistakenly saved into Scite's Settings or something alike .. 

I'm not going to debug this matter as i'm doing other stuff

I'm sure its resolvable, for anyone wanting to try this out :
try running some examples of ChooseFileFolder UDF maybe you will be lucky to reproduce this

Deye

Link to comment
Share on other sites

To all,

I take my above post back: 

,.. when i was testing and suggesting this I had something else in place which made the expanding part break exactly as described   :surprise:

another one is that the user is probably not using  the correct syntax for X64  or for x32

#AutoIt3Wrapper_OutFile_X64=My.exe
#AutoIt3Wrapper_UseX64=y

 all works here for me.   

  not sure about whats happening on 32bit machines ..

eye

Link to comment
Share on other sites

 

Hello What a beautiful question, Initially I thought it was a data alignment problem. But after many tests I have the problem. The problem is IsHWnd. It would seem that this is not the problem but it is. Probably we have all been using this function without being aware of its internal structure. Or perhaps we are very used to using it for any data of handle type. That's where the problem lies. We says IsHWnd (SomeHandle) but we do not worry about the true data type, in this case the handle returned by NMTREEVIEW-> NewhItem will not match. 

You also need to check inside _GUICtrlTreeView_GetItemHandle It sometimes make all work as we would expect due to same issue with IsHWnd.

So You structure is correctly. 

 

Here is an Example where you can check the IsHwnd is not working as we expect.

 

#AutoIt3Wrapper_UseX64=y
#include <GUIConstantsEx.au3>
#include <GuiTreeView.au3>
#include <MsgBoxConstants.au3>
#include <WindowsConstants.au3>

Example()

Func Example()
    Local $idItem, $idTreeView
    Local $iStyle = BitOR($TVS_EDITLABELS, $TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS, $TVS_CHECKBOXES)

    GUICreate("TreeView Get First Item", 400, 300)

    $idTreeView = GUICtrlCreateTreeView(2, 2, 396, 268, $iStyle, $WS_EX_CLIENTEDGE)
    GUISetState(@SW_SHOW)

    _GUICtrlTreeView_BeginUpdate($idTreeview)
    For $x = 1 To 10
        $idItem = GUICtrlCreateTreeViewItem(StringFormat("[%02d] New Item", $x), $idTreeView)
    Next
    _GUICtrlTreeView_EndUpdate($idTreeview)


    Local $hItem = _GUICtrlTreeView_GetFirstItem($idTreeview)
    Local $sText = ""
    Local $hItem7=0

    ;sometimes show correct values sometimes no. same IsHWnd issue.
    For $i = 0 To _GUICtrlTreeView_GetCount($idTreeview) - 1
        $sText = _GUICtrlTreeView_GetText(($idTreeview), $hItem)
        ConsoleWrite($sText & @TAB & @TAB & @TAB & $hItem & @CRLF)
        $hItem = _GUICtrlTreeView_GetNext(($idTreeview), $hItem)
        If $i=5 Then $hItem7=$hItem
    Next


    Local $tStruct = DllStructCreate("handle item")
    DllStructSetData($tStruct, 1, $hItem7)
    Local $hItem = DllStructGetData($tStruct, 1)

    If Not IsHWnd($hItem) Then
            MsgBox(0, "I'm not a Window Handle :(", "TreeView Item Handle: " & $hItem &  @CRLF & "IsHWnd(" & $hItem & ")=" & IsHWnd($hItem) & @CRLF & _
            "Value 7: " & _GUICtrlTreeView_GetText($idTreeview, $hItem) & @CRLF & @CRLF & _
            "The Value must be wrong sometimes. " & @CRLF &  @CRLF &  "Make sure to run many times to get the issue." & @CRLF)
    Else
            MsgBox(0, "this will not be shown", $hItem & @CRLF & "Value: " & _GUICtrlTreeView_GetText($idTreeview, $hItem))
    EndIf

    ; Loop until the user exits.
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    GUIDelete()
EndFunc   ;==>Example

 

Here is a example removing IsWnd verification of _GUICtrlTreeView_GetText2 that makes work all right.

#AutoIt3Wrapper_UseX64=y
#include <GUIConstantsEx.au3>
#include <GuiImageList.au3>
#include <GuiTreeView.au3>
#include <MsgBoxConstants.au3>
#include <WindowsConstants.au3>

Global $g_hImage, $g_hStateImage

Example()

Func Example()
    Local $ahItem[10], $aidChildItem[30], $iYItem = 0, $iRand, $idTreeView
    Local $iStyle = BitOR($TVS_EDITLABELS, $TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS, $TVS_CHECKBOXES)

    GUICreate("TreeView Get Text", 400, 300)

    $idTreeView = GUICtrlCreateTreeView(2, 2, 396, 268, $iStyle, $WS_EX_CLIENTEDGE)
    GUISetState(@SW_SHOW)



    _GUICtrlTreeView_BeginUpdate($idTreeView)
    For $x = 0 To 9
        $ahItem[$x] = _GUICtrlTreeView_Add($idTreeView, 0, StringFormat("[%02d] New Item", $x), 4, 5)
    Next
    _GUICtrlTreeView_EndUpdate($idTreeView)

    _GUICtrlTreeView_SelectItem($idTreeView, $ahItem[0])
    _GUICtrlTreeView_SetStateImageIndex($idTreeView, $ahItem[0], 2)

    Local $iRand = 7
    MsgBox($MB_SYSTEMMODAL, "It Fails sometimes", StringFormat("Text for Item %d: \n %-40s", $iRand, _GUICtrlTreeView_GetText($idTreeView, $ahItem[$iRand])))
    MsgBox($MB_SYSTEMMODAL, "This Always Fine", StringFormat("Text for Item %d: \n %-40s", $iRand, _GUICtrlTreeView_GetText2($idTreeView, $ahItem[$iRand])))

    ; Loop until the user exits.
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    GUIDelete()
EndFunc   ;==>Example

Func _GUICtrlTreeView_GetText2($hWnd, $hItem = 0)
;~  If Not IsHWnd($hItem) Then $hItem = _GUICtrlTreeView_GetItemHandle($hWnd, $hItem) ;remove this to make work all correctly
    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)

    If $hItem = 0x00000000 Then Return SetError(1, 1, "")

    Local $tTVITEM = DllStructCreate($tagTVITEMEX)
    Local $tText
    Local $bUnicode = _GUICtrlTreeView_GetUnicodeFormat($hWnd)
    If $bUnicode Then
        $tText = DllStructCreate("wchar Buffer[4096]") ; create a text 'area' for receiving the text
    Else
        $tText = DllStructCreate("char Buffer[4096]") ; create a text 'area' for receiving the text
    EndIf

    DllStructSetData($tTVITEM, "Mask", $TVIF_TEXT)
    DllStructSetData($tTVITEM, "hItem", $hItem)
    DllStructSetData($tTVITEM, "TextMax", 4096)

    If _WinAPI_InProcess($hWnd, $__g_hTVLastWnd) Then
        DllStructSetData($tTVITEM, "Text", DllStructGetPtr($tText))
        _SendMessage($hWnd, $TVM_GETITEMW, 0, $tTVITEM, 0, "wparam", "struct*")
    Else
        Local $iItem = DllStructGetSize($tTVITEM)
        Local $tMemMap
        Local $pMemory = _MemInit($hWnd, $iItem + 4096, $tMemMap)
        Local $pText = $pMemory + $iItem
        DllStructSetData($tTVITEM, "Text", $pText)
        _MemWrite($tMemMap, $tTVITEM, $pMemory, $iItem)
        If $bUnicode Then
            _SendMessage($hWnd, $TVM_GETITEMW, 0, $pMemory, 0, "wparam", "ptr")
        Else
            _SendMessage($hWnd, $TVM_GETITEMA, 0, $pMemory, 0, "wparam", "ptr")
        EndIf
        _MemRead($tMemMap, $pText, $tText, 4096)
        _MemFree($tMemMap)
    EndIf

    Return DllStructGetData($tText, "Buffer")
EndFunc   ;==>_GUICtrlTreeView_GetText

 

Saludos

 

 

Link to comment
Share on other sites

    I   didn't test but I think it is all coming from  __GUICtrlTreeView_AddItem($hWnd  
    
    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
    
    should go in before starting off this point
 

        Local $hItem, $hItemID = 0
    If $hRelative <> 0x00000000 Then
        Switch $iMethod
            Case $TVNA_ADD, $TVNA_ADDFIRST
                $hItem = _GUICtrlTreeView_GetParentHandle($hWnd, $hRelative)

 

    might as well be the struct to blame (none specific ..) for needing to have in all the functions  these validations ..

Deye

Link to comment
Share on other sites

  • Moderators

Hi,

After a LOT of detective work I have got to the bottom of the problem - in fact there were 2 points of failure (that I have discovered so far!):

- 1. I was using GUICtrlSendToDummy to pass the handle of the element to expand from the message handler to the code which did all the work - it appears this is limited to 32 bits and so the 64bit handle was not correctly passed. Simple to workaround - use a Global variable to hold the handle instead.

- 2. The second is more difficult to fix. It seems _GUICtrlTreeView_DisplayRectEx does not like x64 handles either, but as yet I have not found a solution as it requires the handle of the item .

Thanks to the responders above - I will keep the thread updated with any new information.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

I was checking deeply. and I've noticed that _GUICtrlTreeView_GetItemHandle has an issue exactly in GUICtrlGetHandle because sometimes it returns a value where it should not return a value. (Just fail in x64 compiled version) But all this could be avoided with my first answer because it's related to the way of using IsHWnd. anyway the solution should be rewrite _GUICtrlTreeView_GetItemHandle.

 

About _GUICtrlTreeView_DisplayRectEx You just need to write a handle to the Rect structure. of course it need to be inside of  _GUICtrlTreeView_DisplayRectEx 

 

You can't write the x64 handle to the Rect structure due it use long types so you get your x64 value casted.

But you can overwrite first two members this way.

    Local $tHandle=DllStructCreate("handle hItem",DllStructGetPtr($tRECT))
        DllStructSetData($tHandle, "hItem", $hItem)

 

PD: Sorry for not using sintaxis highlighter my slow connection is unable to load the feature.

Saludos

 

 

 

 

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...