Einfügen-Menue abhängig vom Clipboard aktivieren oder deaktivieren

Veröffentlicht: 09. Dez 2001 | Aktualisiert: 13. Jun 2004

Von Hening Schünke

Oft steht man vor dem Problem, das Clipboard in der eigenen Anwendung benutzen zu wollen. Jetzt soll aber der Menüpunkt "Bearbeiten.Einfügen" nur aktiv sein, wenn sich auch tatsächlich einfügbarer Text im Clipboard befindet. Dies lässt sich mit der Klasse MyClpBoard bewerkstelligen. Diese erzeugt ein Event auf der Form, in welchem das Datenformat abgefragt wird und dem entsprechend kann dann der Menüpunkt aktiviert werden. Den vollständigen Code dieser Klasse finden Sie am Ende dieses Artikels.

Diese Klasse bekommt aber nicht mit, ob das Clipboard von externen Programmen (Word etc.) mit Daten gefüllt wird. In diesem Fall findet ein Taskwechsel statt. Das heißt, der Anwender aktiviert Word und Ihre Anwendung verliert den Fokus. Wenn jetzt in Word Text ins Clipboard kopiert wurde, so genügt es zur korrekten Aktivierung des Menüs, wenn die Prüfung des Clipboard-Inhalts erfolgt, sobald Ihre Anwendung wieder aktiviert wird.

Hier hilft der Artikel Q186908. Dieser zeigt, wie mittels Subclassing der VB-Form die Windows-Message APPACTIVATE abgefangen wird, damit das VB-Programm erkennen kann, wenn es nach einer Taskumschaltung wieder aktiviert wird. Dann wird der Inhalt des Clipboards geprüft und in Abhängigkeit davon wird der Status des Menüpunktes gesetzt.

Ändern Sie das Beispiel aus Q186908 so ab, dass die Form ein Menü mit den Menüpunkten "Kopieren", "Einfügen" und "Zwischenablage löschen" enthält. Dabei sollte das Menü als Array mit den Indizes 0 bis 2 ausgeführt sein und das Menüobjekt sollte "mnuSubEdit" heißen.

Ergänzen Sie dann den Code der Form um die folgenden Teile:

' Deklaration der Klasseninstanz mit Events 
Private WithEvents mobjMyClipboard As MyClipboard 
Private Sub Form_Load() 
    ' Festlegen der Klasseninstanz 
    Set mobjMyClipboard = New MyClipboard 
    '... schon aus Q186908 vorhandenen Code nicht ändern, nur die 
obige Zeile hinzufügen 
End Sub 
' Sub wird als Reaktion auf die AppActivate Mesage aufgerufen 
Public Sub AppActivate() 
    mobjMyClipboard.CheckClipboard 
End Sub 
Private Sub mnuSubEdit_Click(Index As Integer) 
    Select Case Index 
        Case 0 ' Kopieren 
            mobjMyClipboard.SetClipboardText txtEdit.SelText 
        Case 1 ' Einfügen 
            txtEdit.SelText = mobjMyClipboard.GetClipboardText 
        Case 2 ' Zwischenablage löschen 
            mobjMyClipboard.ClearClipboard 
    End Select 
End Sub 
Private Sub mobjMyClipboard_ClipboardChanged(DataFormat As Integer) 
    mnuSubEdit(1).Enabled = (DataFormat <>0) 
End Sub

Im Modul MyClpBoard.bas wird der Code aus dem Artikel an die gewünschten Anforderungen angepasst.
Dazu wird lediglich die Prozedur "WindowProc" wie folgt geändert:

' Modul MyClpBoard.bas 
Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, _ 
    ByVal wParam As Long, ByVal lParam As Long) As Long 
    'Check for the ActivateApp message 
    If (uMsg = WM_ACTIVATEAPP) And (wParam <>0) Then 
        'Check to see if Activating the application 
        Form1.AppActivate 
    End If 
    'Pass message on to the original window message handler 
    WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, 
lParam) 
End Function

Generell erklärt der Artikel Q170570, wie mittels Callback und AddressOf-Operator ein MessageHandler mit VB programmiert werden kann.

' Klasse MyClpBoard.cls 
Public Event ClipboardChanged(DataFormat As Integer) 
' Text im Clipboard speichern 
Public Sub SetClipboardText(strText As String) 
    Dim intFormat As Integer 
    Clipboard.Clear 
    Clipboard.SetText strText 
    intFormat = GetDataFormat 
    RaiseEvent ClipboardChanged(intFormat) 
End Sub 
' Text aus Clipboard abrufen 
Public Function GetClipboardText() As String 
    Dim strReturn As String 
    strReturn = Clipboard.GetText 
    GetClipboardText = strReturn 
End Function 
' Clipboard loeschen 
Public Sub ClearClipboard() 
    Dim intFormat As Integer 
    Clipboard.Clear 
    intFormat = GetDataFormat 
    RaiseEvent ClipboardChanged(intFormat) 
End Sub 
' Clipboard auf Inhalt prüfen 
Public Sub CheckClipboard() 
    Dim intFormat As Integer 
    intFormat = GetDataFormat 
    RaiseEvent ClipboardChanged(intFormat) 
End Sub 
' Welches Datenformat liegt vor ? 
Private Function GetDataFormat() As Integer 
    Dim intReturn As Integer 
    If Clipboard.GetFormat(vbCFLink) Then 
        intReturn = vbCFLink 
    End If 
    If Clipboard.GetFormat(vbCFText) Then 
        intReturn = vbCFText 
    End If 
    If Clipboard.GetFormat(vbCFBitmap) Then 
        intReturn = vbCFBitmap 
    End If 
    If Clipboard.GetFormat(vbCFMetafile) Then 
        intReturn = vbCFMetafile 
    End If 
    If Clipboard.GetFormat(vbCFDIB) Then 
        intReturn = vbCFDIB 
    End If 
    If Clipboard.GetFormat(vbCFPalette) Then 
        intReturn = vbCFPalette 
    End If 
    If (intReturn = vbCFText) And (Len(Clipboard.GetText) = 0) Then 
        ' Wenn bei Datenformat Text die Laenge 0 ist, ist das 
Clipboard effektiv leer 
        intReturn = 0 
    End If 
    GetDataFormat = intReturn 
End Function