QB64.org Forum

Active Forums => Programs => Topic started by: Petr on June 09, 2018, 09:14:14 am

Title: Mouse pointers
Post by: Petr on June 09, 2018, 09:14:14 am
Hello. I just wrote a program that reads some CUR format files. This program shows all the cursors you can draw and at the end one new cursor use. (just for this program, be no worries).

Code: QB64: [Select]
  1. 'CUR file reader for read and draw cursor images from /windows/cursors dir. First version.
  2. 'Writed wihtout format knowledge just only on base from https://en.wikipedia.org/wiki/ICO_(file_format)
  3.  
  4.  
  5. 'can you find, how are writed some "unsupported" files?
  6. 'known bug is bad draw Pen big xl.
  7.  
  8. 'writed for fun by Petr
  9.  
  10.  
  11.  
  12. REDIM CursorsList(0) AS STRING
  13. Path$ = ENVIRON$("systemroot") + "\cursors\"
  14. Mask$ = "*.CUR"
  15. MakeCursorsList Path$, Mask$, CursorsList$()
  16.  
  17. Cursor$ = ENVIRON$("systemroot") + "\cursors\aero_arrow.cur"
  18. Img& = LoadCursor&(Cursor$, x, y)
  19.  
  20. PRINT "One cursor is loaded and will be used. This is Cursor loader info screen. Press any key...": SLEEP
  21.  
  22. _DEST my&
  23. CLS , _RGB32(128, 55, 220)
  24. ShowUsableCursors CursorsList$(), my&
  25.  
  26. SCREEN my&
  27.     PCOPY 1, _DISPLAY
  28.     ViewCursor Img&, x, y
  29.     _LIMIT 25
  30.  
  31. SUB ShowUsableCursors (Cursors() AS STRING, ToScreen AS LONG)
  32.     _DEST ToScreen&
  33.     X = 100: y = 100
  34.     FOR L = LBOUND(cursors) TO UBOUND(cursors)
  35.         P$ = ENVIRON$("systemroot") + "\cursors\" + Cursors(L)
  36.         i& = LoadCursor&(P$, a, b)
  37.         _DEST ToScreen&
  38.         IF i& >= 0 THEN GOSUB Unsupported: _CONTINUE
  39.         _PUTIMAGE (X, y), i&, ToScreen&
  40.         _FREEIMAGE i&
  41.         COLOR _RGB32(255, 255, 254), _RGB32(128, 55, 220)
  42.         _PRINTSTRING (X, y + 80), STR$(L) + ": " + Cursors(L), ToScreen&
  43.         X = X + 300: IF X > _DESKTOPWIDTH - 300 THEN X = 100: y = y + 300
  44.         IF y + 300 > _DESKTOPHEIGHT THEN
  45.             SCREEN ToScreen&: _PRINTSTRING (20, _DESKTOPHEIGHT - 20), "Press any key for view next...", ToScreen&: SLEEP: CLS , _RGB32(128, 55, 220): X = 100: y = 100
  46.             P$ = ""
  47.         END IF
  48.     NEXT L
  49.     _PRINTSTRING (20, _DESKTOPHEIGHT - 20), "New cursor is now used. Press Esc for end.", ToScreen&
  50.     EXIT SUB
  51.  
  52.     Unsupported:
  53.     _PRINTSTRING (X + 20, y + 50), "Not supported", ToScreen&
  54.     _PRINTSTRING (X, y + 80), STR$(L) + ": " + Cursors(L), ToScreen&
  55.     X = X + 300: IF X > _DESKTOPWIDTH - 300 THEN X = 100: y = y + 300
  56.     IF y + 300 > _DESKTOPHEIGHT THEN
  57.         SCREEN ToScreen&: _PRINTSTRING (20, _DESKTOPHEIGHT - 20), "Press any key for view next...", ToScreen&: SLEEP: CLS , _RGB32(128, 55, 220): X = 100: y = 100
  58.         P$ = ""
  59.     END IF
  60.     RETURN
  61.  
  62. SUB MakeCursorsList (Path AS STRING, Mask AS STRING, ToArray() AS STRING)
  63.     '    IF not win THEN PRINT "Error: MakeCursosList SUB is designed for Windows only.": SLEEP 1: END
  64.     Current$ = _CWD$
  65.     IF _DIREXISTS(Path$) THEN
  66.         CHDIR Path$
  67.         commandd$ = "DIR " + Mask$ + " /B > CursorsList.txt"
  68.         SHELL _HIDE commandd$
  69.         IF _FILEEXISTS("CursorsList.txt") THEN
  70.             CH = FREEFILE
  71.             OPEN "CursorsList.txt" FOR INPUT AS #CH
  72.             DO WHILE NOT EOF(CH)
  73.                 LINE INPUT #CH, crs$
  74.                 REDIM _PRESERVE ToArray(i) AS STRING
  75.                 ToArray$(i) = LEFT$(crs$, 20)
  76.                 i = i + 1
  77.             LOOP
  78.             CLOSE #CH
  79.         ELSE PRINT "Unknown error. File CursorsList.txt not created.": SLEEP 1: END
  80.         END IF
  81.     ELSE
  82.         PRINT "Error (Sub MakeCursorList): Specified path not exists.": SLEEP 1
  83.         EXIT SUB
  84.     END IF
  85.  
  86. SUB ViewCursor (Cursor AS LONG, ReductionX AS _BYTE, ReductionY AS _BYTE)
  87.     _DEST 0
  88.     _PUTIMAGE (_MOUSEX - ReductionX - 6, _MOUSEY - ReductionY), Cursor&, 0
  89.  
  90. FUNCTION LoadCursor& (Cursor AS STRING, XReturned, YReturned)
  91.     'returns: 1: File not exists, 2: Unsupported format, Value < 0 - valid cursor image
  92.     TYPE CUR
  93.         Reserved AS INTEGER '       2 bytes, always 00
  94.         Image_Type AS INTEGER '     1 = ICO format, 2 = CUR format, others are invalid
  95.         Number_images AS INTEGER '  number images in file
  96.     END TYPE
  97.  
  98.     TYPE Structure
  99.         Image_Width AS _UNSIGNED _BYTE
  100.         Image_Height AS _UNSIGNED _BYTE
  101.         Image_Color_Palette AS _UNSIGNED _BYTE
  102.         Reserved AS _UNSIGNED _BYTE 'always zero
  103.         Horizontal AS INTEGER '      In ICO format: Specifies color planes. Should be 0 or 1.
  104.         '                            In CUR format: Specifies the horizontal coordinates of the hotspot in number of pixels from the left.
  105.         Vertical AS INTEGER '        In ICO format: Specifies bits per pixel.
  106.         '                            In CUR format: Specifies the vertical coordinates of the hotspot in number of pixels from the top.
  107.         Size_of_image_data AS LONG
  108.         Offset_from_begin AS LONG
  109.     END TYPE
  110.     SCREEN _NEWIMAGE(800, 600, 32)
  111.     CLS
  112.     ERc = 0
  113.     DIM CUR AS CUR, Structure AS Structure
  114.  
  115.     IF _FILEEXISTS(Cursor$) THEN
  116.         CLOSE #1
  117.         OPEN Cursor$ FOR BINARY AS #1
  118.  
  119.  
  120.         GET #1, , CUR
  121.         PRINT "First 2 bytes (always 0):"; CUR.Reserved
  122.         PRINT "Image type (1 = ICO, 2 = CUR):"; CUR.Image_Type
  123.         PRINT "Number images in file:"; CUR.Number_images
  124.  
  125.         re:
  126.         '   _DEST 0
  127.         PRINT "======================================="; R
  128.         PRINT "Position in file:"; SEEK(1)
  129.         GET #1, , Structure
  130.         PRINT "Image width:"; Structure.Image_Width
  131.         PRINT "Image height:"; Structure.Image_Height
  132.         PRINT "Image color palette: (0 = LONG truecolor, 2 = _UNSIGNED _BYTE?)"; Structure.Image_Color_Palette
  133.         PRINT "Reserved (always zero):"; Structure.Reserved
  134.         PRINT "Number image points from left:"; Structure.Horizontal
  135.         PRINT "Number image points from top: "; Structure.Vertical
  136.         PRINT "Size of image data: "; Structure.Size_of_image_data
  137.         PRINT "Start offset: "; Structure.Offset_from_begin
  138.  
  139.         IF LOF(1) < 10000 AND Structure.Image_Color_Palette = 0 THEN LoadCursor& = 2: EXIT FUNCTION 'some CUR files contains record: Structure.Image_Color_Palette = 0 (LONG) but are saved as CASE 2. If is used CASE 2 program, is then cursor view VERY badly. :-/
  140.  
  141.         XReturned = Structure.Horizontal
  142.         YReturned = Structure.Vertical
  143.  
  144.         A$ = SPACE$(Structure.Size_of_image_data)
  145.         GET #1, , A$
  146.         posice = Structure.Offset_from_begin - 1
  147.  
  148.         IF Structure.Image_Width > 1 AND Structure.Image_Height > 1 THEN
  149.             SELECT CASE Structure.Image_Color_Palette '                                In file is writed 0, but it is 4 byte long depth. Interresting...
  150.                 CASE 0
  151.                     posice = Structure.Offset_from_begin - 1
  152.                     LoadCursor& = _NEWIMAGE(Structure.Image_Width, Structure.Image_Height, 32)
  153.                     _DEST LoadCursor&
  154.                     FOR DrawY = Structure.Image_Height - 1 TO 0 STEP -1
  155.                         FOR DrawX = 0 TO Structure.Image_Width - 1
  156.                             IF ERc THEN EXIT FOR ' some files contains record as 4 bytes, but are 1 byte! (uses 256 colors, but not truecolor as is recorded in head)
  157.                             Bod& = CVL(MID$(A$, posice, 4))
  158.                             posice = posice + 4
  159.                             PSET (DrawX, DrawY), Bod&
  160.                     NEXT DrawX, DrawY
  161.  
  162.                 CASE 2
  163.                     SEEK #1, posice + 50
  164.                     GET #1, , A$
  165.                     LoadCursor& = _NEWIMAGE(Structure.Image_Width, Structure.Image_Height, 256) ' 2 bit colored. My lovely. :-D
  166.                     _DEST LoadCursor&
  167.                     _CLEARCOLOR 15, LoadCursor&
  168.                     DrawX = 0: DrawY = 1
  169.                     FOR CursorDraw = 1 TO LEN(A$)
  170.                         Bod = ASC(A$, CursorDraw)
  171.                         Bin$ = DECtoBIN$(Bod)
  172.                         FOR drr = 1 TO LEN(Bin$)
  173.                             comand$ = MID$(Bin$, drr, 1)
  174.                             IF comand$ = "1" THEN clr = 0 ELSE clr = 15
  175.                             PSET (DrawX, Structure.Image_Height - DrawY), clr
  176.                             DrawX = DrawX + 1: IF DrawX > Structure.Image_Width - 1 THEN DrawX = 0: DrawY = DrawY + 1
  177.                         NEXT
  178.                     NEXT
  179.             END SELECT
  180.         END IF
  181.     ELSE LoadCursor& = 1: EXIT FUNCTION 'if file not exists
  182.     END IF
  183.     IF Structure.Image_Color_Palette = 0 THEN _SETALPHA 0, _RGB32(0, 0, 0), Cursor&
  184.     CLOSE #1
  185.     _DEST 0
  186.  
  187. FUNCTION DECtoBIN$ (vstup)
  188.     FOR rj = 7 TO 0 STEP -1
  189.         IF vstup AND 2 ^ rj THEN DECtoBIN$ = DECtoBIN$ + "1" ELSE DECtoBIN$ = DECtoBIN$ + "0"
  190.     NEXT rj
  191.  
