Sign in to follow this  
Followers 0
quaizywabbit

listbox client area error

12 posts in this topic

#1 ·  Posted (edited)

Ive tried the LBItemfromPt( ) in comctl32.dll as well as _SendMessage($Hlb, $LB_ITEMFROMPOINT, 0, $Point) where $Hlb is the hwnd to the listbox.

The $Point structure coordinates used are originally screen coordinates, and ive converted them to client coordinates, as well as window coordinates, but in any case both functions return minus 1 ( not in the client area ) instead of the index.

why this is so, Ive no clue whatsoever...........

EDIT: got it to return index using SendMessage()

Edited by quaizywabbit

[u]Do more with pre-existing apps![/u]ANYGUIv2.8

Share this post


Link to post
Share on other sites



Why is this in Bugs Reports?

I believe the listbox is incorrectly responding to both of these function calls.

I am using the lastest Beta, and XPPro service Pack 2


[u]Do more with pre-existing apps![/u]ANYGUIv2.8

Share this post


Link to post
Share on other sites

This forum is for AutoIt bugs. You are using the function wrong; this is not a problem with AutoIt.

The function expects screen coordinates.

pt

POINT structure that contains the screen coordinates to check.

Share this post


Link to post
Share on other sites

This forum is for AutoIt bugs. You are using the function wrong; this is not a problem with AutoIt.

The function expects screen coordinates.

I added the ScreenToClient functon after it failed with the original screen coordinates. In fact, I've tried every possible combination.

I'm more than happy to be proved wrong on this. If I did it wrong, please post an example of how you got either function to return an Index instead of -1 everytime.


[u]Do more with pre-existing apps![/u]ANYGUIv2.8

Share this post


Link to post
Share on other sites

You are passing a ptr to POINT not POINT itself.

NOBUG.

PS Your subject is more and help&support one :P

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

You are passing a ptr to POINT not POINT itself.

NOBUG.

PS Your subject is more and help&support one :P

How do i pass $Point as you describe?

I have solved getting SendMessage() to return the index....

But I am still interested how to call LBItemFromPt() in Comctl32.dll properly passing the $Point via DllCall()

Edited by quaizywabbit

[u]Do more with pre-existing apps![/u]ANYGUIv2.8

Share this post


Link to post
Share on other sites

How do i pass $Point as you describe?

I have solved getting SendMessage() to return the index....

But I am still interested how to call LBItemFromPt() in Comctl32.dll properly passing the $Point via DllCall()

From the A3LListBox file in Auto3Lib:

; =================================================================================================
; Description ..: Retrieves the zero based index of the item nearest the specified point in a list box
; Parameters ...: $hWnd         - Handle to control
;                 $iX           - X coordinate, relative to the upper-left corner of the client area
;                 $iY           - Y coordinate, relative to the upper-left corner of the client area
; Return values : The index of the nearest item or -1 if the point is outside of the client area
; =================================================================================================
Func _Listbox_ItemFromPoint($hWnd, $iX, $iY)
  Local $iResult

  $iResult = _SendMessage($hWnd, $LB_ITEMFROMPOINT, 0, _MakeLong($iX, $iY))
  if _HiWord($iResult) = 0 then
    Return $iResult
  else
    Return -1
  endif
EndFuncoÝ÷ ØZèØ^r˺گ'âè§ëhܸjëh×6; =================================================================================================
; Description ..: Returns an longint value from two int values
; Parameters ...: $iLo          - Low word
;                 $iHi          - Hi word
; Return values : Longint value
; =================================================================================================
Func _MakeLong($iLo, $iHi)
  Return BitOR(BitShift($iHi, -16), BitAND($iLo, 0xFFFF))
EndFunc

; =================================================================================================
; Description ..: Returns the high word of a longword
; Parameters ...: $iLong        - Longword value
; Return values : High order word of the longword value
; =================================================================================================
Func _HiWord($iLong)
  Return BitShift($iLong, 16)
EndFunc

Auto3Lib: A library of over 1200 functions for AutoIt

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

Thanks PaulIA, I had already found the MakeLong() function.......

