Old 11-24-2020, 04:58 AM   #1
zabukowski
Human being with feelings
 
zabukowski's Avatar
 
Join Date: Nov 2009
Posts: 187
Default "Send key" action

Does anyone know, if it's possible to send key(s) from script to Reaper?

For example: i would like to open "Dynamic Split" dialog from custom action and then send "Enter"key to execute processing with default (last used) parameters.

Thx!
__________________
My software & music...
http://www.zabukowski.com/software
http://www.zabukowski.com
zabukowski is offline   Reply With Quote
Old 11-24-2020, 10:23 AM   #2
Edgemeal
Human being with feelings
 
Edgemeal's Avatar
 
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,913
Default

Normally you'd get the handle to the button and then send it a click message. One tricky part with the Dynamic split window is that the "Split" button is not enabled until after the dynamic split window has finished doing its work when opened, so we'd have to wait until the button is enabled or clicking it won't do anything. I didn't see an IsWindowEnabled function in the API so did it by checking the buttons style bits, only tested on Win10,..

NOTE: This Lua script requires the js_ReaScriptAPI extension!

Code:
local WS_DISABLED = 0x08000000 -- https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles

function ClickSplitButton()
  local parent = reaper.JS_Window_FindTop('Dynamic split items',true) 
  if parent then
    local btn = reaper.JS_Window_FindChildByID(parent, 0x1) -- get handle to "Split" button
    if btn then -- check if button is enabled
      local style = reaper.JS_Window_GetLong(btn, "STYLE")
      if style & WS_DISABLED == WS_DISABLED then
        reaper.defer(ClickSplitButton) -- loop & try again.
      else -- send btn a left mouse click msg
        reaper.JS_WindowMessage_Send(btn, "WM_LBUTTONDOWN", 1, 0, 0, 0)
        reaper.JS_WindowMessage_Send(btn, "WM_LBUTTONUP", 0, 0, 0, 0) 
      end 
    end
  end
end

-- open dynamic split items window
reaper.Main_OnCommand(40760, 0) -- Item: Dynamic split items...
-- click the "Split" button.
ClickSplitButton()

Last edited by Edgemeal; 11-24-2020 at 10:37 AM.
Edgemeal is offline   Reply With Quote
Old 11-24-2020, 10:40 AM   #3
zabukowski
Human being with feelings
 
zabukowski's Avatar
 
Join Date: Nov 2009
Posts: 187
Default

Quote:
Originally Posted by Edgemeal View Post
Normally you'd get the handle to the button and then send it a click message. One tricky part with the Dynamic split window is that the "Split" button is not enabled until after the dynamic split window has finished doing its work when opened, so we'd have to wait until the button is enabled or clicking it won't do anything. I didn't see an IsWindowEnabled function in the API so did it by checking the buttons style bits, only tested on Win10,..

NOTE: This Lua script requires the js_ReaScriptAPI extension!

Code:
local WS_DISABLED = 0x08000000 -- https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles

function ClickSplitButton()
  local parent = reaper.JS_Window_FindTop('Dynamic split items',true) 
  if parent then
    local btn = reaper.JS_Window_FindChildByID(parent, 0x1) -- get handle to "Split" button
    if btn then -- check if button is enabled
      local style = reaper.JS_Window_GetLong(btn, "STYLE")
      if style & WS_DISABLED == WS_DISABLED then
        reaper.defer(ClickSplitButton) -- loop & try again.
      else -- send btn a left mouse click msg
        reaper.JS_WindowMessage_Send(btn, "WM_LBUTTONDOWN", 1, 0, 0, 0)
        reaper.JS_WindowMessage_Send(btn, "WM_LBUTTONUP", 0, 0, 0, 0) 
      end 
    end
  end
end

-- open dynamic split items window
reaper.Main_OnCommand(40760, 0) -- Item: Dynamic split items...
-- click the "Split" button.
ClickSplitButton()
Woooow, perfect, big thanks for this !!!
__________________
My software & music...
http://www.zabukowski.com/software
http://www.zabukowski.com
zabukowski is offline   Reply With Quote
Old 11-24-2020, 11:36 AM   #4
shosty
Human being with feelings
 
Join Date: Aug 2015
Posts: 249
Default

Quote:
Originally Posted by Edgemeal View Post
Normally you'd get the handle to the button and then send it a click message.
How do you find this? I've had a similar problem with the midi learn last touched parameter, I would like to assign it to a button so I can press it, midi learn and the dialog closes but I can't find a way to press OK/enter as an action.
shosty is offline   Reply With Quote
Old 11-24-2020, 12:48 PM   #5
Edgemeal
Human being with feelings
 
Edgemeal's Avatar
 
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,913
Default