Title: Re: Mouse pointers
Post by: TempodiBasic on June 09, 2018, 10:48:50 am
Hi Petr

this is my feedback

very interesting idea... but i got this issue

Hoping that it is useful....
Title: Re: Mouse pointers
Post by: bplus on June 09, 2018, 11:51:36 am
Hi Petr and Tempodibasic,

I had the same report as Tempodibasic so I started tracking down problem.

Things started to work when I removed _HIDE from the SHELL command
Code: QB64: [Select]
  1. SUB MakeCursorsList (Path AS STRING, Mask AS STRING, ToArray() AS STRING)
  2.     '    IF not win THEN PRINT "Error: MakeCursosList SUB is designed for Windows only.": SLEEP 1: END
  3.     Current$ = _CWD$
  4.     'PRINT Path   'OK
  5.     IF _DIREXISTS(Path$) THEN
  6.         'CHDIR Path$   'OK
  7.         PRINT _CWD$
  8.         commandd$ = "DIR " + Mask$ + " /B > CursorsList.txt"
  9.         SHELL commandd$ '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> remove _Hide   aha! now it works
  10.         IF _FILEEXISTS("CursorsList.txt") THEN
  11.             CH = FREEFILE
  12.             OPEN "CursorsList.txt" FOR INPUT AS #CH
  13.             DO WHILE NOT EOF(CH)
  14.                 LINE INPUT #CH, crs$
  15.                 REDIM _PRESERVE ToArray(i) AS STRING
  16.                 ToArray$(i) = LEFT$(crs$, 20)
  17.                 i = i + 1
  18.             LOOP
  19.             CLOSE #CH
  20.         ELSE
  21.             PRINT "Unknown error. File CursorsList.txt not created.": SLEEP 1: END
  22.         END IF
  23.     ELSE
  24.         PRINT "Error (Sub MakeCursorList): Specified path not exists.": SLEEP 1
  25.         EXIT SUB
  26.     END IF
  27.  

probably a coincidence as now it works with _HIDE command, say is that temp file "CursorList.txt" getting KILLED when done with it?
Title: Re: Mouse pointers
Post by: Ashish on June 09, 2018, 12:07:51 pm
Hi Petr! I get error message saying "Unknown error. File CursorsList.txt not created."
Title: Re: Mouse pointers
Post by: bplus on June 09, 2018, 12:12:42 pm
Yeah there still is a problem after file is found, it is empty (being created in same folder as Petr's bas source as Windows wont let you write files in it's folders that I know of...)

So these are screens that follow with an empty cursorlist file and the newimage adjusted to 800x600 so I can access my tool bar. (Man I dislike it immensely when you guys test stuff in full screen!)

PS in test screen there is also giant mouse pointer.

Title: Re: Mouse pointers
Post by: bplus on June 09, 2018, 12:20:12 pm
Oh dang, it started working because I still had CHDIR commented out, foo!

What if we try and make the cursorlist.txt file in the bas source? That might fix Windows forbidden file making in it's folders.
Title: Re: Mouse pointers
Post by: Ashish on June 09, 2018, 12:23:11 pm
Oh! It ran successfully with "Run with Administrator". Need not to worry.
Title: Re: Mouse pointers
Post by: bplus on June 09, 2018, 12:35:26 pm
Oh that worked! Thanks Ashish, that is handy tip!
Title: Re: Mouse pointers
Post by: Petr on June 09, 2018, 02:52:15 pm
Thank you for all your reactions. Good idea, Ashish, I still neglect the possibilities of using hardware images, I will be able to think more about this possibility. I did not think it would be a problem with writing a file in a protected area of windows, I have set my IDE up so that she can do what she wants. But of course, there is no problem and i write this file at source. The only difference is that the file will contain the whole path, not just the .CUR file name. I will issue another source code where this will be fixed (about an hour).

I put it here and went away -  your interest is enjoying me. Stop writing this, i go repair it :-D
Title: Re: Mouse pointers
Post by: Petr on June 09, 2018, 03:01:55 pm
Repaired. Duration cca 1 minute. Small repair in sub MakeCursorList. File contain names, loader (ShowUsableCursors SUB) but use full path returned from ENVIRON$:

