Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1236to1240
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

API - Shape aus Worksheet in Userform

API - Shape aus Worksheet in Userform
Christian
Hallo zusammen,
ich erzeuge per VBA dynamisch ein gruppiertes Shape und möchte dieses in einen Frame in einem Userform kopieren. Das funktioniert soweit auch, ohne das Shape zuvor als Bild auf der Festplatte speichern zu müssen.
Meine Problem:
Das Bild soll schon beim Laden des Userform's in den Frame eingefügt werden. Das klappt leider nicht. Erst nach Drücken des Buttons "Bild zeigen". (Sowohl bei XL2002, und XL2010)
Habt Ihr dazu 'ne Idee?
Beispieldatei:
https://www.herber.de/bbs/user/77484.xls
Vielen Dank vorab
Grüße
Christian
PS: Der Code stammt in großen Teilen von:
http://michael-schwimmer.de/vba090.html

4
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Benutzer
Anzeige
AW: API - Shape aus Worksheet in Userform
13.11.2011 16:32:49
Nepumuk
Hallo,
du musst 1. das Activate-Event benutzen, denn im Initialize ist das Form noch gar nicht geladen und 2. mit DoEvents dem Userform die Zeit geben fertig geladen zu sein. Also, so:
Private Sub UserForm_Activate()
    lngFrameHwnd = Control2Hwnd(Me.fraPicture) 'window handle des Frames
    DoEvents
    Call CreateShape
    Call GetPicture
End Sub

Gruß
Nepumuk
Anzeige
AW: API - Shape aus Worksheet in Userform
13.11.2011 17:20:54
Christian
Hi Nepumuk,
herzlichen Dank! Das war der Trick.
Da war ich schon ziemlich nahe dran - mit Repaint, DoEvents hab ich schon erfolglos rumgespielt und dabei ist es so simple, wenn man weiß wie...
Vielen Dank nochmals.
Da ich weiß, dass du dich mit API bestens auskennst - noch eine Frage:
ich bin mir nicht sicher, ob der Code von "ClipboardToControl" so wirklich sauber ist. Was sagst du dazu?
Wenn man z.B. "Call SelectObject(lngMemDC, lngTmpBitmap)" auskommentiert, läuft der Code ebenso.
Außerdem will ich das Bild nicht an die Größe des Frames anpassen. Gibt es ggf. eine einfachere Alternative zu "StretchBlt"
Ich hab einen Link zu dem Code von Michael Schwimmer hier im Forum gefunden und versucht diesen an meine Bedürfnisse anzupassen - hab aber wenig Ahnung von API.
z.B. hab ich dabei die Methode, das hwnd des Frames zu ermitteln ersetzt durch "GetFocus" - gefunden in:
http://www.vbarchiv.net/tipps/details.php?id=667&print=1
Viele Grüße
Christian
Anzeige
AW: API - Shape aus Worksheet in Userform
13.11.2011 17:53:09
Nepumuk
Hallo,
da gibt es mehrere Möglichkeiten, so z.B.:
Option Explicit

Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" ( _
    ByRef PicDesc As PIC_DESC, _
    ByRef RefIID As GUID, _
    ByVal fPictureOwnsHandle As Long, _
    ByRef IPic As IPictureDisp) As Long
Private Declare Function CopyImage Lib "user32.dll" ( _
    ByVal handle As Long, _
    ByVal un1 As Long, _
    ByVal n1 As Long, _
    ByVal n2 As Long, _
    ByVal un2 As Long) As Long
Private Declare Function IsClipboardFormatAvailable Lib "user32.dll" ( _
    ByVal wFormat As Integer) As Long
Private Declare Function OpenClipboard Lib "user32.dll" ( _
    ByVal hWnd As Long) As Long
Private Declare Function GetClipboardData Lib "user32.dll" ( _
    ByVal wFormat As Integer) As Long
Private Declare Function EmptyClipboard Lib "user32.dll" () As Long
Private Declare Function CloseClipboard Lib "user32.dll" () As Long

Private Type GUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(0 To 7) As Byte
End Type

Private Type PIC_DESC
    lngSize As Long
    lngType As Long
    lnghPic As Long
    lnghPal As Long
End Type

Private Const PICTYPE_BITMAP = 1
Private Const CF_BITMAP = 2
Private Const IMAGE_BITMAP = 0
Private Const LR_COPYRETURNORG = &H4
Private Const GC_CLASSNAMEMSEXCEL = "XLMAIN"

Private Function Paste_Picture() As IPictureDisp
    Dim lngReturn As Long, lngCopy As Long, lngPointer As Long
    If IsClipboardFormatAvailable(CF_BITMAP) <> 0 Then
        lngReturn = OpenClipboard(Application.hWnd)
        If lngReturn > 0 Then
            lngPointer = GetClipboardData(CF_BITMAP)
            lngCopy = CopyImage(lngPointer, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG)
            Call CloseClipboard
            If lngPointer <> 0 Then Set Paste_Picture = Create_Picture(lngCopy)
        End If
    End If
End Function

Private Function Create_Picture( _
        ByVal plnghPic As Long) As IPictureDisp

    Dim udtPicInfo As PIC_DESC, udtID_IDispatch As GUID
    Dim objPicture As IPictureDisp
    With udtID_IDispatch
        .Data1 = &H20400
        .Data4(0) = &HC0
        .Data4(7) = &H46
    End With
    With udtPicInfo
        .lngSize = Len(udtPicInfo)
        .lngType = PICTYPE_BITMAP
        .lnghPic = plnghPic
        .lnghPal = 0
    End With
    Call OleCreatePictureIndirect(udtPicInfo, udtID_IDispatch, 0&, objPicture)
    Set Create_Picture = objPicture
End Function

Private Function GetPicture() As Boolean
    Dim objShape As Shape
    Dim blnFound As Boolean
    With ThisWorkbook.Sheets("Tabelle1")
        For Each objShape In .Shapes
            If objShape.Name = "GroupSh" Then
                objShape.CopyPicture Appearance:=xlScreen, Format:=xlBitmap
                GetPicture = True
                Exit For
            End If
        Next
    End With
End Function

Private Sub CommandButton1_Click()
    Unload Me
End Sub

Private Sub UserForm_Activate()
    Dim objPicture As IPictureDisp
    Call CreateShape
    If GetPicture Then
        Set objPicture = Paste_Picture
        If Not objPicture Is Nothing Then
            UserForm1.Image1.Picture = objPicture
        Else
            MsgBox "''GroupSh'' can't show", vbCritical, "Error"
        End If
    Else
        MsgBox "Shape ''GroupSh'' not found", vbCritical, "Error"
    End If
End Sub

Ich benutz aber ein Image-Control denn das ist dafür gedacht Bilder anzuzeigen.
Gruß
Nepumuk
Anzeige
Wow - das ist perfekt
13.11.2011 18:55:59
Christian
Hi Nepumuk,
der Code macht genau das, was ich will.
ich hab' bestimmt noch lange daran zu knabbern, bis ich das verstanden habe. Auf den ersten Blick ist das aber sehr viel übersichtlicher als mein bisheriger Code.
Das Image-Control ist mir dafür auch sympathischer. Den Frame hatte ich nur verwendet, da dies im Original-Code auch so war und da ich mit "GetFocus" kein Windows Handle für das Image-Control bekommen habe... vielleicht lag der Fehler aber auch mir - muss ich noch mal prüfen.
Klasse - vielen Dank.
Grüße
Christian

Links zu Excel-Dialogen

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige