ABOUT Visual Basic Programmieren Programmierung Download Downloads Tips & Tricks Tipps & Tricks Know-How Praxis VB VBA Visual Basic for Applications VBS VBScript Scripting Windows ActiveX COM OLE API ComputerPC Microsoft Office Microsoft Office 97 Office 2000 Access Word Winword Excel Outlook Addins ASP Active Server Pages COMAddIns ActiveX-Controls OCX UserControl UserDocument Komponenten DLL EXE
Diese Seite wurde zuletzt aktualisiert am 21.02.2000

Diese Seite wurde zuletzt aktualisiert am 21.02.2000
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicActiveX-Komponenten, Controls, Klassen und mehr...AddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für den Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zum ABOUT Visual Basic-Magazin, Kontakt und Impressum

Zurück...

Buchstabendreher-Dreher

Zurück...


Anzeige

(-hg) mailto:hg_swapchars@aboutvb.de

Selbst routinierten Vielschreibern unterlaufen sie ständig, die Ubchstabendreher, pardon, Buchstabendreher. Wie wäre es damit, dass Sie Ihre TextBoxen oder RichTextBoxen mit einer Funktion aufrüsten, die auf Tastendruck einen Dreher korrigiert?


Buchstabendreher auf Tastendruck korrigiert

"Das ist doch kein Problem!" - werden Sie sagen. "Man selektiere einfach die beiden betroffenen Zeichen bzw. schneide sie aus einem String heraus, vertausche den rechten und linken Buchstaben und füge das korrigierte Buchstabenpaar wieder an der richtigen Stelle ein...". Ja, das ist so einfach, dass ich Ihnen dafür sicher kein Code-Beispiel zu zeigen brauche, oder?

Aber ist es wirklich damit getan? Was ist mit dem obenstehenden "Ubchstabendreher", den ich Ihnen durchaus mit voller Absicht untergejubelt habe? Er würde lediglich zu einem "bUchstabendreher" vermurkst - was sicher nicht das gewünschte Resultat wäre. Die Groß- und Kleinschreibung an den betroffenen Positionen müsste also auf jeden Fall noch beibehalten werden. Versuchen wir uns einmal an einer ersten Funktion, die die Aufgabenstellung zu bewältigen versucht. Gleich vorweg gesagt: Zur Prüfung, ob es sich bei einem Zeichen um einen Klein- oder um einen Großbuchstaben handelt, verwenden wir die API-Funktionen MSDN Library - API IsCharLowerIsCharLower und MSDN Library - API IsCharUpperIsCharUpper, die sowohl schneller ausgeführt werden als auch einfacher handzuhaben sind, als die Konstruktion einer Prüfung über MSDN Library - VB LCaseLCase$ und MSDN Library - VB UCaseUCase$.

Der Funktion SwapChars1 wird der zwei Zeichen lange String, der die verdrehten Buchstaben enthält, übergeben. Sie liefert den korrigierten Dreher als Rückgabewert wieder ab. Für den Fall, dass der übergebene String länger als zwei Zeichen sein sollte, wird der Überhang ab dem dritten Zeichen dem Rückgabe-String wieder angehängt.

Private Declare Function IsCharLower Lib "user32" _
 Alias "IsCharLowerA" (ByVal cChar As Byte) As Long
Private Declare Function IsCharUpper Lib "user32" _
 Alias "IsCharUpperA" (ByVal cChar As Byte) As Long

Public Function SwapChars1(Chars As String) As String
  Dim nCharR As String
  Dim nCharL As String
  Dim nCases As Integer
  
  nCharR = Mid$(Chars, 2, 1)
  nCharL = Left$(Chars, 1)
  If IsCharUpper(Asc(nCharL)) Then
    nCases = 1
  End If
  If IsCharUpper(Asc(nCharR)) Then
    nCases = nCases Or 2
  End If
  Select Case nCases
    Case 0, 3
      SwapChars = nCharR & nCharL & Mid$(Chars, 3)
    Case 1
      SwapChars = UCase$(nCharR) & LCase$(nCharL) & _
       Mid$(Chars, 3)
    Case 2
      SwapChars = LCase$(nCharR) & UCase$(nCharL) & _
       Mid$(Chars, 3)
  End Select