Code: QB64: [Select]
  1. 'CUR file reader for read and draw cursor images from /windows/cursors dir. First version.
  2. 'Writed wihtout format knowledge just only on base from https://en.wikipedia.org/wiki/ICO_(file_format)
  3.  
  4.  
  5. 'can you find, how are writed some "unsupported" files?
  6. 'known bug is bad draw Pen big xl.
  7.  
  8. 'writed for fun by Petr
  9.  
  10.  
  11.  
  12. REDIM CursorsList(0) AS STRING
  13. Path$ = ENVIRON$("systemroot") + "\cursors\"
  14. Mask$ = "*.CUR"
  15. MakeCursorsList Path$, Mask$, CursorsList$()
  16.  
  17. Cursor$ = ENVIRON$("systemroot") + "\cursors\aero_arrow.cur"
  18. Img& = LoadCursor&(Cursor$, x, y)
  19.  
  20. PRINT "One cursor is loaded and will be used. This is Cursor loader info screen. Press any key...": SLEEP
  21.  
  22. _DEST my&
  23. CLS , _RGB32(128, 55, 220)
  24. ShowUsableCursors CursorsList$(), my&
  25.  
  26. SCREEN my&
  27.     PCOPY 1, _DISPLAY
  28.     ViewCursor Img&, x, y
  29.     _LIMIT 25
  30.  
  31. SUB ShowUsableCursors (Cursors() AS STRING, ToScreen AS LONG)
  32.     _DEST ToScreen&
  33.     X = 100: y = 100
  34.     FOR L = LBOUND(cursors) TO UBOUND(cursors)
  35.         P$ = ENVIRON$("systemroot") + "\cursors\" + Cursors(L)
  36.         i& = LoadCursor&(P$, a, b)
  37.         _DEST ToScreen&
  38.         IF i& >= 0 THEN GOSUB Unsupported: _CONTINUE
  39.         _PUTIMAGE (X, y), i&, ToScreen&
  40.         _FREEIMAGE i&
  41.         COLOR _RGB32(255, 255, 254), _RGB32(128, 55, 220)
  42.         _PRINTSTRING (X, y + 80), STR$(L) + ": " + Cursors(L), ToScreen&
  43.         X = X + 300: IF X > _DESKTOPWIDTH - 300 THEN X = 100: y = y + 300
  44.         IF y + 300 > _DESKTOPHEIGHT THEN
  45.             SCREEN ToScreen&: _PRINTSTRING (20, _DESKTOPHEIGHT - 20), "Press any key for view next...", ToScreen&: SLEEP: CLS , _RGB32(128, 55, 220): X = 100: y = 100
  46.             P$ = ""
  47.         END IF
  48.     NEXT L
  49.     _PRINTSTRING (20, _DESKTOPHEIGHT - 20), "New cursor is now used. Press Esc for end.", ToScreen&
  50.     EXIT SUB
  51.  
  52.     Unsupported:
  53.     _PRINTSTRING (X + 20, y + 50), "Not supported", ToScreen&
  54.     _PRINTSTRING (X, y + 80), STR$(L) + ": " + Cursors(L), ToScreen&
  55.     X = X + 300: IF X > _DESKTOPWIDTH - 300 THEN X = 100: y = y + 300
  56.     IF y + 300 > _DESKTOPHEIGHT THEN
  57.         SCREEN ToScreen&: _PRINTSTRING (20, _DESKTOPHEIGHT - 20), "Press any key for view next...", ToScreen&: SLEEP: CLS , _RGB32(128, 55, 220): X = 100: y = 100
  58.         P$ = ""
  59.     END IF
  60.     RETURN
  61.  
  62. SUB MakeCursorsList (Path AS STRING, Mask AS STRING, ToArray() AS STRING)
  63.     '    IF not win THEN PRINT "Error: MakeCursosList SUB is designed for Windows only.": SLEEP 1: END
  64.     Current$ = _CWD$
  65.     IF _DIREXISTS(Path$) THEN
  66.         'CHDIR Path$
  67.         commandd$ = "DIR " + Path$ + Mask$ + " /B > CursorsList.txt"
  68.         SHELL _HIDE commandd$
  69.         IF _FILEEXISTS("CursorsList.txt") THEN
  70.             CH = FREEFILE
  71.             OPEN "CursorsList.txt" FOR INPUT AS #CH
  72.             DO WHILE NOT EOF(CH)
  73.                 LINE INPUT #CH, crs$
  74.                 REDIM _PRESERVE ToArray(i) AS STRING
  75.  
  76.  
  77.                 ToArray$(i) = LEFT$(crs$, 20)
  78.                 i = i + 1
  79.             LOOP
  80.             CLOSE #CH
  81.         ELSE PRINT "Unknown error. File CursorsList.txt not created.": SLEEP 1: END
  82.         END IF
  83.     ELSE
  84.         PRINT "Error (Sub MakeCursorList): Specified path not exists.": SLEEP 1
  85.         EXIT SUB
  86.     END IF
  87.  
  88. SUB ViewCursor (Cursor AS LONG, ReductionX AS _BYTE, ReductionY AS _BYTE)
  89.     _DEST 0
  90.     _PUTIMAGE (_MOUSEX - ReductionX - 6, _MOUSEY - ReductionY), Cursor&, 0
  91.  
  92. FUNCTION LoadCursor& (Cursor AS STRING, XReturned, YReturned)
  93.     'returns: 1: File not exists, 2: Unsupported format, Value < 0 - valid cursor image
  94.     TYPE CUR
  95.         Reserved AS INTEGER '       2 bytes, always 00
  96.         Image_Type AS INTEGER '     1 = ICO format, 2 = CUR format, others are invalid
  97.         Number_images AS INTEGER '  number images in file
  98.     END TYPE
  99.  
  100.     TYPE Structure
  101.         Image_Width AS _UNSIGNED _BYTE
  102.         Image_Height AS _UNSIGNED _BYTE
  103.         Image_Color_Palette AS _UNSIGNED _BYTE
  104.         Reserved AS _UNSIGNED _BYTE 'always zero
  105.         Horizontal AS INTEGER '      In ICO format: Specifies color planes. Should be 0 or 1.
  106.         '                            In CUR format: Specifies the horizontal coordinates of the hotspot in number of pixels from the left.
  107.         Vertical AS INTEGER '        In ICO format: Specifies bits per pixel.
  108.         '                            In CUR format: Specifies the vertical coordinates of the hotspot in number of pixels from the top.
  109.         Size_of_image_data AS LONG
  110.         Offset_from_begin AS LONG
  111.     END TYPE
  112.     SCREEN _NEWIMAGE(800, 600, 32)
  113.     CLS
  114.     ERc = 0
  115.     DIM CUR AS CUR, Structure AS Structure
  116.  
  117.     IF _FILEEXISTS(Cursor$) THEN
  118.         CLOSE #1
  119.         OPEN Cursor$ FOR BINARY AS #1
  120.  
  121.  
  122.         GET #1, , CUR
  123.         PRINT "First 2 bytes (always 0):"; CUR.Reserved
  124.         PRINT "Image type (1 = ICO, 2 = CUR):"; CUR.Image_Type
  125.         PRINT "Number images in file:"; CUR.Number_images
  126.  
  127.         re:
  128.         '   _DEST 0
  129.         PRINT "======================================="; R
  130.         PRINT "Position in file:"; SEEK(1)
  131.         GET #1, , Structure
  132.         PRINT "Image width:"; Structure.Image_Width
  133.         PRINT "Image height:"; Structure.Image_Height
  134.         PRINT "Image color palette: (0 = LONG truecolor, 2 = _UNSIGNED _BYTE?)"; Structure.Image_Color_Palette
  135.         PRINT "Reserved (always zero):"; Structure.Reserved
  136.         PRINT "Number image points from left:"; Structure.Horizontal
  137.         PRINT "Number image points from top: "; Structure.Vertical
  138.         PRINT "Size of image data: "; Structure.Size_of_image_data
  139.         PRINT "Start offset: "; Structure.Offset_from_begin
  140.  
  141.         IF LOF(1) < 10000 AND Structure.Image_Color_Palette = 0 THEN LoadCursor& = 2: EXIT FUNCTION 'some CUR files contains record: Structure.Image_Color_Palette = 0 (LONG) but are saved as CASE 2. If is used CASE 2 program, is then cursor view VERY badly. :-/
  142.  
  143.         XReturned = Structure.Horizontal
  144.         YReturned = Structure.Vertical
  145.  
  146.         A$ = SPACE$(Structure.Size_of_image_data)
  147.         GET #1, , A$
  148.         posice = Structure.Offset_from_begin - 1
  149.  
  150.         IF Structure.Image_Width > 1 AND Structure.Image_Height > 1 THEN
  151.             SELECT CASE Structure.Image_Color_Palette '                                In file is writed 0, but it is 4 byte long depth. Interresting...
  152.                 CASE 0
  153.                     posice = Structure.Offset_from_begin - 1
  154.                     LoadCursor& = _NEWIMAGE(Structure.Image_Width, Structure.Image_Height, 32)
  155.                     _DEST LoadCursor&
  156.                     FOR DrawY = Structure.Image_Height - 1 TO 0 STEP -1
  157.                         FOR DrawX = 0 TO Structure.Image_Width - 1
  158.                             IF ERc THEN EXIT FOR ' some files contains record as 4 bytes, but are 1 byte! (uses 256 colors, but not truecolor as is recorded in head)
  159.                             Bod& = CVL(MID$(A$, posice, 4))
  160.                             posice = posice + 4
  161.                             PSET (DrawX, DrawY), Bod&
  162.                     NEXT DrawX, DrawY
  163.  
  164.                 CASE 2
  165.                     SEEK #1, posice + 50
  166.                     GET #1, , A$
  167.                     LoadCursor& = _NEWIMAGE(Structure.Image_Width, Structure.Image_Height, 256) ' 2 bit colored. My lovely. :-D
  168.                     _DEST LoadCursor&
  169.                     _CLEARCOLOR 15, LoadCursor&
  170.                     DrawX = 0: DrawY = 1
  171.                     FOR CursorDraw = 1 TO LEN(A$)
  172.                         Bod = ASC(A$, CursorDraw)
  173.                         Bin$ = DECtoBIN$(Bod)
  174.                         FOR drr = 1 TO LEN(Bin$)
  175.                             comand$ = MID$(Bin$, drr, 1)
  176.                             IF comand$ = "1" THEN clr = 0 ELSE clr = 15
  177.                             PSET (DrawX, Structure.Image_Height - DrawY), clr
  178.                             DrawX = DrawX + 1: IF DrawX > Structure.Image_Width - 1 THEN DrawX = 0: DrawY = DrawY + 1
  179.                         NEXT
  180.                     NEXT
  181.             END SELECT
  182.         END IF
  183.     ELSE LoadCursor& = 1: EXIT FUNCTION 'if file not exists
  184.     END IF
  185.     IF Structure.Image_Color_Palette = 0 THEN _SETALPHA 0, _RGB32(0, 0, 0), Cursor&
  186.     CLOSE #1
  187.     _DEST 0
  188.  
  189. FUNCTION DECtoBIN$ (vstup)
  190.     FOR rj = 7 TO 0 STEP -1
  191.         IF vstup AND 2 ^ rj THEN DECtoBIN$ = DECtoBIN$ + "1" ELSE DECtoBIN$ = DECtoBIN$ + "0"
  192.     NEXT rj
  193.  

Title: Re: Mouse pointers
Post by: Petr on June 09, 2018, 03:27:38 pm
Here is ancestor CUR viewer. Maybe its easyest. Just rewrite CUR file name on line 25:

Code: QB64: [Select]
  1. 'CUR file reader for read ind draw cursor images from /windows/cursors dir. First version, just for fun.
  2. 'Writed on base https://en.wikipedia.org/wiki/ICO_(file_format)
  3. TYPE CUR
  4.     Reserved AS INTEGER '       2 bytes, always 00
  5.     Image_Type AS INTEGER '     1 = ICO format, 2 = CUR format, others are invalid
  6.     Number_images AS INTEGER '  number images in file
  7.  
  8. TYPE Structure
  9.     Image_Width AS _UNSIGNED _BYTE
  10.     Image_Height AS _UNSIGNED _BYTE
  11.     Image_Color_Palette AS _UNSIGNED _BYTE
  12.     Reserved AS _UNSIGNED _BYTE 'always zero
  13.     Horizontal AS INTEGER '      In ICO format: Specifies color planes. Should be 0 or 1.
  14.     '                            In CUR format: Specifies the horizontal coordinates of the hotspot in number of pixels from the left.
  15.     Vertical AS INTEGER '        In ICO format: Specifies bits per pixel.
  16.     '                            In CUR format: Specifies the vertical coordinates of the hotspot in number of pixels from the top.
  17.     Size_of_image_data AS LONG
  18.     Offset_from_begin AS LONG
  19. SCREEN _NEWIMAGE(800, 600, 32)
  20. CLS , _RGB32(128, 100, 250)
  21. ERc = 0
  22. DIM CUR AS CUR, Structure AS Structure
  23. Cursor$ = ENVIRON$("systemroot") + "\cursors\up_i.cur"
  24. OPEN Cursor$ FOR BINARY AS #1
  25.  
  26.  
  27. GET #1, , CUR
  28. PRINT "First 2 bytes (always 0):"; CUR.Reserved
  29. PRINT "Image type (1 = ICO, 2 = CUR):"; CUR.Image_Type
  30. PRINT "Number images in file:"; CUR.Number_images
  31.  
  32. re:
  33. PRINT "======================================="; R
  34. GET #1, , Structure
  35. PRINT "Image width:"; Structure.Image_Width
  36. PRINT "Image height:"; Structure.Image_Height
  37. PRINT "Image color palette: (0 = LONG truecolor, 2 = _UNSIGNED _BYTE?)"; Structure.Image_Color_Palette
  38. PRINT "Reserved (always zero):"; Structure.Reserved
  39. PRINT "Number image points from left:"; Structure.Horizontal
  40. PRINT "Number image points from top: "; Structure.Vertical
  41. PRINT "Size of image data: "; Structure.Size_of_image_data
  42. PRINT "Start offset: "; Structure.Offset_from_begin
  43.  
  44. IF LOF(1) < 10000 AND Structure.Image_Color_Palette = 0 THEN PRINT "Unsupported file format": END
  45.  
  46. A$ = SPACE$(Structure.Size_of_image_data)
  47. GET #1, , A$
  48. posice = Structure.Offset_from_begin - 1
  49.  
  50. IF Structure.Image_Width > 1 AND Structure.Image_Height > 1 THEN
  51.     SELECT CASE Structure.Image_Color_Palette '                                  File write 0, but it is 4 byte long depth. Interresting...
  52.         CASE 0
  53.             posice = Structure.Offset_from_begin - 1
  54.             cursor& = _NEWIMAGE(Structure.Image_Width, Structure.Image_Height, 32)
  55.             _DEST cursor&
  56.             FOR DrawY = Structure.Image_Height - 1 TO 0 STEP -1
  57.                 FOR DrawX = 0 TO Structure.Image_Width - 1
  58.                     IF ERc THEN EXIT FOR ' some files contains record as 4 bytes, but are 1 byte! (uses 256 colors, but not truecolor as is recorded in head)
  59.                     Bod& = CVL(MID$(A$, posice, 4))
  60.                     posice = posice + 4
  61.                     PSET (DrawX, DrawY), Bod&
  62.             NEXT DrawX, DrawY
  63.  
  64.  
  65.         CASE 2
  66.             SEEK #1, posice + 50
  67.             GET #1, , A$
  68.             cursor& = _NEWIMAGE(Structure.Image_Width, Structure.Image_Height, 256) ' 2 bit colored. My lovely. :-D
  69.             _DEST cursor&
  70.             _CLEARCOLOR 15, cursor&
  71.             DrawX = 0: DrawY = 1
  72.             FOR CursorDraw = 1 TO LEN(A$)
  73.                 Bod = ASC(A$, CursorDraw)
  74.                 Bin$ = DECtoBIN$(Bod)
  75.                 FOR drr = 1 TO LEN(Bin$)
  76.                     comand$ = MID$(Bin$, drr, 1)
  77.                     IF comand$ = "1" THEN clr = 0 ELSE clr = 15
  78.                     PSET (DrawX, Structure.Image_Height - DrawY), clr
  79.                     DrawX = DrawX + 1: IF DrawX > Structure.Image_Width - 1 THEN DrawX = 0: DrawY = DrawY + 1
  80.                 NEXT
  81.             NEXT
  82.     END SELECT
  83.  
  84. IF Structure.Image_Color_Palette = 0 THEN _SETALPHA 0, _RGB32(0, 0, 0), cursor&
  85. 'SCREEN cursor&: SLEEP
  86.  
  87.     PCOPY 1, _DISPLAY
  88.     Cx = Structure.Image_Width / 2: Cy = Structure.Image_Height / 2
  89.     _PUTIMAGE (_MOUSEX - Cx, _MOUSEY - Cy), cursor&, 0
  90.     _DISPLAY
  91.     _LIMIT 25
  92.  
  93. FUNCTION DECtoBIN$ (vstup) 'DEC to BIN ok vystup je string, vstup je integer          decimal to binary number convertor   -   FROM QB64WIKI
  94.     FOR rj = 7 TO 0 STEP -1
  95.         IF vstup AND 2 ^ rj THEN DECtoBIN$ = DECtoBIN$ + "1" ELSE DECtoBIN$ = DECtoBIN$ + "0"
  96.     NEXT rj
  97.  
