Die Community zu .NET und Classic VB.
Menü

Addin-Programmierung - Seite 7

 von 

Schlußwort
Nächste Seite >>
Ereignisse abfangen
<< Vorherige Seite

Dockendes Addin  

Dockendes AddIn mit Todo-Funktion

Außer der Möglichkeit normale AddIns zu entwickeln, gibt es noch die Möglichkeit dockende AddIns zu entwickeln. Ein dockendes AddIn wird von der Entwicklungsumgebung so behandelt, als wäre es ein eigenes Fenster der Entwicklungsumgebung wie die Werkzeugleiste oder der Projektexplorer. Wie der Name ja schon sagt, handelt es sich um ein dockendes AddIn. Das bedeutet, das AddIn kann, wie die anderen Fenster von VB, an jeder beliebigen Stelle in der Entwicklungsumgebung an andere Fenster andocken. Ein dockendes AddIn kann über die VBIDE-Schnittstelle angesprochen werden z.B. über das Windows-Objekt.

Ein dockendes AddIn hat im eigentlichen nur zwei Unterschiede. Anstelle einer Form wird in einem dockenden AddIn-Projekt ein Userdokument eingesetzt. Der zweite Unterschied ist, das das Userdokument in ein Fenster der Entwicklungsumgebung umgewandelt wird. Dieses Umwandeln geschieht im Connect-Modul durch die Funktion "CreateToolWindow" des Window-Objektes und zwar beim Laden des AddIn. Dazu muss der Code im Connect-Modul etwas abgeändert werden. Hier der abgeänderte Code.

Option Explicit

'------------------------------------------------------
' Instanzzieren bzw. Implementieren der Verweise und Events
'------------------------------------------------------

' Variable zum zwischenspeichern ob Form gerade
' sichtbar ist oder nicht
Public FormDisplayed As Boolean

' Variable zum Verweis auf die VBIDE-Schnittstelle
' (Microsoft Visual Basic x.x Extensibility)
Public VBInstance As VBIDE.VBE

' Variable zum Verweis auf die Menü-Schnittstelle
' (Microsoft Office x.x Object Library)
Dim mcbMenuCommandBar As Office.CommandBarControl

' Variable auf das Userdokument
Dim mdobAddIn As dobAddIn

' Variable auf das Window-Objekt
Dim mWindow As VBIDE.Window

' Implementierung der Menü-Events Schnittstelle
' Ereignisbehandlungsroutine für die Befehlsleiste
Public WithEvents MenuHandler As CommandBarEvents

'ein dockendes AddIn benötigt eine GUID
'wird beim Laden es AddIns erzeugt
Private DockingAddInGUID As String

Sub Hide()
    
    On Error Resume Next
    
    FormDisplayed = False
    
    ' Fenster verstecken
    mWindow.Visible = False
   
End Sub

Sub Show()
  
    On Error Resume Next

    'Variablen im Userdokument setzen
    Set mdobAddIn.Connect = Me
    Set mdobAddIn.VBInstance = VBInstance
    
    FormDisplayed = True
    
    'Fenster anzeigen
    mWindow.Visible = True
   
End Sub

'------------------------------------------------------
'this method adds the Add-In to VB
'------------------------------------------------------
Private Sub AddinInstance_OnConnection(ByVal Application As Object, _
ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, _
ByVal AddInInst As Object, custom() As Variant)
    
    On Error Goto error_handler
    
    'save the vb instance
    Set VBInstance = Application
    
    'Eintrag im Menü erzeugen
    Set mcbMenuCommandBar = AddToAddInCommandBar("DockingAddIn")
    'Übergeben des Ereignisses an die Behandlungsroutine.
    Set Me.MenuHandler = VBInstance.Events.CommandBarEvents(mcbMenuCommandBar)
  
    If GetSetting(App.Title, "Settings", "DockingAddInGUID", "0") = "0" Then
        'freie GUID ermittel, wenn noch keine vorhanden
        DockingAddInGUID = GUIDGen
        SaveSetting App.Title, "Settings", "DockingAddInGUID", DockingAddInGUID
    Else
        'GUID laden
        DockingAddInGUID = GetSetting(App.Title, "Settings", "DockingAddInGUID", "0")
    End If
  
    'Hier wird das Userdokument in ein Fenster umgewandelt
    Set mWindow = VBInstance.Windows.CreateToolWindow(AddInInst, _
    "MyAddIn.dobAddIn", "DockingAddIn", DockingAddInGUID, mdobAddIn)
    
    If ConnectMode = ext_cm_AfterStartup Then
        If GetSetting(App.Title, "Settings", "DisplayOnConnect", "0") = "1" Then
            'set this to display the form on connect
                Me.Show
        End If
    End If
  
    Exit Sub
    
