18.4 Die Zwischenablage 

In der .NET-Klassenbibliothek erfolgt der Zugriff auf die Zwischenablage über die Klasse Clipboard. Die Klasse hat keine öffentlichen Konstruktoren und kann nicht instanziiert werden.
18.4.1 Speichern und Abrufen von Daten 

Die beiden allgemeingültigsten Methoden der Klasse Clipboard sind GetDataObject und SetDataObject, die den Datenaustausch in jedem Format erlauben. GetDataObject liest den Inhalt der Zwischenablage aus, und die mehrfach überladene Methode SetDataObject schreibt die Daten hinein.
Public Shared Function GetDataObject() As IDataObject |
Speichern mit SetDataObject
Wollen Sie eine Zeichenfolge in die Zwischenablage schreiben, übergeben Sie diese einfach der SetDataObject-Methode:
Clipboard.SetDataObject("Dies ist eine Zeichenfolge.")
Da der Parameter vom Typ Object ist, beschränkt sich die Übergabe aber nicht auf Zeichenfolgen. Sie können beliebige Objekte ablegen, beispielsweise die Referenz auf eine Bitmap:
Clipboard.SetDataObject(myBitmap)
Ein wiederholter Aufruf von SetDataObject hat zur Folge, dass der aktuelle Inhalt der Zwischenablage durch einen neuen überschrieben wird.
Ist der optionale boolesche Parameter True, bleiben die Daten nach dem Beenden der Anwendung in der Zwischenablage. Außerdem enthält die Zwischenablage dann eine Kopie des Objekts mit der Folge, dass bei einer Änderung des Objekts der Inhalt der Zwischenablage unberührt bleibt. Die Standardvorgabe ist False. Mit
Clipboard.SetDataObject(obj, False)
wird die Referenz auf das Objekt obj in die Zwischenablage geschrieben. Änderungen am Objekt wirken sich dann auch auf die Zwischenablage aus.
Hinweis |
Die Serialisierbarkeit der Klasse ist die Voraussetzung dafür, ein Objekt der Zwischenablage übergeben zu können. |
Abrufen mit GetDataObject
Etwas komplexer ist das Abrufen der Daten in der Zwischenablage. Das wird bereits klar, wenn Sie sich die Definition der Methode GetDataObject ansehen: Der Rückgabewert liefert ein Objekt, das die Schnittstelle IDataObject implementiert. Über die Methoden der Schnittstelle können weitere Informationen abgerufen werden.
Nehmen wir an, dass wir uns mit
Dim myData As IDataObject = Clipboard.GetDataObject()
den Inhalt aus der Zwischenablage holen. Auf die Referenz myData vom Typ der in Tabelle 18.11 gezeigten Schnittstelle IDataObject können wir vier Methoden aufrufen, die alle überladen sind.
Methode | Beschreibung |
GetData |
Ruft die Daten aus der Zwischenablage ab. |
GetDataPresent |
Überprüft das Datenformat in der Zwischenablage. |
GetFormats |
Liefert eine Liste aller in der Zwischenablage gespeicherten Formate. |
SetData |
Speichert Daten in einem bestimmten Format in der Zwischenablage. |
Betrachten wir den einfachsten und den in der Praxis vermutlich auch am häufigsten auftretenden Fall, dass in der Zwischenablage eine Zeichenfolge abgelegt ist, die abgerufen werden soll. Dazu sind zwei Anweisungen notwendig:
Dim myData As IDataObject = Clipboard.GetDataObject()
textBox1.Text = CType(myData.GetData(GetType(String)), String)
Mit der ersten Anweisung erhalten wir die Referenz auf ein Objekt vom Typ IDataObject und rufen darauf in der zweiten Anweisung die Methode GetData auf, der wir zur Identifizierung den Datentyp mit GetType übergeben. Damit können die Daten im richtigen Format ausgelesen werden. Den Wert, den uns GetData liefert, müssen wir noch in den entsprechenden Datentyp konvertieren.
Neben der im Codefragment benutzten Variante gibt es noch zwei weitere Überladungen, die anstelle der Type-Referenz eine Zeichenfolge entgegennehmen:
Function GetData(format As Type) As Object |
Damit ist es auch möglich, den Inhalt der Zwischenablage mit
textBox1.Text = CType(myData.GetData("System.String"), String)
auszulesen. Dabei gehen wir davon aus, dass die Daten auch als Zeichenfolge interpretierbar sind. Liegt ein anderes Datenformat vor, kann mit dem booleschen Parameter versucht werden, in das angegebene Format zu konvertieren:
textBox1.Text = CType(myData.GetData("System.String", True), String)
Wollen Sie ermitteln, ob die Zwischenablage Daten enthält, die von Ihrer Anwendung verarbeitet werden können, müssen Sie die Verwertbarkeit überprüfen. Dazu dient die Methode GetDataPresent:
Function GetDataPresent(format As Type) As Boolean |
Der folgende Aufruf testet, ob die Zwischenablage Daten im String-Format enthält:
Clipboard.GetDataObject().GetDataPresent(GetType(String))
Durch den booleschen Rückgabewert ist der Test prädestiniert für eine If-Bedingung:
Dim myData As IDataObject = Clipboard.GetDataObject()
If myData.GetDataPresent(GetType(ClassA)) Then ...
Sie können das Format der Daten abfragen, indem Sie eine Type-Referenz oder eine Zeichenfolge übergeben. Beispielsweise sind die beiden folgenden Ausdrücke gleichwertig:
myData.GetDataPresent(GetType(String))
myData.GetDataPresent("System.String")
Eine dritte Variante besteht darin, eine der statischen Eigenschaften der Klasse DataFormats zu übergeben, die die von .NET unterstützten Zwischenablageformate als Zeichenfolgen zurückgeben. Mit
Dim myData As IDataObject = Clipboard.GetDataObject()
If myData.GetDataPresent(DataFormats.Text) Then MessageBox.Show( _
CType(Clipboard.GetDataObject().GetData(DataFormats.Text),String))
können Sie beispielsweise zuerst testen, ob der Inhalt der Zwischenablage im Textformat vorliegt, und sich diesen anschließend in einem Meldungsfenster ausgeben lassen.
In der Tabelle 18.12 finden Sie die klassengebundenen Felder der Klasse DataFormats, die zum Namensraum System.Windows.Forms gehört.
Datenart | Konstanten |
Grafik/Audio |
Bitmap, Dib, EnhancedMetafile, MetafilePict, Palette, PenData, Riff, Tiff, WaveAudio |
Daten |
CommaSeparatedValues, Dif |
Betriebssystemobjekte |
FileDrop, Locale, SymbolicLink |
Text |
Html, OemText, Rtf, StringFormat, Text (ANSI), UnicodeText |
Allgemein |
Serializable |
18.4.2 Weitere Zugriffsmethoden 

