Guy_

Can _WM_COMMAND check for a dynamic amount of ListBoxes?

6 posts in this topic

#1 ·  Posted (edited)

This is not a working example -- I'm asking about the principle...

Here we have the often seen code to detect a double-click on an item in one ListBox (ID in $idListBox is of course created by other code).
To catch that ListBox item, I have only added $sBookmark to it. This could be a pick list application.

$idListBox = 0x004A0FB0

GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND")

Func _WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg
    Local   $hWndFrom, $iIDFrom, $iCode, $hWndListBox, _
            $sBookmark

    If Not IsHWnd($idListBox) Then $hWndListBox = GUICtrlGetHandle($idListBox)
    
    $hWndFrom   = $lParam
    $iIDFrom    = BitAND($wParam, 0xFFFF)                                       ; Low Word
    $iCode      = BitShift($wParam, 16)                                         ; Hi Word

    Switch $hWndFrom

        Case $idListBox, $hWndListBox

                $sBookmark = _GUICtrlListBox_GetText( $hWndFrom, _GUICtrlListBox_GetCurSel($hWndFrom) )

                Switch $iCode

                    Case $LBN_DBLCLK

                        ConsoleWrite("you double-clicked " & $sBookmark & @CRLF)

                EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG

EndFunc

 

Now, my question is: can one modify the _WM_COMMAND function to allow for a dynamic number of ListBoxes? (meaning, user-defined -- the amount of ListBoxes/pick lists can change at any time).

Let's assume I dynamically obtained an array with ListBox ID's for (in this case) 5 pick lists:

UxaCpwj.png

One part of the solution seems to work with the For... Next loop I added below, but I'm wondering if that is the ultimate? (knowing this Func has to be as fast as possible)

The part where I can't find anything that works for a dynamic amount of ListBox ID's is in the Case check...

I tried _ArrayToTxt($aIdListBox, ", ", 1), messed with Eval(), and trying Case $aIdListBox[start] To $aIdListBox[end]

 

Func _WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg
    Local   $hWndFrom, $iIDFrom, $iCode, $hWndListBox, _
            $sBookmark

    For $i = 1 To UBound($aIdListBox) - 1                       ; is this solution fast enough? (it seems to work well)
        If Not IsHWnd($aIdListBox[$i]) Then
            $hWndListBox = GUICtrlGetHandle($aIdListBox[$i])
            ExitLoop                                            ; cause there can only be one hit(?)
        EndIf
    Next

    $hWndFrom   = $lParam
    $iIDFrom    = BitAND($wParam, 0xFFFF)                       ; Low Word
    $iCode      = BitShift($wParam, 16)                         ; Hi Word

    Switch $hWndFrom

            Case [WHAT TO PUT HERE if nr of ListBoxes is dynamic?], $hWndListBox    ; <=  MAIN question

                $sBookmark = _GUICtrlListBox_GetText( $hWndFrom, _GUICtrlListBox_GetCurSel($hWndFrom) )

                Switch $iCode

                    Case $LBN_DBLCLK

                        ConsoleWrite("you double-clicked " & $sBookmark & @CRLF)
    EndSwitch

    Return $GUI_RUNDEFMSG

EndFunc

- - -

As a workaround, I can probably add the maximum number of allowed ListBoxes to the Case check, seperated by commas, but only display the number of ListBoxes needed. But I'm hoping it can be made truly dynamical...?

Thank You : )

 

Edited by Guy_

Share this post


Link to post
Share on other sites



#2 ·  Posted

You can make it really dynamic by using a dictionary object to store the lisbox handles instead of an array:

; Create dictionary object
$oListboxDict = ObjCreate( "Scripting.Dictionary" )

; Add listboxes to $oListboxDict
$oListboxDict( $ListboxHandle11 ) = 1
$oListboxDict( $ListboxHandle12 ) = 1
$oListboxDict( $ListboxHandle13 ) = 1
$oListboxDict( $ListboxHandle14 ) = 1
$oListboxDict( $ListboxHandle15 ) = 1