Quote:
Originally Posted by shosty View Post
How do you find this? I've had a similar problem with the midi learn last touched parameter, I would like to assign it to a button so I can press it, midi learn and the dialog closes but I can't find a way to press OK/enter as an action.
If you know for sure there is only one child window on the parent window with exact text, lets say its "OK", or "ok" (case doesn't matter) then you can safely use JS_Window_FindChild() to get its handle, for example,..
Code:
btn = reaper.JS_Window_FindChild(parent, "OK", true)
Note that some dialogs can block scripts from running, if you need more help post image(s) of the exact window(s) you're referring to.
Edgemeal is offline   Reply With Quote
Old 11-28-2020, 07:40 AM   #6
zabukowski
Human being with feelings
 
zabukowski's Avatar
 
Join Date: Nov 2009
Posts: 187
Default

Quote:
Originally Posted by Edgemeal View Post
Normally you'd get the handle to the button and then send it a click message. One tricky part with the Dynamic split window is that the "Split" button is not enabled until after the dynamic split window has finished doing its work when opened, so we'd have to wait until the button is enabled or clicking it won't do anything. I didn't see an IsWindowEnabled function in the API so did it by checking the buttons style bits, only tested on Win10,..

NOTE: This Lua script requires the js_ReaScriptAPI extension!
Where can i find more detailed documentation for js_ReaScriptAPI extension?

Unfortunately, your script doesn't work on macOS
__________________
My software & music...
http://www.zabukowski.com/software
http://www.zabukowski.com
zabukowski is offline   Reply With Quote
Old 11-28-2020, 08:36 AM   #7
Edgemeal
Human being with feelings
 
Edgemeal's Avatar
 
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,913
Default

Quote:
Originally Posted by zabukowski View Post
Where can i find more detailed documentation for js_ReaScriptAPI extension?

Unfortunately, your script doesn't work on macOS
That sucks, don't have a MAC here, Ask in the JS_API thread, hopefully someone there with a MAC can help.
Edgemeal is offline   Reply With Quote
Old 08-06-2022, 06:38 AM   #8
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,875
Default

@Edgemeal
Hi !



Can you send a exemple using VK, like VK_SPACE ?


Thx !
X-Raym is offline   Reply With Quote
Old 08-06-2022, 10:44 AM   #9
daniellumertz
Human being with feelings
 
daniellumertz's Avatar
 
Join Date: Dec 2017
Location: Brazil
Posts: 1,992
Default

This is the code I use to pass keys from reaimgui to reaper. You can use PostKey(hwnd, vk_code) to send key presses manually. PassKeys does: 1) Get key pressed with ImGUI AP (could also use JS), save last screen with focus (as this is a snippet used in a GUI it needs to know which were the last REAPER screen with focus (arrange,MIDI, etc)), send key pressed with PostKey (that uses JS).

Code:
 