GetDataObject und SetDataObject sind hinsichtlich des Datentyps sehr allgemein gehalten. Mehrere SetXxx-Methoden gestatten es, Daten eines bestimmten Formats in die Zwischen-ablage zu schreiben. Mit den analogen Methoden GetXxx kann der Inhalt der Zwischenablage ausgelesen werden. Ist das Datenformat nicht bekannt, können Sie dieses mit ContainsXxx-Methoden prüfen. Weitere Methoden finden Sie in Tabelle 18.13.
Methode | Beschreibung |
Clear |
Löscht den Inhalt der Zwischenablage. |
ContainsAudio |
Gibt an, ob die Zwischenablage Daten im WaveAudio-Format enthält. |
ContainsData |
Gibt an, ob in der Zwischenablage Daten in einem spezifizierten Format vorliegen oder in dieses konvertiert werden können. |
ContainsFileDropList |
Gibt an, ob Dateien eines Drag&Drop-Vorgangs aus Windows vorliegen. |
ContainsImage |
Gibt an, ob Daten als (konvertierbare) Bitmap vorliegen. |
ContainsText |
Gibt an, ob in der Zwischenablage Daten im Textformat vorliegen. |
GetAudioStream |
Liefert den Audiostream aus der Zwischenablage. |
GetData |
Liest die Daten im gegebenen Format aus der Zwischenablage. |
GetDataObject |
Liest beliebige Daten aus der Zwischenablage. |
GetFileDropList |
Liefert eine Liste aller Dateinamen aus der Zwischenablage. |
GetImage |
Liefert ein Bild aus der Zwischenablage. |
GetText |
Liefert Text aus der Zwischenablage. |
SetAudio |
Schreibt Daten im WaveAudio-Format in die Zwischenablage. |
SetData |
Schreibt Daten im gegebenen Format in die Zwischenablage. |
SetDataObject |
Schreibt beliebige Daten in die Zwischenablage. |
SetFileDropList |
Schreibt eine Liste von Dateinamen in die Zwischenablage. |
SetImage |
Schreibt ein Bild in die Zwischenablage. |
SetText |
Schreibt Text in die Zwischenablage. |
Der Einsatz der Methoden ist einfach. Wenn Sie darauf Wert legen, die Zwischenablage nur dann auszuwerten, wenn sie ein bestimmtes Datenformat beherbergt, fragen Sie das mit einer der ContainsXxx-Methoden ab. Ist das Ergebnis positiv, rufen Sie die Daten mit der entsprechenden GetXxx-Methode ab.
Private Sub btmShowClipboard_Click(sender As object, e As EventArgs)
If Clipboard.ContainsText() Then
MessageBox.Show(Clipboard.GetText())
Else
MessageBox.Show("Zwischenablage enthält keine Daten im Text-Format.")
End If
End Sub
18.4.3 Mehrere Datenformate gleichzeitig 