Title: Re: Mouse pointers
Post by: bplus on June 09, 2018, 04:05:18 pm
Yep, works fine now for my system.
Title: Re: Mouse pointers
Post by: TempodiBasic on June 11, 2018, 10:08:20 am
So I can confirm that now it works fine...
Thank's
Title: Re: Mouse pointers
Post by: Petr on August 20, 2018, 03:39:28 pm
Here's another version. Tested under Windows and under Linux MINT. Unfortunately, in Linux, an unknown thing causes the program not hide the mouse pointer and not show a new pointer, but it gets stuck. That's why I've enabled the setting of the pointer under Windows only. I'm a newbie under Linux and I just know not why in Linux it works not. The error is in something in the SUB VIEWCURSOR, if someone wanted to advise me. The attachment contains CUR files for Linux users. Windows users do not need this attachment, in Windows it is read from the Windows \ Cursors folder.

This version supports more CUR file types.

Code: QB64: [Select]
  1. 'CUR file reader for read and draw cursor images from /windows/cursors dir. First version.
  2. 'Writed wihtout format knowledge just only on base from https://en.wikipedia.org/wiki/ICO_(file_format)
  3.  
  4.  
  5. 'can you find, how are writed some "unsupported" files?      Upgraded (type 16 supported uncorrectly), type 0, 2 already supported
  6. 'known bug is bad draw Pen big xl.                           Repaired
  7. 'is added LINUX SUPPORT.   (tested in Linux MINT)...
  8. 'known bug: Can not correctly draw structure color palette type 16. Its set to optimal output, but picture, as is set in file is then returned in different width and height image. (help_il.cur, help_im.cur)
  9.  
  10.  
  11.  
  12. 'writed for fun by Petr
  13.  
  14.  
  15.  
  16. DIM SHARED ACTIVE ' variable, which memorize new mouse cursor usage. Used in ViewCursor SUB
  17.  
  18. REDIM CursorsList(0) AS STRING
  19. IF WIN THEN Path$ = ENVIRON$("systemroot") + "\cursors\" ELSE Path$ = _CWD$
  20. Mask$ = "*.cur"
  21.  
  22.  
  23.  
  24.  
  25. MakeCursorsList Path$, Mask$, CursorsList$() '                  show all cursors on screen
  26. IF WIN THEN
  27.     Cursor$ = ENVIRON$("systemroot") + "\cursors\wait_m.cur" '  Windows - read cursors from Your Windows path\Cursors\
  28.     Img& = LoadCursor&(Cursor$, x, y)
  29.     Img& = LoadCursor&(_CWD$ + "/wait_m.cur", x, y) '           Linux - read cursors from program directory
  30.  
  31.  
  32. _DEST my&
  33. CLS , _RGB32(128, 55, 220)
  34. ShowUsableCursors CursorsList$(), my&
  35.  
  36. SCREEN my&
  37.  
  38.     K& = _KEYDOWN(27)
  39.     PCOPY 1, _DISPLAY
  40.     IF WIN THEN ViewCursor Img&, x, y 'in LINUX is here something wrong. Program then show not new mouse cursor and gets stuck. WHY?
  41.     _LIMIT 25
  42.  
  43. SUB ShowUsableCursors (Cursors() AS STRING, ToScreen AS LONG)
  44.     _DEST ToScreen&
  45.     X = 100: y = 100
  46.     FOR L = LBOUND(cursors) TO UBOUND(cursors)
  47.  
  48.         i& = LoadCursor&(Cursors(L), A, b)
  49.         _DEST ToScreen&
  50.         IF i& >= 0 THEN GOSUB Unsupported: _CONTINUE
  51.         _PUTIMAGE (X, y), i&, ToScreen&
  52.         _FREEIMAGE i&
  53.         COLOR _RGB32(255, 255, 254), _RGB32(128, 55, 220)
  54.         _PRINTSTRING (X, y + 80), STR$(L) + ": " + Cursors(L), ToScreen&
  55.         X = X + 300: IF X > _DESKTOPWIDTH - 300 THEN X = 100: y = y + 300
  56.         IF y + 300 > _DESKTOPHEIGHT THEN
  57.             SCREEN ToScreen&: _PRINTSTRING (20, _DESKTOPHEIGHT - 20), "Press any key for view next...", ToScreen&: SLEEP: CLS , _RGB32(128, 55, 220): X = 100: y = 100
  58.             P$ = ""
  59.         END IF
  60.     NEXT L
  61.     _PRINTSTRING (20, _DESKTOPHEIGHT - 20), "New cursor is now used. Press Esc for end.", ToScreen&
  62.     EXIT SUB
  63.  
  64.     Unsupported:
  65.     _PRINTSTRING (X + 20, y + 50), "Not supported", ToScreen&
  66.     _PRINTSTRING (X, y + 80), STR$(L) + ": " + Cursors(L), ToScreen&
  67.     X = X + 300: IF X > _DESKTOPWIDTH - 300 THEN X = 100: y = y + 300
  68.     IF y + 300 > _DESKTOPHEIGHT THEN
  69.         SCREEN ToScreen&: _PRINTSTRING (20, _DESKTOPHEIGHT - 20), "Press any key for view next...", ToScreen&: SLEEP: CLS , _RGB32(128, 55, 220): X = 100: y = 100
  70.         P$ = ""
  71.     END IF
  72.     RETURN
  73.  
  74. SUB MakeCursorsList (Path AS STRING, Mask AS STRING, ToArray() AS STRING)
  75.     '    IF not win THEN PRINT "Error: MakeCursosList SUB is designed for Windows only.": SLEEP 1: END     'now supported.
  76.     Current$ = _CWD$
  77.     IF _DIREXISTS(Path$) THEN
  78.         CHDIR Path$
  79.         IF WIN THEN commandd$ = "DIR " + Mask$ + " /B > CursorsList.txt" ELSE commandd$ = "ls " + Mask$ + "> CursorsList.txt"
  80.         '        PRINT commandd$
  81.         '       SLEEP
  82.         SHELL commandd$
  83.  
  84.         ' SLEEP
  85.         IF _FILEEXISTS("CursorsList.txt") THEN
  86.             CH = FREEFILE
  87.             OPEN "CursorsList.txt" FOR INPUT AS #CH
  88.             DO WHILE NOT EOF(CH)
  89.                 LINE INPUT #CH, crs$
  90.                 REDIM _PRESERVE ToArray(i) AS STRING
  91.  
  92.  
  93.                 ToArray$(i) = LEFT$(crs$, 20)
  94.                 i = i + 1
  95.             LOOP
  96.             CLOSE #CH
  97.         ELSE PRINT "Unknown error. File CursorsList.txt not created.": SLEEP 1: END
  98.         END IF
  99.     ELSE
  100.         PRINT "Error (Sub MakeCursorList): Specified path not exists.": SLEEP 1
  101.         EXIT SUB
  102.     END IF
  103.  
  104. SUB ViewCursor (Cursor AS LONG, ReductionX AS _BYTE, ReductionY AS _BYTE)
  105.  
  106.     _DEST 0
  107.     IF ACTIVE = 0 THEN ACTIVE = 1: _MOUSEMOVE _MOUSEX, _MOUSEY ' because without mouse moving is not _MOUSEHIDE accepted after call _MOUSEHIDE
  108.     _PUTIMAGE (_MOUSEX - ReductionX - 6, _MOUSEY - ReductionY), Cursor&, 0
  109.  
  110. FUNCTION LoadCursor& (Cursor AS STRING, XReturned, YReturned)
  111.     IF LoadCursor& THEN _FREEIMAGE LoadCursor&
  112.     'returns: 1: File not exists, 2: Unsupported format, Value < 0 - valid cursor image
  113.     TYPE CUR
  114.         Reserved AS INTEGER '       2 bytes, always 00
  115.         Image_Type AS INTEGER '     1 = ICO format, 2 = CUR format, others are invalid
  116.         Number_images AS INTEGER '  number images in file
  117.     END TYPE
  118.  
  119.     TYPE Structure
  120.         Image_Width AS _UNSIGNED _BYTE
  121.         Image_Height AS _UNSIGNED _BYTE
  122.         Image_Color_Palette AS _BYTE '_UNSIGNED _BYTE
  123.         Reserved AS _UNSIGNED _BYTE 'always zero
  124.         Horizontal AS INTEGER '      In ICO format: Specifies color planes. Should be 0 or 1.
  125.         '                            In CUR format: Specifies the horizontal coordinates of the hotspot in number of pixels from the left.
  126.         Vertical AS INTEGER '        In ICO format: Specifies bits per pixel.
  127.         '                            In CUR format: Specifies the vertical coordinates of the hotspot in number of pixels from the top.
  128.         Size_of_image_data AS LONG
  129.         Offset_from_begin AS LONG
  130.     END TYPE
  131.  
  132.     TYPE ClrMask ' Thanks to LINUX i see difference. THIS area is not mentoied in my source materials...
  133.         Bb AS _UNSIGNED _BYTE
  134.         Gb AS _UNSIGNED _BYTE
  135.         Rb AS _UNSIGNED _BYTE 'colors use 3 colors, not alpha. Background color.
  136.         Bf AS _UNSIGNED _BYTE
  137.         Gf AS _UNSIGNED _BYTE
  138.         Rf AS _UNSIGNED _BYTE '                                Foreground color.
  139.     END TYPE
  140.     DIM Mask AS ClrMask
  141.  
  142.     SCREEN _NEWIMAGE(800, 600, 32)
  143.     CLS
  144.     ERc = 0
  145.     DIM CUR AS CUR, Structure AS Structure
  146.  
  147.     IF _FILEEXISTS(Cursor$) THEN
  148.         CLOSE #1
  149.  
  150.         SHARED po: po = po + 1
  151.         OPEN Cursor$ FOR BINARY AS #1
  152.  
  153.         GET #1, , CUR
  154.         PRINT "First 2 bytes (always 0):"; CUR.Reserved
  155.         PRINT "Image type (1 = ICO, 2 = CUR):"; CUR.Image_Type
  156.         PRINT "Number images in file:"; CUR.Number_images
  157.  
  158.         re:
  159.  
  160.         PRINT "======================================="; R
  161.         PRINT "File: "; Cursor$; po - 2
  162.         PRINT "Position in file:"; SEEK(1)
  163.         GET #1, , Structure
  164.         PRINT "Image width:"; Structure.Image_Width
  165.         PRINT "Image height:"; Structure.Image_Height
  166.         PRINT "Image color palette: (0 = LONG truecolor, 2 = _UNSIGNED _BYTE?)"; Structure.Image_Color_Palette
  167.         PRINT "Reserved (always zero):"; Structure.Reserved
  168.         PRINT "Number image points from left:"; Structure.Horizontal
  169.         PRINT "Number image points from top: "; Structure.Vertical
  170.         PRINT "Size of image data: "; Structure.Size_of_image_data
  171.         PRINT "Start offset: "; Structure.Offset_from_begin
  172.         PRINT " Palette:"; Structure.Image_Color_Palette
  173.         PRINT "File size: "; LOF(1)
  174.  
  175.  
  176.  
  177.         FOR all_images = 1 TO CUR.Number_images
  178.             GET #1, , Mask
  179.             PRINT "Image: "; all_images
  180.             PRINT "Color mask - foreground: "; Mask.Rf; Mask.Gf; Mask.Bf
  181.             PRINT "Color mask - background: "; Mask.Rb; Mask.Gb; Mask.Bb
  182.             _DELAY .1
  183.  
  184.  
  185.             XReturned = Structure.Horizontal
  186.             YReturned = Structure.Vertical
  187.  
  188.             A$ = SPACE$(Structure.Size_of_image_data)
  189.             posice = Structure.Offset_from_begin + 1
  190.  
  191.             IF Structure.Image_Width > 1 AND Structure.Image_Height > 1 THEN
  192.                 SELECT CASE Structure.Image_Color_Palette '                                In file is writed 0, but it is 4 byte long depth. Interresting...
  193.                     CASE 0
  194.                         SEEK #1, Structure.Offset_from_begin + 1
  195.                         GET #1, , A$
  196.                         posice = Structure.Offset_from_begin - 1
  197.                         IF Structure.Size_of_image_data < (Structure.Image_Width * Structure.Image_Height) THEN ClrDepth = 256 ELSE ClrDepth = 32
  198.                         LoadCursor& = _NEWIMAGE(Structure.Image_Width + 1, Structure.Image_Height + 1, ClrDepth)
  199.  
  200.  
  201.                         _DEST LoadCursor&
  202.                         IF drawy = 0 THEN drawy = Structure.Image_Height
  203.                         IF ClrDepth = 32 THEN
  204.                             DO WHILE drawy <> 0 AND drawx <> Structure.Image_Width
  205.                                 posice = posice + 4
  206.                                 Bod& = CVL(MID$(A$, posice, 4))
  207.                                 PSET (drawx, drawy), Bod&
  208.                                 drawx = drawx + 1
  209.                                 IF drawx = Structure.Image_Width AND drawx MOD 4 = 0 THEN drawx = 0: drawy = drawy - 1
  210.                             LOOP
  211.                         ELSE
  212.                             'upgrade
  213.                             SEEK #1, Structure.Offset_from_begin
  214.                             GET #1, , A$
  215.                             drawy = -2
  216.                             LoadCursor& = _NEWIMAGE(Structure.Image_Width + 1, Structure.Image_Height + 1, 256) ' 2 bit color
  217.                             _DEST LoadCursor&
  218.                             _PALETTECOLOR 1, _RGB32(Mask.Rf, Mask.Gf, Mask.Bf)
  219.                             _PALETTECOLOR 15, _RGB32(Mask.Rb, Mask.Gb, Mask.Bb)
  220.                             _CLEARCOLOR 1, LoadCursor&
  221.                             drawx = -8: drawy = -6
  222.                             FOR CursorDraw = 1 TO LEN(A$)
  223.                                 bod = ASC(A$, CursorDraw)
  224.                                 Bin$ = DECtoBIN$(bod)
  225.                                 FOR drr = 1 TO LEN(Bin$)
  226.                                     comand$ = MID$(Bin$, drr, 1)
  227.                                     IF comand$ = "1" THEN clr = 15 ELSE clr = 1
  228.  
  229.                                     IF drawy < 0 THEN clr = 1
  230.                                     IF drawy > -2 THEN PSET (drawx, (Structure.Image_Height - 1) - drawy), clr
  231.                                     drawx = drawx + 1: IF drawx >= Structure.Image_Width AND drawx MOD 32 = 0 THEN drawx = 0: drawy = drawy + 1
  232.                                 NEXT
  233.                             NEXT
  234.                         END IF
  235.  
  236.                     CASE 2
  237.                         SEEK #1, Structure.Offset_from_begin + 45
  238.                         GET #1, , A$
  239.                         LoadCursor& = _NEWIMAGE(Structure.Image_Width, Structure.Image_Height, 256) ' 2 bit colored. My lovely. :-D
  240.                         _DEST LoadCursor&
  241.  
  242.                         _PALETTECOLOR 1, _RGB32(Mask.Rf, Mask.Gf, Mask.Bf)
  243.                         _PALETTECOLOR 15, _RGB32(Mask.Rb, Mask.Gb, Mask.Bb)
  244.  
  245.  
  246.                         _CLEARCOLOR 1, LoadCursor&
  247.                         drawx = 0: drawy = 0
  248.                         FOR CursorDraw = 1 TO LEN(A$)
  249.                             bod = ASC(A$, CursorDraw)
  250.                             Bin$ = DECtoBIN$(bod)
  251.                             FOR drr = 1 TO LEN(Bin$)
  252.                                 comand$ = MID$(Bin$, drr, 1)
  253.                                 IF comand$ = "1" THEN clr = 15 ELSE clr = 1
  254.                                 PSET (drawx, Structure.Image_Height - drawy), clr
  255.                                 drawx = drawx + 1: IF drawx > Structure.Image_Width - 1 AND drawx MOD 32 = 0 THEN drawx = 0: drawy = drawy + 1
  256.                             NEXT
  257.                         NEXT
  258.  
  259.                     CASE 16
  260.                         SEEK #1, Structure.Offset_from_begin + 817 'i have none informations about file area between color palette record and image data record...
  261.  
  262.                         GET #1, , A$
  263.                         A$ = LEFT$(A$, Structure.Image_Width * Structure.Image_Height)
  264.                         LoadCursor& = _NEWIMAGE(Structure.Image_Width + 12, Structure.Image_Height + 5, 256) '
  265.                         _DEST LoadCursor&
  266.                         _PALETTECOLOR 15, _RGB32(Mask.Rf, Mask.Gf, Mask.Bf)
  267.                         _PALETTECOLOR 1, _RGB32(Mask.Rb, Mask.Gb, Mask.Bb)
  268.                         _CLEARCOLOR 1, LoadCursor&
  269.  
  270.                         drawx = -3: drawy = -4 'Structure.Vertical
  271.                         FOR CursorDraw = 1 TO LEN(A$)
  272.                             bod = ASC(A$, CursorDraw)
  273.                             Bin$ = DECtoBIN$(bod)
  274.                             FOR drr = 1 TO LEN(Bin$)
  275.                                 comand$ = MID$(Bin$, drr, 1)
  276.                                 IF comand$ = "1" THEN clr = 15 ELSE clr = 1
  277.                                 PSET (drawx, Structure.Image_Height - drawy), clr
  278.                                 drawx = drawx + 1: IF drawx > Structure.Image_Width AND drawx MOD 32 = 0 THEN drawx = 0: drawy = drawy + 1
  279.                             NEXT
  280.                         NEXT
  281.                 END SELECT
  282.             END IF
  283.         NEXT ' color palette settings
  284.  
  285.     ELSE LoadCursor& = 1: EXIT FUNCTION 'if file not exists
  286.     END IF
  287.     IF Structure.Image_Color_Palette = 0 THEN _SETALPHA 0, _RGB32(0, 0, 0), cursor&
  288.     CLOSE #1
  289.     _DEST 0
  290.  
  291. FUNCTION DECtoBIN$ (vstup)
  292.     FOR rj = 7 TO 0 STEP -1
  293.         IF vstup AND 2 ^ rj THEN DECtoBIN$ = DECtoBIN$ + "1" ELSE DECtoBIN$ = DECtoBIN$ + "0"
  294.     NEXT rj
  295.  
  296. FUNCTION BINtoDEC (b AS STRING)
  297.     FOR Si = 1 TO LEN(b)
  298.         e$ = MID$(b$, Si, 1)
  299.         c = VAL(e$) '
  300.         Sj = LEN(b) - Si
  301.         BINtoDEC = BINtoDEC + (c * 2 ^ Sj)
  302.     NEXT Si
  303.  
  304.     IF INSTR(_OS$, "WINDOWS") THEN WIN = 1 ELSE WIN = 0
  305.  
