QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: madscijr on March 30, 2021, 12:30:04 pm

Title: events and malloc in QB64?
Post by: madscijr on March 30, 2021, 12:30:04 pm
Hi everyone.

I'm attempting to convert this manymouse library to QB64:
https://github.com/NoobsArePeople2/manymouse (https://github.com/NoobsArePeople2/manymouse)

TempodiBasic pointed out how the API declarations can be done in QB64.
It might help if I knew C, but I figure I'll try slogging through it.
Now I am seeing other stuff that I'm not so sure about.
I'm running into are these references to files that aren't on the github, that I assume are basic C libraries for Windows?
Code: C: [Select]
  1. #define WIN32_LEAN_AND_MEAN 1
  2. #include <windows.h>
  3. #include <setupapi.h>
  4. #include <malloc.h>  /* needed for alloca(). */
  5.  

malloc
I am not finding anything on "malloc" in QB64.
Is there an equivalent or some workaround in QB64 for code like this?
Code: C: [Select]
  1.     lpb = (LPBYTE) alloca(dwSize);
  2.     if (lpb == NULL)
  3.         return;
  4.  

events
There is also some event handling:
Code: C: [Select]
  1. #define MAX_EVENTS 1024
  2. static ManyMouseEvent input_events[MAX_EVENTS];
  3. static volatile int input_events_read = 0;
  4. static volatile int input_events_write = 0;
  5.  