Normalerweise kann in der Zwischenablage immer nur ein Element gleichzeitig gespeichert werden. Dazu verwenden Sie die Methode SetXxx. Es ist allerdings möglich, ein bestimmtes Element in mehreren Formaten oder mehrere Elemente unterschiedlicher Formate in die Zwischenablage zu kopieren. Der Weg dazu führt über ein Objekt vom Typ DataObject. Dieser Typ, den man als Container für Elemente unterschiedlicher Formate ansehen kann, implementiert die IDataObject-Schnittstelle. Damit werden auch alle Methoden dieser Schnittstelle unterstützt, von denen für uns SetData von besonderem Interesse ist. Sie speichert Daten in einem gegebenen Format im DataObject-Objekt. Dem String-Parameter können Sie auch in diesem Fall eine Konstante der Klasse DataFormats übergeben.
Sub SetData(data As Object) |
Der Einsatz der Methode ist sehr einfach. Zuerst erzeugen Sie ein DataObject-Objekt und rufen auf dessen Referenz die Methode SetData auf, der Sie jeweils Elemente unterschiedlichen Formats übergeben. Anschließend schreibt die Methode SetDataObject der Klasse Clipboard das komplette Datenagglomerat in die Zwischenablage.
Dim data As New DataObject()
data.SetData(DataFormats.Text, "Irgendeine Zeichenfolge")
Clipboard.SetDataObject(data)
Soll die Zwischenablage gleichzeitig mehrere Formate speichern, rufen Sie SetData mehrfach auf. Sehen wir uns dazu ein Beispiel an, bei dem der Zwischenablage sowohl eine Bitmap als auch eine Zeichenfolge übergeben wird:
'...\Programmiertechniken\Zwischenablage\Heterogen.vb |
Public Class Heterogen
Dim bild As Bitmap
Private Sub Laden(sender As Object, e As EventArgs) Handles MyBase.Load
Dim data As New DataObject()
' Bitmap erzeugen
bild = New Bitmap(AlsBild.ClientSize.Width, AlsBild.ClientSize.Height)
Dim g As Graphics = Graphics.FromImage(bild)
g.FillRectangle(New SolidBrush(Color.White), 0,0,bild.Width,bild.Height)
Dim pts(36) As PointF, stp As Single = Math.PI / 18
Dim r As Single = Math.Min(bild.Width, bild.Height) * 3 / 8
Dim rnd As New Random()
For no As Integer = 0 To 36
Dim d As Single = r * rnd.Next(95, 105) / 100
pts(no) = New PointF(d * Math.Cos(no * stp), d * Math.Sin(no * stp))
Next
g.TranslateTransform(bild.Width / 2, bild.Height / 2)
g.DrawLines(Pens.Blue, pts)
' Bitmap und Text in die Zwischenablage kopieren
data.SetData(DataFormats.Bitmap, bild)
data.SetData(DataFormats.Text, "Feuchtfröhliche Feier")
Clipboard.SetDataObject(data)
End Sub
Private Sub Anzeige(sender As Object, e As EventArgs) _
Handles Anzeigen.Click
Dim dataObj As IDataObject = Clipboard.GetDataObject()
' Bitmap aus der Zwischenablage in die Picturebox kopieren
If dataObj.GetDataPresent(DataFormats.Bitmap) Then _
AlsBild.Image = dataObj.GetData(DataFormats.Bitmap)
' Text aus der Zwischenablage in die Textbox kopieren
If dataObj.GetDataPresent(DataFormats.Text) Then _
AlsText.Text = dataObj.GetData(DataFormats.Text)
End Sub
End Class
Im Load-Ereignis der Form wird programmgesteuert eine Bitmap in weißer Hintergrundfarbe mit einem »Kreis« erzeugt. Die Bitmap wird dem DataObject-Objekt übergeben, darüber hinaus erhält es auch noch eine Zeichenfolge. Zum Schluss wird das DataObject-Objekt in die Zwischenablage geschrieben.
Die Form enthält neben einer Schaltfläche eine Picturebox und eine Textbox. Wird auf die Schaltfläche geklickt, wird der Inhalt der Zwischenablage einer Typuntersuchung unterzogen – mit dem Ergebnis, dass die Bitmap in der Picturebox angezeigt wird und die Zeichenfolge in der Textbox erscheint (siehe Abbildung 18.6).
Abbildung 18.6 Ausgabe des Beispiels »Heterogen«
Schließen Sie die Anwendung, geht der Inhalt der Zwischenablage verloren. Wollen Sie, dass beispielsweise die Bitmap auch danach noch von einer anderen Anwendung wie MS Paint aus der Zwischenablage geholt werden kann, muss das DataObject-Object mit
Clipboard.SetDataObject(data, True)
der Zwischenablage übergeben werden.
18.4.4 Eigene Datenformate schreiben 