Title: Re: Mouse pointers
Post by: Petr on August 21, 2018, 12:24:20 pm
I am sorry, but i found bug.... after test program in windows and linux (and some repairs in linux) i test it not again in windows.... here is repaired version

Code: QB64: [Select]
  1. 'CUR file reader for read and draw cursor images from /windows/cursors dir. First version.
  2. 'Writed wihtout format knowledge just only on base from https://en.wikipedia.org/wiki/ICO_(file_format)
  3.  
  4.  
  5. 'can you find, how are writed some "unsupported" files?      Upgraded (type 16 supported uncorrectly), type 0, 2 already supported
  6. 'known bug is bad draw Pen big xl.                           Repaired
  7. 'is added LINUX SUPPORT.   (tested in Linux MINT)...
  8. 'known bug: Can not correctly draw structure color palette type 16. Its set to optimal output, but picture, as is set in file is then returned in different width and height image. (help_il.cur, help_im.cur)
  9.  
  10. 'Retested in Windows, repaired under Linux.
  11.  
  12. 'writed for fun by Petr
  13.  
  14.  
  15.  
  16. DIM SHARED ACTIVE ' variable, which memorize new mouse cursor usage. Used in ViewCursor SUB
  17.  
  18. REDIM CursorsList(0) AS STRING
  19. IF WIN THEN Path$ = ENVIRON$("systemroot") + "\cursors\" ELSE Path$ = _CWD$
  20. Mask$ = "*.cur"
  21.  
  22.  
  23.  
  24.  
  25. MakeCursorsList Path$, Mask$, CursorsList$() '                  show all cursors on screen
  26. IF WIN THEN
  27.     Cursor$ = ENVIRON$("systemroot") + "\cursors\wait_m.cur" '  Windows - read cursors from Your Windows path\Cursors\
  28.     Img& = LoadCursor&(Cursor$, x, y)
  29.     Img& = LoadCursor&("wait_m.cur", x, y) '           Linux - read cursors from program directory
  30.     '  PRINT Img&: SLEEP
  31.  
  32.  
  33. _DEST my&
  34. CLS , _RGB32(128, 55, 220)
  35. ShowUsableCursors CursorsList$(), my&
  36.  
  37. SCREEN my&
  38.     K& = _KEYDOWN(27)
  39.     PCOPY 1, _DISPLAY
  40.     ViewCursor Img&, x, y 'in LINUX is here something wrong. Program then show not new mouse cursor and gets stuck. WHY?
  41.     _LIMIT 25
  42.  
  43. SUB ShowUsableCursors (Cursors() AS STRING, ToScreen AS LONG)
  44.     _DEST ToScreen&
  45.     X = 100: y = 100
  46.     FOR L = LBOUND(cursors) TO UBOUND(cursors)
  47.  
  48.         i& = LoadCursor&(Cursors(L), A, b)
  49.         _DEST ToScreen&
  50.         IF i& >= 0 THEN GOSUB Unsupported: _CONTINUE
  51.         _PUTIMAGE (X, y), i&, ToScreen&
  52.         _FREEIMAGE i&
  53.         COLOR _RGB32(255, 255, 254), _RGB32(128, 55, 220)
  54.  
  55.         Lp = LastPos(Cursors(L), CHR$(92))
  56.  
  57.         fname$ = MID$(Cursors(L), Lp)
  58.         _PRINTSTRING (X, y + 80), STR$(L) + ": " + fname$, ToScreen&
  59.         X = X + 300: IF X > _DESKTOPWIDTH - 300 THEN X = 100: y = y + 300
  60.         IF y + 300 > _DESKTOPHEIGHT THEN
  61.             SCREEN ToScreen&: _PRINTSTRING (20, _DESKTOPHEIGHT - 20), "Press any key for view next...", ToScreen&: SLEEP: CLS , _RGB32(128, 55, 220): X = 100: y = 100
  62.             P$ = ""
  63.         END IF
  64.     NEXT L
  65.     _PRINTSTRING (20, _DESKTOPHEIGHT - 20), "New cursor is now used. Press Esc for end.", ToScreen&
  66.     EXIT SUB
  67.  
  68.     Unsupported:
  69.     _PRINTSTRING (X + 20, y + 50), "Not supported", ToScreen&
  70.     _PRINTSTRING (X, y + 80), STR$(L) + ": " + Cursors(L), ToScreen&
  71.     X = X + 300: IF X > _DESKTOPWIDTH - 300 THEN X = 100: y = y + 300
  72.     IF y + 300 > _DESKTOPHEIGHT THEN
  73.         SCREEN ToScreen&: _PRINTSTRING (20, _DESKTOPHEIGHT - 20), "Press any key for view next...", ToScreen&: SLEEP: CLS , _RGB32(128, 55, 220): X = 100: y = 100
  74.         P$ = ""
  75.     END IF
  76.     RETURN
  77.  
  78. SUB MakeCursorsList (Path AS STRING, Mask AS STRING, ToArray() AS STRING)
  79.     '    IF not win THEN PRINT "Error: MakeCursosList SUB is designed for Windows only.": SLEEP 1: END     'now supported.
  80.     Current$ = _CWD$
  81.     IF _DIREXISTS(Path$) THEN
  82.         '        CHDIR Path$
  83.         IF WIN THEN commandd$ = "DIR " + Path$ + Mask$ + " /B >CursorsList.txt" ELSE commandd$ = "ls " + Mask$ + "> CursorsList.txt"
  84.         SHELL commandd$
  85.  
  86.  
  87.         IF _FILEEXISTS("CursorsList.txt") THEN
  88.             CH = FREEFILE
  89.             OPEN "CursorsList.txt" FOR INPUT AS #CH
  90.             DO WHILE NOT EOF(CH)
  91.                 LINE INPUT #CH, crs$
  92.                 REDIM _PRESERVE ToArray(i) AS STRING
  93.  
  94.  
  95.                 IF WIN THEN
  96.                     ToArray$(i) = Path$ + LEFT$(crs$, 20)
  97.                 ELSE ToArray$(i) = LEFT$(crs$, 20)
  98.                 END IF
  99.  
  100.  
  101.  
  102.                 i = i + 1
  103.             LOOP
  104.             CLOSE #CH
  105.         ELSE PRINT "Unknown error. File CursorsList.txt not created.": SLEEP 1: END
  106.         END IF
  107.     ELSE
  108.         PRINT "Error (Sub MakeCursorList): Specified path not exists.": SLEEP 1
  109.         EXIT SUB
  110.     END IF
  111.  
  112. SUB ViewCursor (Cursor AS LONG, ReductionX AS _BYTE, ReductionY AS _BYTE)
  113.  
  114.     _DEST 0
  115.     IF WIN THEN _MOUSEHIDE ' this create program working fail. Program not respond and can not be killed in LINUX   - but is called in my loop and there works under Linux... ????
  116.     IF ACTIVE = 0 AND WIN THEN ACTIVE = 1: _MOUSEMOVE _MOUSEX, _MOUSEY ' because without mouse moving is not _MOUSEHIDE accepted after call _MOUSEHIDE. If is call in Linux, nothing is viewed, but program can be killed.
  117.     _PUTIMAGE (_MOUSEX - ReductionX - 6, _MOUSEY - ReductionY), Cursor&, 0
  118.  
  119. FUNCTION LoadCursor& (Cursor AS STRING, XReturned, YReturned)
  120.     '    IF LoadCursor& THEN _FREEIMAGE LoadCursor&      'This.... in linux it kill cursor image. In windows it KILL NOT cursor image (image in end)
  121.     'returns: 1: File not exists, 2: Unsupported format, Value < 0 - valid cursor image
  122.     TYPE CUR
  123.         Reserved AS INTEGER '       2 bytes, always 00
  124.         Image_Type AS INTEGER '     1 = ICO format, 2 = CUR format, others are invalid
  125.         Number_images AS INTEGER '  number images in file
  126.     END TYPE
  127.  
  128.     TYPE Structure
  129.         Image_Width AS _UNSIGNED _BYTE
  130.         Image_Height AS _UNSIGNED _BYTE
  131.         Image_Color_Palette AS _BYTE '_UNSIGNED _BYTE
  132.         Reserved AS _UNSIGNED _BYTE 'always zero
  133.         Horizontal AS INTEGER '      In ICO format: Specifies color planes. Should be 0 or 1.
  134.         '                            In CUR format: Specifies the horizontal coordinates of the hotspot in number of pixels from the left.
  135.         Vertical AS INTEGER '        In ICO format: Specifies bits per pixel.
  136.         '                            In CUR format: Specifies the vertical coordinates of the hotspot in number of pixels from the top.
  137.         Size_of_image_data AS LONG
  138.         Offset_from_begin AS LONG
  139.     END TYPE
  140.  
  141.     TYPE ClrMask ' Thanks to LINUX i see difference. THIS area is not mentoied in my source materials...
  142.         Bb AS _UNSIGNED _BYTE
  143.         Gb AS _UNSIGNED _BYTE
  144.         Rb AS _UNSIGNED _BYTE 'colors use 3 colors, not alpha. Background color.
  145.         Bf AS _UNSIGNED _BYTE
  146.         Gf AS _UNSIGNED _BYTE
  147.         Rf AS _UNSIGNED _BYTE '                                Foreground color.
  148.     END TYPE
  149.     DIM Mask AS ClrMask
  150.  
  151.     SCREEN _NEWIMAGE(800, 600, 32)
  152.     CLS
  153.     ERc = 0
  154.     DIM CUR AS CUR, Structure AS Structure
  155.  
  156.     IF _FILEEXISTS(Cursor$) THEN
  157.         CLOSE #1
  158.  
  159.         SHARED po: po = po + 1
  160.         OPEN Cursor$ FOR BINARY AS #1
  161.  
  162.         GET #1, , CUR
  163.         PRINT "First 2 bytes (always 0):"; CUR.Reserved
  164.         PRINT "Image type (1 = ICO, 2 = CUR):"; CUR.Image_Type
  165.         PRINT "Number images in file:"; CUR.Number_images
  166.  
  167.         re:
  168.  
  169.         PRINT "======================================="; R
  170.         PRINT "File: "; Cursor$; po - 2
  171.         PRINT "Position in file:"; SEEK(1)
  172.         GET #1, , Structure
  173.         PRINT "Image width:"; Structure.Image_Width
  174.         PRINT "Image height:"; Structure.Image_Height
  175.         PRINT "Image color palette: (0 = LONG truecolor, 2 = _UNSIGNED _BYTE?)"; Structure.Image_Color_Palette
  176.         PRINT "Reserved (always zero):"; Structure.Reserved
  177.         PRINT "Number image points from left:"; Structure.Horizontal
  178.         PRINT "Number image points from top: "; Structure.Vertical
  179.         PRINT "Size of image data: "; Structure.Size_of_image_data
  180.         PRINT "Start offset: "; Structure.Offset_from_begin
  181.         PRINT " Palette:"; Structure.Image_Color_Palette
  182.         PRINT "File size: "; LOF(1)
  183.  
  184.  
  185.  
  186.         FOR all_images = 1 TO CUR.Number_images
  187.             GET #1, , Mask
  188.             PRINT "Image: "; all_images
  189.             PRINT "Color mask - foreground: "; Mask.Rf; Mask.Gf; Mask.Bf
  190.             PRINT "Color mask - background: "; Mask.Rb; Mask.Gb; Mask.Bb
  191.             _DELAY .1
  192.  
  193.  
  194.             XReturned = Structure.Horizontal
  195.             YReturned = Structure.Vertical
  196.  
  197.             A$ = SPACE$(Structure.Size_of_image_data)
  198.             posice = Structure.Offset_from_begin + 1
  199.  
  200.             IF Structure.Image_Width > 1 AND Structure.Image_Height > 1 THEN
  201.                 SELECT CASE Structure.Image_Color_Palette '                                In file is writed 0, but it is 4 byte long depth. Interresting...
  202.                     CASE 0
  203.                         SEEK #1, Structure.Offset_from_begin + 1
  204.                         GET #1, , A$
  205.                         posice = Structure.Offset_from_begin - 1
  206.                         IF Structure.Size_of_image_data < (Structure.Image_Width * Structure.Image_Height) THEN ClrDepth = 256 ELSE ClrDepth = 32
  207.                         LoadCursor& = _NEWIMAGE(Structure.Image_Width + 1, Structure.Image_Height + 1, ClrDepth)
  208.  
  209.  
  210.                         _DEST LoadCursor&
  211.                         IF drawy = 0 THEN drawy = Structure.Image_Height
  212.                         IF ClrDepth = 32 THEN
  213.                             DO WHILE drawy <> 0 AND drawx <> Structure.Image_Width
  214.                                 posice = posice + 4
  215.                                 Bod& = CVL(MID$(A$, posice, 4))
  216.                                 PSET (drawx, drawy), Bod&
  217.                                 drawx = drawx + 1
  218.                                 IF drawx = Structure.Image_Width AND drawx MOD 4 = 0 THEN drawx = 0: drawy = drawy - 1
  219.                             LOOP
  220.                         ELSE
  221.                             'upgrade
  222.                             SEEK #1, Structure.Offset_from_begin
  223.                             GET #1, , A$
  224.                             drawy = -2
  225.                             LoadCursor& = _NEWIMAGE(Structure.Image_Width + 1, Structure.Image_Height + 1, 256) ' 2 bit color
  226.                             _DEST LoadCursor&
  227.                             _PALETTECOLOR 1, _RGB32(Mask.Rf, Mask.Gf, Mask.Bf)
  228.                             _PALETTECOLOR 15, _RGB32(Mask.Rb, Mask.Gb, Mask.Bb)
  229.                             _CLEARCOLOR 1, LoadCursor&
  230.                             drawx = -8: drawy = -6
  231.                             FOR CursorDraw = 1 TO LEN(A$)
  232.                                 bod = ASC(A$, CursorDraw)
  233.                                 Bin$ = DECtoBIN$(bod)
  234.                                 FOR drr = 1 TO LEN(Bin$)
  235.                                     comand$ = MID$(Bin$, drr, 1)
  236.                                     IF comand$ = "1" THEN clr = 15 ELSE clr = 1
  237.  
  238.                                     IF drawy < 0 THEN clr = 1
  239.                                     IF drawy > -2 THEN PSET (drawx, (Structure.Image_Height - 1) - drawy), clr
  240.                                     drawx = drawx + 1: IF drawx >= Structure.Image_Width AND drawx MOD 32 = 0 THEN drawx = 0: drawy = drawy + 1
  241.                                 NEXT
  242.                             NEXT
  243.                         END IF
  244.  
  245.                     CASE 2
  246.                         SEEK #1, Structure.Offset_from_begin + 45
  247.                         GET #1, , A$
  248.                         LoadCursor& = _NEWIMAGE(Structure.Image_Width, Structure.Image_Height, 256) ' 2 bit colored. My lovely. :-D
  249.                         _DEST LoadCursor&
  250.  
  251.                         _PALETTECOLOR 1, _RGB32(Mask.Rf, Mask.Gf, Mask.Bf)
  252.                         _PALETTECOLOR 15, _RGB32(Mask.Rb, Mask.Gb, Mask.Bb)
  253.  
  254.  
  255.                         _CLEARCOLOR 1, LoadCursor&
  256.                         drawx = 0: drawy = 0
  257.                         FOR CursorDraw = 1 TO LEN(A$)
  258.                             bod = ASC(A$, CursorDraw)
  259.                             Bin$ = DECtoBIN$(bod)
  260.                             FOR drr = 1 TO LEN(Bin$)
  261.                                 comand$ = MID$(Bin$, drr, 1)
  262.                                 IF comand$ = "1" THEN clr = 15 ELSE clr = 1
  263.                                 PSET (drawx, Structure.Image_Height - drawy), clr
  264.                                 drawx = drawx + 1: IF drawx > Structure.Image_Width - 1 AND drawx MOD 32 = 0 THEN drawx = 0: drawy = drawy + 1
  265.                             NEXT
  266.                         NEXT
  267.  
  268.                     CASE 16
  269.                         SEEK #1, Structure.Offset_from_begin + 817 'i have none informations about file area between color palette record and image data record...
  270.  
  271.                         GET #1, , A$
  272.                         A$ = LEFT$(A$, Structure.Image_Width * Structure.Image_Height)
  273.                         LoadCursor& = _NEWIMAGE(Structure.Image_Width + 12, Structure.Image_Height + 5, 256) '
  274.                         _DEST LoadCursor&
  275.                         _PALETTECOLOR 15, _RGB32(Mask.Rf, Mask.Gf, Mask.Bf)
  276.                         _PALETTECOLOR 1, _RGB32(Mask.Rb, Mask.Gb, Mask.Bb)
  277.                         _CLEARCOLOR 1, LoadCursor&
  278.  
  279.                         drawx = -3: drawy = -4 'Structure.Vertical
  280.                         FOR CursorDraw = 1 TO LEN(A$)
  281.                             bod = ASC(A$, CursorDraw)
  282.                             Bin$ = DECtoBIN$(bod)
  283.                             FOR drr = 1 TO LEN(Bin$)
  284.                                 comand$ = MID$(Bin$, drr, 1)
  285.                                 IF comand$ = "1" THEN clr = 15 ELSE clr = 1
  286.                                 PSET (drawx, Structure.Image_Height - drawy), clr
  287.                                 drawx = drawx + 1: IF drawx > Structure.Image_Width AND drawx MOD 32 = 0 THEN drawx = 0: drawy = drawy + 1
  288.                             NEXT
  289.                         NEXT
  290.                 END SELECT
  291.             END IF
  292.         NEXT ' color palette settings
  293.  
  294.     ELSE LoadCursor& = 1: EXIT FUNCTION 'if file not exists
  295.     END IF
  296.     IF Structure.Image_Color_Palette = 0 THEN _SETALPHA 0, _RGB32(0, 0, 0), cursor&
  297.     CLOSE #1
  298.     _DEST 0
  299.  
  300. FUNCTION DECtoBIN$ (vstup)
  301.     FOR rj = 7 TO 0 STEP -1
  302.         IF vstup AND 2 ^ rj THEN DECtoBIN$ = DECtoBIN$ + "1" ELSE DECtoBIN$ = DECtoBIN$ + "0"
  303.     NEXT rj
  304.  
  305. FUNCTION BINtoDEC (b AS STRING)
  306.     FOR Si = 1 TO LEN(b)
  307.         e$ = MID$(b$, Si, 1)
  308.         c = VAL(e$) '
  309.         Sj = LEN(b) - Si
  310.         BINtoDEC = BINtoDEC + (c * 2 ^ Sj)
  311.     NEXT Si
  312.  
  313.     IF INSTR(_OS$, "WINDOWS") THEN WIN = 1 ELSE WIN = 0
  314.  
  315. FUNCTION LastPos (bases AS STRING, search AS STRING)
  316.     FOR e = LEN(bases) TO 1 STEP -1
  317.         IF ASC(bases, e) = ASC(search) THEN LastPos = e + 1: EXIT FUNCTION
  318.     NEXT e
  319.  
