Zurück zur Homepage

Bilder in Arbeitsmappen in einer Userform anzeigen

Beispieldatei (PicToClip.zip 99 kB)
Beispieldatei (PicInvert.zip 97 kB)

Mit diesem Beispiel ist es möglich, Bilder, die in beliebigen Arbeitsmappen als Shapes stecken, auf einer Zeichenfläche in einer Userform darzustellen. Als Nebeneffekt können auch beliebige Bilder, die sich als Bitmap in der Zwischenablage tummeln, angezeigt werden.

Die Mappe PicInvert macht im Prinzip das gleiche. Es wird das erste Bild des aktiven Blattes invertiert dargestellt. Es fehlt lediglich die Dateiauswahl und die Konstante SRCCOPY ist durch SRCINVERT ersetzt worden.

 

 

 

 

Die Userform enthält ein Rahmensteuerelement mit dem Namen "frmZiel", in welches das Bild gezeichnet wird. Ich benutze dafür ein Rahmensteuerelement, weil es ein eigenes Fenster darstellt, also auch einen eigenen Devicekontext besitzt. Auf die Userform gehören noch zwei Commandbuttons mit den Namen "cmdNeueDatei" und "cmdRefresh".

Die Datei, die das Bild enthält, muss kurz geöffnet werden, damit das Bild ins Clipboard gebracht werden kann. Das wird durch einen Klick auf den Button "cmdNeueDatei" angestoßen, wobei sich ein Dialog zur Dateiauswahl öffnet. Beim Öffnen der ausgewählten Mappe wird die Bidschirmaktualisierung von Excel ausgeschaltet, man bekommt von dieser Aktion also nur ein kurzes Flackern mit.
In diesem Bleistift wird jeweils das erste Bild auf Blatt 1 gesucht. Wird keine Datei ausgewählt, hält das Programm nach Bildern in der aktuellen Mappe auf Blatt 1 Ausschau.

Ein Klick auf den Button "cmdRefresh" malt das aktuelle Bild, welches sich in der Zwischenablage als Bitmap befindet, in den Rahmen, die Herkunft ist dabei egal. Das ist manchmal ganz hilfreich, denn das gezeichnete Bild im Rahmen ist flüchtig, wird also nicht neu gezeichnet, wenn man beispielsweise mit einem anderen Fenster darüberfährt.

Hier der Code aus dem Klassenmodul der Userform:

Option Explicit
Private Type RECT
        Left 
As Long
        Top 
As Long
        Right 
As Long
        Bottom 
As Long
End Type
Private Type BITMAP
    bmType 
As Long
    bmWidth 
As Long
    bmHeight 
As Long
    bmWidthBytes 
As Long
    udtBMPlanes 
As Integer
    bmBitsPixel 
As Integer
    bmBits 
As Long
End Type
Private Declare Function FindWindowA _
   
Lib "user32" ( _
   
ByVal lpClassName As String, _
   
ByVal lpWindowName As String _
   ) 
As Long
Private Declare Function GetDC _
   
Lib "user32" ( _
   
ByVal hwnd As Long _
   ) 
As Long
Private Declare Function ReleaseDC _
   
Lib "user32" ( _
   
ByVal hwnd As Long, _
   
ByVal hdc As Long _
   ) 
As Long
Private Declare Function GetWindow _
   
Lib "user32" ( _
   
ByVal hwnd As Long, _
   
ByVal wCmd As Long _
   ) 
As Long
Private Declare Function GetObject _
   
Lib "gdi32" Alias "GetObjectA" ( _
   
ByVal hObject As Long, _
   
ByVal nCount As Long, _
   lpObject 
As Any _
   ) 
As Long
Private Declare Function CloseClipboard _
   
Lib "user32" () As Long
Private Declare Function OpenClipboard _
   
Lib "user32" ( _
   
ByVal hwnd As Long _
   ) 
As Long
Private Declare Function GetClipboardData _
   
Lib "user32" ( _
    
ByVal wFormat As Long _
    ) 
As Long
Private Declare Function IsClipboardFormatAvailable _
    
Lib "user32" ( _
    
ByVal wFormat As Long _
    ) 