Would you happen to know how to call LBItemFromPt() in ComCtl32.dll using DllCall ??

apparently it doesn't use a ptr to the Point Struct, but the struct itself (somehow)

Solved SendMessage() returning Index (Updated Script---> see 1st post )

Edited by quaizywabbit

[u]Do more with pre-existing apps![/u]ANYGUIv2.8

Share this post


Link to post
Share on other sites

Thanks PaulIA, I had already found the MakeLong() function.......

Would you happen to know how to call LBItemFromPt() in ComCtl32.dll using DllCall ??

apparently it doesn't use a ptr to the Point Struct, but the struct itself (somehow)

Solved SendMessage() returning Index (Updated Script---> see 1st post )

Here is your script using the DllCall:

CODE
#include "guiconstants.au3"
#include "guilist.au3"
#include <Misc.au3>
;Opt("MouseCoordMode", 2)
#region Constants
;'Windows API Constants
Global Const $DRAGLISTMSGSTRING = "commctrl_DragListMsg" & Chr(0)
Global Const $DL_BEGINDRAG = ($WM_USER + 133)
Global Const $DL_DRAGGING = ($WM_USER + 134)
Global Const $DL_DROPPED = ($WM_USER + 135)
Global Const $DL_CANCELDRAG = ($WM_USER + 136)

Global Const $LB_ITEMFROMPOINT = 0x1A9

#endregion
#region Vars
Dim $Parent; hwnd of parent window where draglist is located
Dim $Hlb; handle to list control modified by MakeDraglist() function
Dim $nItem; item where to place insert image next to
#endregion
#region Structs
#comments-start
    typedef struct {
    UINT uNotification;
    HWND hWnd;
    POINT ptCursor;
    } DRAGLISTINFO, *LPDRAGLISTINFO;
#comments-end
;Dim $Point = DllStructCreate("int;int")
;dim $DraglistInfo = DllStructCreate("uint;uint",$Point)
#endregion
#region Func's
Func DrawInsert( $Parent, $Hlb, $nItem)
    $r = DllCall("comctl32.dll", "int", "DrawInsert", "hwnd", $Parent, "hwnd", $Hlb, "int", $nItem)
    Return $r[0]
EndFunc
Func Makedraglist($hwnd)
    If Not IsHwnd($hwnd) Then $hwnd = Hwnd($hwnd)
    Local $r = DllCall("comctl32.dll", "int", "MakeDragList","hwnd",$hwnd);$r is 0 if unsucccesful
    Return $r[0]
EndFunc
#cs
    int LBItemFromPt(          HWND hLB,
    POINT pt,
    BOOL bAutoScroll
    );
#ce
Func LBItemFromPt( $Hlb, $Point, $autoscroll = 0)
    ;Return _SendMessage($Hlb, $LB_ITEMFROMPOINT, 0, $Point)
    ;Return Value
;The return value contains the index of the nearest item in the low-order word.
;The high-order word is zero if the specified point is in the client area of the list box,
;or one if it is outside the client area.>>>Note. this call to sendmessage always results in the same number<<<
$x=DllStructGetData($Point, 1)
$y=DllStructGetData($Point, 2)
;   $r = DllCall("comctl32.dll", "int", "LBItemFromPt", "hwnd", $Hlb, "ptr", $Point,  "int", $autoscroll)
    $r = DllCall("comctl32.dll", "int", "LBItemFromPt", "hwnd", $Hlb, "int", $x, "int", $y,  "int", $autoscroll)
    ConsoleWrite("ItemFromPt: x: " & $x & " y: " & $y & " Error: " & @Error & " Result: " & $r[0] & @CR)
    Return $r[0]

EndFunc

Func _ResetScreen($TargethWnd)
    Const $SWP_NOMOVE = 0x0002, $SWP_NOSIZE = 0x0001, $SWP_NOZORDER = 0x0004, $SWP_FRAMECHANGED = 0x0020 ;from Winuser.h
    DllCall("user32.dll", "long", "SetWindowPos", "hwnd", $TargethWnd, "hwnd", $TargethWnd, "int", 0, "int", 0, "int", 0, "int", 0, _
            "long", BitOR($SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOZORDER, $SWP_FRAMECHANGED))
