Author Topic: events and malloc in QB64?  (Read 4843 times)

0 Members and 1 Guest are viewing this topic.

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
events and malloc in QB64?
« 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

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!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: events and malloc in QB64?
« Reply #1 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
« Last Edit: March 30, 2021, 12:47:49 pm by bplus »

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
Re: events and malloc in QB64?
« Reply #2 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?

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: events and malloc in QB64?
« Reply #3 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.

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
Re: events and malloc in QB64?
« Reply #4 on: March 30, 2021, 01:48:42 pm »

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • GitHub
Re: events and malloc in QB64?
« Reply #5 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.
Shuwatch!

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
Re: events and malloc in QB64?
« Reply #6 on: March 30, 2021, 02:08:11 pm »
Oy vey! LoL
« Last Edit: March 30, 2021, 02:09:27 pm by madscijr »

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
Re: events and malloc in QB64?
« Reply #7 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/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:
  • HDEVINFO
  • ATOM
  • LRESULT
  • HMODULE
  • DWORD - I think I've seen this keyword in regedit?
  • CRITICAL_SECTION
  • HANDLE
  • HINSTANCE
  • WNDCLASSEX
  • SP_DEVINFO_DATA
  • size_t

and functions too like
  • GetProcAddress
  • FreeLibrary
  • LoadLibrary
  • LOOKUP (a bunch inside routine find_api_symbols)
  • sizeof
  • MSG

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
  • HWND (I remember that from VB6)
  • static
  • volatile

Some that are probably covered under the _MEM functions in QB64 like:
  • CopyMemory
  • ZeroMemory
  • alloca

Some familiar terms I would guess have a QB64 equivalent (I have to look up):
  • uint
  • static unsigned int - what's the difference between "uint" and "unsigned int"?


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!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: events and malloc in QB64?
« Reply #8 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...?

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • GitHub
Re: events and malloc in QB64?
« Reply #9 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
    • SP_DEVINFO_DATA
    //custom struct, 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
    • 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
    [/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
    « Last Edit: March 30, 2021, 02:48:04 pm by SpriggsySpriggs »
    Shuwatch!

    Offline madscijr

    • Seasoned Forum Regular
    • Posts: 295
    Re: events and malloc in QB64?
    « Reply #10 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

    Multiple mice thread #2:
    https://www.qb64.org/forum/index.php?topic=3695.0

    Offline madscijr

    • Seasoned Forum Regular
    • Posts: 295
    Re: events and malloc in QB64?
    « Reply #11 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!

    Offline SpriggsySpriggs

    • Forum Resident
    • Posts: 1145
    • Larger than life
      • GitHub
    Re: events and malloc in QB64?
    « Reply #12 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.
    Shuwatch!

    Offline SpriggsySpriggs

    • Forum Resident
    • Posts: 1145
    • Larger than life
      • GitHub
    Re: events and malloc in QB64?
    « Reply #13 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:
      [ You are not allowed to view this attachment ]  

    Note: This isn't to say I've gotten anything to work yet. I'm still just trying to recreate some functions and declarations.
    Shuwatch!

    FellippeHeitor

    • Guest
    Re: events and malloc in QB64?
    « Reply #14 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.