Seite 1 von 1

Scrollen ListIconGadget,Zeile bleibt in der Mitte - Flimmern

Verfasst: 09.07.2007 22:44
von hjbremer
Wenn man in einem ListIconGadget mit den Pfeiltasten sich bewegt, und man ist oben/unten, dann störte mich, das ich die folgenden Einträge nicht sehen konnte.
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


Verfasst: 09.07.2007 23:06
von Fluid Byte
Das lässt sich nicht abstellen. Selbst die Windows-eigenen Listen flackern/flimmern beim scrollen.

Verfasst: 09.07.2007 23:46
von hjbremer
SHIT :(

Verfasst: 10.07.2007 09:29
von edel
Vielleicht hilft es ja wenn du Doublebuffer fuer das
Listview einschaltest (ab XP).

Du hast fuer deine Variablen ein recht ungluecklichen Namen
gewaehlt, falls es nur fuer dich ist, ist es zwar egal, aber hdc
ist eigentlich ein Handle zu einem Device Context.

Verfasst: 10.07.2007 11:56
von hjbremer
Meinst du LVS_EX_DOUBLEBUFFER ?

zum einen steht in der MSDN erst ab Version 6.00 der comctl.dll
ich habe 5.82

zum anderen kennt meine PB Version 4.02 die Konstante nicht

Hast du eine Lösung ?

Verfasst: 10.07.2007 12:35
von edel
hjbremer hat geschrieben:Meinst du LVS_EX_DOUBLEBUFFER ?
Ja.
hjbremer hat geschrieben: zum einen steht in der MSDN erst ab Version 6.00 der comctl.dll
ich habe 5.82
Dann wird das wohl nichts
hjbremer hat geschrieben: zum anderen kennt meine PB Version 4.02 die Konstante nicht

Hast du eine Lösung ?

Code: Alles auswählen

#LVM_SETEXTENDEDLISTVIEWSTYLE = #lvm_first + 54
#LVM_GETEXTENDEDLISTVIEWSTYLE = #lvm_first + 55
#LVS_EX_DOUBLEBUFFER = 65536
Zu dem Code kann ich nichts sagen , da ich das Problem
nicht erkennen kann 8)

Verfasst: 10.07.2007 13:34
von hjbremer
Danke für die Info :D werds mir notieren bis zum neueren Compu

Verfasst: 10.07.2007 16:15
von Fluid Byte
Du könntest zur Not das ListIconGadget auch Ownerdraw machen und auf ein Bitmap zeichen. Währe ein wenig aufwendig aber ebenfalls "flicker-free".