As Long
Private Declare Function SelectObject _
   
Lib "gdi32" ( _
   
ByVal hdc As Long, _
   
ByVal hObject As Long _
   ) 
As Long
Private Declare Function CreateCompatibleDC _
   
Lib "gdi32" ( _
   
ByVal hdc As Long _
   ) 
As Long
Private Declare Function DeleteDC _
   
Lib "gdi32" ( _
   
ByVal hdc As Long _
   ) 
As Long
Private Declare Function RedrawWindow _
   
Lib "user32" ( _
   
ByVal hwnd As Long, _
   lprcUpdate 
As Any, _
   
ByVal hrgnUpdate As Long, _
   
ByVal fuRedraw As Long _
   ) 
As Long
Private Declare Function GetWindowRect _
   
Lib "user32" ( _
   
ByVal hwnd As Long, _
   lpRect 
As RECT _
   ) 
As Long
Private Declare Function StretchBlt _
   
Lib "gdi32" ( _
   
ByVal hdc As Long, _
   
ByVal As Long, _
   
ByVal As Long, _
   
ByVal nWidth As Long, _
   
ByVal nHeight As Long, _
   
ByVal hSrcDC As Long, _
   
ByVal xSrc As Long, _
   
ByVal ySrc As Long, _
   
ByVal nSrcWidth As Long, _
   
ByVal nSrcHeight As Long, _
   
ByVal dwRop As Long _
   ) 
As Long
   
Private Const RDW_INVALIDATE = &H1
Private Const CF_BITMAP = 2
Private Const GW_CHILD = 5
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDNEXT = 2
Private Const SRCCOPY = &HCC0020

Private Sub cmdRefresh_Click()
   ClipboardToPicture
End Sub

Private Sub cmdNeueDatei_Click()
Dim strFile       As String
Dim objWorkbook   As Workbook

On Error Resume Next

   
' Dateipfad holen
   strFile = Application.GetOpenFilename( _
      
"Excel-Dateien (*.xls), *.xls")
      
   
' Bildschirmaktualisierung ausschalten
   Application.ScreenUpdating = 
False
   
   
' Exceldatei öffnen
   
Set objWorkbook = Workbooks.Open(strFile)
   
   
' Das erste Bild auf Blatt 1 des aktiven
   
' Workbooks ins Clipboard bringen
   
If BringPictureToClip(Worksheets(1).Name) = "" Then
      MsgBox 
"Kein Bild auf Blatt 1"
   
Else
      Me.Caption = ActiveWindow.Caption
      
' Bild aus dem Clipboard in das Rahmenfeld
      ClipboardToPicture
   
End If
   
   
' Geöffnete Mappe schließen
   objWorkbook.Close
   
   
' Bildschirmaktualisierung einschalten
   Application.ScreenUpdating = 
True
End Sub

Private Sub ClipboardToPicture()
Dim lngBitmap        As Long
Dim lngMemoryBMP     As Long
Dim lngOldBitmap     As Long
Dim lngFrameHwnd     As Long
Dim lngFormDC        As Long
Dim lngMemDC         As Long
Dim udtBMP           As BITMAP
Dim dblBreite        As Double
Dim dblHöhe          As Double
Dim udtAbmessungen   As RECT
Dim dblHöheZuBreite  As Double

On Error GoTo fehlerbehandlung

' Handle auf das Rahmenfenster
lngFrameHwnd = GetFrameHwnd()

' Clipboard öffnen
OpenClipboard 0&

If IsClipboardFormatAvailable(CF_BITMAP) Then
   
'Im Clipboard ist eine Bitmap
   
   
'Einen zum Screen kompatiblen Devicekontext erzeugen
   lngMemDC = CreateCompatibleDC(0)
   
   
If lngMemDC Then
    
      
'Zugriffsnummer auf Bitmap im Clip holen
      lngBitmap = GetClipboardData(CF_BITMAP)
      
      
If (lngBitmap) Then
         
' Im Clipboard ist eine Bitmap
         
            
'Die Struktur udtBMP mit Infos füllen
            GetObject lngBitmap, Len(udtBMP), udtBMP
            
            