function PassKeys() -- Might be a little tough on resource
    --Get keys pressed
    local active_keys = {}
    for key_val = 0,255 do
        if reaper.ImGui_IsKeyPressed(ctx, key_val, true) then -- true so holding will perform many times
            active_keys[#active_keys+1] = key_val
        end
    end

    --Send Message
    if LastWindowFocus then 
        if #active_keys > 0  then
            for k, key_val in pairs(active_keys) do
                PostKey(LastWindowFocus, key_val)
            end
        end
    end

    -- Get focus window (if not == Script Title)
    local win_focus = reaper.JS_Window_GetFocus()
    local win_name = reaper.JS_Window_GetTitle( win_focus )

    -- Need to retain the last window focused that isn't this script! 
    if LastWindowFocus ~= win_focus and (win_name == 'trackview' or win_name == 'midiview')  then -- focused win title is different? INSERT HERE
        LastWindowFocus = win_focus
    end    
end

function PostKey(hwnd, vk_code)
    reaper.JS_WindowMessage_Post(hwnd, "WM_KEYDOWN", vk_code, 0,0,0)
    reaper.JS_WindowMessage_Post(hwnd, "WM_KEYUP", vk_code, 0,0,0)
end
daniellumertz is online now   Reply With Quote
Old 08-06-2022, 10:48 AM   #10
Edgemeal
Human being with feelings
 
Edgemeal's Avatar
 
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,913
Default

Quote:
Originally Posted by X-Raym View Post
@Edgemeal
Hi !



Can you send a exemple using VK, like VK_SPACE ?


Thx !
Try,..
Code:
function PostKey(hwnd, vk_code) -- https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
  reaper.JS_WindowMessage_Post(hwnd, "WM_KEYDOWN", vk_code, 0,0,0)
  reaper.JS_WindowMessage_Post(hwnd, "WM_KEYUP", vk_code, 0,0,0)
end
Or sending space " " as char.
Code:
function PostText(hwnd, str) -- https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-char
  for char in string.gmatch(str, ".") do
    local ret = reaper.JS_WindowMessage_Post(hwnd, "WM_CHAR", string.byte(char),0,0,0)
    if not ret then break end
  end
end
Edit: Too slow

Last edited by Edgemeal; 08-06-2022 at 11:03 AM.
Edgemeal is offline   Reply With Quote
Old 08-06-2022, 02:30 PM   #11
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,875
Default

Thanks !!
X-Raym is offline   Reply With Quote
Old 08-07-2022, 05:16 AM   #12
hans
Human being with feelings
 
Join Date: Aug 2020
Posts: 276
Default

This is great. Thanks! Should be on reapack
hans is offline   Reply With Quote
Old 08-06-2023, 01:00 PM   #13
Rumi
Human being with feelings
 
Join Date: Jul 2012
Location: Winterthur, Switzerland
Posts: 61
Default

Quote:
Originally Posted by Edgemeal View Post
Normally you'd get the handle to the button and then send it a click message. One tricky part with the Dynamic split window is that the "Split" button is not enabled until after the dynamic split window has finished doing its work when opened, so we'd have to wait until the button is enabled or clicking it won't do anything. I didn't see an IsWindowEnabled function in the API so did it by checking the buttons style bits, only tested on Win10,..

NOTE: This Lua script requires the js_ReaScriptAPI extension!

Code:
local WS_DISABLED = 0x08000000 -- https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles

function ClickSplitButton()
  local parent = reaper.JS_Window_FindTop('Dynamic split items',true) 
  if parent then
    local btn = reaper.JS_Window_FindChildByID(parent, 0x1) -- get handle to "Split" button
    if btn then -- check if button is enabled
      local style = reaper.JS_Window_GetLong(btn, "STYLE")
      if style & WS_DISABLED == WS_DISABLED then
        reaper.defer(ClickSplitButton) -- loop & try again.
      else -- send btn a left mouse click msg
        reaper.JS_WindowMessage_Send(btn, "WM_LBUTTONDOWN", 1, 0, 0, 0)
        reaper.JS_WindowMessage_Send(btn, "WM_LBUTTONUP", 0, 0, 0, 0) 
      end 
    end
  end
end

-- open dynamic split items window
reaper.Main_OnCommand(40760, 0) -- Item: Dynamic split items...
-- click the "Split" button.
ClickSplitButton()
Can you also do that for "Threshold" etc.? If so, could you please post an example? I couldn't find a clear documentation. I can decipher code, though. :-)
Rumi is offline   Reply With Quote
Old 08-06-2023, 07:40 PM   #14
Edgemeal
Human being with feelings
 
Edgemeal's Avatar
 
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,913
Default

Quote:
Originally Posted by Rumi View Post
Can you also do that for "Threshold" etc.? If so, could you please post an example? I couldn't find a clear documentation. I can decipher code, though. :-)
You need app like MS SPY++ to get those control IDs, Threshold is 0x3F9. Seems when you change that value it recalculates and split button is disable again, so I try setting it at the top of the script to -6.6. Probably better off just using the built-in Presets.

Code:
local WS_DISABLED = 0x08000000 -- https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles

function ClickSplitButton()
  local parent = reaper.JS_Window_FindTop('Dynamic split items',true) 
  if parent then 
    local thrsh_hwnd = reaper.JS_Window_FindChildByID(parent, 0x3F9) -- get threshold edit window handle
    reaper.JS_Window_SetTitle(thrsh_hwnd, "-6.6") -- set Threshold (string)
    local btn = reaper.JS_Window_FindChildByID(parent, 0x1) -- get handle to "Split" button
    if btn then -- check if button is enabled
      local style = reaper.JS_Window_GetLong(btn, "STYLE")
      if style & WS_DISABLED == WS_DISABLED then
        reaper.defer(ClickSplitButton) -- loop & try again.
      else -- click  Split button
        reaper.JS_WindowMessage_Send(parent, "WM_COMMAND", 0x1, 0, 0, 0)
      end 
    end
  end
end

-- open dynamic split items window
reaper.Main_OnCommand(40760, 0) -- Item: Dynamic split items...
-- set threshold and click the "Split" button.
ClickSplitButton()
Edgemeal is offline   Reply With Quote
Old 08-10-2023, 06:38 AM   #15
Rumi
Human being with feelings
 
Join Date: Jul 2012
Location: Winterthur, Switzerland
Posts: 61
Default

Quote:
Originally Posted by Edgemeal View Post
You need app like MS SPY++ to get those control IDs, Threshold is 0x3F9. Seems when you change that value it recalculates and split button is disable again, so I try setting it at the top of the script to -6.6. Probably better off just using the built-in Presets.

Code:
local WS_DISABLED = 0x08000000 -- https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles

function ClickSplitButton()
  local parent = reaper.JS_Window_FindTop('Dynamic split items',true) 
  if parent then 
    local thrsh_hwnd = reaper.JS_Window_FindChildByID(parent, 0x3F9) -- get threshold edit window handle
    reaper.JS_Window_SetTitle(thrsh_hwnd, "-6.6") -- set Threshold (string)
    local btn = reaper.JS_Window_FindChildByID(parent, 0x1) -- get handle to "Split" button
    if btn then -- check if button is enabled
      local style = reaper.JS_Window_GetLong(btn, "STYLE")
      if style & WS_DISABLED == WS_DISABLED then
        reaper.defer(ClickSplitButton) -- loop & try again.
      else -- click  Split button
        reaper.JS_WindowMessage_Send(parent, "WM_COMMAND", 0x1, 0, 0, 0)
      end 
    end
  end
end

-- open dynamic split items window
reaper.Main_OnCommand(40760, 0) -- Item: Dynamic split items...
-- set threshold and click the "Split" button.
ClickSplitButton()
Hmmm, okay, many thanks!

Yes, it seems to be better to take a different route.
Rumi is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 12:37 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.