Gibt es eine Möglichkeit die WM_Notify Messages eines LIstviews per DllCallbackRegister auszuwerten?

    • Offizieller Beitrag

    Servus.
    Ich bastel gerade ein bischen mit einem ListView herum. Normalerweise benutze ich zur Auswertung der WM_Notify Messages
    GUIRegisterMsg. Das scheint mir aber viel zu Programmspezifisch zu sein und ist bei einer Verwendung in einer UDF zu unflexiebel.
    Meine Idee wäre es, die Messages in einer Funktion abzufragen die per DllCallbackRegister angesteuert wird.
    Mir fehlt aber das Wissen, oder besser gesagt ich finde keinen Ansatz. Welche WinApi Funktion müßte ich benutzen um die Messages
    per DLLCallbackRegister benutzen zu können.

    Bin für jeden Tipp dankbar.

    • Offizieller Beitrag

    Ja, genau. Ich wollte innerhalb der UDF die WM_Notify Messages behandeln ohne mit GUIRegisterMsg arbeiten zu müssen.
    Damit wäre sie unabhängiger und späten müßte im Hauptscript nicht Rücksicht auf GUIRegisterMsg genommen werden.

  • Wird das etwa ein Beitrag zum µIt? ;)

    du kannst eine eigene WinProc-Funktion registrieren, die vor der normalen GuiRegisterMsg-Funktion aufgerufen wird:

    Spoiler anzeigen
    [autoit]

    #include <GuiImageList.au3>
    #include <GuiListView.au3>
    #include <ListViewConstants.au3>
    #include <StructureConstants.au3>
    #include <WinAPI.au3>
    #include <WindowsConstants.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("Test", 400, 400)
    $hListView = _GUICtrlListView_Create($hGui, "Listview", 10, 10, 380, 380)
    _GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES))

    [/autoit] [autoit][/autoit] [autoit]

    ; Load images
    $hImage = _GUIImageList_Create()
    _GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap($hListView, 0xFF0000, 16, 16))
    _GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap($hListView, 0x00FF00, 16, 16))
    _GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap($hListView, 0x0000FF, 16, 16))
    _GUICtrlListView_SetImageList($hListView, $hImage, 1)

    [/autoit] [autoit][/autoit] [autoit]

    ; Add columns
    _GUICtrlListView_InsertColumn($hListView, 0, "Column 1", 100)
    _GUICtrlListView_InsertColumn($hListView, 1, "Column 2", 100)
    _GUICtrlListView_InsertColumn($hListView, 2, "Column 3", 100)

    [/autoit] [autoit][/autoit] [autoit]

    ; Add items
    _GUICtrlListView_AddItem($hListView, "Row 1: Col 1", 0)
    _GUICtrlListView_AddSubItem($hListView, 0, "Row 1: Col 2", 1)
    _GUICtrlListView_AddSubItem($hListView, 0, "Row 1: Col 3", 2)
    _GUICtrlListView_AddItem($hListView, "Row 2: Col 1", 1)
    _GUICtrlListView_AddSubItem($hListView, 1, "Row 2: Col 2", 1)
    _GUICtrlListView_AddItem($hListView, "Row 3: Col 1", 2)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $hProc = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;wparam;lparam')
    $hHook = _WinAPI_SetWindowLong($hGui, -4, DllCallbackGetPtr($hProc))

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While GUIGetMsg() <> -3
    Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    _WinAPI_SetWindowLong($hGui, -4, $hHook) ; original WinProc wiederherstellen

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _WinProc($hWnd, $iMsg, $iwParam, $ilParam)
    If $iMsg <> $WM_NOTIFY Then Return _WinAPI_CallWindowProc($hHook, $hWnd, $iMsg, $iwParam, $ilParam)

    [/autoit] [autoit][/autoit] [autoit]

    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo

    [/autoit] [autoit][/autoit] [autoit]

    $hWndListView = $hListView
    If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView)

    [/autoit] [autoit][/autoit] [autoit]

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
    Case $hWndListView
    Switch $iCode
    Case $LVN_COLUMNCLICK ; A column was clicked
    $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
    _DebugPrint("$LVN_COLUMNCLICK" & @LF & "--> hWndFrom:" & @TAB & $hWndFrom & @LF & _
    "-->IDFrom:" & @TAB & $iIDFrom & @LF & _
    "-->Code:" & @TAB & $iCode & @LF & _
    "-->Item:" & @TAB & DllStructGetData($tInfo, "Item") & @LF & _
    "-->SubItem:" & @TAB & DllStructGetData($tInfo, "SubItem") & @LF & _
    "-->NewState:" & @TAB & DllStructGetData($tInfo, "NewState") & @LF & _
    "-->OldState:" & @TAB & DllStructGetData($tInfo, "OldState") & @LF & _
    "-->Changed:" & @TAB & DllStructGetData($tInfo, "Changed") & @LF & _
    "-->ActionX:" & @TAB & DllStructGetData($tInfo, "ActionX") & @LF & _
    "-->ActionY:" & @TAB & DllStructGetData($tInfo, "ActionY") & @LF & _
    "-->Param:" & @TAB & DllStructGetData($tInfo, "Param"))
    Case $NM_CLICK ; Sent by a list-view control when the user clicks an item with the left mouse button
    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
    _DebugPrint("$NM_CLICK" & @LF & "--> hWndFrom:" & @TAB & $hWndFrom & @LF & _
    "-->IDFrom:" & @TAB & $iIDFrom & @LF & _
    "-->Code:" & @TAB & $iCode & @LF & _
    "-->Index:" & @TAB & DllStructGetData($tInfo, "Index") & @LF & _
    "-->SubItem:" & @TAB & DllStructGetData($tInfo, "SubItem") & @LF & _
    "-->NewState:" & @TAB & DllStructGetData($tInfo, "NewState") & @LF & _
    "-->OldState:" & @TAB & DllStructGetData($tInfo, "OldState") & @LF & _
    "-->Changed:" & @TAB & DllStructGetData($tInfo, "Changed") & @LF & _
    "-->ActionX:" & @TAB & DllStructGetData($tInfo, "ActionX") & @LF & _
    "-->ActionY:" & @TAB & DllStructGetData($tInfo, "ActionY") & @LF & _
    "-->lParam:" & @TAB & DllStructGetData($tInfo, "lParam") & @LF & _
    "-->KeyFlags:" & @TAB & DllStructGetData($tInfo, "KeyFlags"))

    [/autoit] [autoit][/autoit] [autoit]

    EndSwitch
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit]

    Return _WinAPI_CallWindowProc($hHook, $hWnd, $iMsg, $iwParam, $ilParam); hier wird die normale WinProc aufgerufen, die man mit GuiRegisterMsg auswerten kann
    EndFunc ;==>_WinProc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _DebugPrint($s_text, $line = @ScriptLineNumber)
    ConsoleWrite( _
    "!===========================================================" & @LF & _
    "+======================================================" & @LF & _
    "-->Line(" & StringFormat("%04d", $line) & "):" & @TAB & $s_text & @LF & _
    "+======================================================" & @LF)
    EndFunc ;==>_DebugPrint

    [/autoit]


    nicht vergessen bei Exit die originale WinProc wieder herzustellen.

    mfgE

    • Offizieller Beitrag

    Danke eukalyptus.
    Genau das habe ich gesucht.

    Wenn die Autoit-Hilfe klar verständlich wäre, dann hätte ich das selber gefunden. :D

    Das soll ein Mensch verstehen:
    $GWL_WNDPROC - Sets the address of the window procedure

    Irgendwie ist das absolut nichtssagend.

    Die Deutsche Hilfe ist noch schlimmer:

    $GWL_WNDPROC - Setzt die Adresse der Fensterprozedur

    Ohne fundamentales Wissen kommt doch kein Schwein drauf, das damit die DLLCallBack Funktion gemeint ist. :thumbdown:

    Edit: Selbst bei MSDN ist das unverständlich:
    GWLP_WNDPROC Sets a new address for the window procedure. :thumbdown:

  • Hi Raupi,
    bitte schreibe kurz wie ich

    Zitat

    $GWL_WNDPROC - Setzt die Adresse der Fensterprozedur


    in der Hilfe ändern soll ;)

    • Offizieller Beitrag

    Vorschlag:

    Setze die Adresse zur neuen Window DllCallBack Funktion oder
    Setze die Adresse zur neuen Window Auswertungsfunktion
    Für weitere Vorschläge bin ich aber zu haben.

  • Hi,

    die originale Beschreibung/Übersetzung ist doch eigentlich ganz klar.
    Ja, das setzt etwas Grundwissen voraus, das sollte man aber auch haben oder sich aneignen, wenn man die DllXxx Funktionen benutzen will.

    Grundsätzlich gilt: Jede Fensterklasse besitzt eine Fensterprozedur, in der die Nachrichten verarbeitet werden. Jedes Fenster der Klasse benutzt diese eine Fensterprozedur. Da sich das Programm im Speicher befindet, hat die Fensterprozedur natürlich auch eine Adresse. Jeder Funktionsaufruf ist letztendlich der Aufruf, bzw. Sprung, zu einer Adresse im Speicher, der Name der Prozedur/Funktion ist nur ein Synonym für die Adresse.

    Das Tutorial auf Pronix.de oder die Übersetzung von Iczelion's Win32 Tutorial sollte etwas Klarheit schaffen ...

    (Übrigens sind Steuerelemente auch nichts anderes als Fenster ;) )

    Sieh dir bitte noch einmal "EzBmpButton" und "Hello AutoIt3" an, dann hast Du es in AutoIt Code und kannst es vielleicht besser verstehen. In "PeaPad" ist ein Beispiel wie die Fensterprozedur des Eingabefeldes gegen eine eigene Prozedur ausgetauscht wird ...


    Gruß
    Greenhorn