'Die Bitmap in den erzeugten DC stellen
            lngOldBitmap = SelectObject(lngMemDC, lngBitmap)
            
            
If lngOldBitmap Then
            
                
' Verhältnis Höhe zu Breite ermitteln
                
With udtBMP
                  dblHöheZuBreite = .bmHeight / .bmWidth
                
End With
                
                
' Rahmengröße anpassen
                
With frmZiel
                
                  .Height = Me.Height - 20
                  .Width = .Height / dblHöheZuBreite
                  
                  
If .Width > (Me.Width - (Me.Width / 3)) Then
                     .Width = .Width / 2
                     .Height = Height / 2
                  
End If
                  
                
End With
                
               
'Abmessungen holen
               GetWindowRect lngFrameHwnd, udtAbmessungen

               
'Alten Kram im Rahmen löschen
               RedrawWindow lngFrameHwnd, 
ByVal 0&, _
                   
ByVal 0&, RDW_INVALIDATE
                   
               
'Zeit lassen
               DoEvents
               
               
'DC Frame ausleihen
               lngFormDC = GetDC(lngFrameHwnd)
               
               
'Bild Maximiert einfügen
               
With udtAbmessungen
                  StretchBlt lngFormDC, 0, 0, _
                     .Right - .Left, _
                     .Bottom - .Top, _
                     lngMemDC, 0, 0, _
                     udtBMP.bmWidth, _
                     udtBMP.bmHeight, _
                     SRCCOPY
               
End With
               
               
' Alte Bitmap zurück in den MemDC
               SelectObject lngMemDC, lngOldBitmap
               
               
'Frame DC zurückgeben
               ReleaseDC lngFrameHwnd, lngFormDC
               
            
End If
        
End If
        
        
'Erzeugten DC löschen
        DeleteDC lngMemDC
        
    
End If
    
End If

' Clipboard schließen
CloseClipboard

Exit Sub
fehlerbehandlung:

'Clipboard schließen
CloseClipboard

If lngOldBitmap <> 0 Then
    SelectObject lngMemDC, lngOldBitmap
    
'Frame DC zurückgeben
    ReleaseDC lngFrameHwnd, lngFormDC
    
'Erzeugten DC löschen
    DeleteDC lngMemDC
End If
End Sub

Private Function BringPictureToClip( _
   strSheetname 
As String, _
   
Optional lngPicNr As Long = 1 _
   ) 
As String
Dim As Long
Dim As Long
On Error GoTo fehlerbehandlung

With Worksheets(strSheetname)
   
For i = 1 To .Shapes.Count
      
' Alle Shapes des Blattes durchsuchen
      
      
If .Shapes(i).Type = msoPicture Then
         
' Bild gefunden
         
         k = k + 1
         
If k = lngPicNr Then
            
' Handelt es sich um die gesuchte Bildnummer
            
            
' ins Clipboard kopieren
            .Shapes(i).CopyPicture _
               Appearance:=xlScreen, Format:=xlBitmap
               
            
' Namen des kopierten Bildes zurückgeben
            BringPictureToClip = .Shapes(i).Name
            
         
End If
      
End If
   
Next
End With
fehlerbehandlung:
End Function

Private Function GetFrameHwnd() As Long
Dim strCaption As String
Dim strGUID    As String
Dim lngHandle  As Long

    
'Hier wird das Fenster mittels einer
    
'eindeutigen Caption gesucht
    strGUID = 
"Disch griige mer aach"
    
    
'Fenstertext zwischenspeichern
    strCaption = Me.Caption
    
    
'Fenstertext kurz ändern
    Me.Caption = strGUID
    
    
'Zugriffsnummer Form
    lngHandle = FindWindowA(vbNullString, strGUID)
    

    
'Zugriffsnummer Clientbereich Form
    lngHandle = GetWindow(lngHandle, GW_CHILD)
    
    
'Zugriffsnummer Frame
    lngHandle = GetWindow(lngHandle, GW_CHILD)
    
    
'Fenstertext zurücksetzen
    Me.Caption = strCaption
    
    
'Handle zurückgeben
    GetFrameHwnd = lngHandle
End Function