TextGadget() im ScrollAreaGadget(), wenn zu langer Text

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
WPö
Moderator
Beiträge: 669
Registriert: 27.05.2008 12:44
Wohnort: Oberland
Kontaktdaten:

TextGadget() im ScrollAreaGadget(), wenn zu langer Text

Beitrag von WPö »

Inhalt: Dies ist ein Demo über ein in der Höhe variables TextGadget(). Minimal- und Maximalhöhe werden getrennt angegeben. Sollte der Text zu lang für die max. Höhe sein, wird der Text in ein ScrollAreaGadget() gepackt.

Nutzung: Verändern der Eigenschaften wie die Farbe geschieht ganz normal mit der Klickflächennummer: z.B.

Code: Alles auswählen

SetGadgetColor(Nr, #PB_GadgetFrontColor, MeineFarbe)
.

Anmerkung: Dynamisches Ändern der Parameter ist entweder nicht möglich (Rahmen) oder nur unter einem irren Aufwand. Ein anderer Text, Zeichensatz oder eine andere Breite erzwingen die komplette Neuberechnung. Geänderte kleinste und größte Höhen würden ausufernde Berechnungen notwendigmachen und Platz für Eigenschaften erfordern, ohne daß dabei die Möglichkeit ausgeschlossen würde, daß die komplette Klickfläche doch neu erzeugt werden müßte. Allein das Verschieben ist ohne Neuberechnungen möglich. Letztlich ist es das schnellste, bei anstehenden Änderungen die Klickfläche neu zu erstellen. Wer mir nicht glauben will, darf sich gerne wie ich tagelang damit beschäftigen, es besser zu machen. Sobald man nämlich versucht, ein Loch zu stopfen, reißt man gleich ein neues Faß auf. Konsequent zuendeprogrammiert, würde das den 3-4fachen Quelltext ergeben und viel langsamer sein als Neuerstellen.

Der Code funktioniert nur bei Windoof, da die WinAPI verwendet wird. Ein großes Danke geht an Kiffi für seinen Lösungsansatz.

Rechtliches: Der Quelltext ist kostenlos :D und Public Domain. Nutzung auf eigene Gefahr!

Code: Alles auswählen

Declare TextGadgetVarHeight(Nr.l, PosX.w,PosY.w, Breite.w,minHohe.w,maxHohe.w, Text.s, ZeichensatzID.l, Flaggen.l)
Declare MoveTextGadgetVarHeight(Nr.l, PosX.w,PosY.w)
Declare FreeTextGadgetVarHeight(Nr.l)

;Filmtext aus der Wikipedia 2007 entnommen, Stichwort "Stirb langsam 2", rechtschreibkorrigiert.
Text.s = "Während eines Schneesturmes begibt sich Polizist John McClane auf den Washingtoner Flugh"
Text + "afen, um seine Frau Holly abzuholen und mit ihr gemeinsam den Weihnachtsabend zu verbringe"
Text + "n."+#LF$+"Zur gleichen Zeit erreicht auch der korrupte Offizier Colonel Stuart mit einer b"
Text + "ewaffneten Söldnertruppe das Flughafengelände und besetzt eine alte Kirche als Kommandopos"
Text + "ten. Er läßt die Energie- und Kommunikationsleitungen anzapfen und übernimmt von der Kirch"
Text + "e aus die Kontrolle über den Flughafen. Seine Forderung: Der ehemalige südamerikanische Di"
Text + "ktator General Ramón Esperanza soll freigelassen werden. Dieser befindet sich gerade in ei"
Text + "ner Transportmaschine im Anflug auf Washington. Sollte die Forderung nicht erfüllt werden,"
Text + " werde Stuart die in der Warteschleife über dem Flughafen kreisenden Linienmaschinen abstü"
Text + "rzen lassen."+#LF$+"McClane, dessen Frau Holly sich in einem der bedrohten Flugzeuge befin"
Text + "det, bietet den Verantwortlichen seine Hilfe an. Alle Versuche, die Kontrolle zurückzugewi"
Text + "nnen, scheitern, obwohl McClane etliche der Terroristen töten kann. Er kann auch Esperanza"
Text + " an der Transportmaschine abfangen, dieser wird aber wenig später von Stuart und dessen Te"
Text + "rroristen befreit."+#LF$+"McClane und die Flughafenmitarbeiter können im weiteren Verlauf "
Text + "Stuart in dessen Hauptquartier aufstöbern und mit Hilfe des Einsatzkommandos von Major Gra"
Text + "nt die Kirche stürmen. Es zeigt sich allerdings, daß Grant mit Stuart und Esperanza unter "
Text + "einer Decke steckt und die Männer planen, sich mit einem Jumbo-Jet in Esperanzas Heimatlan"
Text + "d abzusetzen. Um die anderen Beteiligten zu täuschen, schießen sie mit Platzpatronen aufei"
Text + "nander."+#LF$+"Da Hollys Maschine und die anderen kreisenden Flugzeuge wegen Treibstoffman"
Text + "gels zu einer Notlandung gezwungen sind, begibt sich McClane auf eine Tragfläche der Boein"
Text + "g 747 der Terroristen. Er kann einen Treibstofftank öffnen und das Flugzeug durch Entzünde"
Text + "n des auslaufenden Kerosins zur Explosion bringen. Die Trümmer dienen den notlandenden Mas"
Text + "chinen als Leuchtfeuer."+#LF$+"John und seine Frau sind wieder vereint und feiern Weihnach"
Text + "ten."

;Fensterchen, in dem 10 mal pro Sekunde ein TextGadget() geöffnet und wieder geschlossen wird. Die
;Mindesthöhe ist immer 20 Pixel kleiner als die Maximalhöhe. Diese wandert zwischen zwei Punkten
;hin und her. Den Text sieht man also in allen 3 Szenarien: Höhe<minHöhe, minHöhe<=Höhe<=maxHöhe,
;Höhe>maxHöhe. Die ZeichensatzID kann auch auf #PB_Default festgelegt werden.
If OpenWindow(0, 1100,100, 400,360, "TextGadget() mit definierbaren min. und max. Höhen", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget)
  If CreateGadgetList(WindowID(0))
    LoadFont(1, "Tahoma", 7)
    Startzeit = ElapsedMilliseconds()
    maxHohe = 310
    Hohenschritt = -1
    Repeat
      Event = WaitWindowEvent(1)
      If Event = #PB_Event_Gadget
        Gad = EventGadget()
      EndIf
      If ElapsedMilliseconds()-Startzeit >= 100
        Startzeit + 100
        If maxHohe >= 340 : Hohenschritt = -1 : EndIf
        If maxHohe <= 290 : Hohenschritt = 1 : EndIf
        maxHohe + Hohenschritt
        If Nr : FreeTextGadgetVarHeight(Nr) : EndIf
        Nr = TextGadgetVarHeight(1, 10,10, 380,maxHohe-20,maxHohe, Text, FontID(1), #PB_Text_Border)
      EndIf
    Until Event = #PB_Event_CloseWindow
    If Nr : FreeTextGadgetVarHeight(Nr) : EndIf
  EndIf
  CloseWindow(0)
EndIf
End

Procedure TextGadgetVarHeight(Nr.l, PosX.w,PosY.w, Breite.w,minHohe.w,maxHohe.w, Text.s, ZeichensatzID.l, Flaggen.l)
  Define.w RahmenX,RahmenY, Rollbalkenbreite, h1,h2
  ;Da bei Nr=#PB_Any sehr große Zahlen herauskommen können, die in Folge zu Fehlern führen
  ;(Nr>10000), entledigen wir uns hier einfach der problematischen Automatik.
  If Nr = #PB_Any
    Nr = 0
    Repeat : Nr + 1 : Until IsGadget(Nr) = 0
  EndIf
  TextGadget(Nr, PosX,PosY, Breite,minHohe, "", Flaggen)
  SetGadgetData(Nr, Nr)
  If ZeichensatzID = #PB_Default : ZeichensatzID = GetGadgetFont(#PB_Default) : EndIf
  If Flaggen & #PB_Text_Border
    RahmenX = GetSystemMetrics_(#SM_CXEDGE)
    RahmenY = GetSystemMetrics_(#SM_CYEDGE)
  Else
    ScrollFlaggen = #PB_ScrollArea_BorderLess
  EndIf
  Rollbalkenbreite = GetSystemMetrics_(#SM_CXVSCROLL)
  rc.RECT
  hdc = GetDC_(GadgetID(Nr))
  SetTextAlign_(hdc,#TA_LEFT|#TA_TOP|#TA_NOUPDATECP)
  SelectObject_(hdc,ZeichensatzID)
  rc\right = Breite - 2*RahmenX
  h1 = DrawText_(hdc,Text,Len(Text),rc,#DT_WORDBREAK|#DT_CALCRECT) + 2*RahmenY
  rc\right = Breite - Rollbalkenbreite - 2*RahmenX
  h2 = DrawText_(hdc,Text,Len(Text),rc,#DT_WORDBREAK|#DT_CALCRECT) + 2*RahmenY
  ReleaseDC_(GadgetID(Nr),hdc)
  If h1 > minHohe And h1 <= maxHohe
    ResizeGadget(Nr, #PB_Ignore,#PB_Ignore, #PB_Ignore,h1)
  ElseIf h1 > maxHohe
    FreeGadget(Nr)
    ;Nr=#PB_Any wird nicht notwendigerweise verwendet. Damit wir uns nicht eine Nummer blockieren,
    ;die im Hauptprogramm vielleicht genutzt wird, nehmen wir die größte freie Nummer unter 10000.
    ScrollNr = 10000 : Repeat : ScrollNr - 1 : Until IsGadget(ScrollNr) = 0
    ScrollAreaGadget(ScrollNr, PosX,PosY, Breite,maxHohe, Breite-Rollbalkenbreite-2*RahmenX,h2, maxHohe-2*RahmenY, ScrollFlaggen)
      TextGadget(Nr, 0,0, Breite-Rollbalkenbreite-2*RahmenX,h2, "", Flaggen&~#PB_Text_Border)
      SetGadgetData(Nr, ScrollNr)
    CloseGadgetList()
  EndIf
  SetGadgetFont(Nr, ZeichensatzID)
  SetGadgetText(Nr, Text)
  ProcedureReturn Nr
EndProcedure

Procedure MoveTextGadgetVarHeight(Nr.l, PosX.w,PosY.w)
  ResizeGadget(GetGadgetData(Nr), PosX,PosY, #PB_Ignore,#PB_Ignore)
EndProcedure

Procedure FreeTextGadgetVarHeight(Nr.l)
  ScrollNr = GetGadgetData(Nr)
  FreeGadget(Nr)
  If ScrollNr <> Nr
    FreeGadget(ScrollNr)
  EndIf
EndProcedure
Viel Spaß damit!