Title: Re: Mouse pointers
Post by: Petr on August 23, 2018, 03:13:12 pm
Today something similar, yet much more fun. The program will allow you to use animated ANI cursors (this first version know only one type, but of course this is not last version) What do you say about an animated Windows cursor under Linux?

Code: QB64: [Select]
  1. 'ANI reader - 32 bit files only.    Linux compatible.
  2.  
  3. file$ = "aero_working_xl.ani"
  4.  
  5.  
  6.  
  7. '1] Test, if this is ANI file
  8. '------------------------------
  9. TYPE ANI_Acon_Header
  10.     ID1 AS STRING * 4 'RIFF
  11.     Size AS LONG '     ?
  12.     ID2 AS STRING * 4 'ACON
  13. DIM Ani_Head AS ANI_Acon_Header
  14.     ch = FREEFILE
  15.     OPEN file$ FOR BINARY AS #ch
  16.     GET #ch, , Ani_Head
  17.     IF Ani_Head.ID1 = "RIFF" AND Ani_Head.ID2 = "ACON" THEN PRINT file$; " is valid. Size: "; Ani_Head.Size + 8
  18. ELSE PRINT file$; " not exists.": END
  19.  
  20. '2] Finding in file position for flag "anih" and reading this head
  21. '-----------------------------------------------------------------
  22. TYPE anih
  23.     ID AS STRING * 4 'anih
  24.     Width AS LONG
  25.     Height AS LONG
  26.     NumFrames AS LONG
  27.     NumSteps AS LONG
  28.     Frame_Size AS LONG
  29.     HeaderSize AS LONG
  30.     BitCount AS LONG
  31.     NumPlanes AS LONG 'always 1
  32.     DisplayRate AS LONG 'default rate = 60/anih.displayrate fps
  33.     Flags AS STRING * 4 'currently used 2 bits: bit 31 to 2 are reserved,
  34.     'bit 1: if true, then file contains sequence data,
  35.     'bit 0: True = Frames are icon or cursor dat, False: Frames are RAW data
  36. DIM anih AS anih
  37. REDIM a_rec(0)
  38. Scan file$, "anih", a_rec(), 1
  39. GET #ch, a_rec(0), anih
  40.  
  41. Frames = anih.NumFrames
  42. Width = anih.Width
  43. Height = anih.Height
  44. BpP = anih.BitCount
  45. Rate = anih.DisplayRate
  46.  
  47. '3] Finding start positions for all frames (search flag "icon")
  48. '--------------------------------------------------------------
  49. REDIM a_rec(0)
  50. Scan file$, "icon", a_rec(), Frames 'ok
  51.  
  52. '4] By the BpP (bites per pixel) value now i set output pixelsize and create array with frames. Record 0 contains video LIMIT between frames.
  53. '--------------------------------------------------------------------------------------------------------------------------------------------
  54. TYPE Icon
  55.     icon AS STRING * 4
  56.     cosi AS LONG
  57.     Reserved AS INTEGER '       2 bytes, always 00
  58.     Image_Type AS INTEGER '     1 = ICO format, 2 = CUR format, others are invalid
  59.     Number_images AS INTEGER '  number images in file
  60.  
  61. TYPE Structure '
  62.     Image_Width AS _UNSIGNED _BYTE
  63.     Image_Height AS _UNSIGNED _BYTE
  64.     Image_Color_Palette AS _UNSIGNED _BYTE
  65.     Reserved AS _UNSIGNED _BYTE 'always zero
  66.     Planes AS INTEGER '          In ICO format: Specifies color planes. Should be 0 or 1.
  67.     '                            In CUR format: Specifies the horizontal coordinates of the hotspot in number of pixels from the left.
  68.     Bpp AS INTEGER '             In ICO format: Specifies bits per pixel.
  69.     '                            In CUR format: Specifies the vertical coordinates of the hotspot in number of pixels from the top.
  70.     Size_of_image_data AS LONG
  71.     Offset_from_begin AS LONG
  72.  
  73. DIM icon AS Icon
  74. DIM structure AS Structure
  75.     CASE 32
  76.         DIM Video32(Frames) AS LONG
  77.         Video32(0) = 60 / Rate
  78.         FOR Create_all_frames = 1 TO Frames
  79.             SEEK #ch, a_rec(Create_all_frames - 1)
  80.             GET #ch, , icon
  81.             GET #ch, , structure
  82.             REDIM record AS LONG
  83.             Video32(Create_all_frames) = _NEWIMAGE(structure.Image_Width, structure.Image_Height, 32)
  84.             x = -structure.Image_Width / 4
  85.             Y = structure.Image_Height - 1
  86.             _DEST Video32(Create_all_frames)
  87.             CLS
  88.             FOR frm = 1 TO structure.Image_Height * structure.Image_Width * 4
  89.                 GET #ch, , record&
  90.                 PSET (x, Y), record&
  91.                 x = x + 1: IF x >= structure.Image_Width AND x MOD 4 = 0 THEN Y = Y - 1: x = 0
  92.             NEXT frm
  93.         NEXT
  94.         _DEST 0
  95.     CASE ELSE
  96.         PRINT "Support for other than 32 bit ANI i prepare.": SLEEP 2: END
  97. CLOSE #ch
  98.  
  99. '5] Is time for display it:
  100. '--------------------------
  101. SCREEN _NEWIMAGE(800, 600, 32)
  102.     CLS
  103.     showANI Video32(), _MOUSEX, _MOUSEY, structure.Image_Width, structure.Image_Height
  104.     _LIMIT Video32(0)
  105.     _DISPLAY
  106.  
  107. FOR Erase_memory = 1 TO UBOUND(video32)
  108.     _FREEIMAGE Video32(Erase_memory)
  109.  
  110.  
  111. SUB showANI (arr() AS LONG, x, y, Xres, Yres)
  112.     SHARED internalindex0
  113.     IF internalindex0 = 0 THEN internalindex0 = 1
  114.     _PUTIMAGE (x - (Xres / 2), y - (Yres / 2)), arr(internalindex0)
  115.     internalindex0 = internalindex0 + 1: IF internalindex0 > UBOUND(arr) THEN internalindex0 = 1
  116.  
  117. SUB Scan (file AS STRING, text AS STRING, result(), RECORDS) 'Records = number of records, which are searched
  118.     IF _FILEEXISTS(file$) THEN
  119.         g = FREEFILE
  120.         OPEN file$ FOR BINARY AS #g
  121.         content$ = SPACE$(LOF(g))
  122.         GET #g, , content$
  123.         REDIM result(0)
  124.         FOR S = 1 TO LEN(content$)
  125.             num = INSTR(S, content$, text$)
  126.             IF num THEN
  127.                 REDIM _PRESERVE result(i)
  128.                 result(i) = num
  129.                 S = num
  130.                 num = 0
  131.                 i = i + 1
  132.                 IF RECORDS = i THEN EXIT SUB
  133.             END IF
  134.         NEXT S
  135.         CLOSE #g
  136.     ELSE
  137.         PRINT "File "; file$; "not exist.": END
  138.     END IF
  139.     content$ = ""
  140.  
  141.  
