Bitte auf verschiedenen Systemen testen und anpassen -->_GuiCtrlListView_MarkItem

  • Hallo!

    Ich hab hier eine Funktion, die bei mir auf WinXP (klassischer und XP-Style einigermaßen gut funktioniert). Ich habe aber berechtigten Zweifel, dass es unter Vista und Win7 noch so stimmt.
    Die Funktion _GuiCtrlListView_MarkItem umrandet einfach ein SubItem einer ListView, nur leider sollen auf einigen Systemen die Koordinaten nicht passen, sodass das Quadrat nicht schön über dem SubItem gezeichnet wird. Ich hätte aber natürlich gerne, dass es überall System- und Style-unabhängig gleich gut funktioniert.

    Vielen Dank für eure Hilfe!

    [autoit]

    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #Include <GuiListView.au3>
    #Include <WinAPI.au3>

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

    Opt('MustDeclareVars', 1)

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

    Example()

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

    Func Example()
    Local $hGui, $listview, $button, $item1, $item2, $item3, $item4, $item5, $input1, $msg

    $hGui = GUICreate("listview items", 220, 250, 100, 200)

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

    $listview = GUICtrlCreateListView("col1 |col2|col3 ", 10, 10, 200, 150, -1, 0x21)
    $button = GUICtrlCreateButton("Click Me!!!!", 75, 170, 70, 20)
    $item1 = GUICtrlCreateListViewItem("item1|col12|col13", $listview)
    $item2 = GUICtrlCreateListViewItem("item2|col22|col23", $listview)
    $item3 = GUICtrlCreateListViewItem("item3|col32|col33", $listview)
    $item4 = GUICtrlCreateListViewItem("item4|col42|col43", $listview)
    $item5 = GUICtrlCreateListViewItem("item5|col52|col53", $listview)
    GUISetState()

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

    Do
    $msg = GUIGetMsg()

    Select
    Case $msg = $button
    _GuiCtrlListView_MarkItem($hGui, $listview, Random(0,4,1), Random(0,2,1))
    EndSelect
    Until $msg = $GUI_EVENT_CLOSE
    EndFunc ;==>Example

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

    Func _GuiCtrlListView_MarkItem($hWndGui, $hWnd, $iIndex, $iSubItem, $Color = 0xFF, $Redraw = 1)
    ;funkey April 16, 2010
    Local $aPos, $aRect, $aMenu, $aBorder, $aBorder3D, $aWndSize, $aWndClientSize, $Offset, $iSum = 0
    Local $x, $y, $w, $h
    For $i = 0 To $iSubItem - 1
    $iSum += _GUICtrlListView_GetColumnWidth($hWnd, $i)
    Next
    $aWndSize = WinGetPos($hWndGui)
    $aWndClientSize = WinGetClientSize($hWndGui)
    $aBorder = DllCall("user32.dll", "int", "GetSystemMetrics", "int", 6) ;SM_CYBORDER
    $aBorder3D = DllCall("user32.dll", "int", "GetSystemMetrics", "int", 46) ;SM_CYEDGE

    ;~ ConsoleWrite("Border: " & $aBorder[0] & @CR)
    ;~ ConsoleWrite("Border3D: " & $aBorder3D[0] & @CR)
    ;~ ConsoleWrite("ClientDiff: " & ($aWndSize[2] - $aWndClientSize[0]) / 2 & @CR)

    $Offset = $aWndSize[3] - $aWndClientSize[1]
    $aRect = _GUICtrlListView_GetItemRect($hWnd, $iIndex)
    $aPos = ControlGetPos($hWndGui, "", $hWnd)
    $x = $iSum + $aPos[0] + $aRect[0] + ($aWndSize[2] - $aWndClientSize[0]) / 2 + $aBorder3D[0] + $aBorder[0]
    $y = $aPos[1] + $aRect[1] + $Offset
    $w = _GUICtrlListView_GetColumnWidth($hWnd, $iSubItem)
    $h = $aRect[3] - $aRect[1]

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

    If $Redraw Then _WinAPI_RedrawWindow($hWndGui)

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

    Local $hDC, $hPen, $obj_orig
    $hDC = _WinAPI_GetWindowDC($hWndGui)
    $hPen = _WinAPI_CreatePen($PS_SOLID, 2, $Color)
    $obj_orig = _WinAPI_SelectObject($hDC, $hPen)

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

    _WinAPI_DrawLine($hDC, $x, $y, $x + $w, $y)
    _WinAPI_DrawLine($hDC, $x, $y, $x, $y + $h)
    _WinAPI_DrawLine($hDC, $x + $w, $y, $x + $w, $y + $h)
    _WinAPI_DrawLine($hDC, $x, $y + $h, $x + $w, $y + $h)

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

    ; clear resources
    _WinAPI_SelectObject($hDC, $obj_orig)
    _WinAPI_DeleteObject($hPen)
    _WinAPI_ReleaseDC($hWndGui, $hDC)
    EndFunc ;==>ShowCross

    [/autoit]
  • Danke für's testen!
    Hab's noch einmal überarbeitet:

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GuiListView.au3>
    #include <WinAPI.au3>

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

    Local $hGui, $listview, $button, $item1, $item2, $item3, $item4, $item5, $msg

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

    $hGui = GUICreate("listview items", 220, 250, 100, 200)

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

    If Random(0,1,1) Then GUICtrlCreateMenu("Test") ;manchmal mit, manchmal ohne Menü

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

    $listview = GUICtrlCreateListView("col1 |col2|col3|col4 ", 10, 10, 200, 150, -1, 0x21)
    $button = GUICtrlCreateButton("Click Me!!!!", 75, 170, 70, 20)
    $item1 = GUICtrlCreateListViewItem("item1|col12|col13|col14", $listview)
    $item2 = GUICtrlCreateListViewItem("item2|col22|col23|col24", $listview)
    $item3 = GUICtrlCreateListViewItem("item3|col32|col33|col34", $listview)
    $item4 = GUICtrlCreateListViewItem("item4|col42|col43|col44", $listview)
    $item5 = GUICtrlCreateListViewItem("item5|col52|col53|col54", $listview)
    GUISetState()

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

    Do
    $msg = GUIGetMsg()

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

    Select
    Case $msg = $button
    _GuiCtrlListView_MarkItem($hGui, $listview, Random(0, 4, 1), Random(0, 3, 1))
    EndSelect
    Until $msg = $GUI_EVENT_CLOSE

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

    Func _GuiCtrlListView_MarkItem($hWndGui, $hWnd, $iIndex, $iSubItem, $Color = 0xFF, $Redraw = 1)
    ;funkey April 16, 2010
    Local $x, $y, $w, $h
    Local $aWndSize = WinGetPos($hWndGui)
    Local $aWndClientSize = WinGetClientSize($hWndGui)
    Local $aPos = ControlGetPos($hWndGui, "", $hWnd)

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

    Local $aRect = _GUICtrlListView_GetSubItemRect($hWnd, $iIndex, $iSubItem)
    $x = $aRect[0] + $aPos[0] + $aWndSize[2] - $aWndClientSize[0]
    $y = $aRect[1] + $aWndSize[3] - $aWndClientSize[1] + $aPos[1]
    $w = $aRect[2] - $aRect[0]
    $h = $aRect[3] - $aRect[1]

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

    If $Redraw Then _WinAPI_RedrawWindow($hWndGui)

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

    Local $hDC, $hPen, $obj_orig
    $hDC = _WinAPI_GetWindowDC($hWndGui)
    $hPen = _WinAPI_CreatePen($PS_SOLID, 3, $Color)
    $obj_orig = _WinAPI_SelectObject($hDC, $hPen)

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

    _WinAPI_DrawLine($hDC, $x, $y - 1, $x + $w, $y - 1)
    _WinAPI_DrawLine($hDC, $x, $y - 1, $x, $y + $h - 1)
    _WinAPI_DrawLine($hDC, $x + $w, $y - 1, $x + $w, $y + $h - 1)
    _WinAPI_DrawLine($hDC, $x, $y + $h - 1, $x + $w, $y + $h - 1)

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

    ; clear resources
    _WinAPI_SelectObject($hDC, $obj_orig)
    _WinAPI_DeleteObject($hPen)
    _WinAPI_ReleaseDC($hWndGui, $hDC)
    EndFunc ;==>_GuiCtrlListView_MarkItem

    [/autoit]

    Funktioniert jetzt super bei mir.

    Zitat von Bugfix

    Wäre es nicht einfacher, statt der 4 Einzellinien mit _WinAPI_FrameRect() zu zeichnen?
    Das RECT könntest du dir gleich mit _GUICtrlListView_GetItemRectEx() ausgeben lassen.


    Ganz so einfach geht es auch wieder nicht.

  • Wenn etwas mit deiner Funktion "markiert" ist, und die Zeile dann angewählt wird, gibt es Grafikfehler.

    • Offizieller Beitrag

    Ganz so einfach geht es auch wieder nicht.

    :D - ja, die Offsets muß man leider mit reinrechnen. Aber zumindest muß man nicht 4 Linien zeichnen. ;)

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GuiListView.au3>
    #include <WinAPI.au3>

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

    Local $hGui, $listview, $button, $item1, $item2, $item3, $item4, $item5, $msg

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

    $hGui = GUICreate("listview items", 220, 250, 100, 200)

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

    If Random(0, 1, 1) Then GUICtrlCreateMenu("Test") ;manchmal mit, manchmal ohne Menü

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

    $listview = GUICtrlCreateListView("col1 |col2|col3|col4 ", 10, 10, 200, 150, -1, 0x21)
    $button = GUICtrlCreateButton("Click Me!!!!", 75, 170, 70, 20)
    $item1 = GUICtrlCreateListViewItem("item1|col12|col13|col14", $listview)
    $item2 = GUICtrlCreateListViewItem("item2|col22|col23|col24", $listview)
    $item3 = GUICtrlCreateListViewItem("item3|col32|col33|col34", $listview)
    $item4 = GUICtrlCreateListViewItem("item4|col42|col43|col44", $listview)
    $item5 = GUICtrlCreateListViewItem("item5|col52|col53|col54", $listview)
    GUISetState()

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

    Do
    $msg = GUIGetMsg()

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

    Select
    Case $msg = $button
    _GuiCtrlListView_MarkItem($hGui, $listview, Random(0, 4, 1), Random(0, 3, 1))
    EndSelect
    Until $msg = $GUI_EVENT_CLOSE

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

    Func _GuiCtrlListView_MarkItem($hWndGui, $hWnd, $iIndex, $iSubItem, $Color = 0xFF, $Redraw = 1)
    ;funkey April 16, 2010
    Local $aWndSize = WinGetPos($hWndGui)
    Local $aWndClientSize = WinGetClientSize($hWndGui)
    Local $aPos = ControlGetPos($hWndGui, "", $hWnd)

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

    Local $tRECT = DllStructCreate('int Left;int Top;int Right;int Bottom')
    Local $aRect = _GUICtrlListView_GetSubItemRect($hWnd, $iIndex, $iSubItem)
    DllCall("user32", 'long', 'SetRect', 'ptr', DllStructGetPtr($tRECT), _
    'long', $aRect[0] + $aPos[0] + $aWndSize[2] - $aWndClientSize[0], _
    'long', $aRect[1] + $aPos[1] + $aWndSize[3] - $aWndClientSize[1], _
    'long', $aRect[2] + $aPos[0] + $aWndSize[2] - $aWndClientSize[0], _
    'long', $aRect[3] + $aPos[1] + $aWndSize[3] - $aWndClientSize[1])

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

    If $Redraw Then _WinAPI_RedrawWindow($hWndGui)

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

    Local $hDC, $hBrush, $obj_orig
    $hDC = _WinAPI_GetWindowDC($hWndGui)
    $hBrush = _WinAPI_CreateSolidBrush($Color)
    $obj_orig = _WinAPI_SelectObject($hDC, $hBrush)
    _WinAPI_FrameRect($hDC, DllStructGetPtr($tRECT), $hBrush)

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

    ; clear resources
    _WinAPI_SelectObject($hDC, $obj_orig)
    _WinAPI_DeleteObject($hBrush)
    _WinAPI_ReleaseDC($hWndGui, $hDC)
    EndFunc ;==>_GuiCtrlListView_MarkItem

    [/autoit]
    • Offizieller Beitrag

    Die Ecken sind jetzt richtig abgerundet. Aber die Markierung geht jetzt etwas über den Rand hinaus.
    Und wenn man den Slider bewegt wird die Markierung nicht mit refresht (siehe Screenshot):
    autoit.de/wcf/attachment/9088/
    Die Funktion an sich finde ich aber schon sehr praktisch und könnte sie gut gebrauchen. :thumbup:

  • Bugfix, mit dem Brush kann man jetzt aber nicht mehr die Linienstärke einstellen, ist aber eigentlich sogar besser, weil jetzt die Markierung nicht mehr über das Subitem hinaussteht.
    Ich hatte eigentlich ursprünglich nicht vor die Markierung immer wieder zu erneuern, wenn sie durch scrollen verloren geht, aber wenn jemand eine gute Lösung dafür hat, dann habe ich nichts dagegen einzuwenden.

    Hab die Funktion noch mal erweitert, um entweder das ganze Item zu markieren oder nur wein Subitem.
    Ich hoffe auch, dass sich UEZ hier mal meldet, weil auf seinem System die Markierung nicht richtig positioniert wurde.

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GuiListView.au3>
    #include <WinAPI.au3>

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

    Local $hGui, $listview, $button, $button2, $item1, $item2, $item3, $item4, $item5, $msg

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

    $hGui = GUICreate("listview items", 220, 250, 100, 200)

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

    $listview = GUICtrlCreateListView("col1 |col2|col3|col4 ", 10, 10, 200, 150, -1, 0x21)
    $button = GUICtrlCreateButton("Mark SubItem", 25, 170, 80, 20)
    $button2 = GUICtrlCreateButton("Mark Item", 110, 170, 80, 20)
    $item1 = GUICtrlCreateListViewItem("item1|col12|col13|col14", $listview)
    $item2 = GUICtrlCreateListViewItem("item2|col22|col23|col24", $listview)
    $item3 = GUICtrlCreateListViewItem("item3|col32|col33|col34", $listview)
    $item4 = GUICtrlCreateListViewItem("item4|col42|col43|col44", $listview)
    $item5 = GUICtrlCreateListViewItem("item5|col52|col53|col54", $listview)
    GUISetState()

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

    Do
    $msg = GUIGetMsg()

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

    Select
    Case $msg = $button
    _GuiCtrlListView_MarkItem($hGui, $listview, Random(0, 4, 1), Random(0, 3, 1))
    Case $msg = $button2
    _GuiCtrlListView_MarkItem($hGui, $listview, Random(0, 4, 1), -1, 0xff00)
    EndSelect
    Until $msg = $GUI_EVENT_CLOSE

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

    Func _GuiCtrlListView_MarkItem($hWndGui, $hWnd, $iIndex, $iSubItem, $Color = 0xFF, $Redraw = 1)
    ;funkey April 16, 2010
    Local $iSubItemHelp = $iSubItem
    Local $aWndSize = WinGetPos($hWndGui)
    Local $aWndClientSize = WinGetClientSize($hWndGui)
    Local $aPos = ControlGetPos($hWndGui, "", $hWnd)

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

    Local $tRECT = DllStructCreate('int Left;int Top;int Right;int Bottom')
    If $iSubItem = -1 Then $iSubItemHelp = 0
    Local $aRect = _GUICtrlListView_GetSubItemRect($hWnd, $iIndex, $iSubItemHelp)
    If $iSubItem = 0 Then $aRect[2] = _GUICtrlListView_GetColumnWidth($hWnd, 0)

    DllCall("user32", 'long', 'SetRect', 'ptr', DllStructGetPtr($tRECT), _
    'long', $aRect[0] + $aPos[0] + $aWndSize[2] - $aWndClientSize[0], _
    'long', $aRect[1] + $aPos[1] + $aWndSize[3] - $aWndClientSize[1], _
    'long', $aRect[2] + $aPos[0] + $aWndSize[2] - $aWndClientSize[0], _
    'long', $aRect[3] + $aPos[1] + $aWndSize[3] - $aWndClientSize[1])

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

    If $Redraw Then _WinAPI_RedrawWindow($hWndGui)

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

    Local $hDC, $hBrush, $obj_orig
    $hDC = _WinAPI_GetWindowDC($hWndGui)
    $hBrush = _WinAPI_CreateSolidBrush($Color)
    $obj_orig = _WinAPI_SelectObject($hDC, $hBrush)
    _WinAPI_FrameRect($hDC, DllStructGetPtr($tRECT), $hBrush)

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

    ; clear resources
    _WinAPI_SelectObject($hDC, $obj_orig)
    _WinAPI_DeleteObject($hBrush)
    _WinAPI_ReleaseDC($hWndGui, $hDC)
    EndFunc ;==>_GuiCtrlListView_MarkItem

    [/autoit]