I am not finding anything related to events in QB64.
What would you do to get that functionality to work?
Code: C: [Select]
  1. static void queue_from_rawinput(const RAWINPUT *raw)
  2. {
  3.     int i;
  4.     const RAWINPUTHEADER *header = &raw->header;
  5.     const RAWMOUSE *mouse = &raw->data.mouse;
  6.     ManyMouseEvent event;
  7. etc.
  8.  

Any advice or assistance would be much appreciated!
Title: Re: events and malloc in QB64?
Post by: bplus on March 30, 2021, 12:37:34 pm
Malloc = memory allocation see _Mem stuff @SMcNeill good with that, Steve also has worked with _DEVICE$

API see @SpriggsySpriggs
Here is ref link: https://www.qb64.org/forum/index.php?topic=2930.msg121883#msg121883
Title: Re: events and malloc in QB64?
Post by: madscijr on March 30, 2021, 12:48:26 pm
Malloc = memory allocation see _Mem stuff @SMcNeill good with that, Steve also has worked with _DEVICE$

API see @SpriggsySpriggs

Thanks... Is it even possible to have event handlers in QB64?
Title: Re: events and malloc in QB64?
Post by: bplus on March 30, 2021, 12:52:17 pm
Thanks... Is it even possible to have event handlers in QB64?


I think so, see what @FellippeHeitor has done with InForm working Events driven model. Very much like VB.
Title: Re: events and malloc in QB64?
Post by: madscijr on March 30, 2021, 01:48:42 pm
I think so, see what @FellippeHeitor has done with InForm working Events driven model. Very much like VB.

Thanks... maybe this?
https://www.qb64.org/forum/index.php?topic=2113.msg113549;topicseen#msg113549 (https://www.qb64.org/forum/index.php?topic=2113.msg113549;topicseen#msg113549)
or
https://www.qb64.org/forum/index.php?topic=524.msg3778;topicseen#msg3778 (https://www.qb64.org/forum/index.php?topic=524.msg3778;topicseen#msg3778)
Title: Re: events and malloc in QB64?
Post by: SpriggsySpriggs on March 30, 2021, 01:50:30 pm
@madscijr Hey! I've been super busy recently but I'm glad you have been looking through that manymouse repo. I'm going to try looking at it tonight and see how far I can start getting with QB64. Some portions should be relatively simple but others could be next to impossible.
Title: Re: events and malloc in QB64?
Post by: madscijr on March 30, 2021, 02:08:11 pm
Oy vey! LoL
Title: Re: events and malloc in QB64?
Post by: madscijr on March 30, 2021, 02:09:42 pm
@madscijr Hey! I've been super busy recently but I'm glad you have been looking through that manymouse repo. I'm going to try looking at it tonight and see how far I can start getting with QB64. Some portions should be relatively simple but others could be next to impossible.

That would be great.
I'm trying to stay positive about this, but looking at the C code:
https://github.com/NoobsArePeople2/manymouse/blob/master/windows_wminput.c (https://github.com/NoobsArePeople2/manymouse/blob/master/windows_wminput.c)
https://github.com/NoobsArePeople2/manymouse/blob/master/manymouse.c (https://github.com/NoobsArePeople2/manymouse/blob/master/manymouse.c)

TLDR: is it even possible to translate these to QB64?


I don't know C but I've been able to figure out logic from other languages in the past, enough to translate it to a language I do know. But this code has a ton of keywords, types, and syntax that I don't recognize at all:

and functions too like

I'd have to google some C to understand alien syntax like
Code: C: [Select]
  1. mouse->handle = dev->hDevice;
  2. if (++i >= available_mice)
  3. if (mouse->handle != NULL)
  4.  

Also, then there is OO looking stuff where they reference properties, like:
Code: C: [Select]
  1. if (mice[i].handle == header->hDevice)
  2.  
and
Code: C: [Select]
  1. if (mouse->usFlags & MOUSE_MOVE_ABSOLUTE)
  2.     {
  3.         /* !!! FIXME: How do we get the min and max values for absmotion? */
  4.         event.type = MANYMOUSE_EVENT_ABSMOTION;
  5.         event.item = 0;
  6.         event.value = mouse->lLastX;
  7.         queue_event(&event);
  8.         event.item = 1;
  9.         event.value = mouse->lLastY;
  10.         queue_event(&event);
  11.     } /* if */
  12.  
and
Code: C: [Select]
  1. static const ManyMouseDriver ManyMouseDriver_interface =
  2. {
  3.     "Windows XP and later WM_INPUT interface",
  4.     windows_wminput_init,
  5.     windows_wminput_quit,
  6.     windows_wminput_name,
  7.     windows_wminput_poll
  8. };
  9.  
I'm very fuzzy on how interfaces work, I would expect that is outside the capability of QB64?

I found a couple of sites that look like they might have some info on some of the above keywords

Some things look familiar, but not sure if QB64 has an equivalent of, like

Some that are probably covered under the _MEM functions in QB64 like:

Some familiar terms I would guess have a QB64 equivalent (I have to look up):


I guess what I'm asking now is, does this look like something that can be converted to QB64, or would I need to get a C compiler and somehow compile it into a DLL library that I would call from QB?

Despairingly yours,
Not a C programmer!
Title: Re: events and malloc in QB64?
Post by: bplus on March 30, 2021, 02:10:07 pm
Quote
Thanks... maybe this?

@madscijr

There is a whole board at this forum devoted to InForm, but for your needs, setting event driven app, you might have to dig into his source code. There is probably a github link in the InForm Board.

I have to admit, yours is first inquiry I've ever seen about multiple mice. I do know that with device you can pickup joystick input but more than one mouse...?
Title: Re: events and malloc in QB64?
Post by: SpriggsySpriggs on March 30, 2021, 02:45:06 pm
@madscijr
  • HDEVINFO
//a handle will always be _OFFSET
  • ATOM
//an INTEGER
  • LRESULT
//an _OFFSET
  • HMODULE
//a handle will always be _OFFSET
  • DWORD - I think I've seen this keyword in regedit?
//DWORD corresponds to LONG
  • CRITICAL_SECTION
//not sure, will have to look this up. From what I see, similar to a MUTEX object.
  • HANDLE
//a handle will always be _OFFSET
  • HINSTANCE
//handle, _OFFSET
  • WNDCLASSEX
//just a custom struct, https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassexa (https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassexa)
  • SP_DEVINFO_DATA
//custom struct, https://docs.microsoft.com/en-us/windows/win32/api/setupapi/ns-setupapi-sp_devinfo_data (https://docs.microsoft.com/en-us/windows/win32/api/setupapi/ns-setupapi-sp_devinfo_data)
  • size_t
//I believe that this is also an _OFFSET

and functions too like
  • GetProcAddress
//this function, along with FreeLibrary and LoadLibrary are some that I have used in a different topic about runtime calls here https://www.qb64.org/forum/index.php?topic=3756.0 (https://www.qb64.org/forum/index.php?topic=3756.0)
  • FreeLibrary
  • LoadLibrary
  • LOOKUP (a bunch inside routine find_api_symbols)
//this should be able to be done using the above functions in our own wrapper
  • sizeof
//this is just our LEN() keyword
  • MSG
//this is a struct. We'd have to rewrite it in QB64: https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msg (https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msg)
[/list][/list]
Code: C: [Select]
  1. mouse->handle = dev->hDevice; //this is basically saying mouse.handle = dev.hDevice
  2. if (++i >= available_mice)
  3. if (mouse->handle != NULL) //if mouse.handle <> 0
  4.  

Also, then there is OO looking stuff where they reference properties, like: //the stuff is really just using custom TYPEs, or structs. Like a UDT in QB64
Code: C: [Select]
  1. if (mice[i].handle == header->hDevice) //if mice(i).handle = header.hDevice
  2.  
and
Code: C: [Select]
  1. if (mouse->usFlags & MOUSE_MOVE_ABSOLUTE) //if mouse.usFlags AND MOUSE_MOVE_ABSOLUTE
  2.     {
  3.         /* !!! FIXME: How do we get the min and max values for absmotion? */
  4.         event.type = MANYMOUSE_EVENT_ABSMOTION;
  5.         event.item = 0;
  6.         event.value = mouse->lLastX;
  7.         queue_event(&event);
  8.         event.item = 1;
  9.         event.value = mouse->lLastY;
  10.         queue_event(&event);
  11.     } /* if */
  12.  
        Some things look familiar, but not sure if QB64 has an equivalent of, like
        • HWND (I remember that from VB6)
        //HWND is the Handle to the Window. For QB64, if referencing OUR program's window, it's
_WINDOWHANDLE
  • static
//we have STATIC as well
  • volatile
//I will have to look this one up
[/list]

Some that are probably covered under the _MEM functions in QB64 like:
  • CopyMemory
//we have this
  • ZeroMemory
//we also have this
  • alloca
//I will have to look this one up
[/list]

  • uint
//we have this as _UNSIGNED LONG
  • static unsigned int - what's the difference between "uint" and "unsigned int"?
//I think "UINT" is used in Win32 API and "unsigned int" is just the regular C++ definition, I believe
[/list]


I guess what I'm asking now is, does this look like something that can be converted to QB64, or would I need to get a C compiler and somehow compile it into a DLL library that I would call from QB?  //probably, but looks difficult in some areas

I hope this helps to answer some of the questions, at least
Title: Re: events and malloc in QB64?
Post by: madscijr on March 30, 2021, 02:53:55 pm
@madscijr
I have to admit, yours is first inquiry I've ever seen about multiple mice. I do know that with device you can pickup joystick input but more than one mouse...?

Thank you for your reply.
I did try using _DEVICE, but it didn't seem to work.
Maybe I'm doing something wrong?
Here is my test code:
Code: QB64: [Select]
  1. ' #############################################################################
  2. ' MULTIMOUSE
  3. ' ----------
  4. ' A proof of concept / experiment to try to get the computer to read
  5. ' 2 or mice plugged into the computer, as separate devices,
  6. ' to control 2 or more cursors on the screen (for multiplayer games, etc.)
  7. '
  8. ' #############################################################################
  9.  
  10. ' =============================================================================
  11. ' GLOBAL DECLARATIONS a$=string, i%=integer, L&=long, s!=single, d#=double
  12. CONST FALSE = 0
  13. CONST TRUE = NOT FALSE
  14.  
  15. DIM ProgramPath$
  16. DIM ProgramName$
  17.  
  18. ' =============================================================================
  19. ' INITIALIZE
  20. ProgramName$ = MID$(COMMAND$(0), _INSTRREV(COMMAND$(0), "\") + 1)
  21. ProgramPath$ = LEFT$(COMMAND$(0), _INSTRREV(COMMAND$(0), "\"))
  22.  
  23. ' =============================================================================
  24. ' TRY THE MOUSE
  25. main ProgramName$
  26.  
  27. ' =============================================================================
  28. ' FINISH
  29. SYSTEM ' return control to the operating system
  30. PRINT ProgramName$ + " finished."
  31.  
  32. ' /////////////////////////////////////////////////////////////////////////////
  33.  
  34. SUB main (ProgName$)
  35.     DIM in$: in$ = ""
  36.     DO
  37.         CLS
  38.         PRINT ProgName$
  39.         PRINT
  40.         PRINT "How can we get separate input from 2 or more USB mice "
  41.         PRINT "plugged into one computer?"
  42.         PRINT
  43.         PRINT "1. Test using _MOUSEX, _MOUSEY, etc."
  44.         PRINT
  45.         PRINT "2. Test using _DEVICE commands"
  46.         PRINT
  47.         PRINT "3. Enumerate devices with _DEVICES to try and detect >1 mouse"
  48.         PRINT
  49.         PRINT "What to do ('q' to exit)"
  50.  
  51.         INPUT in$: in$ = LCASE$(LEFT$(in$, 1))
  52.         IF in$ = "1" THEN
  53.             MouseInputTest in$
  54.         ELSEIF in$ = "2" THEN
  55.             MouseInputTest in$
  56.         ELSEIF in$ = "3" THEN
  57.             EnumerateDevices
  58.         END IF
  59.     LOOP UNTIL in$ = "q"
  60. END SUB ' main
  61.  
  62. ' /////////////////////////////////////////////////////////////////////////////
  63. ' Gets mouse input using _MOUSEX, _MOUSEY, _MOUSEBUTTON commands.
  64.  
  65. SUB MouseInputTest (in$)
  66.     ' UDT TO HOLD THE INFO FOR EACH MOUSE
  67.     TYPE InfoType
  68.         c AS STRING ' cursor character
  69.         x AS INTEGER ' screen x position
  70.         y AS INTEGER ' screen y position
  71.         wheel AS INTEGER ' mouse wheel value
  72.         LeftDown AS INTEGER ' tracks left mouse button state, TRUE=down
  73.         MiddleDown AS INTEGER ' tracks middle mouse button state, TRUE=down
  74.         RightDown AS INTEGER ' tracks right mouse button state, TRUE=down
  75.         LeftCount AS INTEGER ' counts left clicks
  76.         MiddleCount AS INTEGER ' counts middle clicks
  77.         RightCount AS INTEGER ' counts right clicks
  78.     END TYPE ' InfoType
  79.  
  80.     ' MIN/MAX VALUES
  81.     CONST cMinX = 2
  82.     CONST cMaxX = 79
  83.     CONST cMinY = 16
  84.     CONST cMaxY = 24
  85.     CONST cMinWheel = 0
  86.     CONST cMaxWheel = 255
  87.  
  88.     ' MAIN VARIABLES
  89.     DIM iCount AS INTEGER ' # OF MICE ATTACHED
  90.     DIM arrMouseID(8) AS STRING ' device IDs for mice connected to system (guessing this would be a string, dunno)
  91.     DIM arrInfo(8) AS InfoType ' STORES INFO FOR EACH MOUSE
  92.     DIM left%, middle%, right% ' temp mouse variables
  93.     DIM iLoop AS INTEGER
  94.     DIM iIndex AS INTEGER
  95.  
  96.     ' TEMP VARIABLES FOR DISPLAYING FORMATTED VALUES TO SCREEN
  97.     DIM iLen AS INTEGER
  98.     DIM sCount AS STRING
  99.     DIM sX AS STRING
  100.     DIM sY AS STRING
  101.     DIM sWheel AS STRING
  102.     DIM sLeftDown AS STRING
  103.     DIM sMiddleDown AS STRING
  104.     DIM sRightDown AS STRING
  105.     DIM sLeftCount AS STRING
  106.     DIM sMiddleCount AS STRING
  107.     DIM sRightCount AS STRING
  108.  
  109.     ' MOUSE CURSORS (JUST SOME LETTERS)
  110.     CData:
  111.     DATA A,b,C,D,E,f,G,H
  112.  
  113.     ' DEFAULT/INTIAL X COORDINATE OF EACH CURSOR ON SCREEN
  114.     XData:
  115.     DATA 5,15,25,35,45,55,65,75
  116.  
  117.     ' DEFAULT/INTIAL Y COORDINATE OF EACH CURSOR ON SCREEN
  118.     YData:
  119.     DATA 17,17,19,19,21,21,23,23
  120.  
  121.     ' DEFAULT/INITIAL VALUE OF EACH SCROLL WHEEL
  122.     WData:
  123.     DATA 224,192,160,128,96,64,32,0
  124.  
  125.     ' COUNT # OF MICE CONNECTED + GET DEVICE IDs
  126.     iCount = GetMouseCount% ' THIS FUNCTION WOULD ENUMERATE MICE, SHOULD RETURN 1+
  127.     IF (iCount > 8) THEN iCount = 8: ' FOR NOW ONLY SUPPORT UPTO 8 MICE
  128.     GetMouseIDs arrMouseID() ' GET MOUSE IDs
  129.  
  130.     ' INITIALIZE CURSORS, MOUSE STATE, ETC.
  131.     RESTORE CData
  132.     iIndex = LBOUND(arrInfo) - 1
  133.     FOR iLoop = 1 TO iCount
  134.         iIndex = iIndex + 1
  135.         READ arrInfo(iIndex).c
  136.         ' INITIALIZED BELOW: arrInfo(iIndex).x = 0
  137.         ' INITIALIZED BELOW: arrInfo(iIndex).y = 0
  138.         ' INITIALIZED BELOW: arrInfo(iIndex).wheel = 127
  139.         arrInfo(iIndex).LeftDown = FALSE
  140.         arrInfo(iIndex).MiddleDown = FALSE
  141.         arrInfo(iIndex).RightDown = FALSE
  142.         arrInfo(iIndex).LeftCount = 0
  143.         arrInfo(iIndex).MiddleCount = 0
  144.         arrInfo(iIndex).RightCount = 0
  145.     NEXT iLoop
  146.  
  147.     ' INITIALIZE X COORDINATES
  148.     RESTORE XData
  149.     iIndex = LBOUND(arrInfo) - 1
  150.     FOR iLoop = 1 TO iCount
  151.         iIndex = iIndex + 1
  152.         READ arrInfo(iIndex).x
  153.     NEXT iLoop
  154.  
  155.     ' INITIALIZE Y COORDINATES
  156.     RESTORE YData
  157.     iIndex = LBOUND(arrInfo) - 1
  158.     FOR iLoop = 1 TO iCount
  159.         iIndex = iIndex + 1
  160.         READ arrInfo(iIndex).y
  161.     NEXT iLoop
  162.  
  163.     ' INITIALIZE SCROLL WHEEL
  164.     RESTORE WData
  165.     iIndex = LBOUND(arrInfo) - 1
  166.     FOR iLoop = 1 TO iCount
  167.         iIndex = iIndex + 1
  168.         READ arrInfo(iIndex).wheel
  169.     NEXT iLoop
  170.  
  171.     ' DRAW PLAYING FIELD
  172.     CLS ' clear screen
  173.     LOCATE 1, 1: PRINT "1. PLUG 1-8 MICE INTO THE COMPUTER"
  174.     LOCATE 2, 1: PRINT "2. USE MICE TO POSITION LETTERS ON SCREEN"
  175.     LOCATE 3, 1: PRINT "3. PRESS <ESC> TO QUIT"
  176.     LOCATE 4, 1: PRINT "--------------------------------------------------------------------------------";
  177.     LOCATE 5, 1: PRINT "#  X  Y  Wheel LeftDown MiddleDown RightDown LeftCount MiddleCount RightCount   "
  178.     LOCATE 6, 1: PRINT "--------------------------------------------------------------------------------";
  179.  
  180.     ' NOTE: LEAVE THE NEXT 8 LINES FREE (ROWS 8-15)
  181.     '       TO DISPLAY TEST VALUES FOR UPTO 8 MICE
  182.  
  183.     ' DRAW BORDER AROUND PLAYING FIELD
  184.     DrawTextLine cMinX - 1, cMinY - 1, cMinX - 1, cMaxY + 1, "#"
  185.     DrawTextLine cMinX - 1, cMinY - 1, cMaxX + 1, cMinY - 1, "#"
  186.     DrawTextLine cMaxX + 1, cMaxY + 1, cMaxX + 1, cMinY - 1, "#"
  187.     DrawTextLine cMaxX + 1, cMaxY + 1, cMinX - 1, cMaxY + 1, "#"
  188.  
  189.     ' GET INPUT AND MOVE PLAYERS
  190.     DO
  191.         iIndex = LBOUND(arrInfo) - 1
  192.         FOR iLoop = 1 TO iCount
  193.             iIndex = iIndex + 1
  194.  
  195.             ' ERASE CURSORS AT CURRENT POSITION
  196.             LOCATE arrInfo(iIndex).y, arrInfo(iIndex).x: PRINT " ";
  197.  
  198.             ' GET NEXT MOUSE INPUT
  199.             IF in$ = "1" THEN
  200.                 ReadMouse1 arrMouseID(iIndex), arrInfo(iIndex).x, arrInfo(iIndex).y, left%, middle%, right%, arrInfo(iIndex).wheel, cMinWheel, cMaxWheel
  201.             ELSEIF in$ = "2" THEN
  202.                 ReadMouse2 arrMouseID(iIndex), arrInfo(iIndex).x, arrInfo(iIndex).y, left%, middle%, right%, arrInfo(iIndex).wheel, cMinWheel, cMaxWheel
  203.             END IF
  204.  
  205.             ' HANDLE LEFT MOUSE BUTTON
  206.             IF left% THEN
  207.                 IF arrInfo(iIndex).LeftDown = FALSE THEN
  208.                     ' BUTTON DOWN EVENT
  209.                     arrInfo(iIndex).LeftDown = TRUE
  210.                     arrInfo(iIndex).LeftCount = arrInfo(iIndex).LeftCount + 1
  211.                 END IF
  212.             ELSE
  213.                 IF arrInfo(iIndex).LeftDown = TRUE THEN
  214.                     ' BUTTON UP EVENT
  215.                     arrInfo(iIndex).LeftDown = FALSE
  216.                 END IF
  217.             END IF
  218.  
  219.             ' HANDLE MIDDLE MOUSE BUTTON (SCROLL WHEEL BUTTON)
  220.             IF middle% THEN
  221.                 IF arrInfo(iIndex).MiddleDown = FALSE THEN
  222.                     ' BUTTON DOWN EVENT
  223.                     arrInfo(iIndex).MiddleDown = TRUE
  224.                     arrInfo(iIndex).MiddleCount = arrInfo(iIndex).MiddleCount + 1
  225.                 END IF
  226.             ELSE
  227.                 IF arrInfo(iIndex).MiddleDown = TRUE THEN
  228.                     ' BUTTON UP EVENT
  229.                     arrInfo(iIndex).MiddleDown = FALSE
  230.                 END IF
  231.             END IF
  232.  
  233.             ' HANDLE RIGHT MOUSE BUTTON
  234.             IF right% THEN
  235.                 IF arrInfo(iIndex).RightDown = FALSE THEN
  236.                     ' BUTTON DOWN EVENT
  237.                     arrInfo(iIndex).RightDown = TRUE
  238.                     arrInfo(iIndex).RightCount = arrInfo(iIndex).RightCount + 1
  239.                 END IF
  240.             ELSE
  241.                 IF arrInfo(iIndex).RightDown = TRUE THEN
  242.                     ' BUTTON UP EVENT
  243.                     arrInfo(iIndex).RightDown = FALSE
  244.                 END IF
  245.             END IF
  246.  
  247.             ' CHECK BOUNDARIES
  248.             IF arrInfo(iIndex).x < cMinX THEN arrInfo(iIndex).x = cMinX
  249.             IF arrInfo(iIndex).x > cMaxX THEN arrInfo(iIndex).x = cMaxX
  250.             IF arrInfo(iIndex).y < cMinY THEN arrInfo(iIndex).y = cMinY
  251.             IF arrInfo(iIndex).y > cMaxY THEN arrInfo(iIndex).y = cMaxY
  252.  
  253.             ' PLOT CURSOR
  254.             LOCATE arrInfo(iIndex).y, arrInfo(iIndex).x: PRINT arrInfo(iIndex).c;
  255.  
  256.             ' DISPLAY VARIABLES
  257.             iLen = 3: sCount = LEFT$(LTRIM$(RTRIM$(STR$(iLoop))) + STRING$(iLen, " "), iLen)
  258.             iLen = 3: sX = LEFT$(LTRIM$(RTRIM$(STR$(arrInfo(iIndex).x))) + STRING$(iLen, " "), iLen)
  259.             iLen = 3: sY = LEFT$(LTRIM$(RTRIM$(STR$(arrInfo(iIndex).y))) + STRING$(iLen, " "), iLen)
  260.             iLen = 6: sWheel = LEFT$(LTRIM$(RTRIM$(STR$(arrInfo(iIndex).wheel))) + STRING$(iLen, " "), iLen)
  261.             iLen = 9: sLeftDown = LEFT$(LTRIM$(RTRIM$(STR$(arrInfo(iIndex).LeftDown))) + STRING$(iLen, " "), iLen)
  262.             iLen = 11: sMiddleDown = LEFT$(LTRIM$(RTRIM$(STR$(arrInfo(iIndex).MiddleDown))) + STRING$(iLen, " "), iLen)
  263.             iLen = 10: sRightDown = LEFT$(LTRIM$(RTRIM$(STR$(arrInfo(iIndex).RightDown))) + STRING$(iLen, " "), iLen)
  264.             iLen = 10: sLeftCount = LEFT$(LTRIM$(RTRIM$(STR$(arrInfo(iIndex).LeftCount))) + STRING$(iLen, " "), iLen)
  265.             iLen = 12: sMiddleCount = LEFT$(LTRIM$(RTRIM$(STR$(arrInfo(iIndex).MiddleCount))) + STRING$(iLen, " "), iLen)
  266.             iLen = 11: sRightCount = LEFT$(LTRIM$(RTRIM$(STR$(arrInfo(iIndex).RightCount))) + STRING$(iLen, " "), iLen)
  267.  
  268.             'LOCATE 5,       1: PRINT "#  X  Y  Wheel LeftDown MiddleDown RightDown LeftCount MiddleCount RightCount   "
  269.             LOCATE 6 + iLoop, 1: PRINT sCount + sX + sY + sWheel + sLeftDown + sMiddleDown + sRightDown + sLeftCount + sMiddleCount + sRightCount
  270.  
  271.         NEXT iLoop
  272.  
  273.         _LIMIT 100 ' keep loop at 100 frames per second
  274.     LOOP UNTIL _KEYDOWN(27) ' escape key exit
  275.     _KEYCLEAR: '_DELAY 1
  276. END SUB ' MouseInputTest
  277.  
  278. ' /////////////////////////////////////////////////////////////////////////////
  279. ' Returns a count of # of mouse devices connected to the system
  280.  
  281. ' *** Currently hardcoded to 1 until we figure out how to do this. ***
  282.  
  283. FUNCTION GetMouseCount% ()
  284.     GetMouseCount% = 1
  285. END FUNCTION ' GetMouseCount%
  286.  
  287. ' /////////////////////////////////////////////////////////////////////////////
  288. ' Gets ID of each mouse device connected to the system (for now upto 8)
  289. ' and returns the IDs in an array of strings
  290. ' (assuming the ID is a string and not numeric?).
  291. ' If no mouse found, the ID will just be a blank string.
  292.  
  293. ' *** Currently hardcoded to "1" until we figure out how to do this. ***
  294.  
  295. SUB GetMouseIDs (arrMouseID( 8) AS STRING)
  296.     DIM iLoop AS INTEGER
  297.  
  298.     ' CLEAR OUT IDs
  299.     FOR iLoop = 1 TO 8
  300.         arrMouseID(iLoop) = ""
  301.     NEXT iLoop
  302.  
  303.     ' GET IDs
  304.     arrMouseID(1) = "1" ' for now just fudge it!
  305.  
  306. END SUB ' GetMouseCount%
  307.  
  308. ' /////////////////////////////////////////////////////////////////////////////
  309. ' Read mouse method #1, using _MOUSEX, _MOUSEY, etc.
  310.  
  311. ' Gets input from mouse identified by deviceid$
  312. ' (or does that needs to be an ordinal position?)
  313.  
  314. ' For version 1 we only return the input from the one mouse
  315. ' regardless of deviceid$.
  316.  
  317. ' NOTE: click events (mouse up/mouse down) are handled by the calling sub,
  318. '       this routine just sends back
  319. '       TRUE if the given button is currently down or FALSE if it is up.
  320.  
  321. ' Parameters (values returned):
  322. ' x% = x position of mouse pointer
  323. ' y% = y position of mouse pointer
  324. ' left% = current state of left mouse button (up or down)
  325. ' middle% = current state of middle mouse button / scroll wheel button (up or down)
  326. ' right% = current state of right mouse button (up or down)
  327. ' wheel% = value of mouse scroll wheel (passed in and incremented/decremented by 1 if wheel move detected)
  328.  
  329. ' Parameters (input only):
  330. ' wheelmin% = minimum value to allow wheel% to be decremented to
  331. ' wheelmax% = maximum value to allow wheel% to be incremened to
  332.  
  333. SUB ReadMouse1 (deviceid$, x%, y%, left%, middle%, right%, wheel%, wheelmin%, wheelmax%)
  334.     DIM scrollAmount%
  335.  
  336.     ' read scroll wheel
  337.     WHILE _MOUSEINPUT ' get latest mouse information
  338.         scrollAmount% = _MOUSEWHEEL ' (Returns -1 when scrolling up and 1 when scrolling down with 0 indicating no movement since last read.)
  339.         IF (scrollAmount% = -1) AND (wheel% > wheelmin%) THEN
  340.             wheel% = wheel% + scrollAmount%
  341.         ELSEIF (scrollAmount% = 1) AND (wheel% < wheelmax%) THEN
  342.             wheel% = wheel% + scrollAmount%
  343.         END IF
  344.     WEND
  345.  
  346.     ' read x position
  347.     x% = _MOUSEX
  348.  
  349.     ' read y position
  350.     y% = _MOUSEY
  351.  
  352.     ' read mouse buttons
  353.     left% = _MOUSEBUTTON(1)
  354.     middle% = _MOUSEBUTTON(3)
  355.     right% = _MOUSEBUTTON(2)
  356.  
  357. END SUB ' ReadMouse1
  358.  
  359. ' /////////////////////////////////////////////////////////////////////////////
  360. ' Read mouse method #2, using _DEVICE commands.
  361.  
  362. ' Gets input from mouse identified by deviceid$
  363. ' (or does that needs to be an ordinal position?)
  364.  
  365. ' For version 1 we only return the input from the one mouse
  366. ' regardless of deviceid$.
  367.  
  368. ' NOTE: click events (mouse up/mouse down) are handled by the calling sub,
  369. '       this routine just sends back
  370. '       TRUE if the given button is currently down or FALSE if it is up.
  371.  
  372. ' Parameters (values returned):
  373. ' x% = x position of mouse pointer
  374. ' y% = y position of mouse pointer
  375. ' left% = current state of left mouse button (up or down)
  376. ' middle% = current state of middle mouse button / scroll wheel button (up or down)
  377. ' right% = current state of right mouse button (up or down)
  378. ' wheel% = value of mouse scroll wheel (passed in and incremented/decremented by 1 if wheel move detected)
  379.  
  380. ' Parameters (input only):
  381. ' wheelmin% = minimum value to allow wheel% to be decremented to
  382. ' wheelmax% = maximum value to allow wheel% to be incremened to
  383.  
  384. SUB ReadMouse2 (deviceid$, x%, y%, left%, middle%, right%, wheel%, wheelmin%, wheelmax%)
  385.     DIM scrollAmount%
  386.     DIM ScreenWidth% ' screen width
  387.     DIM ScreenHeight% ' screen height
  388.  
  389.     ' read scroll wheel
  390.     WHILE _DEVICEINPUT(2) ' clear and update the mouse buffer
  391.         scrollAmount% = _WHEEL(3)
  392.         IF (scrollAmount% = -1) AND (wheel% > wheelmin%) THEN
  393.             wheel% = wheel% + scrollAmount%
  394.         ELSEIF (scrollAmount% = 1) AND (wheel% < wheelmax%) THEN
  395.             wheel% = wheel% + scrollAmount%
  396.         END IF
  397.     WEND ' clear and update the mouse buffer
  398.  
  399.     ' read x position
  400.     ScreenWidth% = _WIDTH \ 2
  401.     x% = _AXIS(1) * ScreenWidth% + ScreenWidth%
  402.  
  403.     ' read y position
  404.     ScreenHeight% = _HEIGHT \ 2
  405.     y% = _AXIS(2) * ScreenHeight% + ScreenHeight%
  406.  
  407.     ' read mouse buttons
  408.     left% = _BUTTON(1)
  409.     middle% = _BUTTON(2)
  410.     right% = _BUTTON(3)
  411.  
  412. END SUB ' ReadMouse2
  413.  
  414. ' /////////////////////////////////////////////////////////////////////////////
  415. ' ORIGINAL VERSION OF FUNCTION FOR READING MOUSE WITH _DEVICE:
  416.  
  417. ' Gets mouse input using _DEVICE commands (part 2 of 2, subroutine)
  418.  
  419. ' SOURCE : https://www.qb64.org/forum/index.php?topic=1087.0
  420. ' Subject: Mouse demo using _DEVICE commands
  421. ' From   : SMcNeill
  422. ' Date   : February 21, 2019, 06:15:28 AM »
  423.  
  424. SUB UpdateMouseInfo (MouseX AS INTEGER, MouseY AS INTEGER, MOUSEWHEEL AS INTEGER, LeftMouse AS INTEGER, RightMouse AS INTEGER, MiddleMouse AS INTEGER, ClickThreshold AS SINGLE)
  425.     DIM SW AS INTEGER, SH AS INTEGER
  426.     DIM LM AS INTEGER, MM AS INTEGER, RM AS INTEGER
  427.  
  428.     STATIC leftdown AS SINGLE, middledown AS SINGLE, rightdown AS SINGLE
  429.  
  430.     WHILE _DEVICEINPUT(2): MOUSEWHEEL = MOUSEWHEEL + _WHEEL(3): WEND 'clear and update the mouse buffer
  431.  
  432.     SW = _WIDTH \ 2: SH = _HEIGHT \ 2
  433.     MouseX = _AXIS(1) * SW + SW: MouseY = _AXIS(2) * SH + SH
  434.  
  435.  
  436.  
  437.     LM = _BUTTON(1): MM = _BUTTON(2): RM = _BUTTON(3)
  438.  
  439.     IF leftdown THEN 'if it was down
  440.         IF LM = 0 THEN 'and is now up
  441.             IF TIMER - leftdown < ClickThreshold THEN
  442.                 LeftMouse = 2 'clicked
  443.             ELSE 'if it's still down
  444.                 LeftMouse = 0 'the mouse was just released
  445.             END IF
  446.             leftdown = 0 'timer is cleared either way
  447.         ELSE
  448.             LeftMouse = 1 'the left mouse is down , timer should have already been set
  449.         END IF
  450.     ELSE
  451.         IF LM THEN
  452.             leftdown = TIMER 'set the timer to see if we have click or hold events
  453.             LeftMouse = 1 'the left mouse is down
  454.         ELSE
  455.             LeftMouse = 0
  456.         END IF
  457.     END IF
  458.  
  459.     IF middledown THEN 'if it was down
  460.         IF MM = 0 THEN 'and is now up
  461.             IF TIMER - middledown < ClickThreshold THEN
  462.                 MiddleMouse = 2 'clicked
  463.             ELSE 'if it's still down
  464.                 MiddleMouse = 0 'the mouse was just released
  465.             END IF
  466.             middledown = 0 'timer is cleared either way
  467.         ELSE
  468.             MiddleMouse = 1 'the middle mouse is down , timer should have already been set
  469.         END IF
  470.     ELSE
  471.         IF MM THEN
  472.             middledown = TIMER 'set the timer to see if we have click or hold events
  473.             MiddleMouse = 1 'the middle mouse is down
  474.         ELSE
  475.             MiddleMouse = 0
  476.         END IF
  477.     END IF
  478.  
  479.     IF rightdown THEN 'if it was down
  480.         IF RM = 0 THEN 'and is now up
  481.             IF TIMER - rightdown < ClickThreshold THEN
  482.                 RightMouse = 2 'clicked
  483.             ELSE 'if it's still down
  484.                 RightMouse = 0 'the mouse was just released
  485.             END IF
  486.             rightdown = 0 'timer is cleared either way
  487.         ELSE
  488.             RightMouse = 1 'the right mouse is down , timer should have already been set
  489.         END IF
  490.     ELSE
  491.         IF RM THEN
  492.             rightdown = TIMER 'set the timer to see if we have click or hold events
  493.             RightMouse = 1 'the right mouse is down
  494.         ELSE
  495.             RightMouse = 0
  496.         END IF
  497.     END IF
  498.  
  499.  
  500. END SUB ' UpdateMouseInfo
  501.  
  502. ' /////////////////////////////////////////////////////////////////////////////
  503. ' Example: Checking for the system's input devices.
  504.  
  505. ' _DEVICES FUNCTION (QB64 REFERENCE)
  506. ' http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/wiki/index_title_DEVICES/
  507. '
  508. ' The _DEVICES function returns the number of INPUT devices on your computer
  509. ' including keyboard, mouse and game devices.
  510. '
  511. ' Syntax:
  512. '
  513. ' device_count% = _DEVICES
  514. '
  515. ' Returns the number of devices that can be listed separately with the _DEVICE$
  516. ' function by the device number.
  517. ' Devices include keyboard, mouse, joysticks, game pads and multiple stick game
  518. ' controllers.
  519. ' Note: This function MUST be read before trying to use the _DEVICE$,
  520. ' _DEVICEINPUT or _LAST control functions!
  521.  
  522. ' Note: The STRIG/STICK commands won't read from the keyboard
  523. '       or mouse device the above example lists.
  524.  
  525. SUB EnumerateDevices
  526.     DIM devices%
  527.     DIM iLoop%
  528.     DIM sCount$
  529.     DIM iLen AS INTEGER
  530.  
  531.     devices% = _DEVICES ' MUST be read in order for other 2 device functions to work!
  532.  
  533.     CLS
  534.     PRINT "Total devices found: "; STR$(devices%)
  535.     FOR iLoop% = 1 TO devices%
  536.         iLen = 4
  537.         sCount$ = LEFT$(LTRIM$(RTRIM$(STR$(iLoop%))) + STRING$(iLen, " "), iLen)
  538.         PRINT sCount$ + _DEVICE$(iLoop%) + " (" + LTRIM$(RTRIM$(STR$(_LASTBUTTON(iLoop%)))) + " buttons)"
  539.     NEXT iLoop%
  540.     PRINT
  541.     PRINT "PRESS <ESC> TO CONTINUE"
  542.     DO: LOOP UNTIL _KEYDOWN(27) ' leave loop when ESC key pressed
  543.     _KEYCLEAR: '_DELAY 1
  544.  
  545. END SUB ' EnumerateDevices
  546.  
  547. ' /////////////////////////////////////////////////////////////////////////////
  548. ' based on code from:
  549. ' Qbasic Programs - Download free bas source code
  550. ' http://www.thedubber.altervista.org/qbsrc.htm
  551.  
  552. SUB DrawTextLine (y%, x%, y2%, x2%, c$)
  553.     'bError% = FALSE
  554.     'LOCATE 2, 2: PRINT "(" + STR$(x%) + "," + STR$(y%) + ") to (" + STR$(x2%) + "," + STR$(y2%) + ") of " + CHR$(34) + c$ + CHR$(34);
  555.  
  556.     i% = 0: steep% = 0: e% = 0
  557.     IF (x2% - x%) > 0 THEN sx% = 1: ELSE sx% = -1
  558.     dx% = ABS(x2% - x%)
  559.     IF (y2% - y%) > 0 THEN sy% = 1: ELSE sy% = -1
  560.     dy% = ABS(y2% - y%)
  561.     IF (dy% > dx%) THEN
  562.         steep% = 1
  563.         SWAP x%, y%
  564.         SWAP dx%, dy%
  565.         SWAP sx%, sy%
  566.     END IF
  567.     e% = 2 * dy% - dx%
  568.     FOR i% = 0 TO dx% - 1
  569.         IF steep% = 1 THEN
  570.             'PSET (y%, x%), c%:
  571.             LOCATE y%, x%
  572.             PRINT c$;
  573.         ELSE
  574.             'PSET (x%, y%), c%
  575.             LOCATE x%, y%
  576.             PRINT c$;
  577.         END IF
  578.  
  579.         WHILE e% >= 0
  580.             y% = y% + sy%: e% = e% - 2 * dx%
  581.         WEND
  582.         x% = x% + sx%: e% = e% + 2 * dy%
  583.     NEXT
  584.     'PSET (x2%, y2%), c%
  585.     LOCATE x2%, y2%
  586.     PRINT c$;
  587.  
  588. END SUB ' DrawTextLine
  589.  

^^^
From: Multiple mice therad #1:
https://www.qb64.org/forum/index.php?topic=3348.msg127110#msg127110 (https://www.qb64.org/forum/index.php?topic=3348.msg127110#msg127110)

Multiple mice thread #2:
https://www.qb64.org/forum/index.php?topic=3695.0 (https://www.qb64.org/forum/index.php?topic=3695.0)
Title: Re: events and malloc in QB64?
Post by: madscijr on March 30, 2021, 02:56:14 pm
I hope this helps to answer some of the questions, at least

I am a fish out of water in the world of C and low-level Windows programming, so any information helps.
Thank you!
Title: Re: events and malloc in QB64?
Post by: SpriggsySpriggs on March 30, 2021, 03:05:16 pm
@madscijr I will do my best to allocate some time tonight to work on this a bit. If you want, you can join our discord server using the link on the forum home. I'm very active there and can answer your questions quickly.
Title: Re: events and malloc in QB64?
Post by: SpriggsySpriggs on March 31, 2021, 12:36:56 am
@madscijr Just so you know that I didn't forget you, here is proof that I'm looking into this:
  [ This attachment cannot be displayed inline in 'Print Page' view ]  

Note: This isn't to say I've gotten anything to work yet. I'm still just trying to recreate some functions and declarations.
Title: Re: events and malloc in QB64?
Post by: FellippeHeitor on March 31, 2021, 08:40:06 am
@bplus instead of in-house event-based programming - which is what InForm offers - it seems from context that madscijr is looking to handle OS events - likely with callback functions.
Title: Re: events and malloc in QB64?
Post by: SpriggsySpriggs on March 31, 2021, 08:43:35 am
@FellippeHeitor Exactly. I'm actually using callback code shared by Petr here: https://www.qb64.org/forum/index.php?topic=3217.msg124966#msg124966 (https://www.qb64.org/forum/index.php?topic=3217.msg124966#msg124966)
Title: Re: events and malloc in QB64?
Post by: madscijr on March 31, 2021, 08:44:01 am
@madscijr Just so you know that I didn't forget you, here is proof that I'm looking into this:
Note: This isn't to say I've gotten anything to work yet. I'm still just trying to recreate some functions and declarations.

Great - much appreciated!

PS Sorry I wasn't able to join on the discord server (what is a discord server?), I'm often pretty busy after hours on weekdays, this QB stuff is mainly a lunchtime activity for me!
Title: Re: events and malloc in QB64?
Post by: FellippeHeitor on March 31, 2021, 08:52:22 am
Discord is a fancy chatroom. Registration required. http://discord.qb64.org
Title: Re: events and malloc in QB64?
Post by: madscijr on March 31, 2021, 08:54:39 am
Discord is a fancy chatroom. Registration required. http://discord.qb64.org
Cool, thanks for cluing me in.
Title: Re: events and malloc in QB64?
Post by: madscijr on March 31, 2021, 08:58:23 am
PPS Down the road (assuming this ever ends up working) it would be cool to also get this working for Linux / macOS.

I'm not sure if there are commands in QB64 code that can auto-detect the OS, and conditionally use Windows / Linux / Mac versions of a library, or if we would just need to have separate versions of the library for each OS.
But the ManyMouse library seems to be cross-platform, with separate versions of code for
and common files for all platforms

I just thought I would mention this to gauge how people approach making a cross-platform library in QB64...
Title: Re: events and malloc in QB64?
Post by: SpriggsySpriggs on March 31, 2021, 09:04:47 am
I'm not sure if there are commands in QB64 code that can auto-detect the OS, and conditionally use Windows / Linux / Mac versions of a library, or if we would just need to have separate versions of the library for each OS.

There are! Check out this Wiki page: https://www.qb64.org/wiki/$IF (https://www.qb64.org/wiki/$IF)
Title: Re: events and malloc in QB64?
Post by: madscijr on March 31, 2021, 09:28:57 am
There are! Check out this Wiki page: https://www.qb64.org/wiki/$IF (https://www.qb64.org/wiki/$IF)

Aha, yes, that's the stuff!
Thanks!
(Now we would just need someone who can understand Mac "C" code and Linux "C" code to help convert the respective modules! I'm not going to worry about this until later...)
Title: Re: events and malloc in QB64?
Post by: SpriggsySpriggs on March 31, 2021, 09:34:07 am
(Now we would just need someone who can understand Mac "C" code and Linux "C" code to help convert the respective modules! I'm not going to worry about this until later...)

Well, I have written code that is multiplatform before which required me to convert C code for Linux and Mac to QB64. Not too much of a challenge. I'll give that a go if I can get some functionality in Windows first.
Title: Re: events and malloc in QB64?
Post by: SpriggsySpriggs on April 01, 2021, 09:05:54 am
@madscijr Well, it turns out that this software you want to recreate or use in QB64 requires SDL. Our older versions of QB64 use SDL. I'm trying now to find a way to do what you want without SDL. May prove difficult
Title: Re: events and malloc in QB64?
Post by: madscijr on April 01, 2021, 10:04:13 am
@madscijr Well, it turns out that this software you want to recreate or use in QB64 requires SDL. Our older versions of QB64 use SDL. I'm trying now to find a way to do what you want without SDL. May prove difficult

No kidding... So THAT's how they're doing it cross-platform?
I saw stuff in there about the Raw Input API, though.
I think that's a standard Microsoft API included in all Windows versions from XP on.
With that, we shouldn't need SDL for the Windows version, right?

PS Here are the MS RawInput API docs:
https://docs.microsoft.com/en-us/windows/win32/inputdev/raw-input?redirectedfrom=MSDN (https://docs.microsoft.com/en-us/windows/win32/inputdev/raw-input?redirectedfrom=MSDN)

PPS and here is some sample code to use the RawInput API (yet more C code I can flounder around with and try to convert to QB64! yay!):
https://jstookey.com/multiple-mice-raw-input/ (https://jstookey.com/multiple-mice-raw-input/)
Title: Re: events and malloc in QB64?
Post by: SpriggsySpriggs on April 01, 2021, 11:29:25 am
@madscijr Exactly. I've been looking at some raw input examples online.

https://asawicki.info/news_1533_handling_multiple_mice_with_raw_input (https://asawicki.info/news_1533_handling_multiple_mice_with_raw_input)
Title: Re: events and malloc in QB64?
Post by: madscijr on April 01, 2021, 11:48:44 pm
@madscijr Exactly. I've been looking at some raw input examples online.
https://asawicki.info/news_1533_handling_multiple_mice_with_raw_input (https://asawicki.info/news_1533_handling_multiple_mice_with_raw_input)

From my end, I think starting off simple is probably the best way to get off the ground, so I started off by figuring out the minimal example from
https://jstookey.com/multiple-mice-raw-input/ (https://jstookey.com/multiple-mice-raw-input/)

Hopefully tomorrow I'll get something working...

Code: C: [Select]
  1. /**********************************************************************************************
  2. FROM: https://jstookey.com/arcade/rawmouse/HelloRawInput.c
  3.  
  4. testmouse.c: A demonstration of how to use Rawinput to access multiple mice in Windows XP.
  5.  
  6. ------------------  COMPILING WITH GCC ------------------------------
  7.  
  8. This program was compiled using MinGW/GCC
  9.  
  10. In order to recreate the compile environment:
  11.  
  12.   1) Install the "Win32 compile utilities" (MinGW/GCC) for Mame from http://www.mame.net/downmain.html
  13.   2) From the command line, run "gcc HelloRawInput.c"
  14.  
  15. -------------------  COMPILING WITH MS VISUAL C++ --------------------
  16.  
  17. This example can also be compiled with Microsoft Visual C++ version 6, but first you need to download
  18.         and install the Microsoft Platform SDK.  In order to access the Microsoft Platform SDK from VStudio,
  19.         I had to go to tools->options->directories and add the SDK's bin, include, lib, and src folders.
  20.         In the same window, I had drag each of the SDK's folders to the top of the respective list
  21.         to give those folders priority over the others.
  22.  
  23.         To create your project for Visual Studio (after you prepare VStudio to work with the MS
  24.              Platform SDK), do the following:
  25.  
  26.         1) Open Visual C++ and start a new Win32 Application as a "blank project"
  27.            (This is necessary because if you simply open the .c file in VStudio
  28.            VStudio will assume it's a "console application" and it won't compile properly.)
  29.         2) Copy the .c file into the new project's root folder
  30.         3) In the left pane, click "File View" and left click "Source Files" and select
  31.              "add files to folder" from the popup menu, and add your file.
  32.         4) You're all set!  Press f5 to build the program.
  33.  
  34. **********************************************************************************************/
  35. #define _WIN32_WINNT 0x0501   // Identify this as a Windows XP application.  This is necessary
  36.                                                           //    so we can access rawinput
  37. #include <stdio.h>
  38. #include <conio.h>                      //  Provides getch()
  39. #include <windows.h>            //  Provides rawinput
  40.  
  41. main()
  42. {
  43.         UINT nInputDevices;
  44.  
  45.         // 1st call to GetRawInputDeviceList: Pass NULL to get the size of the list.
  46.         if (GetRawInputDeviceList(NULL, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) != 0) return 0;
  47.         printf("Number of raw input devices: %i\n\n", nInputDevices);
  48.  
  49.         printf("Press any key...");
  50.         getch();
  51.  
  52.         return 1;
  53. }
  54.  
  55.  
  56. /*
  57.  
  58. -------------------------------------------------------------------------------
  59. What is GetRawInputDeviceList?
  60.         UINT GetRawInputDeviceList(
  61.           PRAWINPUTDEVICELIST pRawInputDeviceList,
  62.           PUINT               puiNumDevices,
  63.           UINT                cbSize
  64.         );
  65.  
  66. -------------------------------------------------------------------------------
  67. What is PRAWINPUTDEVICELIST?
  68.         PRAWINPUTDEVICELIST:
  69.         typedef struct tagRAWINPUTDEVICELIST {
  70.           HANDLE hDevice;
  71.           DWORD  dwType;
  72.         } RAWINPUTDEVICELIST, *PRAWINPUTDEVICELIST;
  73.  
  74. -------------------------------------------------------------------------------
  75. What is getch?
  76.         getch() is a nonstandard function and is present in conio.h header file
  77.         which is mostly used by MS-DOS compilers like Turbo C. It is not part of
  78.         the C standard library or ISO C, nor is it defined by POSIX.
  79.         Like these functions, getch() also reads a single character from the
  80.         keyboard. But it does not use any buffer, so the entered character is
  81.         immediately returned without waiting for the enter key.
  82.         Syntax: int getch(void);
  83.         Parameters: This method does not accept any parameters.
  84.         Return value: This method returns the ASCII value of the key pressed.
  85.        
  86. */
  87.  
Title: Re: events and malloc in QB64?
Post by: madscijr on April 02, 2021, 05:09:50 pm
From my end, I think starting off simple is probably the best way to get off the ground, so I started off by figuring out the minimal example from
https://jstookey.com/multiple-mice-raw-input/ (https://jstookey.com/multiple-mice-raw-input/)
Hopefully tomorrow I'll get something working...

I tried to convert the C code to QB64, using the QB64 equivalents of the C types that SpriggsySpriggs shared, and googling.
I'm currently stuck on line 55 of the below code, when I run the QB64 IDE says "Expected &H... or &O...".
When I try changing & to &H or &O, the QB64 IDE says a ")" is missing. No idea how to get this working!
Any help appreciated...

Code: QB64: [Select]
  1. ' ****************************************************************************************************************************************************************
  2. ' testmouse.c: A demonstration of how to use Rawinput to access multiple mice in Windows XP.
  3. ' https://jstookey.com/arcade/rawmouse/HelloRawInput.c
  4. ' ****************************************************************************************************************************************************************
  5.  
  6. ' #define _WIN32_WINNT 0x0501   // Identify this as a Windows XP application.
  7. '                               // This is necessary so we can access rawinput
  8. ' #include <stdio.h>            
  9. ' #include <conio.h>            //  Provides getch()
  10. ' #include <windows.h>          //  Provides rawinput
  11.  
  12. ' =============================================================================
  13. ' GLOBAL DECLARATIONS a$=string, i%=integer, L&=long, s!=single, d#=double
  14.  
  15. ' -----------------------------------------------------------------------------
  16. ' BOOLEAN CONSTANTS
  17. CONST FALSE = 0
  18. CONST TRUE = NOT FALSE
  19.  
  20. ' -----------------------------------------------------------------------------
  21. ' USER DEFINED TYPES
  22.  
  23. ' What is PRAWINPUTDEVICELIST?
  24. '     PRAWINPUTDEVICELIST:
  25. '     typedef struct tagRAWINPUTDEVICELIST {
  26. '       HANDLE hDevice;
  27. '       DWORD  dwType;
  28. '     } RAWINPUTDEVICELIST, *PRAWINPUTDEVICELIST;
  29.  
  30. TYPE RAWINPUTDEVICELIST
  31.     hDevice AS _OFFSET ' a handle will always be _OFFSET
  32.     dwType AS LONG ' DWORD corresponds to LONG
  33.  
  34. ' -----------------------------------------------------------------------------
  35. ' API FUNCTIONS
  36.  
  37. ' What is GetRawInputDeviceList?
  38. '     UINT GetRawInputDeviceList(
  39. '       PRAWINPUTDEVICELIST pRawInputDeviceList,
  40. '       PUINT               puiNumDevices,        <---- what is a aPUINT?
  41. '       UINT                cbSize
  42. '     );
  43.  
  44. ' what is a aPUINT? According to
  45. '     WIN32 API Data Types
  46. '     https://www.csie.ntu.edu.tw/~r92094/c++/w32api_data_type.html
  47. ' PUINT Pointer to a UINT.
  48. ' Q: What QB64 type is equivalent to a pointer?
  49. ' A: is it _OFFSET ?
  50.  
  51.     ' COMPILER ERROR HERE: Expected &H... or &O...
  52.     ' THEN WHEN I TRY CHANGING & TO &H OR &O, COMPILER SAYS MISSING )
  53.     FUNCTION GetRawInputDeviceList (pRawInputDeviceList AS RAWINPUTDEVICELIST, puiNumDevices AS _OFFSET, cbSize AS _UNSIGNED LONG)&
  54.  
  55. ' =============================================================================
  56. ' GLOBAL VARIABLES
  57. DIM ProgramPath$
  58. DIM ProgramName$
  59.  
  60. ' =============================================================================
  61. ' INITIALIZE
  62. ProgramName$ = MID$(COMMAND$(0), _INSTRREV(COMMAND$(0), "\") + 1)
  63. ProgramPath$ = LEFT$(COMMAND$(0), _INSTRREV(COMMAND$(0), "\"))
  64.  
  65. ' =============================================================================
  66. ' START
  67. main ProgramName$
  68.  
  69. ' =============================================================================
  70. ' FINISH
  71. SYSTEM ' return control to the operating system
  72. PRINT ProgramName$ + " finished."
  73.  
  74. ' /////////////////////////////////////////////////////////////////////////////
  75.  
  76. SUB main
  77.         PRINT "MinimalRawInputTest% RETURNS: " + cstr$( MinimalRawInputTest%() )
  78. END SUB ' main
  79.  
  80. FUNCTION MinimalRawInputTest%
  81.     DIM iResult%
  82.         'UINT nInputDevices;
  83.         DIM nInputDevices AS _UNSIGNED LONG
  84.         DIM MEM AS _MEM
  85.        
  86.     ' 1st call to GetRawInputDeviceList: Pass NULL to get the size of the list.
  87.     'if (GetRawInputDeviceList(NULL, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) != 0) return 0;
  88.        
  89.         ' **********
  90.         ' UNKNOWNS:
  91.         ' Q1: how do you pass NULL in QB64?
  92.         ' A1: ?
  93.        
  94.         ' Q2: what is &nInputDevices vs nInputDevices and what is the QB64 equivalent?
  95.         ' A2: is it the pointer to the variable? in QB64, The _OFFSET function returns the memory offset of/within a given variable.
  96.        
  97.         ' Q3: what is the QB64 equivalent of sizeof?
  98.         ' A3: maybe _MEM and _MEM.SIZE ?
  99.        
  100.         MEM = _MEM(RAWINPUTDEVICELIST)
  101.        
  102.         'IF (GetRawInputDeviceList(NULL, _OFFSET(nInputDevices), sizeof(RAWINPUTDEVICELIST)) <> 0) THEN
  103.         IF (GetRawInputDeviceList(NULL, _OFFSET(nInputDevices), MEM.SIZE) <> 0) THEN
  104.                 iResult% = 0
  105.     ELSE
  106.                 PRINT "Number of raw input devices: " + cstr$(nInputDevices)
  107.                 PRINT "Press any key..."
  108.                 SLEEP ' SLEEP without an argument waits until a keypress.)
  109.                 iResult% = 1
  110.         END IF
  111.    
  112.         ' RETURN RESULT (ONE EXIT POINT!)
  113.         MinimalRawInputTest% = iResult%
  114. END FUNCTION ' MinimalRawInputTest%
  115.  
  116. ' /////////////////////////////////////////////////////////////////////////////
  117. ' Equivalent to vbscript / VBA / VB6 cstr
  118.  
  119. FUNCTION cstr$ (myValue)
  120.     'cstr$ = LTRIM$(RTRIM$(STR$(myValue)))
  121.     cstr$ = _TRIM$(STR$(myValue))
  122. END FUNCTION ' cstr$
  123.  
  124. ' /////////////////////////////////////////////////////////////////////////////
  125. ' Equivalent to getch
  126.  
  127. ' -----------------------------------------------------------------------------
  128. ' What is getch?
  129. '     getch() is a nonstandard function and is present in conio.h header file
  130. '     which is mostly used by MS-DOS compilers like Turbo C. It is not part of
  131. '     the C standard library or ISO C, nor is it defined by POSIX.
  132. '     Like these functions, getch() also reads a single character from the
  133. '     keyboard. But it does not use any buffer, so the entered character is
  134. '     immediately returned without waiting for the enter key.
  135. '     Syntax: int getch(void);
  136. '     Parameters: This method does not accept any parameters.
  137. '     Return value: This method returns the ASCII value of the key pressed.
  138.  
  139. ' -----------------------------------------------------------------------------
  140. ' QB64 alternate to getch
  141. '
  142. ' SLEEP ' SLEEP without an argument waits until a keypress.)
  143. '
  144. ' or
  145. '
  146. ' DO
  147. '       x = _KEYHIT
  148. '       IF x THEN
  149. '               EXIT DO
  150. '       END IF
  151. ' LOOP
  152.  
Title: Re: events and malloc in QB64?
Post by: SMcNeill on April 02, 2021, 06:35:14 pm
    FUNCTION GetRawInputDeviceList& (pRawInputDeviceList AS RAWINPUTDEVICELIST, puiNumDevices AS _OFFSET, cbSize AS _UNSIGNED LONG)


& *after* the function name.
Title: Re: events and malloc in QB64?
Post by: madscijr on April 03, 2021, 11:13:42 am
    FUNCTION GetRawInputDeviceList& (pRawInputDeviceList AS RAWINPUTDEVICELIST, puiNumDevices AS _OFFSET, cbSize AS _UNSIGNED LONG)


& *after* the function name.

Aha... DUH! LoL
Thank you.

Any idea how you would send a NULL value as one of the parameters?
Title: Re: events and malloc in QB64?
Post by: madscijr on April 05, 2021, 04:23:57 pm
I returned to this and made some minor changes, and am now stuck on this error:
Code: [Select]
Cannot convert _OFFSET type to other types on line 118.
Caused by (or after): IF ( GETRAWINPUTDEVICELIST ( MYLIST , MYADDR , MEM . SIZE ) <> 0 ) THEN

This is probably outside the scope of this thread, so I'll start a new one for this, related to type "_OFFSET".