Buchempfehlung
Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie
Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie
Umfassend, aber leicht verständlich führt dieses Buch in die Programmierung von ATMEL AVR Mikrocontrollern ein. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Code-Beispiel

Code-Beispiele » Maus und Tastatur

DRAW-STRING-Eingabefunktion Textbox.bi

Lizenz:Erster Autor:Letzte Bearbeitung:
MIT-LizenzAdministratorSebastian 08.05.2010
INPUT auf grafischem Hintergrund
Vergrößern
INPUT auf grafischem Hintergrund

Möchte man Texteingaben im Grafikmodus abfragen, steht dazu üblicherweise nur BefehlsreferenzeintragINPUT (Anweisung) zur Verfügung. INPUT zerstört jedoch einen etwaigen grafischen Hintergrund, indem der gesamte Eingabebereich einfarbig den Hintergrund übermalt (siehe Screenshot rechts). Zudem lässt sich die Eingabe nur zeilen- und spaltenweise mit BefehlsreferenzeintragLOCATE positionieren und nicht pixelgenau wie eine Ausgabe mit BefehlsreferenzeintragDRAW STRING.

Der folgende Code stellt eine alternative Eingaberoutine bereit, die die oben genannten Probleme mit der Eingabe in Grafikmodi umgeht. Der Autor, Ray Britton, hat den Code ursprünglich im Externer Link!internationalen FB-Forum gepostet. Der Code unterliegt der MIT-/X11-Lizenz.

Code für Eingaberoutine

'Draw string/inkey input type

'Ray Britton (C) 2010
'Veroeffentlicht unter der X11/MIT Lizenz
'Quelle: http://www.freebasic.net/forum/viewtopic.php?t=15355
'Eingedeutscht von Sebastian
'  http://www.freebasic-portal.de/benutzer/sebastian-1.html

#include once "fbgfx.bi"

type TextBoxType 'Textbox-Klasse
    private: 'Private Attribute
        as string message 'Die eingegebene Zeichenkette
        as string prompt 'Eingabeaufforderung (z.B. ein "-->" Symbol)
        as integer max 'Sichtbare Laenge des Eingabefelds in Zeichen
                       'Hinweis: Wenn eine Eingabeaufforderung angegeben wurde, ergibt
                       'sich die Anzahl der Zeichen auf dem Bildschirm als(max-LEN(prompt))
        as integer length 'Gegenwaertige Laenge des eingegebenen Strings
        as integer startpoint=1 'Zeichenposition Ausgabebeginn
        as integer x,y 'Position des Texts (X-/Y-Koordinaten)
        as uinteger colour=rgb(255,255,255) 'Schriftfarbe
        as fb.image ptr textback 'Puffer für grafischen Hintergrund
    public: 'Oeffentliche Methoden
        declare constructor(newx as integer, newy as integer, newmax as integer)
        declare destructor()
        declare sub CopyBackground()
        declare sub SetColour(newcolour as uinteger)
        declare sub SetXY(newx as integer, newy as integer)
        declare sub NewLetter(letter as string)
        declare sub Redraw()
        declare sub SetPrompt(newprompt as string)
        declare sub SetString(news as string)
        declare function GetString () as string
        declare function GetX() as integer
        declare function GetY() as integer
        declare function GetColour() as uinteger
end type

sub textboxtype.setstring(news as string)
    if news<>"" then
        message=left(news,len(message)-1)
        length=len(message)
        newletter(right(news,1))
    else
        message=""
        length=0
        Redraw()
    end if
end sub

Constructor TextBoxType(newx as integer, newy as integer, newmax as integer)
    'Ueberprueft, ob ein Grafikmodus aktiv ist
    if ScreenPtr<>0 then 'Wenn ja, ...
        textback=imagecreate(newmax*8+20,24) '...Speicher fuer Hintergrund reservieren
        x=newx
        y=newy
        max=newmax
    else 'Wenn nein, Fehlermeldung ausgeben:
        print "Fehler: Diese Eingaberoutine funktioniert nur in Grafikmodi."
        sleep
        end
    end if
end constructor

sub TextBoxType.Redraw()
    put (x-3,y-3),textback,pset 'Gesicherten Hintergrund wiederherstellen
    'Aktuellen Text ausgeben:
    draw string (x,y),str(prompt + mid(message,startpoint)),colour
end sub

sub TextBoxType.SetColour(newcolour as uinteger) 'Textfarbe setzen
    colour=newcolour
end sub

function TextBoxType.GetColour() as uinteger 'Textfarbe abfragen
    return colour