; In _WM_COMMAND use an If ... EndIf instead of a Switch ... EndSwitch
If $oListboxDict.Exists( $hWndFrom ) Then
    ...
    ...
    ...
EndIf

Here you do not need a loop in _WM_COMMAND function.

1 person likes this

Share this post


Link to post
Share on other sites

#3 ·  Posted

Awesome!  Thanks a bunch, Larsj :)

Objects in AutoIt are new to me, but at first sight it seemed easy enough. Yet, after double-clicking an item, I'm getting a crash on ...

If $oListboxDict.Exists( $hWndFrom )

What I have done in preparation (simplified) (I'm using $aIdListbox for other purposes too) ... :

Global $oListboxDict, $aIdListbox

Func _CreateListboxes()

    $oListboxDict = ObjCreate("Scripting.Dictionary")

    For $i = 1 To $NrOfLists
        $aIdListbox[$i] = _GUICtrlListBox_Create( ... )
        $oListboxDict( $aIdListbox[$i] ) = 1                    ; add Listbox ID's to dictionary
    Next
    ; (more creation code)
EndFunc

I'm not sure how to replace the For...Next loop, but I hoped I at least placed the If... condition like you suggested...?

Func _WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    
    #forceref $hWnd, $iMsg
    Local   $hWndFrom, $iIDFrom, $iCode, $hWndListBox, _
            $_bookmark

    For $i = 1 To UBound($aIdListbox) - 1                                       ; loop ok, or replace how?
        If Not IsHWnd($aIdListbox) Then
            $hWndListBox = GUICtrlGetHandle($aIdListbox)
            ExitLoop
        EndIf
    Next

    $hWndFrom   = $lParam
    $iIDFrom    = BitAND($wParam, 0xFFFF)
    $iCode      = BitShift($wParam, 16)

    If $oListboxDict.Exists( $hWndFrom ) And $hWndListBox Then                  ; CRASHES on $oListboxDict.Exists

        $_bookmark = _GUICtrlListBox_GetText( $hWndFrom, _GUICtrlListBox_GetCurSel($hWndFrom) )

        Switch $iCode
            Case $LBN_DBLCLK
                ConsoleWrite("you double-clicked " & $_bookmark & @CRLF)
        EndSwitch
    EndIf

    Return $GUI_RUNDEFMSG

EndFunc

 

Share this post


Link to post
Share on other sites

#4 ·  Posted

Please show some executable code that works when the GUIRegisterMsg command is commented out, and I'll look into the problem.

Share this post


Link to post
Share on other sites

#5 ·  Posted

Guy_,

Note the use of "number" and "hwnd"...

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListBox.au3>
#include <array.au3>

Local $NumListBoxes = 5
$oLBH = ObjCreate("Scripting.Dictionary")

Local $gui010 = GUICreate('LB Dictionary Example', 600, 200)

For $1 = 0 To $NumListBoxes - 1
    $oLBH.add(Number(_GUICtrlListBox_Create($gui010, '', $1 * 105 + 40, 10, 100, 100)), $1)
    $akeys = $oLBH.keys
    ;_arraydisplay($akeys)
    For $2 = 1 To $NumListBoxes
        _GUICtrlListBox_AddString(HWnd($akeys[$1]), $1 & '-' & $2)
    Next
Next

GUISetState()

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)

    If $oLBH.exists(Number($lParam)) And _WinAPI_HiWord($wParam) = $lbn_selchange Then _
            ConsoleWrite('listbox #' & $oLBH.item(Number($lParam)) & ' actioned' & ' Value = ' & _GUICtrlListBox_GetText($lParam, _GUICtrlListBox_GetCurSel($lParam)) & @CRLF)

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND

kylomas

1 person likes this

Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

18 hours ago, LarsJ said:

Please show some executable code that works when the GUIRegisterMsg command is commented out, and I'll look into the problem.

Not sure what you mean, but seems I would have to make an almost working example? That would take quite some time and luckily I got it working now using Kylomas contribution :)  But I thoroughly appreciate your help in the past and future :sweating:

