WM_RBUTTONDOWN wird nicht immer aufgerufen

  • Beim Rumexperimentieren mit meinem ListBox-Control hat mich gestört, dass bei einem Rechtsklick (welcher das Kontextmenü aufruft) das Item nicht ausgewählt wird (anders als beim ListView), und deswegen habe ich mir etwas zusammengebastelt. Bei ListView hatte ich mit NM_RCLICK mit WM_NOTIFY gearbeitet, aber das wird von einer ListBox nicht gesendet. Hier der relevante Auszug:

    Spoiler anzeigen
    [autoit]

    #include <WinAPI.au3>
    #include <GUIConstants.au3>
    #include <WindowsConstants.au3>
    #include <GuiListBox.au3>

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

    $hGUI_Main = GUICreate("TestGUI", 300, 400)
    $hList_Downloads = GUICtrlCreateList("list1", 10, 20, 280, 360)
    GUICtrlSetData(-1, "list2|list3|list4")

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

    GUIRegisterMsg($WM_RBUTTONDOWN, "WM_RBUTTONDOWN")
    GUISetState()

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

    Do
    Until GUIGetMsg() = -3

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

    Func WM_RBUTTONDOWN($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Local $cx = _WinAPI_LoWord($lParam), $cy = _WinAPI_HiWord($lParam);, $aiWinPos = WinGetPos($hGUI_Main)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $cx = ' & $cx & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    $iIndex = _GUICtrlListBox_ItemFromPoint($hList_Downloads, $cx, $cy);$cx - $aiWinPos[0], $cy - $aiWinPos[1])
    If $iIndex <> -1 Then _GUICtrlListBox_SetCurSel($hList_Downloads, $iIndex)

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

    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_RBUTTONDOWN

    [/autoit]

    Wie man am Debug sehen kann, wird die Funktion (zumindest bei mir) extrem selten ausgeführt, alle 10 Klicks, und liefert manchmal einen völlig schwachsinnigen Wert zurück (teilweise 1800, was auf der der "totalen" Mausposition entspräche, auf der rechten Seite, obwohl die Position relativ zum Client sein soll). Ähnliche Ergebnisse bei WM_RBUTTONDOWN und WM_RBUTTONCLICK sowie WM_NCRBUTTONUP und WM_NCRBUTTONDOWN, welche allerdings zuverlässig ausgeführt werden, wenn man auf den X-Button drück (Rechtsklick natürlich). Ich kann mir ehrlich gesagt nicht erklären, wie es dazu kommt. Link zur MSDN.

    • Offizieller Beitrag

    Warum benutzt du denn überhaupt eine ListBox? Ein 1 Spalten Listview ohne Header sieht genauso aus und ist viel leichter auszuwerten.

  • Habe mittlerweile noch etwas mit dem ListView rumgespielt, um es so aussehen zu lassen, wie ich das gerne hätte.... Wie kann ich verhindern, dass eine horizontale Scrollleiste angezeigt wird? Wenn ich die Größe der ersten Spalte auf das Maximum setze und anschließend so viele Einträge hnzufüge, dass eine vertikalte Sl angezeigt werden muss, dann wird auch eine horz. angezeigt, da die vert. dann den Rest der Zeile verdeckt.
    Wie kann ich erreichen, dass Items in dem ListView per Drag&Drop verschoben werden können? Ich meine beim Cursor wird ja immer washinzugefügt, also muss es auch so eine Funktion geben.
    Und auch habe ich bei der ListBox mit _SetData gearbeitet, aber das ließe sich mit Assign und Eval lösen.

  • Hi,

    Spoiler anzeigen
    [autoit]


    Opt("MustDeclareVars", 1)

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

    #include <WinAPI.au3>
    #include <GUIConstants.au3>
    #include <WindowsConstants.au3>
    #include <GuiListBox.au3>

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

    Global $user32dll

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

    If (not $user32dll) Then _
    Global $user32dll = DllOpen ("user32.dll")

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

    Global Const $SC_CLOSE = 0xF060

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

    Global Const $GWLP_WNDPROC = (-4)
    Global Const $GWLP_HINSTANCE = (-6)
    Global Const $GWLP_HWNDPARENT = (-8)
    Global Const $GWLP_USERDATA = (-21)
    Global Const $GWLP_ID = (-12)

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

    ; ID des Listenfeldes
    Global $IDC_LB_DOWNLOADS

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

    ; Handlevariablen für die Adressen der Fensterprozeduren,
    ; die des Listenfeldes und unsere Ersatzfunktion.
    Global $g_hListBoxProc = 0
    Global $g_hOldListBoxProc = 0

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

    Func Main ( )

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

    Local $hGUI_Main
    Local $hList_Downloads

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

    $hGUI_Main = GUICreate("TestGUI", 300, 400)
    $IDC_LB_DOWNLOADS = GUICtrlCreateList("list1", 10, 20, 280, 360, _
    BitOR($LBS_SORT, $WS_BORDER, $WS_CHILD, $WS_TABSTOP, $WS_VSCROLL, $LBS_NOTIFY))
    GUICtrlSetData(-1, "list2|list3|list4")

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

    $hList_Downloads = GUICtrlGetHandle ($IDC_LB_DOWNLOADS)

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

    ;~ GUIRegisterMsg($WM_RBUTTONDOWN, "WM_RBUTTONDOWN")
    GUIRegisterMsg ($WM_CLOSE, "OnClose")
    GUIRegisterMsg ($WM_DESTROY, "OnDestroy")
    GUIRegisterMsg ($WM_SYSCOMMAND, "OnSysCommand")

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

    ; Unsere Rückruf-Funktion registrieren ...
    $g_hListBoxProc = DllCallbackRegister ("ListBoxProc", "LONG", "HWND;UINT;WPARAM;LPARAM")

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

    If ($g_hListBoxProc) Then

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

    ; Das Listenfeld "subclassen" ...
    $g_hOldListBoxProc = SetWindowLongPtr ($hList_Downloads, $GWLP_WNDPROC, DllCallbackGetPtr ($g_hListBoxProc))
    EndIf

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

    GUISetState()

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

    ; Schleife ...

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

    While (WinExists ($hGUI_Main))
    GUIGetMsg (FALSE)
    WEnd

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

    Return 0

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

    EndFunc

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

    ;««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

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

    Func OnClose ($hwnd, $message, $wParam, $lParam)

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

    ; Fenster löschen
    GUIDelete ($hwnd)

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

    Return 0

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

    EndFunc

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

    Func OnDestroy ($hwnd, $message, $wParam, $lParam)

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

    ; Die originale Fensterprozedur des Listenfeldes
    ; wiederherstellen

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

    If ($g_hOldListBoxProc) Then _
    SetWindowLongPtr ( _
    GUICtrlGetHandle ($IDC_LB_DOWNLOADS), _
    $GWLP_WNDPROC, _
    $g_hOldListBoxProc _
    )

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

    Return $GUI_RUNDEFMSG

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

    EndFunc

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

    Func OnSysCommand ($hwnd, $message, $wParam, $lParam)

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

    If ($wParam == $SC_CLOSE) Then
    GUISetState (@sw_hide, $hwnd)
    Return 0
    EndIf

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

    Return DefWindowProc ($hwnd, $message, $wParam, $lParam)

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

    EndFunc

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

    Func WM_RBUTTONDOWN($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Local $cx = _WinAPI_LoWord($lParam), $cy = _WinAPI_HiWord($lParam);, $aiWinPos = WinGetPos($hGUI_Main)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $cx = ' & $cx & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    Local $iIndex = _GUICtrlListBox_ItemFromPoint($IDC_LB_DOWNLOADS, $cx, $cy);$cx - $aiWinPos[0], $cy - $aiWinPos[1])
    If $iIndex <> -1 Then _GUICtrlListBox_SetCurSel($IDC_LB_DOWNLOADS, $iIndex)

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

    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_RBUTTONDOWN

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

    ;««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

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

    ; Diese Funktion ersetzt die originale Fensterprozedur des Listenfeldes
    Func ListBoxProc ($hwnd, $message, $wParam, $lParam)

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

    Local $cx, $cy
    Local $iIndex
    Local $hList_Downloads

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

    Switch ($message)

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

    Case $WM_RBUTTONDOWN

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

    $cx = _WinAPI_LoWord($lParam)
    $cy = _WinAPI_HiWord($lParam)
    $hList_Downloads = GUICtrlGetHandle ($IDC_LB_DOWNLOADS)
    $iIndex = _GUICtrlListBox_ItemFromPoint($hList_Downloads, $cx, $cy);$cx - $aiWinPos[0], $cy - $aiWinPos[1])
    ConsoleWrite(StringFormat ("--- cx: %d\n--- cy: %d\n--- iIndex: %d\n---------------\n", $cx, $cy, $iIndex)) ;### Debug Console
    If $iIndex <> -1 Then _GUICtrlListBox_SetCurSel($hList_Downloads, $iIndex)

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

    ; Die Nachricht an die ursprüngliche Fensterprozedur
    ; des Listenfeldes weiterleiten

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

    Return CallWindowProc ($g_hOldListBoxProc, _
    $hwnd, $message, $wParam, $lParam)

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

    Case Else

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

    Return CallWindowProc ($g_hOldListBoxProc, _
    $hwnd, $message, $wParam, $lParam)

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

    EndSwitch

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

    Return 0

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

    EndFunc

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

    ;««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

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

    ; Win32 API Funktionen

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

    Func CallWindowProc ($lpPrevWndFunc, $hWnd, $Msg, $wParam, $lParam)

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

    Local $aRes = DllCall ($user32dll, 'ULONG', 'CallWindowProcW', _
    'PTR', $lpPrevWndFunc, _
    'HWND', $hWnd, _
    'UINT', $Msg, _
    'WPARAM', $wParam, _
    'LPARAM', $lParam)
    Return $aRes[0]

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

    EndFunc

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

    Func DefWindowProc ($hWnd, $Msg, $wParam, $lParam)

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

    Local $aRes = DllCall ($user32dll, "ULONG", "DefWindowProcW", _
    "HWND", $hWnd, _
    "UINT", $Msg, _
    "WPARAM", $wParam, _
    "LPARAM", $lParam)
    Return $aRes[0]

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

    EndFunc

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

    Func GetWindowLongPtr ($hWnd, $nIndex)

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

    Local $aRes

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

    If (DllStructGetSize (DllStructCreate ("HWND", $hWnd)) == 8) Then ; x64

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

    $aRes = DllCall ($user32dll, "LONG_PTR", "GetWindowLongPtrW", _
    "HWND", $hWnd, _
    "INT" , $nIndex)
    Else ; x86
    $aRes = DllCall ($user32dll, "LONG", "GetWindowLongW", _
    "HWND", $hWnd, _
    "INT" , $nIndex)
    EndIf

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

    Return $aRes[0]

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

    EndFunc

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

    Func SetWindowLongPtr ($hWnd, $nIndex, $dwNewLong)

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

    Local $aRes

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

    If (DllStructGetSize (DllStructCreate ("HWND", $hWnd)) == 8) Then ; x64

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

    $aRes = DllCall ($user32dll, "LONG_PTR", "SetWindowLongPtrW", _
    "HWND", $hWnd, _
    "INT" , $nIndex, _
    "LONG_PTR", $dwNewLong)
    Else ; x86
    $aRes = DllCall ($user32dll, "LONG", "SetWindowLongW", _
    "HWND", $hWnd, _
    "INT" , $nIndex, _
    "LONG", $dwNewLong)
    EndIf

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

    Return $aRes[0]

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

    EndFunc

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

    Exit (Main ( ))

    [/autoit]

    Gruß
    Greenhorn


    • Offizieller Beitrag

    Hatte geade Langeweile, so funzt das Selektieren mit der Rechten Maustaste bei der ListBox.

    Spoiler anzeigen
    [autoit]

    #include <WinAPI.au3>
    #include <GUIConstants.au3>
    #include <WindowsConstants.au3>
    #include <GuiListBox.au3>

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

    $hGUI_Main = GUICreate("TestGUI", 300, 400)
    $hList_Downloads = GUICtrlCreateList("list1", 10, 20, 280, 360)
    GUICtrlSetData(-1, "list2|list3|list4")
    GUISetState()

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

    While 1
    $msg = GUIGetMsg()
    Switch $msg
    Case $GUI_EVENT_SECONDARYDOWN
    Local $aWinPos = GUIGetCursorInfo($hGUI_Main)
    If $aWinPos[4] = $hList_Downloads Then
    Local $tPoint = _WinAPI_GetMousePos(True, GUICtrlGetHandle($hList_Downloads))
    Local $iIndex = _GUICtrlListBox_ItemFromPoint($hList_Downloads, DllStructGetData($tPoint, "X"), DllStructGetData($tPoint, "Y"));$cx - $aiWinPos[0], $cy - $aiWinPos[1])
    If $iIndex <> -1 Then _GUICtrlListBox_SetCurSel($hList_Downloads, $iIndex)
    EndIf
    Case $GUI_EVENT_CLOSE
    Exit
    EndSwitch
    WEnd

    [/autoit] [autoit][/autoit] [autoit][/autoit]
  • Danke Greenhorn, dein Beispiel funktioniert bestens. Allerdings verstehe ich nicht, warum du mit 'GUIRegisterMsg ($WM_SYSCOMMAND, "OnSysCommand")' WM_SYSCOMMAND registrierst. Wenn man "$wParam = $SC_CLOSE" (also ein "=") benutzt, wird der If-Zweig ausgeführt, aber durch das "Return 0" wird anschließend kein WM_CLOSE oder WM_DESTROY ausgeführt, was mich verwundert; man könnte auch einfach bei WM_CLOSE 0 zurückgeben...

    Ich überlege noch, ob ich die WndProc-Variante oder einfach ein ListView nehmen soll, vielleicht kann mir jemand meine Fragen im Post oben beantworten. Währenddessen arbeite ich an meinen Unicode-Ini-Funktionen.

    Edit: Seite lange nicht aktualisiert,
    Raupi : Auf $GUI_EVENT_SECONDARYDOWN hätte ich eigentlich selbst kommen können, das erspart mir WM_RBUTTONDOWN komplett. Ich denke, dass ich dann wohl erst einmal dise Methode benutze, bis ich das Drag&Drop vom ListView rausgefunden habe. Dann würde sich eine Umstellung lohnen (ich weiß, dass man auch ein Workaround für ListBox machen könnte, aber dazu hätte ich auch keine Lust).

    Danke auf jeden Fall euch beiden für die Hilfe.

    • Offizieller Beitrag

    Benutze doch mein Beispiel. Ist nicht so aufwändig wie das Teil von Greenhorn.


    PS: Das könnte dir mit deinem Drag n Drop mit dem Listview helfen: http://www.autoitscript.com/forum/topic/12…rsion-3-feb-11/