End Function

Das sieht schon ganz gut aus, nicht wahr? Die Lösung enthält aber noch ein paar Fallgrübchen. Eine solche Operation sollte ohne weiteres reversibel sein. Der korrigierte Dreher muss sich zurückdrehen lassen, falls sich etwa der Anwender nachträglich entscheiden sollte, dass der Dreher nun doch keiner war. In der gezeigten Form ist sie unter bestimmten Umständen jedoch nicht umkehrbar. Ist nämlich eines der Zeichen ein Großbuchstabe, das andere jedoch eine Ziffer oder irgendein anderes nicht alphanumerisches Zeichen (wie etwa ein Leerzeichen oder ein Bindestrich), wird der Großbuchstabe zwar als solcher erkannt, die Ziffer bzw. das Zeichen jedoch als Kleinbuchstabe identifiziert. Der Großbuchstabe wird daher in einen Kleinbuchstaben an der vertauschten Position verwandelt, was bereits der erste Fehler wäre. Des weiteren muss die versuchte Umwandlung der Ziffer bzw. des Zeichens in einen Großbuchstaben zwangsläufig scheitern. Ein erneuter, rückgängigmachender Aufruf für diese Kombination träfe dann auf vermeintliche zwei Kleinbuchstaben, die einfach nur ausgetauscht würden. Die umgekehrte Umkehrung hätte nun also einen Kleinbuchstaben plus der Ziffer bzw. dem Zeichen an den ursprünglichen Positionen zur Folge.

Wir führen daher zuallererst mittels der API-Funktion MSDN Library - API IsCharAlphaIsCharAlpha eine Prüfung durch, ob beide Zeichen reine Buchstabenzeichen sind. Trifft dies für mindestens eines der beiden Zeichen nicht zu, wird lediglich eine einfache Vertauschung vorgenommen.

Private Declare Function IsCharAlpha Lib "user32" _
 Alias "IsCharAlphaA" (ByVal cChar As Byte) As Long

Public Function SwapChars2(Chars As String) As String
  Dim nCharR As String
  Dim nCharL As String
  Dim nCases As Integer
  
  nCharR = Mid$(Chars, 2, 1)
  nCharL = Left$(Chars, 1)
  If CBool(IsCharAlpha(Asc(nCharL))) _
   And CBool(IsCharAlpha(Asc(nCharR))) Then
    If IsCharUpper(Asc(nCharL)) Then
      nCases = 1
    End If
    If IsCharUpper(Asc(nCharR)) Then
      nCases = nCases Or 2
    End If
    Select Case nCases
      Case 0, 3
        SwapChars = nCharR & nCharL & Mid$(Chars, 3)
      Case 1
        SwapChars = UCase$(nCharR) & LCase$(nCharL) & _
         Mid$(Chars, 3)
      Case 2
        SwapChars = LCase$(nCharR) & UCase$(nCharL) & _
         Mid$(Chars, 3)
    End Select
  End If
End Function

So weit, so gut - wir könnten es bei diesem Stadium der Lösung belassen. Nun wäre es aber möglich, dass zufällig (oder aus welchem Grund auch immer) eines der beiden Zeichen ein Zeilentrennzeichen ist. Etwa dann, wenn sich die Schreibmarke gerade am Anfang oder am Ende einer Zeile befindet, während der Anwender (versehentlich) den Befehl zum Tauschen gibt. Allerdings macht es jedoch nicht viel Sinn, eine Vertauschung über einen Zeilenwechsel (in der Regel wäre ein solcher ja sogar ein Absatzbeginn) vorzunehmen. Und zudem besteht eine Zeilentrennung meistens aus den zwei aufeinanderfolgenden Zeichen für den (historischen) Wagen- bzw. Druckkopfrücklaufs (vbCR = "Carriage Return") und der eigentlichen Zeilenschaltung (vbLf = "Line Feed"), die nicht auseinander gerissen werden dürfen. In diesen Fall müssen wir also eine Tauschung strikt unterbinden. Fügen wir nun noch die im Bedarfsfall vielleicht ganz nützliche Option hinzu, eine einfache Tauschung ohne Berücksichtigung der Groß-/Kleinschreibung zu erzwingen (optionaler Parameter SwapSimple, Datentyp Boolean), haben wir eine Funktion, die wir universell und sicher einsetzen können:

Public Function SwapChars(Chars As String, _
 Optional ByVal SwapSimple As Boolean) As String

  Dim nCharR As String
  Dim nCharL As String
  Dim nCases As Integer
  
  nCharR = Mid$(Chars, 2, 1)
  nCharL = Left$(Chars, 1)
  If Not SwapSimple Then
    If CBool(IsCharAlpha(Asc(nCharL))) _
     And CBool(IsCharAlpha(Asc(nCharR))) Then
      If IsCharUpper(Asc(nCharL)) Then
        nCases = 1
      End If
      If IsCharUpper(Asc(nCharR)) Then
        nCases = nCases Or 2
      End If
      Select Case nCases
        Case 0, 3
          SwapChars = nCharR & nCharL & Mid$(Chars, 3)
        Case 1
          SwapChars = UCase$(nCharR) & LCase$(nCharL) & _
           Mid$(Chars, 3)
        Case 2
          SwapChars = LCase$(nCharR) & UCase$(nCharL) & _
           Mid$(Chars, 3)
      End Select
      Exit Function
    End If
  End If
  If Not (CBool(InStr(Chars, vbCr)) _
   Or CBool(InStr(Chars, vbLf))) Then
    SwapChars = nCharR & nCharL & Mid$(Chars, 3)
  Else
    SwapChars = Chars
  End If
End Function

Diese Funktion ist jedoch erst etwas mehr als die halbe Miete. Sie verarbeitet ja nur ein bereits isoliertes Zeichenpaar und gibt es korrigiert zurück. Es fehlen noch die Operationen, die das zu korrigierende Zeichenpaar an der Position der Schreibmarke in einer TextBox oder einer RichTextBox auslesen und wieder einfügen.

In den Prozeduren SwapCharsTextBox und SwapCharsRichTextBox (die sich nur im Datentyp des übergebenen Objekts unterscheiden) wird zunächst die Position der Schreibmarke ermittelt und festgehalten - sie entspricht der Eigenschaft MSDN Library - VB SelStart, SelLength, SelTextSelStart. Dann werden der Beginn der Markierung vor das Zeichen links von der Position und die Länge der Markierung auf 2 gesetzt (Eigenschaft MSDN Library - VB SelStart, SelLength, SelTextSelLength gleich 2). Unserer Funktion SwapChars wird nun der Inhalt der Eigenschaft MSDN Library - VB SelStart, SelLength, SelTextSelText (eben die zwei nun markierten Zeichen) übergeben und nach Rückkehr aus der Funktion durch den Rückgabewert, also durch das korrigierte Zeichenpaar ersetzt. Nun stellen wir die Schreibmarke wieder an die ursprüngliche Position zurück. Falls sich die Schreibmarke am Textanfang oder am Textende befindet, wird die Tauschung nicht ausgeführt - weil es ja nichts zu vertauschen gibt. Im optionalen Parameter SwapSimple übergeben wir gegebenenfalls wieder die Anforderung einer strikten Tauschung, die wir an unsere Funktion SwapChars weiterreichen.

Public Sub SwapCharsTextBox(TextBox As TextBox, _
 Optional ByVal SwapSimple As Boolean)

  Dim nSelStartOld As Integer
  
  With TextBox
    nSelStartOld = .SelStart
    Select Case nSelStartOld
      Case 1 To Len(.Text) - 1
        .SelStart = nSelStartOld - 1
        .SelLength = 2
        .SelText = SwapChars(.SelText, SwapSimple)
        .SelStart = nSelStartOld
    End Select
  End With
End Sub

Public Sub SwapCharsRichTextBox(TextBox As RichTextBox, _
 Optional ByVal SwapSimple As Boolean)

' *** Inhalt identisch zu SwapCharsTextBox ***