14 hours ago, kylomas said:

Note the use of "number" and "hwnd"...

I had to burn some grey matter here, but I got it working in the end. It's a thing of beauty :drool:   Thanks so much!

- - - - - - -

I have 2 final questions related to this ...

(1) If I want to include modifier key detection, can I use the (working) code below, or do I need something more professional for this type of function?
IIRC, it  turns out I can not put these detections in the targetted _findBookmark() function, because then WM_COMMAND behaves differently.

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)

    $_modKey = ""

    If _IsPressed("11") And _IsPressed("10") Then
        $_modKey = "Ctrl+Shift"
    ElseIf _IsPressed("11") Then
        $_modKey = "Ctrl"
    ElseIf _IsPressed("10") Then
        $_modKey = "Shift"
    EndIf   

    If $oLBH.exists(Number($lParam)) And _WinAPI_HiWord($wParam) = $LBN_DBLCLK Then
    
        $_Bookmark  = _GUICtrlListBox_GetText($lParam, _GUICtrlListBox_GetCurSel($lParam))
        $_ListboxNr = $oLBH.item( Number($lParam) )
        
        _findBookmark($_Bookmark, $_modKey, $_ListboxNr)    
    EndIf

    Return $GUI_RUNDEFMSG

EndFunc   ;==>WM_COMMAND

(2) And to be 100% sure... Am I right that, similar to MouseUp, a KeyUp kinda thing does not exist? (and therefore you see the _IsPressed loops instead?)

An example would be if I would use the Alt key and would arrive in a WordPad file. The Alt_down puts WordPad in a specific mode and crashes my program, so I'm not using Alt (or I could put a loop in _findBookmark() till it's up again). A KeyUp function could solve this easier or earlier  :)

Thank You both again!  :)