Die Klasse DataFormats definiert eine Reihe von Formaten. Sie sind aber nicht an diese Liste gebunden, sondern können auch eigene Datentypen in die Zwischenablage kopieren. Dabei kommt die dreiparametrige Variante der Methode SetData zum Einsatz. Der erste Parameter gibt den Namen des neuen Datenformats an, der boolesche Parameter legt fest, ob die Konvertierung in ein anderes Format zulässig ist, und dem dritten Parameter werden die zu kopierenden Daten übergeben.
Nehmen wir an, es sei der Typ ClassA wie folgt definiert:
<Serializable()> Class ClassA
public Number As Integer
public Name As String
End Class
Beachten Sie, dass die Zwischenablage nur Typen akzeptiert, die das Attribut Serializable haben. Mit dem folgenden Code können wir ein Objekt des benutzerdefinierten Typs ClassA in die Zwischenablage kopieren:
Dim obj As New ClassA()
obj.Number = 5500
obj.Name = "Pelztier"
Dim data As New DataObject()
data.SetData("ClassA", True, obj)
Clipboard.SetDataObject(data, True)
Dem SetDataObject-Aufruf übergeben wir True. Daher kann auch nach dem Beenden der aktuellen Anwendung eine andere Anwendung die Daten auswerten – vorausgesetzt, die Anwendung akzeptiert den Typ ClassA.
Die Daten aus der Zwischenablage zu lesen ist sehr einfach:
Dim dataObj As IDataObject = Clipboard.GetDataObject()
If dataObj.GetDataPresent("ClassA") Then
Dim obj As ClassA = CType(dataObj.GetData("ClassA"), ClassA)
MessageBox.Show(obj.Number.ToString() & Environment.NewLine & obj.Name)
End If
18.4.5 Leeren der Zwischenablage 

Das Leeren der Zwischenablage erfolgt durch Aufruf der Methode Clear:
Clipboard.Clear()
18.4.6 Beispielprogramm Menü »Bearbeiten« 

