Page 2 of 2 FirstFirst 12
Results 41 to 56 of 56

Thread: Create and load Cursor from byte array.

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

    Re: Create and load Cursor from byte array.

    DeleteObject may work, may not. DeleteObject is used for stuff that are associated with things that can be selected into hDCs: bitmaps, pens, brushes, etc. Icons & cursors aren't selected into DCs and have their own destruction APIs. Your call.

    Regarding your 2nd question above: that's what we call a leak.
    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. #42

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: Create and load Cursor from byte array.

    Quote Originally Posted by LaVolpe View Post
    DeleteObject may work, may not. DeleteObject is used for stuff that are associated with things that can be selected into hDCs: bitmaps, pens, brushes, etc. Icons & cursors aren't selected into DCs and have their own destruction APIs. Your call.

    Regarding your 2nd question above: that's what we call a leak.
    Thanks .

    To prevent leaks,as a precaution, I tend to store the resource handles in the application window Property using SetProp API so I can recover the resource handle in case there is a loss of state in the vbproject and the variables are released.

    Regards.

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

    Re: Create and load Cursor from byte array.

    I'd be tempted to store it in a stdPicture object so the system destroys it for me...

    Dim tPicIcon As stdPicture
    Set tPicIcon = zzHandleToStdPicture(hIcon, vbPicTypeIcon)
    Code:
    Private Declare Function OleCreatePictureIndirect Lib "oleaut32.dll" (lpPictDesc As Any, riid As Any, ByVal fPictureOwnsHandle As Long, iPic As IPicture) As Long
    
    Private Function zzHandleToStdPicture(hImage As Long, imgType As PictureTypeConstants) As IPicture
    
        ' function creates a stdPicture object from an image handle (bitmap or icon used in this class)
        
        'Private Type PictDesc
        '    Size As Long
        '    Type As Long
        '    hHandle As Long
        '    lParam As Long       for bitmaps only: Palette handle
        '                         for WMF only: extentX (integer) & extentY (integer)
        '                         for EMF/ICON: not used
        'End Type
        
        Dim lpPictDesc(0 To 3) As Long, aGUID(0 To 3) As Long
        
        lpPictDesc(0) = 16&
        lpPictDesc(1) = imgType
        lpPictDesc(2) = hImage
        aGUID(0) = &H7BF80980   ' Picture GUID {7BF80981-BF32-101A-8BBB-00AA00300CAB}
        aGUID(1) = &H101ABF32
        aGUID(2) = &HAA00BB8B
        aGUID(3) = &HAB0C3000
        Call OleCreatePictureIndirect(lpPictDesc(0), aGUID(0), 1&, zzHandleToStdPicture)
        
    End Function
    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}

  4. #44

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: Create and load Cursor from byte array.

    Quote Originally Posted by LaVolpe View Post
    I'd be tempted to store it in a stdPicture object so the system destroys it for me...
    Hi,

    How would storing the icon\cursor handle in a stdPicture prevent a resource leak ? Is that a mechanism behind the scenes ? And is there a way to verify it?

    BTW, calling DestroyICon or DeleteObject on the cursor handle right after creating the cursor doesn't seem to stop the cursor from being used .. I thought that by calling those APIs, the resource would be destroyed and could no longer be used .
    Code:
        GetCurHandle = CreateIconFromResourceEx(longs(0), UBound(longs) * 4, 1, &H30000, 0, 0, &H8000)
        
        DestroyIcon GetCurHandle
    
        SetCursor GetCurHandle '<=== This still works after destroying the cursor !
    Regards.
    Last edited by JAAFAR; Jun 18th, 2019 at 12:50 AM.

  5. #45
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,094

    Re: Create and load Cursor from byte array.

    Quote Originally Posted by JAAFAR View Post
    BTW, calling DestroyICon or DeleteObject on the cursor handle right after creating the cursor doesn't seem to stop the cursor from being used ..
    Do this only if today you are in a juggle-chainsaws mood and playing with fire is simply not enough :-))

    Quote Originally Posted by JAAFAR View Post
    I thought that by calling those APIs, the resource would be destroyed and could no longer be used.
    Technically the resource memory gets deallocated which marks the very resource as destoyed i.e. no one is going to draw an X over the image of the icon to "mark" it "destroyed, don't use!" for instance -- not worth the effort.

    Deallocated memory is (unfortunately) readable so there you have the side-effect. Try to restart the process to check is the behavior is repeatable (could be).

    cheers,
    </wqw>

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

    Re: Create and load Cursor from byte array.

    How would storing the icon\cursor handle in a stdPicture prevent a resource leak ?
    Don't know VBA as well as VB, so I am going to assume they are very similar in their garbage collection, tear down. In VB if we wrap an hIcon in a stdPicture and close the application, VB always releases its COM objects. Therefore, the hIcon is destroyed. If we didn't wrap it in a stdPicture and forgot to destroy the icon or the hit the "End" button, then the icon is leaked.

    Deallocated memory is (unfortunately) readable so there you have the side-effect. Try to restart the process to check is the behavior is repeatable (could be).
    Who of us haven't been bitten by that in the past, especially when accessing memory via CopyMemory... works in IDE but crashes when compiled, or random crashes. Probably got lucky when it seemed to work because the 'deallocated' memory just wasn't written over or freed at that point.
    Last edited by LaVolpe; Jun 18th, 2019 at 09:09 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}

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

    Re: Create and load Cursor from byte array.

    FYI, DestroyIcon and DestroyCursor are the same function, just named differently, starting at least with Vista. We can prove this with a couple of APIs. They may have been different functions at some point in earlier operating systems -- or they may have always been the same function, exported under 2 different names.
    Code:
    MsgBox (GetProcAddress(GetModuleHandle("user32.dll"), "DestroyCursor") = _    
           GetProcAddress(GetModuleHandle("user32.dll"), "DestroyIcon"))
    DeleteObject on the other hand is a different DLL (gdi32.dll vs. user32.dll). Since one DLL creates icons/cursors, I wouldn't opt to use a different DLL to destroy them unless documented to do so. When I look at the disassembled code for DeleteObject, I see no immediate references to the address of DestroyIcon/DestroyCursor. But I didn't try to follow that code through all of its jumps/redirection.
    Last edited by LaVolpe; Jun 18th, 2019 at 10:01 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}

  8. #48

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: Create and load Cursor from byte array.

    *
    Deallocated memory is (unfortunately) readable so there you have the side-effect
    Probably got lucky when it seemed to work because the 'deallocated' memory just wasn't written over or freed at that point.
    makes sense when you think in terms of windows allocating\deallocating memory for resources which I never really properly understood or paid much attention to... So thanks for clarifying.



    *
    In VB if we wrap an hIcon in a stdPicture and close the application, VB always releases its COM objects. Therefore, the hIcon is destroyed.
    By the same token, wouldn't wrapping the hIcon in the Form itself via some built-in Property or custom Propery of the form be enough then simply let the form itself release its COM objects (including the wrapped hIcon) when unloading the form?

    Regards.

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

    Re: Create and load Cursor from byte array.

    Quote Originally Posted by JAAFAR View Post
    *By the same token, wouldn't wrapping the hIcon in the Form itself via some built-in Property or custom Propery of the form be enough then simply let the form itself release its COM objects (including the wrapped hIcon) when unloading the form?

    Regards.
    Not sure what you mean by custom property. If you mean something like "Property Let/Get", then no. During form unload, would need to call code to get the value of that property and destroy the icon. If one hits "End" then that code won't be called, otherwise, the answer would be yes. By wrapping the icon in a stdPicture object, it will get released even when "End" is executed. I've verified this by creating my own COM objects via thunks and executing "End". The COM object reference count was still decremented to zero, and therefore it knows it is released and could execute its internal code for clean-up.

    You don't really need code to release COM objects unless you want to release them before they would technically go out of scope.

    Edited & just FYI. Let's take "End" off the table which you wouldn't be executing in a compiled application -- yes, I know you are messing with VBA & I'm talking VB. The normal way to prevent leaks follows. The word "object" is a used as a GDI object, i.e., hIcon, hBitmap, etc.

    1) destroy objects when no longer needed, resetting their variables to zero. Any object variables that are non-zero when project terminates may be a leak

    2) never let an object go out of scope without destroying the object. Usually this is a locally created object in a routine/class and destroyed before the routine's exit or class is terminated.

    3) for global/public objects, destroy them during unload/terminate events, if their variable values are not already zero

    In my signature below is a link for a FAQ regarding memory leaks prevention. Memory leaks in the IDE due to executing "End" can be expected and not really a big deal -- worse case is that you may have to restart the IDE if memory runs too low. The big deal is when you allow leaks to happen in any other scenario.
    Last edited by LaVolpe; Jun 18th, 2019 at 12:39 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}

  10. #50

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: Create and load Cursor from byte array.

    LaVolpe,

    Thanks for the explanation.

    In my signature below is a link for a FAQ regarding memory leaks prevention.
    I'll have a read through that.

    Regards

  11. #51

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: Create and load Cursor from byte array.

    Quote Originally Posted by LaVolpe View Post
    In my signature below is a link for a FAQ regarding memory leaks prevention.
    Very useful info in that tutorial !

    Anyways, Thank you very much indeed for all your guidance and assistance with my questions and for all the detailed explanations.

    I have come out of this thread with plenty of useful information and I have learnt a lot in the process.

    Again, Thank you Mr LaVolpe.

    Regards.

  12. #52
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,094

    Re: Create and load Cursor from byte array.

    @LaVolpe: Off-topic (kind of), do you have any pointers about detecting GDI+ leaks? I recently debugged some nasty ones (missing a GdipDisposeImage on handle re-assignment) that only manifested by over-consuming process working memory only and nothing in GDI/USER handles counts for instance.

    Is there some debug build of gdiplus.dll that is supposed to be used in this case or any other pointers? Most other languages use class wrappers that are impl RAII and leaks are mostly non-existent, provided that client code does not call flat API directly, so info on preventing leaks is scarce.

    cheers,
    </wqw>

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

    Re: Create and load Cursor from byte array.

    Quote Originally Posted by wqweto View Post
    @LaVolpe: Off-topic (kind of), do you have any pointers about detecting GDI+ leaks?
    The obvious but inefficient method is: Start GDI+ do what's needed, cleanup, stop GDI+ in the same routine. That is not a good solution for a heavily GDI+ based project.

    Other than above, comparing memory in use between project startup and unload. If you are leaking a lot, say due to not releasing a GDI+ object in a loop, it should show up there. But that's a very specific case.

    The only thing I can suggest is to always include the destruction line of code immediately after typing the creation line of code. Then insert other code between those lines. That tutorial of mine suggests that method as a "good habit". Also, in class cleanup, look at module-level variables and dispose of them if non-zero, always remembering to reset their variables to zero when they are disposed, another "good habit".

    If anyone felt really creative, they could create a COM object via TLB (early-bound) or thunk (late-bound) that wraps a GDI+ object. The thought is that the object would have an initialization method, something like:
    Code:
    Sub SetObject(hHandle As Long, IStreamPtr As Long, DestroyFunction As BSTR)
    Property Get Handle() to return the GDI+ handle
    When the COM object ref count reaches zero, it will deref the stream after destroying the handle using the passed function. Internally, the function pointer retrieved via GetProcessAddressW. If the GDI+ object is not stream based, i.e., file-based image, brush handle, etc, then a null IStreamPtr would be passed. Something like that COM object could be pretty useful. No need to worry about destruction, simply set the object to Nothing or let it go out of scope, much like VB's stdPicture & stdFont objects.

    Last but not least. Hitting "End" in any way while GDI+ is loaded most certainly introduces leaks otherwise. And it is often the case, it may crash the IDE at some point.

    I'm not aware of any "GDI+ handle/object" tracking in apps like task manager
    Last edited by LaVolpe; Jun 19th, 2019 at 06:51 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}

  14. #54
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,094

    Re: Create and load Cursor from byte array.

    FYI, there is such cleanup thunk already implemented in MST that for instance I'm using here to perform socket cleanup to prevent End button/statement sockets leak esp. listening sockets cannot share common port and second socket open fails if the previous listening socket is not properly closed.

    I think its constant usage would be an overkill for the mostly ephemeral GDI+ handles though.

    The trouble w/ missing GDI+ resources reporting tools is that I'm used to writing cleanup code on solid principles for quite some years now (long time since I was a junior dev) and the control that was leaking above is production quality (this is not a quick PoC project) but still I found out about the leak through accidental memory usage logging on a live system. At the end of the workday there were 400MB allocated by the process that could not be accounted for. And it was this small GDI+ image leak that was slowly poisoning the process though still the end-users did not observe any visible side-effects (yet) until I fixed it.

    My search continues then. . .

    cheers,
    </wqw>

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

    Re: Create and load Cursor from byte array.

    Quote Originally Posted by wqweto View Post
    I think its constant usage would be an overkill for the mostly ephemeral GDI+ handles though.
    A thunk designed specifically for GDI+ handles should not really be overkill, especially if it has just 1 public method, which is also the default method: Handle. Even a late-bound version I would think shouldn't introduce any significant speed bumps for a vast majority of applications.

    If I were to write one, I think I'd create a "factory" thunk that manages the GDI+ token and creates the COM wrapper for any GDI+ handle. The factory thunk may be somewhat large, since it will handle creation/destruction of itself, the token, and any wrappers. The individual wrapper objects would only be about 2 dozen bytes each, exposing just that one read-only property: 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}

  16. #56
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,094

    Re: Create and load Cursor from byte array.

    Quote Originally Posted by LaVolpe View Post
    A thunk designed specifically for GDI+ handles should not really be overkill, especially if it has just 1 public method, which is also the default method: Handle. Even a late-bound version I would think shouldn't introduce any significant speed bumps for a vast majority of applications.
    MST cleanup thunk has only one purpose in life -- on refcount=0 to call a initially designated destroy function on a specific 4-byte handle. This handle itself has to be stored in *another* m_hImage member variable for instance, so that it can be accessed w/ no overhead from VB6 code.

    On second thought probably this small thunk object can be neatly reused. For instance when a GDI+ image is recreated its associated thunk can be instructed to swap it's "doomed to be destroyed" handle for the new fresh one so to skip releasing/allocating the thunk object on every repaint for instance.

    I might actually try this approach, esp. now that this particular control has a similar to built-in AutoRedraw repaint impl but using a 32-bit DIBs to be usable for alpha-transparent user-controls so control's heavy repaint is done from this DIB cache w/ no GDI+ operations whatsoever.

    cheers,
    </wqw>

Page 2 of 2 FirstFirst 12

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