EndFunc

#endregion
#region Main
$Parent = GUICreate("draglist test")
$list = GUICtrlCreateList("my draglist", 40, -1, Default, Default)
$label = GUICtrlCreateLabel("" ,30, 200,100, 40 )
GUISetState (@SW_SHOW)
$Hlb = ControlGetHandle($Parent,"",$list)
GUICtrlSetData($list, "you|me|them|us")
GUISetState (@SW_SHOW)       ; will display an empty dialog box
Makedraglist($Hlb)
$draglistmessage = DllCall("user32.dll", "int", "RegisterWindowMessage", "str", $DRAGLISTMSGSTRING)
;MsgBox(0, "",($draglistmessage[0]))
$x = GUIRegisterMsg(($draglistmessage[0]), "MyDraglistHandler")
;MsgBox(0, "guiregmssge", $x)
; Run the GUI until the dialog is closed
While 1
    Dim $msg = GUIGetMsg()


    If $msg = $GUI_EVENT_CLOSE Then ExitLoop

Wend
#cs from msdn:
    The wParam parameter of the drag list message is the control identifier for the drag list box.
    The lParam parameter is the address of a DRAGLISTINFO structure,
    which contains the notification code for the drag event and other information.
    The return value of the message depends on the notification
#ce
Func MyDraglistHandler($hwnd, $msg, $wParam, $lParam)
    ;Opt("MouseCoordMode", 2)
    $nID = BitAND($wParam, 0x0000FFFF)
    If $nID = $list Then
        Local $DraglistInfo = DllStructCreate("uint;hwnd;int;int",$lParam)
        $nNotifyCode = (DllStructGetData($DraglistInfo,1))
        $Hlb = DllStructGetData($DraglistInfo, 2)
        ;if not IsHWnd($Hlb) then ConsoleWrite("control hwnd invalid")
        dim $chwnd = ControlGetHandle($Parent, "", $list)
;       $Point = _MakeWord(DllStructGetData($DraglistInfo, 3), DllStructGetData($DraglistInfo, 4))
        $Point = DllStructCreate("int;int")
        DllStructSetData($Point,1, DllStructGetData($DraglistInfo, 3))
        DllStructSetData($Point,2, DllStructGetData($DraglistInfo, 4))
;       DllCall("User32.dll", "int", "ScreenToClient", "hwnd", $chwnd, "ptr", DllStructGetPtr($Point))
;       ConsoleWrite("$Point1: " & DllStructGetData($Point,1) & @LF)
;       ConsoleWrite("$Point2: " & DllStructGetData($Point,2) & @LF)
;       ConsoleWrite($chwnd & "  " & "0x"&Hex($Hlb) & @LF)
        Select
            Case $nNotifyCode = $DL_BEGINDRAG

                $dragIdx = LBItemFromPt($chwnd, $Point)
                ;reset screen here
                ;return something
;               ConsoleWrite("$DRAGIDX =" & $dragIdx & @LF)
;               ConsoleWrite("begin drag" & @LF)
                Return True
            Case $nNotifyCode = $DL_CANCELDRAG
                ;reset screen here
                ;return something
                ConsoleWrite("drag canceled")
            Case $nNotifyCode = $DL_DRAGGING
                $dragIdto = LBItemFromPt($chwnd, $Point)
                DrawInsert($Parent, $chwnd, $dragIdto)
                ConsoleWrite("dragging" & @LF & "Dragidto = " & $dragIdto & @LF)
                ;return something
            Case $nNotifyCode = $DL_DROPPED
                ;reset screen here
                ;If LBItemFromPt($Hlb, $Pointx) <> $dragIdx Then
                ConsoleWrite("ok  Dl_Dropped" & @LF)
                ;do something with it
                ;EndIf
            Case Else
                Return $GUI_RUNDEFMSG
        EndSelect
        $Point = 0

    EndIf
EndFunc   ;==>MyDraglistHandler

