Im ListIconGadget zeichnen

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Im ListIconGadget zeichnen

Beitrag 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.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Im ListIconGadget zeichnen

Beitrag von Nino »

Ja, jetzt läuft Dein erster Code bei mir auch.
Danke für die viele Mühe, Danilo!

Grüße, Nino
BSP
Beiträge: 203
Registriert: 01.02.2009 14:04

Re: Im ListIconGadget zeichnen

Beitrag 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
PB 5.31 (x86) & (x64) Win10
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Im ListIconGadget zeichnen

Beitrag von ts-soft »

Dann werfe Deine Textverkürzungsfunktion mal raus und setze:

Code: Alles auswählen

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

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
BSP
Beiträge: 203
Registriert: 01.02.2009 14:04

Re: Im ListIconGadget zeichnen

Beitrag von BSP »

Hallo Thomas. (ts-soft).
Spitze. :allright: Danke.

Gruß: Bernd
PB 5.31 (x86) & (x64) Win10
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Im ListIconGadget zeichnen

Beitrag 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_().
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
BSP
Beiträge: 203
Registriert: 01.02.2009 14:04

Re: Im ListIconGadget zeichnen

Beitrag 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
PB 5.31 (x86) & (x64) Win10
Antworten