error_handler:
    
    MsgBox Err.Description
    
End Sub

'------------------------------------------------------
'this method removes the Add-In from VB
'------------------------------------------------------
Private Sub AddinInstance_OnDisconnection(ByVal RemoveMode As AddInDesignerObjects.ext_DisconnectMode, custom() As Variant)
    On Error Resume Next
    
    'delete the command bar entry
    mcbMenuCommandBar.Delete
    
    'shut down the Add-In
    If FormDisplayed Then
        SaveSetting App.Title, "Settings", "DisplayOnConnect", "1"
        FormDisplayed = False
    Else
        SaveSetting App.Title, "Settings", "DisplayOnConnect", "0"
    End If
    
    Unload mdobAddIn
    Set mdobAddIn = Nothing

End Sub

Private Sub IDTExtensibility_OnStartupComplete(custom() As Variant)
    If GetSetting(App.Title, "Settings", "DisplayOnConnect", "0") = "1" Then
        'set this to display the form on connect
        Me.Show
    End If
End Sub

'this event fires when the menu is clicked in the IDE
Private Sub MenuHandler_Click(ByVal CommandBarControl As Object, handled As Boolean, CancelDefault As Boolean)
    Me.Show
End Sub

Function AddToAddInCommandBar(sCaption As String) As Office.CommandBarControl
    Dim cbMenuCommandBar As Office.CommandBarControl  'command bar object
    Dim cbMenu As Object
  
    On Error Goto AddToAddInCommandBarErr
    
    'see if we can find the Add-Ins menu
    Set cbMenu = VBInstance.CommandBars("Add-Ins")
    If cbMenu Is Nothing Then
        'not available so we fail
        Exit Function
    End If
    
    'add it to the command bar
    Set cbMenuCommandBar = cbMenu.Controls.Add(1)
    'set the caption
    cbMenuCommandBar.Caption = sCaption
    Clipboard.SetData LoadResPicture(101, 0)
    cbMenuCommandBar.PasteFace
    
    Set AddToAddInCommandBar = cbMenuCommandBar
    
    Exit Function
    
AddToAddInCommandBarErr:

End Function

Hier der Code zum ermitteln der nächsten freien GUID im Modul "modGenerateGUID".

'dieses Modul dient zum ermitteln
'der nächsten freien GUID

Option Explicit

Private Type GUID
    Data1 As Long
    Data2 As Long
    Data3 As Long
    Data4(8) As Byte
End Type

Private Declare Function CoCreateGuid Lib "ole32.dll" _
(pguid As GUID) As Long

Private Declare Function StringFromGUID2 Lib "ole32.dll" _
(rguid As Any, ByVal lpstrClsId As Long, _
ByVal cbMax As Long) As Long

Public Function GUIDGen() As String
    Dim uGUID As GUID
    Dim sGUID As String
    Dim tGUID As String
    Dim bGUID() As Byte
    Dim lLen As Long
    Dim RetVal As Long
    lLen = 40
    bGUID = String(lLen, 0)
    CoCreateGuid uGUID
    RetVal = StringFromGUID2(uGUID, VarPtr(bGUID(0)), lLen)
    sGUID = bGUID
    If (Asc(Mid$(sGUID, RetVal, 1)) = 0) Then RetVal = RetVal - 1
    GUIDGen = Left$(sGUID, RetVal)
End Function

Der Code im Userdokument ist im Urzustand der gleiche wie in der Form.

'------------------------------------------------------
' Instanzieren bzw. Implementieren der Verweise
'------------------------------------------------------

' Variable zum Verweis auf die VBIDE-Schnittstelle
' (Microsoft Visual Basic x.x Extensibility)
Public VBInstance As VBIDE.VBE

' Variable auf den Designer bzw. Klassenmodul "Connect"
Public Connect As Connect

Option Explicit

Private Sub CancelButton_Click()
    ' Verstecken der Form
    ' Ruft im Modul "Connect" die Sub "Hide" auf
    Connect.Hide
End Sub

Private Sub OKButton_Click()
    ' Gibt den vollständigen Pfad zur
    'Visual Basic-Anwendung zurück.
    MsgBox "AddIn operation on: " & VBInstance.FullName
End Sub

Einen kleine Nachteil hat aber dieses dockende AddIn: Wenn das Fenster des AddIn in der Entwicklungsumgebung den Fokus hat, werden einige Buttons in der Menüleiste deaktiviert. Verliert das Fenster den Fokus, ist alles wieder aktiviert. Dieses Problem tritt nur in der VB6-Entwicklungsumgebung auf. Ein dockendes AddIn in der VB5-Entwicklungsumgebung verursacht diese Problem nicht. Eine Lösung für das VB6 Focus-Problem gibt es aber bisher noch nicht. Eventuell handelt es sich hier um einen Bug in der VB6-IDE-Schnittstelle.