Func _MakeWord($LoByte, $HiByte)
    Return BitOR($LoByte, 0x100 * $HiByte)
EndFunc   ;==>_MakeWord

Auto3Lib: A library of over 1200 functions for AutoIt

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Here is your script using the DllCall:

CODE
#include "guiconstants.au3"
#include "guilist.au3"
#include <Misc.au3>
;Opt("MouseCoordMode", 2)
#region Constants
;'Windows API Constants
Global Const $DRAGLISTMSGSTRING = "commctrl_DragListMsg" & Chr(0)
Global Const $DL_BEGINDRAG = ($WM_USER + 133)
Global Const $DL_DRAGGING = ($WM_USER + 134)
Global Const $DL_DROPPED = ($WM_USER + 135)
Global Const $DL_CANCELDRAG = ($WM_USER + 136)

Global Const $LB_ITEMFROMPOINT = 0x1A9

#endregion
#region Vars
Dim $Parent; hwnd of parent window where draglist is located
Dim $Hlb; handle to list control modified by MakeDraglist() function
Dim $nItem; item where to place insert image next to
#endregion
#region Structs
#comments-start
    typedef struct {
    UINT uNotification;
    HWND hWnd;
    POINT ptCursor;
    } DRAGLISTINFO, *LPDRAGLISTINFO;
#comments-end
;Dim $Point = DllStructCreate("int;int")
;dim $DraglistInfo = DllStructCreate("uint;uint",$Point)
#endregion
#region Func's
Func DrawInsert( $Parent, $Hlb, $nItem)
    $r = DllCall("comctl32.dll", "int", "DrawInsert", "hwnd", $Parent, "hwnd", $Hlb, "int", $nItem)
    Return $r[0]
EndFunc
Func Makedraglist($hwnd)
    If Not IsHwnd($hwnd) Then $hwnd = Hwnd($hwnd)
    Local $r = DllCall("comctl32.dll", "int", "MakeDragList","hwnd",$hwnd);$r is 0 if unsucccesful
    Return $r[0]
EndFunc
#cs
    int LBItemFromPt(          HWND hLB,
    POINT pt,
    BOOL bAutoScroll
    );
#ce
Func LBItemFromPt( $Hlb, $Point, $autoscroll = 0)
    ;Return _SendMessage($Hlb, $LB_ITEMFROMPOINT, 0, $Point)
    ;Return Value
;The return value contains the index of the nearest item in the low-order word.
;The high-order word is zero if the specified point is in the client area of the list box,
;or one if it is outside the client area.>>>Note. this call to sendmessage always results in the same number<<<
$x=DllStructGetData($Point, 1)
$y=DllStructGetData($Point, 2)
;   $r = DllCall("comctl32.dll", "int", "LBItemFromPt", "hwnd", $Hlb, "ptr", $Point,  "int", $autoscroll)
    $r = DllCall("comctl32.dll", "int", "LBItemFromPt", "hwnd", $Hlb, "int", $x, "int", $y,  "int", $autoscroll)
    ConsoleWrite("ItemFromPt: x: " & $x & " y: " & $y & " Error: " & @Error & " Result: " & $r[0] & @CR)
    Return $r[0]

EndFunc

Func _ResetScreen($TargethWnd)
    Const $SWP_NOMOVE = 0x0002, $SWP_NOSIZE = 0x0001, $SWP_NOZORDER = 0x0004, $SWP_FRAMECHANGED = 0x0020 ;from Winuser.h
    DllCall("user32.dll", "long", "SetWindowPos", "hwnd", $TargethWnd, "hwnd", $TargethWnd, "int", 0, "int", 0, "int", 0, "int", 0, _
            "long", BitOR($SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOZORDER, $SWP_FRAMECHANGED))
EndFunc