Title: Re: Mouse pointers
Post by: bplus on August 23, 2018, 06:47:07 pm
Hi Petr,

This is weird, I have a perpetual circle circling over the screen. Is this OK to run on Windows?

I was hoping to see an animated cursor.

Oh maybe that's it, the animation? Ha! I thought it was stuck processing...
Title: Re: Mouse pointers
Post by: Petr on August 24, 2018, 12:38:03 pm
Hi BPlus,
what you see is not the work of windows, but the result of a program that uses an ANI file that contains just this animated icon. I think it's good to be able to use CUR and ANI files in programs. Soon I will release both versions with the support of 16 color icons. There is bad documentation, so I often have to look for connections. But this is fun for me.
Title: Re: Mouse pointers
Post by: FellippeHeitor on August 24, 2018, 01:22:57 pm
Very good job on this one, Petr. It's similar to what Zom-B did for viewing animated GIF files.

https://qb64.org/wiki/GIF_Images

Do you think you could streamline your code so it'd behave more like a library? Maybe a reduced set of methods like Load, Display, Unload, so that the actual inner workings could be hidden away in a $INCLUDE file? That'd be interesting to have.

I have added Zom-B's code to the next release of InForm. Here's the readme that'll come with Beta 8 showing how to display animated GIFs in a form: https://github.com/FellippeHeitor/InForm/blob/Beta8/InForm/extensions/README%20-%20gifplay.txt

