Results 1 to 26 of 26

Thread: IPicture interface methods

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Jul 2020
    Posts
    186

    IPicture interface methods

    1).
    Code:
    Public Mypic As IPicture
    '....................
        Set Mypic = LoadPicture("d:\image.jpg")
    This method works with standard images. But when the .png needs to be loaded, the method will not work.
    I donít understand how to use the GdipLoadImageFromFile function for this.
    2). The IPicture interface has a SetHDC method and CurDC and Handle properties. How to use them? This is not clear from Microsoft's description.

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

    Re: IPicture interface methods

    You cannot load a PNG via VB's LoadPicture. VB doesn't support PNG/TIFF and some other image formats/subformats.

    If you search the forum, you will find lots of examples of getting a PNG into a stdPicture object using GDI+ and other APIs. Some are fairly simple routines that fill any PNG transparency with a solid color and convert the PNG to bitmap for use in stdPictures. Some use hooking/subclassing of the IPicture interface to display PNGs with transparency by handling the details in 'thunks'. The option you choose depends on how you want to handle transparency (if at all) and whether the background that the transparency is rendered over will ever change.

    Here's a complex option: https://www.vbforums.com/showthread....-GDI&p=5272035
    Here's a simple option that draws to a picturebox: https://www.vbforums.com/showthread....o-draw-PNG-GDI
    Last edited by LaVolpe; Oct 28th, 2020 at 01:18 PM.
    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
    Jul 2020
    Posts
    186

    Re: IPicture interface methods

    Quote Originally Posted by LaVolpe View Post
    You cannot load a PNG via VB's LoadPicture. VB doesn't support PNG/TIFF and some other image formats/subformats.
    1). That's what I wrote about.
    The challenge is to use Ipicture not tied to StdPicture. For example, on the page:
    https://www.vbforums.com/showthread....cture-instance
    a way to get a backup copy of the image is discussed. In this case, we are talking about loading an image of any type into the interface.
    2). I've dealt with the Ipicture.Render method.
    To use the GDI functions, an hDC receiver is required. Will I be able to get the hDC of the "independent" Ipicture? How can I use the same Handle property for it?

  4. #4
    PowerPoster
    Join Date
    Feb 2006
    Posts
    22,314

    Re: IPicture interface methods

    The IPicture is just one interface exposed by a StdPicture object. Interfaces don't exist separate from their implementations. StdPictures do not have an hDC at all, they only wrap around an image handle.

    The properties and methods you are talking about reflect whether a StdPicture's wrapped hBitmap has been selected into some DC.

  5. #5

    Thread Starter
    Addicted Member
    Join Date
    Jul 2020
    Posts
    186

    Re: IPicture interface methods

    Quote Originally Posted by dilettante View Post
    The properties and methods you are talking about reflect whether a StdPicture's wrapped hBitmap has been selected into some DC.
    But you can load an image into it using the LoadPicture method and use it for both storage and recording.
    Code:
    Set Picture1.Picture = Mypic
    Mypic = SavePicture("d:\image.bmp")
    Which means that the image is loaded into a certain area of memory in the form of a raster, regardless of the interface ownership.
    Something like this happens in a function:
    Code:
        Public img As Long
    '......................
     tmp_status = GdipLoadImageFromFile(StrConv(FileName, vbUnicode), img)
    If it has a Handle, then it can be used somehow. When trying to use it in the GdipDrawImageRect function, error № 2 occurs.
    Last edited by Argus19; Oct 28th, 2020 at 09:59 PM.

  6. #6
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    3,022

    Re: IPicture interface methods

    All StdPictures in VB6 (and in ole32) are created with OleCreatePictureIndirect API function call or with a OleLoadPictureEx API function call.

    Consider the PICTDESC struct which is wrapped by such StdPicture instance:

    Code:
    typedef struct tagPICTDESC {
      UINT  cbSizeofstruct;
      UINT  picType;
      union {
        struct {
          HBITMAP  hbitmap;
          HPALETTE hpal;
        } bmp;
        struct {
          HMETAFILE hmeta;
          int       xExt;
          int       yExt;
        } wmf;
        struct {
          HICON hicon;
        } icon;
        struct {
          HENHMETAFILE hemf;
        } emf;
      };
    } PICTDESC, *LPPICTDESC;
    It's likely (obvious) that the IPicture::Handle property is either an HBITMAP, an HMETAFILE/HENHMETAFILE or an HICON depending on IPicture::Type property value.

    But GdipDrawImageRect function does *not* work with any of these handle types as it clearly needs a handle to a GDI+ bitmap and nothing else.

    cheers,
    </wqw>

  7. #7
    PowerPoster
    Join Date
    Feb 2006
    Posts
    22,314

    Re: IPicture interface methods

    This example uses GDI+ to load a PNG file as a GDI+ bitmap then convert that to a GDI bitmap. Afterward its Render() method can be used to AlphaBlend() it onto a "canvas" object like a Form or PictureBox.

    The code does not use StdPicture because its version of Render() will not use AlphaBlend(). StdPicture.Render() only choses among BitBlt(), StretchBlt(), and TransparentBlt() in the case of GIFs with transparency and icons, in addition to metafile playback calls for WMF and EMF images.

    Name:  sshot.png
