Jump to content

_GUICtrlComboBoxEx_Create handle array


Go to solution Solved by Blaxxun,

Recommended Posts

Posted

Hello Forum,

What is the proper way to dynamically create ComboBoxes that are able to us WM_NOTIFY.

I get correct messaging when i dont use an handle array.
But with handle array it stops working to trigger messages. (User changes content in Editbox my typing or choosing from the dropdown list)

Posted
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiComboBoxEx.au3>

Global $hCombo[4]
Global $hGUI = GUICreate("GUI", 450, 200, 0, 0, BitOR($WS_MAXIMIZEBOX, $WS_MINIMIZEBOX, $WS_SIZEBOX))

For $i = 0 To 3
    $hCombo[$i] = _GUICtrlComboBoxEx_Create($hGUI, "Item1", 10 + ($i * 101), 10, 100, 200)
    _GUICtrlComboBoxEx_AddString($hCombo[$i], "Item2")
Next

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState(@SW_SHOW)

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

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

    Local $tNMCOMBOBOXEX = DllStructCreate($tagNMCOMBOBOXEX, $lParam)
    Local $hWndFrom = DllStructGetData($tNMCOMBOBOXEX, 'hWndFrom')
    Local $Code = DllStructGetData($tNMCOMBOBOXEX, 'Code')

    Switch $hWndFrom
        Case $hCombo[0] To $hCombo[UBound($hCombo) - 1]
            Switch $Code
                Case $CBEN_GETDISPINFOA, $CBEN_GETDISPINFOW
                    ConsoleWrite(DllStructGetData($tNMCOMBOBOXEX, 'Item') & @LF)
            EndSwitch
    EndSwitch
EndFunc   ;==>WM_NOTIFY

Now it seems to work but sometimes stops messaging. After SciTE restart and Tidy it works again. Weird somehow.
At the moment it reports the Item ID Number everytime i hover over an Item in the dropdown list.
How can i limit this to just report once, once an item is actually selected?

Thanks

Posted

This line is the problem :

Case $hCombo[0] To $hCombo[UBound($hCombo) - 1]

Handles are not created sequentially.  Consider looping into the array, or another solution would be to use control ids.

As for your single report, you could use a Static variable to check if it is the last reported or not...

Posted
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiComboBoxEx.au3>
#include <Array.au3>

Global $hCombo[4]
Global $ComboID[4]
Global $hGUI = GUICreate("GUI", 450, 200, 0, 0, BitOR($WS_MAXIMIZEBOX, $WS_MINIMIZEBOX, $WS_SIZEBOX))

For $i = 0 To 3
    $hCombo[$i] = _GUICtrlComboBoxEx_Create($hGUI, "Item1", 10 + ($i * 101), 10, 100, 200)
    $ComboID[$i] = _WinAPI_GetDlgCtrlID($hCombo[$i])
    _GUICtrlComboBoxEx_AddString($hCombo[$i], "Item2")
    _GUICtrlComboBoxEx_SetExtendedStyle($hCombo[$i], $CBES_EX_NOSIZELIMIT)
Next

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState(@SW_SHOW)

_ArrayDisplay($ComboID,"$ComboID")

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
    Sleep(10)
WEnd

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

    Local $tNMCOMBOBOXEX = DllStructCreate($tagNMCOMBOBOXEX, $lParam)
    Local $hWndFrom = DllStructGetData($tNMCOMBOBOXEX, 'hWndFrom')
    Local $Code = DllStructGetData($tNMCOMBOBOXEX, 'Code')

    Switch $hWndFrom
        Case $ComboID[0] To $ComboID[UBound($hCombo) - 1]
            Switch $Code
                Case $CBEN_GETDISPINFOA, $CBEN_GETDISPINFOW
                    ConsoleWrite(DllStructGetData($tNMCOMBOBOXEX, 'Item') & " - " & $hWndFrom & @LF)
            EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG

EndFunc   ;==>WM_NOTIFY

 

I changed the code, and i get the ID from the handle.
But now i don't get any event reported...

In the final program the comboboxes are generated by the user.
They are on top of a Listviews colums.
Colums can be added and removed and so the number of Comboboxes also change.
If i use a loop to go through the array i run into timing problems...

Posted (edited)

🤦‍♂️ Yeah, now that you say it. Thank you!

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

    Local $tNMCOMBOBOXEX = DllStructCreate($tagNMCOMBOBOXEX, $lParam)
    Local $hWndFrom = DllStructGetData($tNMCOMBOBOXEX, 'hWndFrom')
    Local $WndFromID = _WinAPI_GetDlgCtrlID($hWndFrom)
    Local $Code = DllStructGetData($tNMCOMBOBOXEX, 'Code')

    Switch $WndFromID
        Case $ComboID[0] To $ComboID[UBound($hCombo) - 1]
            Switch $Code
                Case $CBEN_GETDISPINFOA, $CBEN_GETDISPINFOW
                    ConsoleWrite(DllStructGetData($tNMCOMBOBOXEX, 'Item') & " - " & $hWndFrom & @LF)
            EndSwitch
    EndSwitch

EndFunc   ;==>WM_NOTIFY

Now this works!

 

Case $CBEN_GETDISPINFOA, $CBEN_GETDISPINFOW

I just need a report when the user chose an item from the dropdown list and it appears in the editbox.
At the moment it fires already when i click the dropdown arrow.
What can i use to achive this?

Edited by Blaxxun
Posted
Case $CBEN_ENDEDITW

"Sent when the user has concluded an operation within the edit box or has selected an item from the control's drop-down list."

In my case this reports already when i click the dropdown arrow. (Which is empty at first)
Then when i choose an actual Item it does not report anymore.

Just when i click in another combobox edit box it reports...
 

  • Solution
Posted (edited)
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiComboBoxEx.au3>

Global $hCombo[4]
Global $iCombo[4]
Global $sComboTxt
Global $hGUI = GUICreate("GUI", 450, 200, 0, 0, BitOR($WS_MAXIMIZEBOX, $WS_MINIMIZEBOX, $WS_SIZEBOX))

For $i = 0 To 3
    $hCombo[$i] = _GUICtrlComboBoxEx_Create($hGUI, "Item1", 10 + ($i * 101), 10, 100, 200)
    $iCombo[$i] = _WinAPI_GetDlgCtrlID($hCombo[$i])
    _GUICtrlComboBoxEx_AddString($hCombo[$i], "Item2")
Next

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUISetState(@SW_SHOW)

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

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

    Local $nCode = BitShift($wParam, 16) ;      Hiword
    Local $iCtrl = BitAND($wParam, 0xFFFF) ;    Loword
    Local $hCtrl = $lParam

    Switch $iCtrl
        Case $iCombo[0] To $iCombo[UBound($iCombo) - 1]
            Switch $nCode
                ;Case $CBN_EDITUPDATE, $CBN_EDITCHANGE ; When user types in new Data
                ;ConsoleWrite("Types" & @LF)

                Case $CBN_SELCHANGE    ; Item from Dropdown selected
                    $iComboIdx = _GUICtrlComboBox_GetCurSel($hCtrl)
                    $aComboAtt = _GUICtrlComboBoxEx_GetItem($hCtrl, $iComboIdx)
                    $sComboTxt = $aComboAtt[0]
                    ConsoleWrite($sComboTxt & @TAB & $iCtrl & @TAB & $hCtrl & @LF)
            EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG

EndFunc   ;==>WM_COMMAND

This works and only fires when an Item was selected

Edited by Blaxxun

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
  • Recently Browsing   0 members

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