Please see the methods I describe in the document above for an idea of what I mean about your animated cursors code.
Title: Re: Mouse pointers
Post by: Petr on August 24, 2018, 02:58:45 pm
Hi Fellippe,
Yes, I have such an idea. However, it will be necessary to use the BI file at the beginning and the BM at the end due to the input field declarations. Now, during development, I need to get as many CUR and ANI files as possible for thorough testing. It has the following features: Cursor& = LOADCUR ("curfile_name.cur") and then PlayCUR Cursor&,x, y   the same for ANI files. In Inform I'll look at how it's done there.
I could open a detective office literally because it has happened many times that the content that is mentioned in various sources for these files did not correspond to reality.
Of course, the correct placement of the cursor will also be very important.
This version are "direct", but finaly version i write as BI and BM (and then re-testing it in Win and Linux).

I am glad for your reaction.
 
Title: Re: Mouse pointers
Post by: FellippeHeitor on August 24, 2018, 03:06:55 pm
You don't even need to worry about InForm specifics. If it becomes a detachable library, a user of InForm would be able to use it as is, probably.

Again, good investigation job.
Title: Re: Mouse pointers
Post by: Petr on August 26, 2018, 03:58:10 pm
Hi. So you say, make it as easy and user-friendly as possible. I tried it. Here is the result, the same thing I do for CUR files, this here is for ANI files. It supports the 16 color ANI and Truecolor ANI, but I have a few ANI files, that do not work right, so I still do it.
I do not have the speed between frames of the shot correct, but that's exactly what I'm doing now.

Code: QB64: [Select]
  1. '$include:'ani.bi'
  2.  
  3. FileA$ = "coin.ani"
  4. FileB$ = "dinosau2.ani"
  5. FileC$ = "horse.ani"
  6.  
  7. A& = LoadAni(FileA$)
  8. B& = LoadAni(FileB$)
  9. C& = LoadAni(FileC$)
  10.  
  11. SCREEN _NEWIMAGE(800, 600, 32)
  12. 'program know playing ANIs and EXTRACT FRAMES from ANI:
  13.  
  14. FOR Extract = 1 TO FrameAni(A&) '               function return number frames in file
  15.     Image& = ExtractAni(A&, Extract) '          function return decoded image
  16.     _PUTIMAGE (50 + Extract * 50, 100), Image&
  17. NEXT Extract
  18. 'this is just option, normal you need not, but it is here for you.
  19.  
  20.  
  21.     PCOPY 1, _DISPLAY
  22.     PutAni A&, 100, 200
  23.     PutAni B&, 300, 500
  24.     PutAni C&, _MOUSEX, _MOUSEY
  25.     _DISPLAY
  26.     _LIMIT 20
  27.  
  28. FreeAni A& 'clear it from memory
  29. FreeAni B&
  30. FreeAni C&
  31.  
  32. '$include:'ani.bm'
  33.  
Title: Re: Mouse pointers
Post by: FellippeHeitor on August 26, 2018, 04:53:03 pm
Nice, Petr!

I do not have the speed between frames of the shot correct, but that's exactly what I'm doing now.

Maybe you'll need to keep track of the last time a frame is served, store TIMER for reference, and only serve a new frame after that frame's delay is reached.
Title: Re: Mouse pointers
Post by: Petr on August 31, 2018, 03:50:40 pm
Hi all,
This version is beta. If some CUR or ANI file is not displayed correctly, send it here and i look at it.Program allow using CUR (static mouse cursors) or ANI (animated mouse cursors), extracting frames from ANI and do some experiments.
Usage:
CursorA& = LOADCURSOR("Cursor.cur")
CursorsB& = LOADCURSOR("CursorB.ani")
load cursors to memory. If CursorA& or CursorB& return -1, is something wrong (file not exist?)

For inserting it to screen use PUTCURSOR CursorA&, coordinate X, coordinate Y
For erase it from memory use FREECURSOR CursorB&

If loaded cursor is ANI file, you can extract frames:
LENCURSOR return number of frames in ANI file, DECOMPOSECURSOR (source&, frame_number) return image.

So is possible easy all frames view:

For Show = 1 to LENCURSOR(CursorA&)
Image& = DECOMPOSECURSOR(Show)
_PUTIMAGE (100,100), image&,0
SLEEP
NEXT

If you call LENCURSOR or DECOMPOSECURSOR to CUR file, it return always -1 as error code.

In attachment is BAS file, BI file, BM file and folder CURSORS contains all CUR and ANI files, on which i test this program. So if you found some, which is not right displayed, please send it
here. Thank you.