Results 1 to 27 of 27

Thread: Get image size of IPicture with GDI routine

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Get image size of IPicture with GDI routine

    Hi all...

    how do we get the image size (real one) of a IPicture with GDI call.
    (let's suppose I don't want to use the IPicture.width for some IDE crash issue)

    1. I Open GDI+
    2. I load an Image with GDI+ in a IPicture Struct
    3. I Close GDI+

    somewhere elses in the program...

    I need the size of the picture ?

    I got a project I'll post here soon when I'm finish, it's a PNG ocx (not fancy like the AIC - Lavolpe)
    wich I want to use for futur application I do because I'm using new way to "skin" that require transparency.

    I wanted to go with PNG instead of using TransparentBlt wich would have required all my image to have the "same" transparency color.

    My new ocx is using the alpha blend (per pixel) and background transparency all in one.

    thank

  2. #2
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Get image size of IPicture with GDI routine

    That may explain the problem. GDI+ image handle (hImage) is not a picture handle that can be used with GDI APIs or VB. I'm interested in how you created a valid IPicture from a GDI+ image handle.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    sure, let me post the code... (give me a minute)
    in the meanwhile, accessing the .width and .height of the IPicture only crash when you put your mouse cursor over it in debug mode.
    and I answered my own question with your post from where I came here, that is with:

    lngSrcWidth = ScaleX(pobjIPicture.Width, vbHimetric, vbPixels)
    lngSrcHeight = ScaleY(pobjIPicture.Height, vbHimetric, vbPixels)


    the nice part is that my "aic" (promise I won't call it that) take only a few line of code to read png and store it in the OCX
    (so thanks for the solution you gave in the other thread)

    I'm gonna get the routine and post it here for your evaluation.

  4. #4

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    why people doesn't put their credential in ZIP file with code it elude me...

    so again... credit is due to the author, I borrowed a few routine from a project and I got the zip but not where I took it.
    so if you recognize your work, plz tell me so I can FIX that and give you the credit. (post me the link where I took the zip, I'll recognize it)

    I'm sorry again.

    Lavolpe: I adapted some code to fit my idea and I can now use full transparency and alpha blending (per pixel) transparency in OCX with the following routine:

    Code:
    Public Function LoadPictureGDIPlus(ByVal pstrPicFile As String, ByRef pobjIPicture As IPicture, Optional ByVal plngDestWidth As Long = -1, Optional ByVal plngDestHeight As Long = -1, Optional ByRef plngSrcWidth As Long = 0, Optional ByRef plngSrcHeight = 0, Optional ByVal plngBackColor As Long = lngTransparency, Optional ByRef pblnRetainRatio As Boolean = True, Optional ByVal penmInterpolation As InterpolationModeEnum = InterpolationModeEnum.[3 - enmNearestNeighbor]) As Long
      Dim lngRetValue As Long
      Dim lngSuccess  As Long
      Dim lngHdc      As Long
      Dim lngHBitmap  As Long
      Dim lngImg      As Long
      Dim ptrPicFile  As Long
      
      'Assume Fail
      lngRetValue = 0
      'Err.Raise 13, "GDI+ Module", "Error loading picture [" & pstrPicFile & "]"
      
      ' Load the image
      ptrPicFile = StrPtr(pstrPicFile)
      lngSuccess = GdipLoadImageFromFile(ptrPicFile, lngImg)
      If (lngSuccess = 0) Then
        'Get real Size
        lngSuccess = GdipGetImageWidth(lngImg, plngSrcWidth)
        lngSuccess = GdipGetImageHeight(lngImg, plngSrcHeight)
        If (plngDestWidth = -1) Then
          plngDestWidth = plngSrcWidth
        End If
        
        If (plngDestHeight = -1) Then
          plngDestHeight = plngSrcHeight
        End If
        
        ' Initialise the hDC
        InitDC lngHdc, lngHBitmap, plngBackColor, plngDestWidth, plngDestHeight
        
        ' Resize the picture
        GdipResize lngImg, lngHdc, plngDestWidth, plngDestHeight, pblnRetainRatio, penmInterpolation
        lngSuccess = GdipDisposeImage(lngImg)
        
        ' Get the bitmap back
        GetBitmap lngHdc, lngHBitmap
        
        ' Create the picture
        lngSuccess = CreatePicture(lngHBitmap, pobjIPicture)
        
        lngRetValue = 1
      End If
      
      LoadPictureGDIPlus = lngRetValue
    End Function
    and the important function:

    Code:
    ' Creates a Picture Object from a handle to a bitmap
    Private Function CreatePicture(ByVal plngHBitmap As Long, ByRef pobjIPicture As IPicture) As Long
      Dim lngRetValue As Long
      Dim typGuid     As GUID
      Dim typPicDesc  As PICTDESC
      
      ' Fill in OLE IDispatch Interface ID
      typGuid.Data1 = &H20400
      typGuid.Data4(0) = &HC0
      typGuid.Data4(7) = &H46
          
      ' Fill typPicDesc with necessary parts
      typPicDesc.size = Len(typPicDesc)     ' Length of structure
      typPicDesc.Type = PICTYPE_BITMAP      ' Type of Picture (bitmap)
      typPicDesc.hBmp = plngHBitmap         ' Handle to bitmap
    
      ' Create the picture
      lngRetValue = OleCreatePictureIndirect(typPicDesc, typGuid, True, pobjIPicture)
      
      'Set CreatePicture = pobjIPicture
      CreatePicture = lngRetValue
    End Function
    it's eyes candy for me

  5. #5
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Get image size of IPicture with GDI routine

    Let's see these functions: GetBitmap and also InitDC
    I don't see an immediate problem with anything you posted

    Also, you should check the return value of CreatePicture. If successful, that value should be zero.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  6. #6

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    Quote Originally Posted by LaVolpe View Post
    Let's see these functions: GetBitmap and also InitDC
    I don't see an immediate problem with anything you posted

    Also, you should check the return value of CreatePicture. If successful, that value should be zero.
    yes, it does return 0, S_OK = 0. The guy that made the code didn't used Long for function (wich I hate)
    he was doing:

    Set mIPicture = CreatePicture(...)

    I modified all function so the IPicture object is passed as parameter, therefore, all value returned by theses fonction are mine.
    However and I checked them with MSDN specification, all seem ok.



    Code:
    ' Replaces the old bitmap of the hDC, Returns the bitmap and Deletes the hDC
    Private Sub GetBitmap(ByVal plngHdc As Long, ByRef plngHBitmap As Long)
      Dim lngSuccess As Long
      
      plngHBitmap = SelectObject(plngHdc, plngHBitmap)
      lngSuccess = DeleteDC(plngHdc)
    End Sub
    Code:
    ' Initialises the hDC to draw
    Private Sub InitDC(ByRef plngHdc As Long, ByRef plngHBitmap As Long, ByVal plngBackColor As Long, ByVal plngWidth As Long, ByVal plngHeight As Long)
      Dim lngHBrush As Long
      
      ' Create a memory DC and select a bitmap into it, fill it in with the backcolor
      plngHdc = CreateCompatibleDC(ByVal 0&)
      plngHBitmap = CreateBitmap(plngWidth, plngHeight, GetDeviceCaps(plngHdc, PLANES), GetDeviceCaps(plngHdc, BITSPIXEL), ByVal 0&)
      plngHBitmap = SelectObject(plngHdc, plngHBitmap)
      lngHBrush = CreateSolidBrush(plngBackColor)
      lngHBrush = SelectObject(plngHdc, lngHBrush)
      PatBlt plngHdc, 0, 0, plngWidth, plngHeight, PATCOPY
      DeleteObject SelectObject(plngHdc, lngHBrush)
    End Sub
    I made over 300 small modification on the code to ehnance it. what I didn't do yet is check if all created object are deleted to avoid memory leak.

  7. #7

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    I got a question...

    if I'm using StretchBlt (from GDI32)
    can I set it to work with GdipSetInterpolationMode() ?

    if not, what the best way to stretch an IPicture using NearestNeighbor ?

    thanks

    I should have named this thread help with GDI+ :S

  8. #8
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Get image size of IPicture with GDI routine

    My gut feeling for your problems is that you somehow created an IPicture on the bitmap that came with the new DC you created and not the bitmap you created from CreateBitmap. You can verify that...

    1. in your InitDC function, debug.print plngHBitmap returned from CreateBitmap
    2. in your CreatePicture function, debug.print plngHBitmap
    Are they the same values?

    If not, maybe they got swapped somehow in your GdipResize function (which we haven't seen).

    Now regarding your other question. GdipSetInterpolationMode should be used in your GdipResize function when you render the GDI+ image to the target DC. There is no way to directly mix GDI and GDI+. In fact, when GDI+ creates an hGraphics object on a GDI hDC, you should not be calling any GDI APIs on that DC until you destroy that GDI+ hGraphics object
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  9. #9

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    Quote Originally Posted by LaVolpe View Post
    My gut feeling for your problems is that you somehow created an IPicture on the bitmap that came with the new DC you created and not the bitmap you created from CreateBitmap. You can verify that...

    1. in your InitDC function, debug.print plngHBitmap returned from CreateBitmap
    2. in your CreatePicture function, debug.print plngHBitmap
    Are they the same values?

    If not, maybe they got swapped somehow in your GdipResize function (which we haven't seen).

    Now regarding your other question. GdipSetInterpolationMode should be used in your GdipResize function when you render the GDI+ image to the target DC. There is no way to directly mix GDI and GDI+. In fact, when GDI+ creates an hGraphics object on a GDI hDC, you should not be calling any GDI APIs on that DC until you destroy that GDI+ hGraphics object
    I apreciated your deep knowledge of the subject.

    <<Are they the same values?
    I checked the first value of plngHBitmap on the CreateBitmap()
    and yes, they are ok, I checked as you suggested.
    I was wondering 2 thing in InitDC()
    is that ok to reuse plngHBitmap that way ?
    plngHBitmap = SelectObject(plngHdc, plngHBitmap)

    because we're returning the second value. (byref)
    I'm guessing since it's a selectObject (returning previous object) we'll use the new value later to delete it and passing back the old value.

    so here the other subroutine:

    Code:
    ' Resize the picture using GDI plus
    Public Sub GdipResize(ByRef plngImg As Long, ByVal plngHdc As Long, ByVal plngWidth As Long, ByVal plngHeight As Long, Optional ByVal pblnRetainRatio As Boolean = True, Optional ByVal penmInterpolation As InterpolationModeEnum = InterpolationModeEnum.[3 - enmNearestNeighbor])
      Dim lngGraphics   As Long      ' Graphics Object Pointer
      Dim lngOrWidth    As Long      ' Original Image Width
      Dim lngOrHeight   As Long      ' Original Image Height
      Dim dblOrRatio    As Double    ' Original Image Ratio
      Dim dblDesRatio   As Double    ' Destination rect Ratio
      Dim lngDestX      As Long      ' Destination image X
      Dim lngDestY      As Long      ' Destination image Y
      Dim lngDestWidth  As Long      ' Destination image Width
      Dim lngDestHeight As Long      ' Destination image Height
      Dim lngRetValue   As Long
      
      lngRetValue = GdipCreateFromHDC(plngHdc, lngGraphics)
      lngRetValue = GdipSetInterpolationMode(lngGraphics, penmInterpolation)
      
      If (pblnRetainRatio = True) Then
        lngRetValue = GdipGetImageWidth(plngImg, lngOrWidth)
        lngRetValue = GdipGetImageHeight(plngImg, lngOrHeight)
        
        dblOrRatio = (lngOrWidth / lngOrHeight)
        dblDesRatio = (plngWidth / plngHeight)
        
        ' Calculate destination coordinates
        lngDestWidth = IIf(dblDesRatio < dblOrRatio, plngWidth, plngHeight * dblOrRatio)
        lngDestHeight = IIf(dblDesRatio < dblOrRatio, plngWidth / dblOrRatio, plngHeight)
        'lngDestX = (plngWidth - lngDestWidth) \ 2
        'lngDestY = (plngHeight - lngDestHeight) \ 2
        lngDestX = 0
        lngDestY = 0
        
        lngRetValue = GdipDrawImageRectRectI(lngGraphics, plngImg, lngDestX, lngDestY, lngDestWidth, lngDestHeight, 0, 0, lngOrWidth, lngOrHeight, UnitPixel, 0, 0, 0)
      Else
        lngRetValue = GdipDrawImageRectI(lngGraphics, plngImg, 0, 0, plngWidth, plngHeight)
      End If
        
      lngRetValue = GdipDeleteGraphics(lngGraphics)
    End Sub

  10. #10

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    Quote Originally Posted by LaVolpe View Post
    when GDI+ creates an hGraphics object on a GDI hDC, you should not be calling any GDI APIs on that DC until you destroy that GDI+ hGraphics object
    didn't know that.... I was using AlphaBlend() and a StretchBlt() on the DC before calling the FreeGDIPlus lngToken

    maybe that explain why on some occasion IDE crash on mouse over the IPicture.width element.
    I just changed it. I didn't needed to keep the DC open after the LoadPictureGDIPlus() anyway.

  11. #11
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Get image size of IPicture with GDI routine

    Sorry took so long to get back to you. I don't think I've ever seen OleCreatePictureIndirect used directly with IDispatch as you are doing in your CreatePicture function and that may be the problem? Try using this instead & let us know if results change.

    Code:
    Private Function CreatePicture(ByVal plngHBitmap As Long, ByRef pobjIPicture As IPicture) As Long
      Dim lngRetValue As Long
      Dim typGuid     As Guid
      Dim typPicDesc  As PICTDESC
      
      Dim aGUID(0 To 3) As Long
      
      ' Fill typPicDesc with necessary parts
      typPicDesc.Size = Len(typPicDesc)     ' Length of structure
      typPicDesc.Type = PICTYPE_BITMAP      ' Type of Picture (bitmap)
      typPicDesc.hBmp = plngHBitmap         ' Handle to bitmap
    
      ' Fill in OLE IPicture Interface ID
        aGUID(0) = &H7BF80980
        aGUID(1) = &H101ABF32
        aGUID(2) = &HAA00BB8B
        aGUID(3) = &HAB0C3000
        ' create stdPicture
        lngRetValue = OleCreatePictureIndirect(typPicDesc, aGUID(0), True, pobjIPicture)
      
      'Set CreatePicture = pobjIPicture
      CreatePicture = lngRetValue
    End Function
    Note: I used an array for the GUID so if needed, change your API OleCreatePictureIndirect second parameter to:
    ByRef parameterName As Any

    Regarding GDI+ and GDI interoperability. You misunderstood. I did not mean you needed to shut down GDI+, I just mean that you should call GdipDeleteGraphics before using any GDI drawing APIs on a DC wrapped in GDI+ hGraphics. Your code is doing that.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  12. #12

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    Quote Originally Posted by LaVolpe View Post
    Sorry took so long to get back to you.
    meh! You're the fastest answer I got and the one I was awaiting for. I applaude your willingness to help me

    Quote Originally Posted by LaVolpe View Post
    I don't think I've ever seen OleCreatePictureIndirect used directly with IDispatch as you are doing in your CreatePicture function and that may be the problem?
    some part of this code is way out of my leagues. I don't do graphics, I'm a database and SQL programist. Logic and Array are easy for me. Graphics and GDI+, the most I know come from you and your AIC. Otherwise, I don't do graphics.

    Quote Originally Posted by LaVolpe View Post
    Note: I used an array for the GUID so if needed, change your API OleCreatePictureIndirect second parameter to:
    ByRef parameterName As Any
    will do but still faill to understand the change you did... I'll analyze the memory value and come back at you.

    Quote Originally Posted by LaVolpe View Post
    Regarding GDI+ and GDI interoperability. You misunderstood. I did not mean you needed to shut down GDI+, I just mean that you should call GdipDeleteGraphics before using any GDI drawing APIs on a DC wrapped in GDI+ hGraphics. Your code is doing that.
    oh... k.... make sense.

  13. #13

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    Hi Lavolpe.

    I check the code and I don't understand the value you're using for [riid] param in OleCreatePictureIndirect
    can you explain to me or point out to documentation ??

    since value you use are different then thoses I previously use.

    thanks.

    Edit: Still don't know where you took thoses value. I understand you traded 16 bytes for 16 differents bytes. still looking the documenation about it. I tried it and it work. I prefer to use a type GUID_I composed of 4 long instead of array, I don't like the as any type but it's all the same.


    Code:
    Private Declare Function OleCreatePictureIndirectGuidI Lib "olepro32.dll" Alias "OleCreatePictureIndirect" (ByRef PicDesc As PICTDESC, ByRef RefIID As GUIDI, ByVal fPictureOwnsHandle As Long, ByRef IPic As IPicture) As Long
    
    Private Type GUIDI
      Data1   As Long
      Data2   As Long
      Data3   As Long
      Data4   As Long
    End Type
    
    Dim typGuidI   As GUIDI
    
      ' Fill in OLE [IPicture] Interface ID and create the picture
      typGuidI.Data1 = &H7BF80980
      typGuidI.Data2 = &H101ABF32
      typGuidI.Data3 = &HAA00BB8B
      typGuidI.Data4 = &HAB0C3000
      lngRetValue = OleCreatePictureIndirectGuidI(typPicDesc, typGuidI, True, pobjIPicture)
    Last edited by VbNetMatrix; Feb 13th, 2018 at 11:49 PM.

  14. #14
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Get image size of IPicture with GDI routine

    Quote Originally Posted by VbNetMatrix View Post
    Hi Lavolpe.

    I check the code and I don't understand the value you're using for [riid] param in OleCreatePictureIndirect
    can you explain to me or point out to documentation ??
    The IID is: 7BF80980-BF32-101A-8BBB-00AA00300CAB
    Here is the documentation

    but still faill to understand the change you did
    I changed the interface from IDispatch to IPicture.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  15. #15

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    Quote Originally Posted by LaVolpe View Post
    The IID is: 7BF80980-BF32-101A-8BBB-00AA00300CAB
    Here is the documentation


    I changed the interface from IDispatch to IPicture.
    Sorry, I faulty explained myself....what I meant was : I understood you changed the IDispatch to IPicture interface from your comment, I didn't understood the hex value because I couldn't find the documentation about it. that's what I meant.
    I'm not sure why the IDispatch was working I'll look more at documentation you gave.

    there again, I apreciate your wisdom. My component is almost finished, I would like to dedicate it to you and to post it as my first project on VbForum.

    I think you'll find it interesting because I'm using unusual technique for my OCX (wich allow me to use a template creator for all my OCX) soon I'll post to you in private a link where you can download the source.

    I'm left with only 1 problem... how to translate IPicture into byte() array back and forth...
    I think I found 1 of the solution but not the other... can't test it without both! lol.

    thanks again for all your help.

  16. #16
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Get image size of IPicture with GDI routine

    Quote Originally Posted by VbNetMatrix View Post
    Sorry, I faulty explained myself....what I meant was : I understood you changed the IDispatch to IPicture interface from your comment, I didn't understood the hex value because I couldn't find the documentation about it. that's what I meant...

    I'm left with only 1 problem... how to translate IPicture into byte() array back and forth...
    I think I found 1 of the solution but not the other... can't test it without both!
    I use an API to convert string GUIDs to 16 byte values. This API requires the enclosed curly braces, but is not case-sensitive
    Code:
    Private Declare Function IIDFromString Lib "ole32.dll" (ByVal lpszProgID As Long, piid As Any) As Long
    ' sample of getting the IDataObject GUID. 
    Dim aGUID(0 To 3) As Long
    Call IIDFromString(StrPtr("{0000010e-0000-0000-C000-000000000046}"), ByVal VarPtr(aGUID(0)))
    As far as saving IPicture to bytes, not sure how that will be useful? The CreatePicture routine you have is creating a bitmap, no transparency. You don't have the original bytes any longer. You might want to consider saving the bytes earlier in the process? If you don't care about the original bytes, which may be PNG format for example, then there are lots of sample code about to convert a bitmap handle (stdPicture/IPicture.Handle) to array. In fact, you could actually use VB's SavePicture to file then open file & get bytes that way -- but not a pretty solution.

    Edited: If you are concerned with bytes for your usercontrol's WriteProperties event and only need to save the bitmap, you don't need bytes. You can simply save the stdPicture/IPicture object directly
    Last edited by LaVolpe; Feb 14th, 2018 at 09:41 AM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  17. #17

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    Quote Originally Posted by LaVolpe View Post
    I use an API to convert string GUIDs to 16 byte values. This API requires the enclosed curly braces, but is not case-sensitive
    Code:
    Private Declare Function IIDFromString Lib "ole32.dll" (ByVal lpszProgID As Long, piid As Any) As Long
    ' sample of getting the IDataObject GUID. 
    Dim aGUID(0 To 3) As Long
    Call IIDFromString(StrPtr("{0000010e-0000-0000-C000-000000000046}"), ByVal VarPtr(aGUID(0)))
    I have noticed the high bit and low bit are reversed. Probably because how memory store value.
    although not really related to our problem, I found this:

    http://codes-sources.commentcamarche...controle-image

    therefore, I understand your value from "7BF80980-BF32-101A-8BBB-00AA00300CAB"

    Code:
      'typGUID.Data1 = &H7BF80980
      'typGUID.Data2 = &H101ABF32
      'typGUID.Data3 = &HAA00BB8B
      'typGUID.Data4 = &HAB0C3000
    
    can be translated as:
    
        Private Type GUID 
            Data1 As Long 
            Data2 As Integer 
            Data3 As Integer 
            Data4(0 To 7) As Byte 
        End Type 
    		
      typGUID.Data1 = &H7BF80980
      typGUID.Data2 = &HBF32
      typGUID.Data3 = &H101A
      typGUID.Data4(0) = &H8B
      typGUID.Data4(1) = &HBB
      typGUID.Data4(2) = &H0
      typGUID.Data4(3) = &HAA
      typGUID.Data4(4) = &H0
      typGUID.Data4(5) = &H30
      typGUID.Data4(6) = &HC
      typGUID.Data4(7) = &HAB
    and I do not have to reverse any bit.
    I tested it and it work.

    Quote Originally Posted by LaVolpe View Post
    As far as saving IPicture to bytes, not sure how that will be useful? The CreatePicture routine you have is creating a bitmap, no transparency. You don't have the original bytes any longer. You might want to consider saving the bytes earlier in the process? If you don't care about the original bytes, which may be PNG format for example, then there are lots of sample code about to convert a bitmap handle (stdPicture/IPicture.Handle) to array. In fact, you could actually use VB's SavePicture to file then open file & get bytes that way -- but not a pretty solution.

    Edited: If you are concerned with bytes for your usercontrol's WriteProperties event and only need to save the bitmap, you don't need bytes. You can simply save the stdPicture/IPicture object directly
    damn... I didn't know I could simply save the IPicture in property. I wonder if that will retain the transparency I kept.
    I'll go try

    THANKS A LOT your knowledge on the subject is eye opening for me.
    the idea of saving the bytes early is also an idea to consider... I'll see if it is required, for now, the transparency and Alpha are maintained.

  18. #18

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    Quote Originally Posted by VbNetMatrix View Post
    I'll see if it is required, for now, the transparency and Alpha are maintained.
    I saved the IPicture directly as suggested.
    I confirm the IPicture can be saved that way, I can retrieve the content on a picture box.

    but my OCX fail to print it directly on the OCX when the project is reopened in IDE.
    it is "saving" the IPicture but I think something is loss.

    before closing the IDE, I confirmed both, the hidden picture box and direct print on the OCX is working.

    maybe I got a bug in my code... I'll check furthermore this afternoon.

  19. #19
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Get image size of IPicture with GDI routine

    but my OCX fail to print it directly on the OCX when the project is reopened in IDE...

    maybe I got a bug in my code.
    If you are drawing your picture to your usercontrol, you may need to use AutoRedraw=True or respond to the Paint events. But having the IPicture/stdPicture interface, this should work too: Set UserControl.Picture = yourCachedIPicture

    Of course you would retrieve your saved picture from ReadProperties using the same property name you gave it in WriteProperties.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  20. #20

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    Quote Originally Posted by LaVolpe View Post
    If you are drawing your picture to your usercontrol, you may need to use AutoRedraw=True or respond to the Paint events. But having the IPicture/stdPicture interface, this should work too: Set UserControl.Picture = yourCachedIPicture

    Of course you would retrieve your saved picture from ReadProperties using the same property name you gave it in WriteProperties.
    yeah I'm aware of the autoredraw but that's not the problem. It's showing the image properly before I close IDE
    and showing garbabge when I open it back.

    I tried with bigger picture and I realized the "gargage" was in fact a picture of upper left corner of screen where you can read:
    "Project1 - Microsoft Visual Basic"

    but like a NOT blue "mask"

    in other word, I got a picture, but not the one I got recorder... strangly, the picture I got recorder get assigned in the picturebox holder but NOT in the IPicture object....

    puzzle me...

    here what I did:
    Code:
    Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
      Set mobjIPicture = PropBag.ReadProperty("Picture", Nothing)
    
    Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
      PropBag.WriteProperty "Picture", mobjIPicture, Nothing
    what am I missing ?

  21. #21
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Get image size of IPicture with GDI routine

    Can you make sure that mobIPicture is what you expect. Maybe something like the following, just before it is written to the propertybag.
    Code:
    Clipboard.Clear
    Clipboard.SetData mobjIPicture
    Then go and paste the image into Paint and verify.

    If that was verified, then maybe doing this may solve the problem? But I doubt it and is just a guess at best.
    Code:
    Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
      Dim tPic As stdPicture
      Set tPic = mobjIPicture
      PropBag.WriteProperty "Picture", tPic, Nothing
      ...
    End Sub
    Likewise, you can use the Clipboard test when you read the picture from the propertybag, just as a test.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  22. #22

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    Quote Originally Posted by LaVolpe View Post
    Can you make sure that mobIPicture is what you expect. Maybe something like the following, just before it is written to the propertybag.
    Code:
    Clipboard.Clear
    Clipboard.SetData mobjIPicture
    Then go and paste the image into Paint and verify.

    If that was verified, then maybe doing this may solve the problem? But I doubt it and is just a guess at best.
    Code:
    Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
      Dim tPic As stdPicture
      Set tPic = mobjIPicture
      PropBag.WriteProperty "Picture", tPic, Nothing
      ...
    End Sub
    Likewise, you can use the Clipboard test when you read the picture from the propertybag, just as a test.
    thanks Lavolpe.

    I tried your suggestion... I was still puzzle because everything looked fine...
    so I decided to make a simple test project.

    a simple OCX that show a BMP but saving and reading the BMP (instead of png) as IPicture
    and... it worked...
    so I started to use same syntax and same variable to get where there was a mismatch...

    well... as you know... and you'll laugh because you probably had that bug in the past.,
    IPicture is not in the auto complete of the IDE and when you type IPicture , sometime it get completed to
    IPictuteDisp

    for some reason, as long as I don't quit the IDE, it was working but when I left IDE and load back, the image was somehow corrupted.

    I'm doing the modification right now, I'll keep you informed.

  23. #23

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    The IPictureDisp bug didn't fix the problem...

    same thing...

    I'm really puzzled. maybe too tired... tomorow is another day.

  24. #24
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Get image size of IPicture with GDI routine

    well... as you know... and you'll laugh because you probably had that bug in the past.,
    IPicture is not in the auto complete of the IDE and when you type IPicture , sometime it get completed to
    IPictuteDisp
    Tip: If you are referencing "hidden" objects in VB, if you open the object explorer (F2) and right click in the bottom right "members" listview and select "Show hidden members", they will become visible to VB's intellisense/autocomplete
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  25. #25

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    Quote Originally Posted by LaVolpe View Post
    Tip: If you are referencing "hidden" objects in VB, if you open the object explorer (F2) and right click in the bottom right "members" listview and select "Show hidden members", they will become visible to VB's intellisense/autocomplete
    Sometime I wonder if there is someting you don't know about Vb6
    as for me... I really consider myself... a high level user... but still, I believe I have touch only a fraction of what Vb6 had to offer. sad choice Microsoft did in 1998.

    Edit: the problem still elude me. after the property is saved and loaded back, the image can be put in picture box but not directly on the ocx dc... still checking...

    there is also that bug I found a way out but don't know where it came out where when component finish loading, a resize event is fired and usercontrol gain 1pixel height and width. I had to make special check for that.

  26. #26

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    ok... I found the problem... but at first I was stuck with my INITIAL problem

    I'm using AlphaBlend() Api with AC_SRC_ALPHA flag
    The AlphaBlend flag FAIL if there is no transparency in the picture.

    everything work as long as the property is not saved because somehow, iPicture and even StdPicture keep transparency in memory as long as you don't save theses as property. When you load them from property, transparency is gone.
    and AlphaBlend (silently) FAIL because of AC_SRC_ALPHA flag. There is no error, just no output

    However. I have designed a way so the PNG transparency is replaced with WHITE color and I can now afford not using the AC_SRC_ALPHA flag...

    hourray !

    not perfect though, my preview box doesn't work the way it did, I'll have to find a workaround.

  27. #27

    Thread Starter
    Addicted Member
    Join Date
    May 2011
    Posts
    230

    Re: Get image size of IPicture with GDI routine

    Hi Lavolpe,

    you'll be glad to know that I arrived at a decent solution...
    only glitch are Alphachannel... not good... but regular (background) transparency work well
    not sure how I could get the quality you get with your AIC... I'm not sure how you show the original Data of the png on the the ocx I have simply used AlphaBlend api

    I think you'll like when you'll see the source... I'll send you a link soon.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width