Wir wollen über ein Menü mit den Elementen Ausschneiden, Kopieren und Einfügen Texte in einer Textbox manipulieren. Dazu ergänzen wir das in Abschnitt 12.13.3, »Eigenschaften von Menüs«, begonnene Beispielprogramm MenuStrip, in dem wir auch noch nicht die gleichlautenden Untermenüs von Bearbeiten codiert haben.
Als ersten Schritt sorgen wir beim Aufklappen des Menüs dafür, dass nur die Menüpunkte aktiv sind, die aufgrund von Textselektion und Inhalt der Zwischenablage eine Aktion nach sich ziehen können. Dazu ermittelt erst einmal die Hilfsmethode TextBox, ob eine Textbox aktiv ist. Da sich die Textbox in einem ToolStripContainer-Objekt befindet, kann sie nicht direkt aktives Element der Form sein. In einem ersten Schritt ermitteln wir, ob der Container fokussiert ist. Wenn ja, schauen wir nach dem aktiven Element innerhalb des Containers. Ist es eine Textbox, wird dessen Referenz zurückgegeben. In allen anderen Fällen gibt die Methode Nothing zurück.
'...\Programmiertechniken\Zwischenablage\MenuStrip.vb |
Private Function TextBox() As TextBox
Dim ctrl As Control = Me.ActiveControl
If TypeOf ctrl Is ToolStripContainer Then
ctrl = CType(ctrl, ToolStripContainer).ActiveControl
If TypeOf ctrl Is TextBox Then
Return CType(ctrl, TextBox)
End If
End If
Return Nothing
End Function
Nun ist die kontextabhängige Aktivierung der Menüpunkte einfach. Nur aus einer nichtleeren Zwischenablage kann eingefügt werden, und nur dann, wenn Text selektiert ist, kann gelöscht, kopiert oder ausgeschnitten werden. Die Methode TextBox liefert uns die Referenz der fokussierten Textbox oder Nothing, wenn keine selektiert ist.
Private Sub Aufklappen(sender As Object, e As EventArgs) _
Handles Bearbeiten.DropDownOpening
Einfügen.Enabled = Clipboard.ContainsText()
Dim txt As TextBox = TextBox()
Kopieren.Enabled = txt IsNot Nothing AndAlso txt.SelectionLength > 0
Ausschneiden.Enabled = Kopieren.Enabled
Löschen.Enabled = Kopieren.Enabled
End Sub
Auch die Implementierung der Ereignishandler der Menüpunkte wird durch die Hilfsmethode vereinfacht. Fangen wir mit Kopieren an, der einen Text in die Zwischenablage schreibt. Den selektierten Text der von TextBox() gelieferten aktiven Textbox schreiben wir mit SetText in die Zwischenablage. TextBox() kann keine Nullreferenz sein, da in diesem Fall der Menüpunkt beim Aufklappen des Bearbeiten-Menüs deaktiviert wurde und gar kein Ereignishandler angesprochen wird.
Private Sub Kopieren_Click(sender As Object, e As EventArgs) _
Handles Kopieren.Click
Clipboard.SetText(TextBox().SelectedText)
End Sub
Beim Löschen muss der selektierte Text entfernt werden, ohne dass die Zwischenablage ins Spiel kommt. Bei einer Zuweisung eines neuen Textes verliert die Textbox die Cursorposition. Deswegen speichern wir den Start der Selektion. Nach dem Ausschneiden sind Selektionsanfang und -ende identisch, und die Zuweisung der gespeicherten Cursorposition an SelectionStart liefert die richtige Position. Das Entfernen besteht aus dem Zusammensetzen der Textteile vor und nach der Selektion.
Private Sub Löschen_Click(sender As Object, e As EventArgs) _
Handles Löschen.Click
Dim txt As TextBox = TextBox()
If txt.SelectionLength = 0 Then Return
Dim cursorPosition As Integer = txt.SelectionStart
txt.Text = txt.Text.Substring(0, cursorPosition) & _
txt.Text.Substring(cursorPosition + txt.SelectionLength)
txt.SelectionStart = cursorPosition
End Sub
Damit wird das Ausschneiden fast trivial. Wir verwenden einfach die bereits definierten Ereignishandler, um die Selektion in die Zwischenablage zu schreiben und dann zu löschen.
Private Sub Ausschneiden_Click(sender As Object, e As EventArgs) _
Handles Ausschneiden.Click
Kopieren_Click(sender, e)
Entfernen()
End Sub
Das Einfügen eines Textes ist etwas aufwändiger. Wir müssen zwei Situationen betrachten:
- Ist kein Text in der Textbox markiert, ist die Position des Cursors die Einfügeposition.
- Ist Text markiert, muss er durch den Inhalt der Zwischenablage ersetzt werden.
Das Einfügen bildet die neue Zeichenfolge und setzt den Cursor an das Ende des eingefügten Textes. Wenn vor dem Einfügen Text markiert ist, entfernt ihn der Ereignishandler Löschen_Click. Der neue Text besteht aus drei Teilen: aus dem Text bis zur Cursorposition (gegebenenfalls entstanden durch Löschen), aus dem Text der Zwischenablage und aus dem Rest des Textes.
Private Sub Einfügen_Click(sender As Object, e As EventArgs) _
Handles Einfügen.Click
Dim txt As TextBox = TextBox()
Löschen_Click(sender, e) ' markierten Text ggf. entfernen
Dim cursorPosition As Integer = txt.SelectionStart
txt.Text = txt.Text.Substring(0, cursorPosition) & _
Clipboard.GetText() & _
txt.Text.Substring(cursorPosition)
txt.SelectionStart = cursorPosition + Clipboard.GetText().Length
End Sub
Da die Signaturen der Menüpunkte für Kontextmenüs identisch sind, können Sie die hier gemachten Definitionen direkt für Kontextmenüs übernehmen, indem Sie die Handles-Klauseln entsprechend erweitern. Lediglich die Aktivierung der Menüpunkte im Ereignis Opening des Kontextmenüs muss nochmals wie im Ereignis DropDownOpening des Menüs implementiert werden, da andere Menüelemente referenziert werden.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.