Edited by Guy_

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

  • Similar Content

    • Daka
      By Daka
      I know there are listbox and listview, but now I have?
      here is the video of infowindow 
      I tried to read mouse selection like for listbox:
      $listWindow = "[CLASS:TFormResearchGR]" $topicsList = "[CLASS:TMWrapper; INSTANCE:255]" WinWait($listWindow, "", 60) $hdlWindow = WinGetHandle($listWindow) $hdlList = ControlGetHandle($hdlWindow, "", $topicsList) _GUICtrlListBox_ClickItem($hdlList, 0, "left") $countOfList = _GUICtrlListBox_GetCount($hdlList) ConsoleWrite("Count of list: " & $countOfList & @LF) count of list is not working.
      I realiezed that there are difference between listbox and listview, but this is something different.
      and till now I never saw that you can go inside with infotool and also get instances.
       
      so Im confused how to get the list number and the names of selection?
    • Codartizan
      By Codartizan
      Hi Guys
      I got a problem, hope someone can help me, many thanks.
      I'm trying to read items from a listbox1($ListChoCom) to an array, and load this array to another listbox2($ListSuitCmd) which is on the different  tab. But, now, I cannot select items on the listbox2. I only can select from listbox1. Here is the code and the screenshots.
      Func btnNext2() Dim $SelCmdArray[10] For $i = 0 To _GUICtrlListBox_GetCount($ListChoCom) - 1 $SelCmdArray[$i] = _GUICtrlListBox_GetText($ListChoCom, $i) ReDim $SelCmdArray[UBound($SelCmdArray) + 1] GUICtrlSetData($ListSuitCmd, $SelCmdArray[$i]) Next _GUICtrlTab_ClickTab($Tab1, 2) EndFunc Screenshot 1: I can select item from this listbox1.

      screenshot2: I cannot select item from listbox2, The item that been highlight is what I select from listbox1.

      Thank you very much indeed.
    • kcvinu
      By kcvinu
      Hi all,
      I am playing with GUIRegisterMsg function for learning it. This is my code. It is not working. The error msg is this
      Variable used without being declared.:
      $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
      $tNMHDR = DllStructCreate($tagNMHDR, ^ ERROR
      I can't find lParam as a declared variable in _GUICtrlListView_Create.au3 in help file.
      #include <ButtonConstants.au3> #include <ComboConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <GUIListBox.au3> #include <WindowsConstants.au3> #include <MouseOnEvent.au3> #include <Alert.au3> #include <ListBoxConstants.au3> Opt("GUIOnEventMode", 1) #Region ### START Koda GUI section ### Form=K:\GUI Reg Msg Test works\GRM test GUI.kxf Global $Form1 = GUICreate("Form1", 611, 430, 260, 140) GUISetFont(12, 400, 0, "Segoe UI") GUISetOnEvent($GUI_EVENT_CLOSE, "Form1Close") GUISetOnEvent($GUI_EVENT_MINIMIZE, "Form1Minimize") GUISetOnEvent($GUI_EVENT_MAXIMIZE, "Form1Maximize") GUISetOnEvent($GUI_EVENT_RESTORE, "Form1Restore") Global $Button1 = GUICtrlCreateButton("Button1", 368, 360, 137, 49) GUICtrlSetOnEvent(-1, "Button1Click") Global $List1 = GUICtrlCreateList("", 16, 216, 161, 181) GUICtrlSetOnEvent(-1, "List1Click") Global $Combo1 = GUICtrlCreateCombo("Combo1", 352, 24, 193, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL)) GUICtrlSetOnEvent(-1, "Combo1Change") Global $Input1 = GUICtrlCreateInput("Input1", 48, 32, 169, 33) GUICtrlSetOnEvent(-1, "Input1Change") Global $Edit1 = GUICtrlCreateEdit("", 248, 80, 321, 161) GUICtrlSetData(-1, "Edit1") GUICtrlSetOnEvent(-1, "Edit1Change") GUIRegisterMsg($WM_NOTIFY,"List1Click") GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### Local $tmp = ["Orange","Apple","Banana","Papaya","Grapes"] For $i = 0 to 4 GUICtrlSetData($List1,$tmp[$i]) Next While 1 Sleep(100) WEnd Func List1Click($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg Local $hWndFrom,$iIDfrom, $iCode, $tNMHDR, $hWndList, $tInfo $hWndList = $List1 if Not IsHWnd($List1) Then $hWndList = GUICtrlGetHandle($List1) $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR,"hWndFrom")) $iIDfrom = DllStructGetData($tNMHDR,"IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") Switch $hWndFrom Case $List1 Switch $iCode Case $LBN_DBLCLK ;$tInfo = DllStructCreate($tagNMMOUSE) Alert("You Clicked Twice") EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc This gui is only for learning pupose. So please don't mind its aesthetic style.
    • automaterk
      By automaterk
      Hello all!
      With your help I have been able to conquer every problem I've faced thus far in using AutoIt, but I've come across something that I 1) don't fully understand and 2) am not sure how to even begin tackling.
      I have the following list box in a GUI that I am trying to automate that I cannot read any data from. I have discussed this in a previous thread and tried several solutions, but the conclusion was that OCR would probably be the best way to go. You can see the list info and the list box(the data has been edited out) below:

       
      I need to find a way to view the data in the list box and choose the user parameter(in this case, the correct library). There will also be instances where I will simply need to get data from another list and validate it it. I believe the major issue is that the list is populated at runtime(this was discussed in a previous thread) and that is why I cannot directly access the data in the list.
      I have viewed both of these threads:


      but am not able to full grasp how I should be using either of them. Unfortunately this means that I also don't really have a script to post at this point in time either. If anyone that has experience with this can help me out or point me in the right direction, that would be a huge help. This is the last piece of the puzzle for me and it has absolutely driven me crazy  
      I am trying to incorporate everything into AutoItx4Java, but am prepared to run an executable for these portions if necessary. Thanks in advance for any help you might be able to give! I will do my best to get back to you with any questions as soon as I can.
    • digitalexpl0it
      By digitalexpl0it
      Hello All,
      I have searched the forums and google trying to see if there is a way to disable click on any of the items in a listbox. I also am trying to update the listbox items, I have certain populated items which I would like to update each one on the fly. Any help is appreciated.