lualogitechlogitech-gaming-software

How could I recreate this script using only WinAPI functions?


Like the title states, I'm attempting to recreate a script I made using only standard WinAPI functions such as IsMouseButtonPressed() PressMouseButton() ReleaseMouseButton() in hopes of making it work using a non-logitech mouse. The script is a simple one that detects when mb5/mb4 is pressed together with right mouse button to simulate keypresses, in this case pressing respectively the key O and P. So if mb5 is pressed together with right mb, it would press O, if mb4 is pressed together with right mb, it would press P. Here is the script:

local mouseButton5Pressed = false
local mouseButton4Pressed = false
local rightMouseButtonPressed = false

function OnEvent(event, arg)
    if event == "MOUSE_BUTTON_PRESSED" then
        if arg == 5 then
            mouseButton5Pressed = true
        elseif arg == 4 then
            mouseButton4Pressed = true
        elseif arg == 2 then
            rightMouseButtonPressed = true
        end
    elseif event == "MOUSE_BUTTON_RELEASED" then
        if arg == 5 then
            mouseButton5Pressed = false
        elseif arg == 4 then
            mouseButton4Pressed = false
        elseif arg == 2 then
            rightMouseButtonPressed = false
        end
    end
    if rightMouseButtonPressed and (mouseButton5Pressed or mouseButton4Pressed) then
        if mouseButton5Pressed then
            PressKey("o")
        else
            ReleaseKey("o")
        end
        if mouseButton4Pressed then
            PressKey("p")
        else
            ReleaseKey("p")
        end
    else
        ReleaseKeys()
    end
end

function ReleaseKeys()
    ReleaseKey("o")
    ReleaseKey("p")
end

So far I've tried a few other versions of the script along these lines:

function OnEvent(event, arg)
    if IsMouseButtonPressed(3) and (IsMouseButtonPressed(5) or IsMouseButtonPressed(4)) then
        if IsMouseButtonPressed(5) then
            PressKey("o")
        else
            ReleaseKey("o")
        end
        
        if IsMouseButtonPressed(4) then
            PressKey("p")
        else
            ReleaseKey("p")
        end
    else
        ReleaseKeys()
    end
end

function ReleaseKeys()
    ReleaseKey("o")
    ReleaseKey("p")
end

However they all feel way less responsive, they stop working when you press the mouse buttons too quickly and fail to release the keys reliably once either mouse button is released, which isn't optimal considering what I intend to use the script for.

Also, since I mentionned how I would like to make it work using a non-logitech mice, I was also curious as to whether or not it was possible to implement (event == "PROFILE_ACTIVATED") in the script so you can invoke the OnEvent function without the logitech mouse. A bit like this script that can be used with any mouse:

EnablePrimaryMouseButtonEvents(true);

function OnEvent(event, arg)
    if (event == "PROFILE_ACTIVATED") then
        repeat  
            if IsMouseButtonPressed(5) then
                repeat
                    PressMouseButton(1)
                    Sleep(15) 
                    ReleaseMouseButton(1)
                    Sleep(15) 
                until not IsMouseButtonPressed(5)
            end             
        until not (event == "PROFILE_ACTIVATED")
    end         
end

I know the formating is different since this a loop and it might not be feasible but I don't really know what else I could do. I'm a bit out of options here so any help would be greatly appreciated.


Solution

  • ------ outputs
    
    local simulated_by_you = {}
    
    local orig_PressKey = PressKey
    local orig_ReleaseKey = ReleaseKey
    local orig_PressMouseButton = PressMouseButton
    local orig_ReleaseMouseButton = ReleaseMouseButton
    
    function PressKey(key)
       key = tostring(key)
       simulated_by_you[key] = true
       orig_PressKey(key)
    end
    
    function ReleaseKey(key)
       key = tostring(key)
       simulated_by_you[key] = false
       orig_ReleaseKey(key)
    end
    
    function PressMouseButton(button)
       button = tonumber(button)
       simulated_by_you[button] = true
       orig_PressMouseButton(button)
    end
    
    function ReleaseMouseButton(button)
       button = tonumber(button)
       simulated_by_you[button] = false
       orig_ReleaseMouseButton(button)
    end
    
    local function release_keys_on_exit()
       for key, status in pairs(simulated_by_you) do
          if status then
             if type(key) == "number" then
                ReleaseMouseButton(key)
             else
                ReleaseKey(key)
             end
          end
       end
    end
    
    ------ inputs
    
    local input = {}                   -- current value of input
    local input_has_changed = {}       -- changed just now in either direction
    local input_has_turned_on = {}     -- changed just now from OFF to ON
    local input_has_turned_off = {}    -- changed just now from ON to OFF
    
    local input_functions = {
       [IsMouseButtonPressed] = {1, 2, 3, 4, 5},
       [IsModifierPressed]    = {"lalt", "ralt", "alt", "lshift", "rshift", "shift", "lctrl", "rctrl", "ctrl"},
       [IsKeyLockOn]          = {"numlock", "capslock", "scrolllock"},
    }
    
    local function refresh_input(ms)
       local tm = GetRunningTime() + (ms or 0)
       repeat
          Sleep(10)
          local something_has_changed
          for func, args in pairs(input_functions) do
             for _, arg in ipairs(args) do
                local old = input[arg]
                local new = func(arg)
                input[arg]                = new
                input_has_changed[arg]    = old ~= new
                input_has_turned_on[arg]  = new and not old
                input_has_turned_off[arg] = not new and old
                something_has_changed = something_has_changed or old ~= new
             end
          end
       until GetRunningTime() >= tm or something_has_changed
    end
    
    ------ main loop
    
    function OnEvent(event, arg)
       if event == "PROFILE_ACTIVATED" then
          refresh_input()
          repeat
             refresh_input()
             ------------------------------------------------
             -- Your code is here
             -- Read from tables: input, input_has_changed, input_has_turned_on, input_has_turned_off
             --    to obtain inputs: mouse buttons ([1]...[5]), modifier keys (".shift",...), lock key LEDs (".numlock",...)
             -- Invoke functions: PressKey, ReleaseKey, PressAndReleaseKey, PressMouseButton, ReleaseMouseButton, PressAndReleaseMouseButton
             --    to simulate outputs
             -- Read from table simulated_by_you
             --    to determine which keyboard keys (".o",...) and mouse buttons ([1]...[5]) press you have previously simulated and not released them yet
             ------------------------------------------------
    
             -- if (RMB is currently down) and (button#5 has been pressed just now) or vice versa
             if input[3] and input_has_turned_on[5] or input_has_turned_on[3] and input[5] then
                PressKey("o")
             end
             -- if (you previously simulated key "o" pressed) and (RMB or button#5 has been released just now)
             if simulated_by_you.o and (input_has_turned_off[3] or input_has_turned_off[5]) then
                ReleaseKey("o")
             end
    
             -- if (RMB is currently down) and (button#4 has been pressed just now) or vice versa
             if input[3] and input_has_turned_on[4] or input_has_turned_on[3] and input[4] then
                PressKey("p")
             end
             -- if (you previously simulated key "p" pressed) and (RMB or button#4 has been released just now)
             if simulated_by_you.p and (input_has_turned_off[3] or input_has_turned_off[4]) then
                ReleaseKey("p")
             end
    
             ------------------------------------------------
          until input_has_changed.numlock
          release_keys_on_exit()
       end
    end
    

    This script works without touching Logitech mouse.
    When LGS/GHub profile is switched (when starting another application or when making another application window foreground), OnEvent function is starting.
    You must press NumLock (to exit OnEvent function) before every switch to another profile, otherwise LGS/GHub will crash.