Views: 243
Size:  7.2 KB


    So how did we get screwed? I blame the people who wouldn't get off Windows 95. Otherwise we might have gotten blending in an OLE update or something. But "Baby can't eat steak so we all get pablum."
    Attached Files Attached Files
    Last edited by Shaggy Hiker; Oct 29th, 2020 at 11:29 AM. Reason: Removed some inappropriate commentary.

  8. #8

    Thread Starter
    Addicted Member
    Join Date
    Jul 2020
    Posts
    186

    Re: IPicture interface methods

    Apparently because of my ignorance of the English language, there was no understanding.
    1). How to load into abstract, i.e. independent of anything, IPicture interface any type of image?
    2). I am interested in examples of practical use of properties and methods of the IPicture interface:
    Attachment 179159
    In addition to the Render, LoadPicture and SavePicture methods, which I already figured out.
    Last edited by Argus19; Oct 29th, 2020 at 10:53 AM.

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

    Re: IPicture interface methods

    How to load into abstract, i.e. independent of anything, IPicture interface any type of image?
    IPicture can't support all image formats, it supports bitmaps, icon/cursor, and metafiles. JPGs are converted to bitmaps, GIFs (1st frame) are converted to bitmaps with a transparency mask/color associated with the bitmap.

    So for all image formats not supported by IPicture, that format should be converted to one that it does support. Otherwise, you can't wrap it with an IPicture interface. You can use a 32bpp bitmap as a common denominator and render it manually whenever needed using AlphaBlend or GDI+ APIs. The IPicture does expose the bitmap handle to enable that.

    Any solution you are looking for (if I understand you correctly) requires hooking the IPicture interface to intercept its rendering requests and do the rendering manually. It would be fantastic if we could easily implement stdPicture.
    Last edited by LaVolpe; Oct 29th, 2020 at 11:33 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}

  10. #10
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    36,144

    Re: IPicture interface methods

    @Dil: I just called somebody a recluse and got a funny picture back about a pot and a kettle.
    Perhaps one shouldn't complain about the mote in their neighbors eye...
    Last edited by Shaggy Hiker; Oct 29th, 2020 at 11:38 AM.
    My usual boring signature: Nothing

  11. #11
    PowerPoster
    Join Date
    Feb 2006
    Posts
    22,314

    Re: IPicture interface methods

    Point taken.

    I guess it was more than a bit of a rant. Extending OLE to handle PNG and AlphaBlend should have been easy for Microsoft though. I can't do anything about it so I just work around it.

  12. #12
    Frenzied Member
    Join Date
    Feb 2015
    Posts
    1,780

    Re: IPicture interface methods

    You could use a metafile with the EMR_ALPHABLEND record. You don't need to do some extra work excepting the conversion to EMF. You can use most of the standard features with EMF including LoadPicture, controls etc. The disadvantage is the big file size. The attached project has the small example of using such EMF files.

    Alternatively you could use VBPNG which allows to store all the resources using original formats. As a bonus you have ani cursors/32bpp icons support.
    Attached Files Attached Files

  13. #13

  14. #14

    Thread Starter
    Addicted Member
    Join Date
    Jul 2020
    Posts
    186

    Re: IPicture interface methods

    Quote Originally Posted by LaVolpe View Post
    IPicture can't support all image formats, it supports bitmaps, icon/cursor, and metafiles. JPGs are converted to bitmaps, GIFs (1st frame) are converted to bitmaps with a transparency mask/color associated with the bitmap.
    Thanks. The first question is clear. It is necessary to convert the image to a raster. I'm already afraid to continue. If possible, let's move on to the second question, because I have not been able to find anywhere descriptions of the practical use of the properties and methods of the IPicture interface, except for the three that I wrote about.
    If they exist, then somehow they are used. I want to understand with examples how. That's all.
    VB has a lot of interesting "things" about which nothing is written anywhere.
    Last edited by Argus19; Oct 29th, 2020 at 01:08 PM.

  15. #15
    PowerPoster
    Join Date
    Feb 2006
    Posts
    22,314

    Re: IPicture interface methods

    IPicture is a hidden interface for a reason.

    Most of its useful members are exposed by the default interface of a StdPicture object. The rest are mainly meant for internal use by ActiveX controls.

  16. #16
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    3,022

    Re: IPicture interface methods

    Btw, this weirdly loads a transparent PNG into an StdPicture as proposed by The trick above

    Code:
    Option Explicit
    
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length 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 SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
    Private Declare Function CreateEnhMetaFile Lib "gdi32" Alias "CreateEnhMetaFileA" (ByVal hdcRef As Long, ByVal lpFileName As Long, lpRect As RECT, ByVal lpDescription As Long) As Long
    Private Declare Function CloseEnhMetaFile Lib "gdi32" (ByVal hDC As Long) As Long
    Private Declare Function DeleteEnhMetaFile Lib "gdi32" (ByVal hEmf As Long) As Long
    Private Declare Function CreateDIBSection Lib "gdi32" (ByVal hDC As Long, lpBitsInfo As BITMAPINFOHEADER, ByVal wUsage As Long, lpBits As Long, ByVal Handle As Long, ByVal dw As Long) As Long
    Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
    Private Declare Function AlphaBlend Lib "msimg32" (ByVal hDestDC As Long, ByVal lX As Long, ByVal lY As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal widthSrc As Long, ByVal heightSrc As Long, ByVal blendFunct As Long) As Boolean
    Private Declare Function OleCreatePictureIndirect Lib "oleaut32" (lpPictDesc As PICTDESC, riid As Any, ByVal fPictureOwnsHandle As Long, ipic As IPicture) As Long
    Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
    '--- GDI+
    Private Declare Function GdiplusStartup Lib "gdiplus" (hToken As Long, pInputBuf As Any, Optional ByVal pOutputBuf As Long = 0) As Long
    Private Declare Function GdipLoadImageFromFile Lib "gdiplus" (ByVal sFilename As Long, hImage As Long) As Long
    Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal hImage As Long) As Long
    Private Declare Function GdipBitmapLockBits Lib "gdiplus" (ByVal hBitmap As Long, lpRect As Any, ByVal lFlags As Long, ByVal lPixelFormat As Long, uLockedBitmapData As BitmapData) As Long
    Private Declare Function GdipBitmapUnlockBits Lib "gdiplus" (ByVal hBitmap As Long, uLockedBitmapData As BitmapData) As Long
    
    Private Type BitmapData
        Width               As Long
        Height              As Long
        Stride              As Long
        PixelFormat         As Long
        Scan0               As Long
        Reserved            As Long
    End Type
    
    Private Type RECT
        Left                As Long
        Top                 As Long
        Right               As Long
        Bottom              As Long
    End Type
    
    Private Type BITMAPINFOHEADER
        biSize              As Long
        biWidth             As Long
        biHeight            As Long
        biPlanes            As Integer
        biBitCount          As Integer
        biCompression       As Long
        biSizeImage         As Long
        biXPelsPerMeter     As Long
        biYPelsPerMeter     As Long
        biClrUsed           As Long
        biClrImportant      As Long
    End Type
    
    Private Type PICTDESC
        lSize               As Long
        lType               As Long
        hBmp                As Long
        hPal                As Long
    End Type
    
    Public Function LoadPngMetafile(sFilename As String) As StdPicture
        Const ImageLockModeRead As Long = 1
        Const PixelFormat32bppPARGB As Long = &HE200B
        Const DIB_RGB_COLORS As Long = 0
        Const AC_SRC_ALPHA  As Long = 1
        Const Opacity       As Long = 255
        Const PixPerInch    As Long = 96
        Dim aInput(0 To 3)  As Long
        Dim hBitmap         As Long
        Dim uData           As BitmapData
        Dim hMemDC          As Long
        Dim uHdr            As BITMAPINFOHEADER
        Dim hDib            As Long
        Dim lpBits          As Long
        Dim hPrevDib        As Long
        Dim rc              As RECT
        Dim hEnhDC          As Long
        Dim hEmf            As Long
        Dim uDesc           As PICTDESC
        Dim oPic            As IPicture
        
        If GetModuleHandle("gdiplus") = 0 Then
            aInput(0) = 1
            Call GdiplusStartup(0, aInput(0))
        End If
        If GdipLoadImageFromFile(StrPtr(sFilename), hBitmap) <> 0 Then
            GoTo QH
        End If
        If GdipBitmapLockBits(hBitmap, ByVal 0, ImageLockModeRead, PixelFormat32bppPARGB, uData) <> 0 Then
            GoTo QH
        End If
        hMemDC = CreateCompatibleDC(0)
        With uHdr
            .biSize = Len(uHdr)
            .biPlanes = 1
            .biBitCount = 32
            .biWidth = uData.Width
            .biHeight = -uData.Height
            .biSizeImage = uData.Stride * uData.Height
        End With
        hDib = CreateDIBSection(hMemDC, uHdr, DIB_RGB_COLORS, lpBits, 0, 0)
        If hDib = 0 Then
            GoTo QH
        End If
        Call CopyMemory(ByVal lpBits, ByVal uData.Scan0, uData.Stride * uData.Height)
        hPrevDib = SelectObject(hMemDC, hDib)
        rc.Right = (uData.Width * 2540 + PixPerInch \ 2) \ PixPerInch
        rc.Bottom = (uData.Height * 2540 + PixPerInch \ 2) \ PixPerInch
        hEnhDC = CreateEnhMetaFile(hMemDC, 0, rc, 0)
        Call AlphaBlend(hEnhDC, 0, 0, uData.Width, uData.Height, hMemDC, 0, 0, uData.Width, uData.Height, AC_SRC_ALPHA * &H1000000 + Opacity * &H10000)
        hEmf = CloseEnhMetaFile(hEnhDC)
        hEnhDC = 0
        With uDesc
            .lSize = Len(uDesc)
            .lType = vbPicTypeEMetafile
            .hBmp = hEmf
        End With
        '--- IID_IPicture
        aInput(0) = &H7BF80980
        aInput(1) = &H101ABF32
        aInput(2) = &HAA00BB8B
        aInput(3) = &HAB0C3000
        If OleCreatePictureIndirect(uDesc, aInput(0), 1, oPic) <> 0 Then
            GoTo QH
        End If
        hEmf = 0
        '--- success
        Set LoadPngMetafile = oPic
    QH:
        If hEnhDC <> 0 Then
            hEmf = CloseEnhMetaFile(hEnhDC)
        End If
        If hEmf <> 0 Then
            Call DeleteEnhMetaFile(hEmf)
        End If
        If hPrevDib <> 0 Then
            Call SelectObject(hMemDC, hPrevDib)
        End If
        If hDib <> 0 Then
            Call DeleteObject(hDib)
        End If
        If hMemDC <> 0 Then
            Call DeleteDC(hMemDC)
        End If
        If uData.Scan0 <> 0 Then
            Call GdipBitmapUnlockBits(hBitmap, uData)
        End If
        If hBitmap <> 0 Then
            Call GdipDisposeImage(hBitmap)
        End If
    End Function
    Not tested on XP for instance.

    cheers,
    </ww>

  17. #17

  18. #18
    PowerPoster
    Join Date
    Feb 2006
    Posts
    22,314

    Re: IPicture interface methods

    But can you use them for anything valuable in a real program?

    Is there some way to stuff them into an ImageList? Assign them to MSHFlexGrid.CellPicture? CommandButton.Picture? MDIForm.Picture? Anything useful? Anything? Bueller? Bueller?

    Feels as if we are back to making fingerpaint programs or games again.

    Don't get me wrong, stunt programs can be fun when you have nothing better to do. I'm just not sure how valuable such things are or whether they deserve to survive even the most superficial code review in the real world.

  19. #19

  20. #20

    Thread Starter
    Addicted Member
    Join Date
    Jul 2020
    Posts
    186

    Re: IPicture interface methods

    Quote Originally Posted by dilettante View Post
    Don't get me wrong, stunt programs can be fun when you have nothing better to do. I'm just not sure how valuable such things are or whether they deserve to survive even the most superficial code review in the real world.
    I once studied resistance of materials, integral dead reckoning and logarithms, organic and inorganic chemistry, the design of electric machines and so on. Over the past forty years, this has never come in handy for me and I have forgotten everything safely.

  21. #21
    PowerPoster
    Join Date
    Jun 2013
    Posts
    5,473

    Re: IPicture interface methods

    Quote Originally Posted by wqweto View Post
    Everything else yes.
    Just tested this here... and it seems, the MSHFlexGrid does not support StdPictures with the MetaFile-SubType (generally).
    (the vsFlexGrid-8-versions from ComponentOne though, will render these "Alpha-Metafile-StdPictures" nicely into their Cells).

    BTW, the "vbFriendly-Interfaces" Project contains support for IPicture-Interface-SubClassing
    (and an example, which allows to create "enhanced StdPicture-instances" which can then render PNG- and other Alpha-Channel-Resources properly also into a normal MSHFlexGrid)

    Olaf

  22. #22
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    3,022

    Re: IPicture interface methods

    Unfortunately yes. . . There are controls that try to draw StdPictures "by hand" and support vbPicTypeBitmap and vbPicTypeIcon only with no fallback to Render method. (Guilty as charged myself.)

    Couple of reasons come to mind:

    1. The always late-bound StdPicture::Render (which is IPictureDisp::Render in disguise) goes totally bonkers with VT_BYREF parameters. (The IPicture::Render is another method altogether, is early-bound and the callsite is compiled to a different bytecode and as a consequence has no problems with VT_BYREF params)

    2. The negative height trick with Render is an abomination

    3. The HIMETRIC sizes are much inconvenient too

    All of these convince control creators that Render is broken, surely made by insane monkeys at MS. That is why it's not widely used and thus metafiles (incl. enhanced metafiles) become poster child of a subtype of StdPictures.

    cheers,
    </wqw>

  23. #23

    Thread Starter
    Addicted Member
    Join Date
    Jul 2020
    Posts
    186

    Re: IPicture interface methods

    Quote Originally Posted by wqweto View Post
    2. The negative height trick with Render is an abomination
    Similarly, the origin of coordinates for normal people is located in the lower left corner.
    I wrote a short program to see the properties of the interface.
    Attached Files Attached Files

  24. #24
    PowerPoster
    Join Date
    Feb 2006
    Posts
    22,314

    Re: IPicture interface methods

    Quote Originally Posted by wqweto View Post
    There are controls that try to draw StdPictures "by hand" and support vbPicTypeBitmap and vbPicTypeIcon only with no fallback to Render method.
    Well that would be another argument against updating OLE to handle PNG rendering via AlphaBlend(). Not enough controls would respect it anyway, limiting its value. Perhaps "wrapping a PNG as an icon" is the closest thing to built-in support we can expect? I just don't know the limitations of that technique and haven't fiddled with it.

  25. #25
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    3,022

    Re: IPicture interface methods

    Quote Originally Posted by Argus19 View Post
    Similarly, the origin of coordinates for normal people is located in the lower left corner.
    More like in the center of the screen like DirectX/GPUs have it.

    Lower left is as much arbitrary as upper left and upper left is akin to CRT monitors beam traversal -- must have made sense back then, when all of this was invented :-))

    cheers,
    </wqw>

  26. #26

    Thread Starter
    Addicted Member
    Join Date
    Jul 2020
    Posts
    186

    Re: IPicture interface methods

    And that's not all. In Feng Yuan's book "Graphics Programming for Windows", the author writes that GDI manipulators are poorly documented and buggy.
    Checked it out. Handle Ipicture does not "understand" the GDI and GDI + functions.
    I tried to get hDC interface:
    Code:
    Public Mypic As IPicture
        Public ihDC As OLE_HANDLE
    '.................
    'Here we write the image to the PictureBox
            Set Mypic = Form1.Picture1.image
          Mypic.SetHdc (ihDC)
    The last line causes a crash.
    Last edited by Argus19; Oct 30th, 2020 at 03:33 PM.

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