Results 1 to 3 of 3

Thread: [API] HICON/HCURSOR from Array

  1. #1

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

    [API] HICON/HCURSOR from Array

    Actually needed to do this & couldn't find any help on the net. Much researching resulted in posts saying to extract the icon/cursor bits to 2 bitmaps and use CreateIconIndirect. Doable, but why? I mean if I already have everything in a proper icon/cursor image format, there must be an easier way and there is... But first some other alternatives.

    a. Send array to OleLoadPicture API, but no support for 32bpp or PNG (not sure 16 bit is supported either)
    b. Save array to file and use LoadImage API but don't use VB's LoadPicture for same reasons as OleLoadPicture API


    Ensure you know the proper format if you create them yourself. Each icon/cursor resource contains a 6 byte directory structure, followed by a 16 byte entry structure per icon. Along with that comes your BitmapInfoHeader (40 bytes) then the palette (if any & 4 bytes per color), then the actual bitmap and last, followed by the mask, per icon. All icons/cursors have masks even if 32bpp ones don't use masks. PNGs are a bit different. There is no BitmapInfoHeader nor palette nor bitmap nor mask. The entire PNG file is used in their place. The structures would look something like the following.
    Code:
    Private Type ICONDIRENTRY   ' ICONS                     CURSORS
        bWidth As Byte          ' width 256=0               width 256=0
        bHeight As Byte         ' height 256=0              height 256=0
        bColorCount As Byte     ' >= 8bpp = 0               >= 8bpp = 0
        bReserved As Byte
        wPlanes As Integer      ' must be 1                 X hot spot
        wBitCount As Integer    ' bit depth                 Y hot spot
        dwBytesInRes As Long    ' nr bytes in resource      nr bytes in resource
        dwImageOffset As Long   ' offset to 1st byte        offset to 1st byte
    End Type
    Private Type ICONDIR
        idReserved As Integer
        idType As Integer       ' value is 1                value is 2
        idCount As Integer      ' nr idEntries              nr idEntries
        idEntries() As ICONDIRENTRY
    End Type
    The API to use is not well documented but works perfectly. On Vista, it can even be used to create an icon/cursor handle from PNGs embedded in icons. Or really any PNG (256x256 or less) if you create your own icon directory & entry structures.

    Here is the API and there are only slight differences in usage if using it for a cursor vs. an icon. The differences in the two calls are highlighted in blue below.

    Supply valid parameters & am assuming imgData() is a byte array, zero-bound, and imgData() has only 1 icon/cursor resource. If so, at byte 22 will be the BitmapInfoHeader which is what needs to be pointed to for icons & 4 bytes earlier for cursors. If the desired width & height are left at zero, then system default icon size will be used. If all goes well, and it should, the return value is a valid icon/cursor handle that must be destroyed sometime with DestroyIcon or DestroyCursor APIs, respectively. Exception to that rule would be using LR_Shared flag in the final parameter of the API. See MSDN documentation link provided below.

    Icon:
    Code:
    Const ICRESVER As Long = &H30000
    
    HICON = CreateIconFromResourceEx(imgData(22), UBound(imgData) - 21&, True, ICRESVER, _
        DesiredWidth, DesiredHeight, 0&)
    Note: If you don't need a real cursor, you can create an HICON from the cursor source simply by treating the cursor source as an icon source, i.e., process the cursor resource same as an icon resource.

    Cursor. Requires a little extra. It is nearly identical but requires the cursor's hotspot as the first 4 bytes being referenced. Below I simply back them up, then move them in front of the BitmapInfoHeader, then restore them later
    Code:
    Dim lOldData As Long
    Const ICRESVER As Long = &H30000
    
    CopyMemory lOldData, imgData(18), 4&        ' copy to restore
    CopyMemory imgData(18), imgData(10), 4&     ' move cursor hotspot to this position
    
    HCURSOR = CreateIconFromResourceEx(imgData(18), UBound(imgData) - 17&, False, ICRESVER, _
        DesiredWidth, DesiredHeight, 0&)
    
    CopyMemory imgData(18), lOldData, 4&        ' restore
    And the API ... http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
    Code:
    Private Declare Function CreateIconFromResourceEx Lib "user32.dll" (presbits As Any, ByVal dwResSize As Long, ByVal fIcon As Long, ByVal dwVer As Long, ByVal cxDesired As Long, ByVal cyDesired As Long, ByVal Flags As Long) As Long
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
    Private Declare Function DestroyCursor Lib "user32.dll" (ByVal hCursor As Long) As Long
    Private Declare Function DestroyIcon Lib "user32.dll" (ByVal hIcon As Long) As Long
    Last edited by LaVolpe; Feb 11th, 2011 at 09:38 AM. Reason: Added the final NOTE
    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}

  2. #2

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

    Re: [API] HICON/HCURSOR from Array

    And I foresee a question being asked... "I have an icon file that has 10 icons in it and I want to extract the 7th one. How do I do that then?"

    The offset into the array and size of the resource are the only 2 variables in that API call. To answer that question, simple math is involved. Using same code as 1st post above with slight modifications.
    Code:
     Dim lDirPos As Long, lSize As Long, lBMPpos As Long
    
       lDirPos = 6 + (7-1) * 16  
       ' ^^ (7-1) is 7th icon, but from zero-bound it is really the 6th
       ' ^^ 6 is the icon directory structure size
       ' ^^ 16 is the size of each directory entry structure
    
       CopyMemory lSize, imgData(lDirPos + 8), 4&
       ' ^^ 8 is how many bytes into the directory where we can find the size of the resource
    
       CopyMemory lBMPpos, imgData(lDirPos + 12), 4&
       ' ^^ 12 is how many bytes into the directory where we can find the offset to the BitmapInfoHeader (or PNG)
    
       ' Now call your function
        HICON = CreateIconFromResourceEx(imgData(lBMPpos), lSize, True, ICRESVER, _
              DesiredWidth, DesiredHeight, 0&)
    
       ' FOR CURSORS & SAME QUESTION, just one more offset will help
       Dim lHotSpot As Long, lOldData As Long
    
       CopyMemory lHotSpot, imgData(lDirPos + 4), 4&
       ' ^^ 4 is how many bytes into the directory where we can find the X hotspot
    
       lBMPpos = lBMPpos - 4   ' move pointer back 4 bytes
       lSize = lSize + 4     ' add 4 bytes to resource size
       CopyMemory lOldData, imgData(lBMPpos), 4&
       CopyMemory imgData(lBMPpos), imgData(lHotSpot), 4&
    
        HCURSOR = CreateIconFromResourceEx(imgData(lBMPpos), lSize, False, ICRESVER, _
             DesiredWidth, DesiredHeight, 0&)
    
        CopyMemory imgData(lBMPpos), lOldData, 4&
    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
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [API] HICON/HCURSOR from Array

    FYI. Glad someone besides me found a real-world use for this code.
    If interested, this is the thread I'm referring to.
    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}

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