#endregion
#region Main
$Parent = GUICreate("draglist test")
$list = GUICtrlCreateList("my draglist", 40, -1, Default, Default)
$label = GUICtrlCreateLabel("" ,30, 200,100, 40 )
GUISetState (@SW_SHOW)
$Hlb = ControlGetHandle($Parent,"",$list)
GUICtrlSetData($list, "you|me|them|us")
GUISetState (@SW_SHOW)       ; will display an empty dialog box
Makedraglist($Hlb)
$draglistmessage = DllCall("user32.dll", "int", "RegisterWindowMessage", "str", $DRAGLISTMSGSTRING)
;MsgBox(0, "",($draglistmessage[0]))
$x = GUIRegisterMsg(($draglistmessage[0]), "MyDraglistHandler")
;MsgBox(0, "guiregmssge", $x)
; Run the GUI until the dialog is closed
While 1
    Dim $msg = GUIGetMsg()


    If $msg = $GUI_EVENT_CLOSE Then ExitLoop

Wend
#cs from msdn:
    The wParam parameter of the drag list message is the control identifier for the drag list box.
    The lParam parameter is the address of a DRAGLISTINFO structure,
    which contains the notification code for the drag event and other information.
    The return value of the message depends on the notification
#ce
Func MyDraglistHandler($hwnd, $msg, $wParam, $lParam)
    ;Opt("MouseCoordMode", 2)
    $nID = BitAND($wParam, 0x0000FFFF)
    If $nID = $list Then
        Local $DraglistInfo = DllStructCreate("uint;hwnd;int;int",$lParam)
        $nNotifyCode = (DllStructGetData($DraglistInfo,1))
        $Hlb = DllStructGetData($DraglistInfo, 2)
        ;if not IsHWnd($Hlb) then ConsoleWrite("control hwnd invalid")
        dim $chwnd = ControlGetHandle($Parent, "", $list)
;      $Point = _MakeWord(DllStructGetData($DraglistInfo, 3), DllStructGetData($DraglistInfo, 4))
        $Point = DllStructCreate("int;int")
        DllStructSetData($Point,1, DllStructGetData($DraglistInfo, 3))
        DllStructSetData($Point,2, DllStructGetData($DraglistInfo, 4))
;      DllCall("User32.dll", "int", "ScreenToClient", "hwnd", $chwnd, "ptr", DllStructGetPtr($Point))
;      ConsoleWrite("$Point1: " & DllStructGetData($Point,1) & @LF)
;      ConsoleWrite("$Point2: " & DllStructGetData($Point,2) & @LF)
;      ConsoleWrite($chwnd & "  " & "0x"&Hex($Hlb) & @LF)
        Select
            Case $nNotifyCode = $DL_BEGINDRAG

                $dragIdx = LBItemFromPt($chwnd, $Point)
                ;reset screen here
                ;return something
;            ConsoleWrite("$DRAGIDX =" & $dragIdx & @LF)
;            ConsoleWrite("begin drag" & @LF)
                Return True
            Case $nNotifyCode = $DL_CANCELDRAG
                ;reset screen here
                ;return something
                ConsoleWrite("drag canceled")
            Case $nNotifyCode = $DL_DRAGGING
                $dragIdto = LBItemFromPt($chwnd, $Point)
                DrawInsert($Parent, $chwnd, $dragIdto)
                ConsoleWrite("dragging" & @LF & "Dragidto = " & $dragIdto & @LF)
                ;return something
            Case $nNotifyCode = $DL_DROPPED
                ;reset screen here
                ;If LBItemFromPt($Hlb, $Pointx) <> $dragIdx Then
                ConsoleWrite("ok  Dl_Dropped" & @LF)
                ;do something with it
                ;EndIf
            Case Else
                Return $GUI_RUNDEFMSG
        EndSelect
        $Point = 0

    EndIf
EndFunc   ;==>MyDraglistHandler

Func _MakeWord($LoByte, $HiByte)
    Return BitOR($LoByte, 0x100 * $HiByte)
EndFunc   ;==>_MakeWord
Thanks so much Paul!

Here's a working version of a DragListBox:

still have a few things to add like changing cursors from arrow to hand )and back, as well as to the NOTALLOWED when out of range.....

Edited by quaizywabbit

[u]Do more with pre-existing apps![/u]ANYGUIv2.8

Share this post


Link to post
Share on other sites

Masterful work!

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  
Followers 0