end function

function TextBoxType.GetString() as string 'Eingabe als STRING abfragen
    return message
end function

function TextBoxType.GetX() as integer 'X-Koordinate abfragen
    return x
end function

function TextBoxType.GetY() as integer 'Y-Koordinate abfragen
    return y
end function

sub TextBoxType.SetXY(newx as integer, newy as integer) 'Eingabe positionieren
    x=newx
    y=newy
end sub

destructor TextBoxType() 'Destructor fuer die Textbox
    imagedestroy(textback)
end destructor

sub TextBoxType.CopyBackground() 'Eingabehintergrund in Puffer sichern
    get (x-3,y-3)-(x+(max*8+15),y+18),textback
end sub

sub TextBoxType.SetPrompt(newprompt as string) 'Eingabeaufforderung festlegen
    prompt=newprompt
end sub

sub TextBoxType.NewLetter(letter as string)
    dim as integer redrawflag=0
    if asc(letter)=8 then 'Wenn das eingegebene Zeichen BACKSPACE war, ...
        message=left(message,len(message)-1) '... letztes Zeichen entfernen
        length-=1 'Laengenangabe um 1 verringern
        if length<0 then length=0 'Ggf. unsinnvollen, negativen Wert korrigeren
        redrawflag=1 'Eingabe wurde veraendert -> Neu zeichnen!
    end if
    if asc(letter)>31 and asc(letter)<127 then 'Buchstabe, Zahl oder Sonderzeichen ...
        message+=letter '... an gespeicherte Gesamteingabe anhaengen
        length+=1 'Laengenangabe um 1 erhoehen
        redrawflag=1
    end if
    if length+len(prompt)>max then 'Wird die maximale Feldlaenge ueberschritten, ...
        startpoint=length+len(prompt)-max 'scrollt die Eingabe: Ausgabe nicht mit dem
                                          'ersten Zeichen sondern spaeter beginnen
    else 'Kein Scrollen noetig.
        startpoint=1 'Daher Eingabe von Beginn an ausgeben
    end if
    if redrawflag=1 then Redraw() 'Falls noetig, neu zeichnen.
end sub

Anwendungsbeispiel

Das folgende Beispiel demonstriert die Vorzüge der alternativen Eingaberoutine. Die Eingabe lässt sich mit Pfeiltaste-Hoch/-Runter pixelgenau verschieben und funktioniert sogar vor einem animierten Grafikhintergrund.
Speichern Sie Textboxroutinen (Code siehe oben) als textbox.bi im gleichen Verzeichnis wie den folgenden Beispielcode.

#include "textbox.bi"

screen 19,32 'Grafikmodus

dim TextField as textboxtype=textboxtype(4,4,40) 'Neue Textbox erzeugen

dim as string letter

TextField.SetColour(rgb(0,255,255))

TextField.SetPrompt("----->")

do

    screenlock
        cls 'Bildschirm leeren
        'Animierten Hintergrund zeichnen:
        for i as integer = 1 to 800 step 2
            'Linien mit zufaelligen Koordinaten zeichnen
            line(i+(int(rnd*(20--20)+-20)),1)-(i+(int(rnd*(20--20)+-20)),600),rgb(150,0,0)
        next
        'Textbox aktualisieren:
        TextField.CopyBackground()
        TextField.Redraw()
    screenunlock

    'Pfeiltaste-Unten verschiebt die Eingabe um 1 Pixel nach unten rechts.
    if multikey(fb.sc_down) then
        TextField.SetXY(TextField.GetX()+1,TextField.GetY()+1)
    end if

    'Pfeiltaste-Oben verschiebt die Eingabe um 1 Pixel nach oben links.
    if multikey(fb.sc_up) then
        TextField.SetXY(TextField.GetX()-1,TextField.GetY()-1)
    end if

    letter=inkey 'Eingabe abfragen
    if letter<>"" then 'Es wurde etwas eingeben.
        TextField.NewLetter(letter) 'Zeichen an Textbox weiterreichen.
    end if

    sleep 1 'CPU-Auslastung reduzieren

loop until asc(letter)=13 or asc(letter)=27 'Programmende durch ESC oder ENTER


Zusätzliche Informationen und Funktionen
  • Das Code-Beispiel wurde am 08.05.2010 von AdministratorSebastian angelegt.
  • Die aktuellste Version wurde am 08.05.2010 von AdministratorSebastian gespeichert.
  Bearbeiten Bearbeiten  

  Versionen Versionen