Seite 4 von 4

Re: Im ListIconGadget zeichnen

Verfasst: 17.03.2012 14:48
von Danilo
Nino hat geschrieben:das führt hier
PB 4.60 unter Win XP SP3 x86 (egal ob im Unicode-Modus compiliert oder nicht)
zum selben Ergebnis wie vorher.
Danke, Nino. Habe es auf XP debuggt und es kamen dort immer falsche Werte für \rc\top von Windows.
Könnte ein Bug in der Comctl32.dll auf veralteten Windows-Systemen sein, jedenfalls habe ich dazu
einen Kommentar bei MSDN gefunden, wo Jemand das gleiche rausgefunden hat.

Habe im ersten Code einen 2-Zeilen-Fix hinzugefügt:

Code: Alles auswählen

              \rc\left = 0
              SendMessage_(GadgetID(gadget),#LVM_GETITEMRECT,\dwItemSpec,@\rc)
Braucht keine externe *.exe.manifest, aber XP Skin anschalten, so daß es auf allen Systemen ab XP geht.

Re: Im ListIconGadget zeichnen

Verfasst: 17.03.2012 15:41
von Nino
Ja, jetzt läuft Dein erster Code bei mir auch.
Danke für die viele Mühe, Danilo!

Grüße, Nino

Re: Im ListIconGadget zeichnen

Verfasst: 18.03.2012 03:03
von BSP
Hallo.
Ich habe das Beispiel von Danilo, wo die Balken gezeichnet werden,
in mein Programm eingebaut.
Nun aber folgendes:
Meine Liste hat mehrere Spalten und natürlich kann es vorkommen,
das ein Text breiter als die Spalte ist.
Das führt so zu unschöner Darstellung.
Nun habe ich nach einer Lösung gesucht und den API:
GetTextExtentPoint32_
gefunden und dazu eine "Textverkürzugsschleife" gebastellt.
Funktioniert auch ganz gut.
Nun die Frage:
Geht die Schleife auch schneller zu gestalten,
oder gibt es sogar ein API, der das erledigt?

Gruß : Bernd

Code: Alles auswählen

;
; by Danilo, March 2012, PB4.60
;
; http://forums.purebasic.com/german/viewtopic.php?f=3&t=25336
;
EnableExplicit

Define EventID
Define i, font
font = LoadFont(#PB_Any, "Lucida Sans Unicode", 10)

Procedure WinCallback(hWnd, Msg, wParam, lParam)
  Protected gadget

  If Msg = #WM_DRAWITEM
    Protected *di.DRAWITEMSTRUCT = lParam
    If *di And *di\CtlType = #ODT_LISTVIEW
      With *di
        gadget = \CtlID

        If IsGadget(gadget) And GadgetType(gadget)=#PB_GadgetType_ListIcon
          Protected text.s    = GetGadgetItemText(gadget,\itemID,0)                    ; text holen
          Protected width0    = GetGadgetItemAttribute(gadget,0,#PB_ListIcon_ColumnWidth)   ; breite von column 0 holen
          Protected width1.f  = GetGadgetItemAttribute(gadget,0,#PB_ListIcon_ColumnWidth,1) ; breite von column 1 holen
          Protected brush     = CreateSolidBrush_(RGB($00,$00,$FF))                    ; pinsel mit farbe für die balken erstellen
          Protected brushsel  = CreateSolidBrush_(RGB($FF,$FF,$00))                    ; pinsel mit farbe für selektierte items
          Protected background= CreateSolidBrush_(RGB($C2,$D4,$EF))                    ; hintergrundfarbe setzen
          Protected percent.f = width1/100*ValF(text)                                  ; balkenlaenge in prozent ausrechnen
          Protected oldBrush,oldPen,bbrush

          If GetGadgetItemState(gadget,\itemID)=#PB_ListIcon_Selected
            bbrush = brushsel                                                          ; hintergrund fuer ausgewaehlte items
          Else
            bbrush = background                                                        ; hintergrund fuer normale items
          EndIf
          oldBrush = SelectObject_(\hDC,bbrush)
          oldPen   = SelectObject_(\hDC,GetStockObject_(#NULL_PEN))
          Rectangle_(\hDC,0,\rcItem\top,\rcItem\right+1,\rcItem\bottom+1)              ; hintergrund zeichnen
          SelectObject_(\hDC,oldBrush)
          SelectObject_(\hDC,oldPen)

          ; optional: den text umranden
;               oldBrush = SelectObject_(\hdc,GetStockObject_(#HOLLOW_BRUSH))                   ; innenfarbe durchsichtig
;               oldPen   = SelectObject_(\hdc,GetStockObject_(#BLACK_PEN))                      ; umrandung schwarz
;               Rectangle_(\hdc,\rcItem\left,\rcItem\top,\rcItem\left+width0,\rcItem\bottom+1)                 ; text umranden
;               Rectangle_(\hdc,\rcItem\left+width0-1,\rcItem\top,\rcItem\left+width0+width1,\rcItem\bottom+1) ; balken umranden
;               SelectObject_(\hDC,oldBrush)
;               SelectObject_(\hDC,oldPen)

; text in column 0 zeichnen
        ; erst Textlänge prüfen & G.g. anpassen
          Protected tw.SIZE , i
          GetTextExtentPoint32_(\hdc, text, Len(text), tw)
          If tw\cx > width0-5
            For i = 1 To  Len(text)
              Protected text1.s = PeekS(@text,Len(text)-i)+"..."
              GetTextExtentPoint32_(\hdc, text1, Len(text1), tw)
              If tw\cx < width0-5
                text = text1
                Break
              EndIf
            Next
          EndIf
        ; Nun Text zeichnen
          SetTextColor_(\hdc,RGB($00,$00,$00))                                         ; textfarbe setzen
          TextOut_(\hdc,\rcItem\left+5,\rcItem\top+1,@text,Len(text))
          ;ExtTextOut_(\hdc,\rcItem\left+5,\rcItem\top+1,#ETO_CLIPPED,0,@text,Len(text),0)

; balken mit dem pinsel in column 1 zeichen
          oldBrush = SelectObject_(\hdc,brush)
          oldPen   = SelectObject_(\hdc,GetStockObject_(#NULL_PEN))
          Rectangle_(\hdc,\rcItem\left+width0,\rcItem\top+1,\rcItem\left+width0+percent,\rcItem\bottom)       ; normale balken
          ;RoundRect_(\hdc,\rcItem\left+width0,\rcItem\top+2,\rcItem\left+width0+percent,\rcItem\bottom,12,12) ; alternativ: abgerundete balken ohne AntiAliasing
          SelectObject_(\hDC,oldBrush)
          SelectObject_(\hDC,oldPen)

          ; pinsel loeschen
          DeleteObject_(brush)
          DeleteObject_(brushsel)
          DeleteObject_(background)
        EndIf
      EndWith
    EndIf
    ProcedureReturn #True
  EndIf
  ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

RandomSeed(3)

If OpenWindow(0,0,0,650,400,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  SetWindowCallback(@WinCallback())
 
  ListIconGadget(2,10,10,WindowWidth(0)-20,WindowHeight(0)-20,"Zahl",50,#LVS_OWNERDRAWFIXED|#PB_ListIcon_MultiSelect|#PB_ListIcon_GridLines) ; ListIconGadget mit Flag #LVS_OWNERDRAWFIXED
  AddGadgetColumn(2,1,"Balken",550)
  SetGadgetFont(2, FontID(font))
  
  SetGadgetColor(2,#PB_Gadget_BackColor,RGB($C2,$D4,$EF))
 
  For i=0 To 199
    AddGadgetItem(2,-1,Str(Random(100))+" Ein super langer Text")
  Next
 
  Repeat
    EventID=WaitWindowEvent()
    If EventID = #PB_Event_CloseWindow
      End
    EndIf
  ForEver
EndIf

Re: Im ListIconGadget zeichnen

Verfasst: 18.03.2012 03:41
von ts-soft
Dann werfe Deine Textverkürzungsfunktion mal raus und setze:

Code: Alles auswählen

PathCompactPath_(\hDC, text, width0 - 4)
ein.

Gruß
Thomas

Re: Im ListIconGadget zeichnen

Verfasst: 18.03.2012 04:14
von BSP
Hallo Thomas. (ts-soft).
Spitze. :allright: Danke.

Gruß: Bernd

Re: Im ListIconGadget zeichnen

Verfasst: 18.03.2012 05:11
von Danilo
Dein ExtTextOut_() hat nicht abgeschnitten (geclipped), weil Du \rcItem nicht mit übergeben hast.
So gehts, der Text wird einfach nur in das RECT gezeichnet, nicht darüber hinaus:

Code: Alles auswählen

          \rcItem\right=width0
          ExtTextOut_(\hdc,\rcItem\left+5,\rcItem\top+1,#ETO_CLIPPED,\rcItem,@text,Len(text),0)
Mit DrawText hast Du noch mehr Formatierungsmöglichkeiten. Vertikales zentrieren macht Sinn,
so dass der Text von der Höhe her in der Mitte gezeichnet wird.
Aber auch #DT_LEFT, #DT_RIGHT und #DT_CENTER sind möglich.

#DT_END_ELLIPSIS zeichnet am Ende automatisch "...".

Code: Alles auswählen

          \rcItem\right = width0
          DrawText_(\hDC,@text,Len(text),\rcItem,#DT_VCENTER|#DT_END_ELLIPSIS|#DT_SINGLELINE)
Schau Dir mal die Hilfe zu DrawText_() und DrawTextEx_() an, da stehen alle Formatierungsflags.
Macht mehr Sinn eine Funktion mit Clipping zu verwenden, statt einfaches TextOut_().

Re: Im ListIconGadget zeichnen

Verfasst: 18.03.2012 05:50
von BSP
Hallo Leute.
Tja, was soll ich noch sagen:
Ich bin schlichtweg überwältigt.

Mein Problem ist leider, das ich mit der MS- Apihilfe nicht klar komme.
Und so weiss ich zwar, was ich will,
aber nicht wie das heisst, was ich suche.
Oder richtiger noch, wo ich suchen muss.
Werde ich aber auf die richtigen Namen gestossen,
finde ich meistens auch weiter.

Eure Hilfe bisher war klasse.
Und so bleibt mir nur nochmals Danke zu sagen.
Da habe ich ja nun eine Menge zum Basteln bekommen.

Danke: Bernd