Eine Todo-Funktion im Projekt einbauen

Einige Programmierer vermissen eine Art Todo-Funktion für Ihre Projekte mit der man z.B. noch nicht erledigte Programmieraufgaben im Projekt abspeichern kann um später beim Laden des Projektes eine Überblick zu bekommen, was noch gemacht werden muss. Man könnte so eine Todo-Liste in eine separate Datei schreiben oder eine Funktion des VBProject-Objekt nutzen. Gemeint ist die ReadProperty- und die WriteProperty-Funktion dieses Objektes. Nicht zu verwechseln mit der Property-Funktion in anderen Objekten, mit der man die Eigenschaften eines Objektes auslesen und schreiben kann. Hier handelt es sich um eine Funktion, mit der man Benutzerdefinierte Einträge in die VBP-Datei eines Projektes schreiben kann. Diese Benutzerdefinierten Einträge werden nicht in der Entwicklungsumgebung angezeigt. Der Aufbau dieser Einträge entspricht der von INI-Dateien mit einer Sektion, Schlüssel und einem Wert. Eigenartigerweise tritt beim Auslesen dieser Einträge in VB ein Fehler auf, wenn noch kein Eintrag mit entsprechender Sektion usw. vorhanden ist. Bei INI-Dateien wird automatisch dieser fehlende Eintrag ohne Fehler angelegt. Bei VB leider nicht und so muss dieser Fehler per "On Error Resume Next" abgefangen werden und der fehlende Eintrag selbst erzeugt werden. Hier die beiden wichtigsten Sub für das Auslesen und Schreiben von benutzerdefinierten Einträgen. (Der komplette Code befindet sich zusammen im Projekt für das dockende AddIn)

Private Sub ReadTodo()
' Diese Sub liest das Benutzerdefinierte Property "Todo"
' aus der VBP-Datei des aktuellen Projektes aus

    'diese Zeile muss sein
    On Error Resume Next

    tempStr = vbNullString
    
    'aktuelles Projekt
    Set VBProj = VBInstance.ActiveVBProject
    
    'beim auslesen tritt ein Fehler auf,
    'wenn die Section, Key und Value noch nicht
    'vorhanden sind, daher "On Error Resume Next"
        
    'auslesen der Section "Todo" mit dem Key "List"
    'Rückgabewert ist der Value von "List"
    tempStr = VBProj.ReadProperty("Todo", "List")

    'wenn der Rückgabewert = vbNullString ist,
    'dann eine Section, Key und Value anlegen
    If tempStr = vbNullString Then
        VBProj.WriteProperty "Todo", "List", "Empty"
        tempStr = "Empty"
    End If

    'anzeigen für welches Projekt
    Label1.Caption = "ToDo für das Projekt: " & VBProj.Name

    'wenn beim auslesen der Rückgabestring = "Empty" ist,
    'dann tempStr = vbNullstring
    If Left$(tempStr, 5) = "Empty" Then tempStr = vbNullString
    
    'wenn beim auslesen der Rückgabestring <> "Empty" ist,
    'dann das Zeichen CHR(255) durch vbNewLine ersetzen
    'und in der Textbox anzeigen
    Text1.Text = Replace(tempStr, Chr$(255), vbNewLine)
    
    'wenn beim auslesen der Rückgabestring <> "Empty" ist,
    'dann den "Löschen-Button" aktivieren
    If tempStr <> vbNullString Then Command1.Enabled = True
    
    'Textänderungen
    isChanged = False
    
    'Textbox bekommt den Focus
    Text1.SetFocus
End Sub
Private Sub SaveTodo()
' Diese Sub schreibt das Benutzerdefinierten Property "Todo"
' in die VBP-Datei des aktuellen Projektes

    'wenn Textlänge=0, dann schreibe "Empty"
    If Len(Text1.Text) = 0 Then
        'VBProj.WriteProperty "Todo", "List", "Empty"
        VBProj.WriteProperty "Todo", "List", "Empty"
    Else
        'wenn Textlänge<>0, dann ersetze vbNewLine durch CHR(255)
        'schreibe in die VBP-Datei
        VBProj.WriteProperty "Todo", "List", Replace(Text1.Text, vbNewLine, Chr$(255))
    End If
End Sub

Das Zeichen CHR(255) wird hier benutzt, um den Zeilenumbruch (vbNewLine) umzuwandeln, da der Value-Wert keine Zeilenumbrüche erlaubt. Ein löschen der Sektion, wie bei INI-Dateien, ist über diese Funktionen aber nicht möglich.

Nächste Seite >>
Schlußwort
<< Vorherige Seite
Ereignisse abfangen