IonicWind Software

IWBasic => General Questions => Topic started by: ckoehn on October 27, 2018, 10:59:21 am

Title: Cursor from Resource
Post by: ckoehn on October 27, 2018, 10:59:21 am
I made a simple animation cursor called "paper.ani".  I can load and run it with LOADIMAGE("paper.ani",@IMGCURSOR).  But when embedded in the resource file I cannot figure out how to load it.

I have it in the resource file as: 300 CURSOR "c:\paper.ani"

LOADIMAGE(300, @IMGCURSOR) and LOADIMAGE("300", @IMGCURSOR) doesn't work.  What am I not doing right?  I would like to include it in the resource file.

Later,
Clint
Title: Re: Cursor from Resource
Post by: ckoehn on October 27, 2018, 12:32:18 pm
Guess I'll answer my own question.  I don't think you can have an animation cursor in a resource file.  It doesn't support it.

So.....

I'm using LarryMc's  ExtractResource sub to move from a resource to file and loading it from there.

Kind of an interesting thing.  If you use LOADIMAGE, you have to do a DELETEIMAGE.  However, if you use LoadCursorFromFile(filename), you don't have to do anything else.

Later,
Clint
Title: Re: Cursor from Resource
Post by: fasecero on October 27, 2018, 02:25:46 pm
LoadCursor can load a cursor from the executable resource
https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-loadcursora

Code Select
LoadCursor(GetModuleHandle(0), MAKEINTRESOURCE(300))

SUB MAKEINTRESOURCE(n as WORD),POINTER
pointer pReturn = 0

_asm
lea eax,[ebp-4]
mov ebx,[ebp+8]
mov [eax],ebx
_endasm

RETURN pReturn
ENDSUB


MSDN states the following about resources:

Quote
When you are finished using a bitmap, cursor, or icon, you can release its associated memory by calling one of the functions in the following table.

Bitmap  DeleteObject
Cursor   DestroyCursor
Icon      DestroyIcon

The system automatically deletes these resources when the process that created them terminates; however, calling the appropriate function saves memory and decreases the size of the process's working set.
Title: Re: Cursor from Resource
Post by: ckoehn on October 27, 2018, 03:10:47 pm
fasecero,

It will load a ".cur" but not a ".ani"  cursor file.

Later,
Clint
Title: Re: Cursor from Resource
Post by: fasecero on October 27, 2018, 04:10:17 pm
Oh I see, didnt notice the .ani extension... let's see if we can solve this :)
Title: Re: Cursor from Resource
Post by: fasecero on October 27, 2018, 05:05:41 pm
Found several sites claiming that loading the .ani as a custom resource (FindResource/LoadResource/LockResource...) would work but no luck in here.

QuoteI'm using LarryMc's  ExtractResource sub to move from a resource to file and loading it from there.


This seems to be the only way.
Title: Re: Cursor from Resource
Post by: fasecero on October 27, 2018, 07:11:37 pm
Well, the code that I had written actually worked, short story there are several .ani "versions" and the function CreateIconFromResource(...) only accepts some of them. The long explanation in here.
https://stackoverflow.com/questions/5519480/once-again-about-animation-ani-cursors-from-program-resources-delphi-2010

So use the code below, if it does NOT work then you have to change the .ani version. This can be done with a hexagesimal editor but the easiest way is to use this open source software, Greenfish Icon Editor. I do not want to advertise anything but that program is the only one I've found that is "aware" of this problem. Just open the .ani and save it again and the program will make the .ani fully compatible with the windows API.
http://greenfishsoftware.org/gfie.php

The .rc file

Code Select

300 ANIMCURSOR "C:\\Example\\cursor.ani"


Code Select

$INCLUDE "windowssdk.inc"

$MAIN

WINDOW w1
OPENWINDOW w1,0,0,600,400,@MINBOX|@MAXBOX|@SIZE,NULL,"Simple Window",&w1_handler
SETCURSOR w1, @CSCUSTOM, LoadAnimatedCursor(300)

' main loop
WAITUNTIL w1 = 0
END

' window procedure
SUB w1_handler(), INT
SELECT @MESSAGE
CASE @IDCREATE
CENTERWINDOW w1

CASE @IDCLOSEWINDOW
CLOSEWINDOW w1
ENDSELECT

RETURN 0
ENDSUB

SUB LoadAnimatedCursor(UINT imgno), HCURSOR
    HCURSOR hCursor = 0
    HINSTANCE hInstance = GetModuleHandle(0)

    IF hInstance THEN
HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(imgno), "ANIMCURSOR")
DWORD dwResourceSize = SizeofResource(hInstance, hResource)

        IF dwResourceSize THEN
HGLOBAL hRsrcGlobal = _LoadResource(hInstance, hResource)

            IF hRsrcGlobal THEN
LPBYTE pResource = LockResource(hRsrcGlobal)

                IF pResource THEN
hCursor = CreateIconFromResource(pResource, dwResourceSize, FALSE, 0x00030000)
                ENDIF

                FreeResource(hRsrcGlobal)
            ENDIF
        ENDIF
    ENDIF

    RETURN hCursor
ENDSUB


Or you can avoid all this mess just by using Larry's method  ;D
Title: Re: Cursor from Resource
Post by: Andy on October 27, 2018, 09:17:21 pm
Fasecero is right Clint,

Best to use LarryMc's ExtractResourse code, it works very well and I have used it many times.

Andy.
:)
Title: Re: Cursor from Resource
Post by: ckoehn on October 31, 2018, 06:14:50 am
fasecero,  I'll take a look at it, and thanks for looking at it. :)

Andy, I currently am using it and it does work good.

Later,
Clint
Title: Re: Cursor from Resource
Post by: ckoehn on November 02, 2018, 10:06:15 am
fasecero,

Added your LoadAnimatedCursor sub to my "toolbox".  Worked good.   :D

Later,
Clint
Title: Re: Cursor from Resource
Post by: fasecero on November 03, 2018, 11:13:07 am
Glad it helped. It have the adventage of not needing the resource extraction (chance to trigger UAC consent prompt on some folder and non admin accounts) but with the chance of having to use an unknown external program... Is a win lose situation.