End Sub

Warum ich die Vertauschung nicht gleich in dieser Prozedur vornehme? Ganz einfach - damit die folgende Funktion SwapCharsString für die Tauschung zweier Zeichen innerhalb eines Strings beliebiger Herkunft ebenfalls in den Genuss der separaten Vertauschungsfunktion kommt und wir uns doppelten, identischen Code sparen.

Auch hier wird die Tauschung nur vorgenommen, wenn sich die Tauschposition (die wir hier natürlich extra als Parameter angeben müssen) nicht am Anfang oder am Ende des String befindet. Der Einfachheit halber machen wir uns zunutze, dass die (historisch-anachronistische Basic-)Funktion MSDN Library - VB MidMid$ auch MSDN Library - VB Mid (Anweisung)links von einer Zuweisung stehen darf. Sie funktioniert quasi wie die SelText-Eigenschaft einer TextBox, indem einerseits der über ihre Parameter angegebene Bereich ausgelesen wird und andererseits ein angegebener Bereich durch einen anderen String ersetzt werden kann.

Public Function SwapCharsString(Text As String, _
 ByVal Position As Long, _
 Optional ByVal SwapSimple As Boolean) As String

  Dim nText As String
  
  nText = Text
  Select Case Position
    Case 1 To Len(nText) - 1
      Mid$(nText, Position, 2) = _
       SwapChars(Mid$(nText, Position, 2))
  End Select
  SwapCharsString = nText
End Function

Als Eingangs erwähnten Tastendruck, mit dem der Anwender komfortabel die Tauschung veranlassen kann, bieten Sie am besten eine Kombination aus einem Buchstaben und der Strg-Taste an, zum Beispiel Strg+W - diese Kombination ist bequem zu erreichen und leicht zu merken. Buchstabenkombinationen mit der Strg-Taste werden auch als KeyAscii-Wert in der Ereignisprozedur KeyPressKeyPress einer TextBox (bzw. RichTextBox) gemeldet, auch wenn sie eigentlich gar kein darstellbares Zeichen repräsentieren. Dies stammt wahrscheinlich noch aus den Zeiten, als alle Ascii-Zeichen als "druckbar" galten, wobei die Zeichen-Codes kleiner als 32 zur unmittelbaren Druckersteuerung verwendet wurden (wie etwa die bereits erwähnten Zeilenschaltungszeichen vbCr = Ascii-Code 13 und vbLf = Ascii-Code 10). Wenn auch diese Zeichen nicht in einer TextBox sichtbar werden, erscheinen sie jedoch hörbar - es wird ein Beep-Signal ausgelöst. Daher sollten Sie die Rückgabe des KeyAscii-Wertes unterdrücken, indem Sie diesen gleich 0 setzen. Für die Zeichen mit Ascii-Codes kleiner als 32 gibt es allerdings keine von Visual Basic vordefinierten Key-Konstanten. Die Auswertung stellt aber kein Problem dar, da der Unterschied zum entsprechenden Großbuchstaben immer genau 64 beträgt ("W" ist 87, Strg+W ist 23).

Private Sub Text1_KeyPress(KeyAscii As Integer)
  Select Case KeyAscii + 64
    Case vbKeyW
      SwapCharsTextBox Text1
      KeyAscii = 0
  End Select
End Sub


Beispiel-Projekt SwapCharsTest (swapchars.zip - ca. 3 KB)


Artikel
Zum Download-Bereich dieses Artikel
Mail an den Autor dieses Artikel

KnowHow
Zur KnowHow-Übersicht

KnowHow-Themen
Themen - Allgemeines
Themen - Entwicklungsumgebung (VB-IDE)
Themen - Forms
Themen - Steuerelemente (Controls)
Themen - Grafik
Themen - Dateien
Themen - UserControls
Themen - Einsteiger-Tipps
Themen - Wussten Sie...?

Übersicht nach Titeln in alphabetischer Reihenfolge
Übersicht nach Erscheinungsdatum

Schnellsuche



Zum Seitenanfang

Copyright © 1999 - 2017 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...

Download Internet Explorer