December 07, 2019, 09:50:26 pm

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Cursor from Resource

Started by ckoehn, October 27, 2018, 10:59:21 am

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ckoehn

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

ckoehn

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

fasecero

October 27, 2018, 02:25:46 pm #2 Last Edit: October 27, 2018, 02:44:31 pm by fasecero
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.

ckoehn

fasecero,

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

Later,
Clint

fasecero

Oh I see, didnt notice the .ani extension... let's see if we can solve this :)

fasecero

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.

fasecero

October 27, 2018, 07:11:37 pm #6 Last Edit: October 27, 2018, 07:20:26 pm by fasecero
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

Andy

Fasecero is right Clint,

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

Andy.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

ckoehn

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

ckoehn

fasecero,

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

Later,
Clint

fasecero

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.