Hier die Abhilfe.
Meine Frage: in der 2.Prozedur flimmert es etwas auf meinem etwas betagten Rechner (1 Ghz). Gibt es eine bessere Lösung als meine in der 1.Prozedur ?
Code: Alles auswählen
;Beim Scrollen in einem ListIconGadget bleibt die markierte Zeile in der Mitte
;außer am Anfang und am Ende
;
;die beiden Prozeduren tun im Ergebnis das Gleiche, nur eine flimmert etwas auf
;langsameren Rechnern, dafür ist Sie aber kürzer und einfacher.
Declare Api_LVM_Scroll_zurMitte_Version1 (hdc,actPos)
Declare Api_LVM_Scroll_zurMitte_Version2 (hdc,actPos)
Enumeration
#list_nr0
#list_nr1
EndEnumeration
#alle=-1
#list_sp=10
#list_br=600
#list_hh=200
#list_ze0=10
#list_ze1=230
#list_brCol0=289
#list_brCol1=289
hwnd = OpenWindow(0,0,0,640,480,"Testfenster")
CreateGadgetList(hwnd)
maxlist = 500
listflags = #PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect
hdc0=ListIconGadget(#list_nr0,#list_sp,#list_ze0, #list_br, #list_hh, "Test 0" ,#list_brCol0,listflags)
AddGadgetColumn(#list_nr0, 1, "Spalte 2", #list_brCol1)
hdc1=ListIconGadget(#list_nr1,#list_sp,#list_ze1, #list_br, #list_hh, "Test 1" ,#list_brCol0,listflags)
AddGadgetColumn(#list_nr1, 1, "Spalte 2", #list_brCol1)
;für schnelleren Bildaufbau,
SendMessage_(hdc0, #WM_SETREDRAW, #False, 0)
SendMessage_(hdc1, #WM_SETREDRAW, #False, 0)
backfarbe = $F0F0F0 ;oder GetSysColor_(#COLOR_INACTIVEBORDER)
;Gadget füllen
For i = 1 To maxlist
AddGadgetItem(#list_nr0,-1,"Test"+Str(i)+#LF$+"Spalte 2")
AddGadgetItem(#list_nr1,-1,"Test"+Str(i))
;jede 2.Zeile farbiger Hintergrund
If i % 2
SetGadgetItemColor(#list_nr0, i-1, #PB_Gadget_BackColor, backfarbe, #alle)
SetGadgetItemColor(#list_nr1, i-1, #PB_Gadget_BackColor, backfarbe, #alle)
EndIf
Next
;Gadget anzeigen/redraw
SendMessage_(hdc0, #WM_SETREDRAW, #True, 0)
SendMessage_(hdc1, #WM_SETREDRAW, #True, 0)
Repeat
EventID = WaitWindowEvent()
If EventID = #PB_Event_Gadget
welcherButton=EventGadget()
Select welcherButton
Case #list_nr0
;welche Zeile, mit der Maus angeklickt oder mit den Pfeiltasten
listzeiger = GetGadgetState(#list_nr0)
Api_LVM_Scroll_zurMitte_Version1(hdc0,listzeiger)
Case #list_nr1
listzeiger = GetGadgetState(#list_nr1)
Api_LVM_Scroll_zurMitte_Version2(hdc1,listzeiger)
EndSelect
EndIf
Until EventID = #PB_Event_CloseWindow
End
Procedure Api_LVM_Scroll_zurMitte_Version1(hdc,actPos)
;ermittelt Höhe einer Zeile
SendMessage_(hdc,#LVM_GETITEMRECT,0,r.RECT)
lvm_itemhh = r\bottom - r\top
;lvm_mitte kann auch einen anderen Wert haben, z.b. 2
; / 2 = ca mittlere Zeile des Listicongadget
lvm_mitte = SendMessage_(hdc,#LVM_GETCOUNTPERPAGE ,0,0) / 2
;1.sichtbare Zeile
lvm_topidx = SendMessage_(hdc,#LVM_GETTOPINDEX,0,0)
;errechnet Anzahl Pixel zum scrollen
abstand2 = lvm_itemhh * actPos
abstand1 = lvm_itemhh * (lvm_topidx + lvm_mitte)
diff = abstand2 - abstand1
;oder das Gleiche nur etwas unverständlicher
;diff = lvm_itemhh * (actPos - (lvm_topidx+lvm_mitte))
SendMessage_(hdc, #LVM_SCROLL, 0, diff)
EndProcedure
Procedure Api_LVM_Scroll_zurMitte_Version2(hdc,actPos)
;diese Version flimmert bei langsamen Rechnern etwas, besonders der rechte Scrollbalken
;ist dafür aber kürzer und einfacher
;#WM_SETREDRAW hilft nicht viel gegen das Flimmern, im Gegenteil,
;Windows kommt durcheinander, wenn man den Finger auf den Pfeiltasten läßt, auch mit InvalidateRect_
SendMessage_(hdc,#LVM_GETITEMRECT,0,r.RECT)
lvm_itemhh = r\bottom - r\top
lvm_mitte = SendMessage_(hdc,#LVM_GETCOUNTPERPAGE ,0,0) / 2
;scrollt zuerst ganz nach oben
SendMessage_(hdc,#LVM_ENSUREVISIBLE,0,0)
;scrollt in die mitte
SendMessage_(hdc, #LVM_SCROLL, 0, (actPos-lvm_mitte) * lvm_itemhh)
EndProcedure