PureBasic Forum
https://www.purebasic.fr/english/

record keystrokes and playback
https://www.purebasic.fr/english/viewtopic.php?f=5&t=73296
Page 1 of 1

Author:  IdeasVacuum [ Mon Jul 29, 2019 9:59 pm ]
Post subject:  record keystrokes and playback

My program uses an Editor Gadget for the User to prepare/modify text.

I would like to add a macro function where the User can record keystrokes and then play them back to 'auto edit' multiple lines. Has anyone already coded something like this?

Author:  Joris [ Tue Jul 30, 2019 9:08 am ]
Post subject:  Re: record keystrokes and playback

I've got this sample code (don't know the origin ... me, don't think so ???) :)
Might be a start.
Code:
Structure L4B
  StructureUnion
    l.l
    b.b[4]
  EndStructureUnion
EndStructure
Global key$= Space(255)
Global chk_ctrl.l,chk_shft.l,chk_alt.l
Procedure WindowCallback(hWnd, uMsg, wParam, lParam)   
  Select uMsg
    Case #WM_CHAR
      k.L4B : k\l=lParam
     
      SetGadgetText(1, Str(lParam))
      SetGadgetText(2, Str(k\b[0])+"   "+Str(k\b[1])+"   "+Str(k\b[2])+"   "+Str(k\b[3]))
      GetKeyNameText_(lParam, key$,255)
      SetGadgetText(3,key$)
      SetGadgetText(4,"WM_CHAR")
      SetGadgetText(5,Str(wParam))
    Case #WM_KEYDOWN
      k.L4B : k\l=lParam
     
      SetGadgetText(1, Str(lParam))
      SetGadgetText(2, Str(k\b[0])+"   "+Str(k\b[1])+"   "+Str(k\b[2])+"   "+Str(k\b[3]))
      GetKeyNameText_(lParam, key$,255)
      SetGadgetText(3,key$)
      SetGadgetText(4,"WM_KEYDOWN")
      SetGadgetText(5,Str(wParam))
     
      Select wParam
        Case #VK_CONTROL : SetGadgetState(chk_ctrl, #PB_Checkbox_Checked)   
        Case #VK_SHIFT   : SetGadgetState(chk_shft, #PB_Checkbox_Checked)
      EndSelect
     
    Case #WM_KEYUP ;hier opslaan van de ingevoerde toetsen
      k.L4B : k\l=lParam
     
      SetGadgetText(1, Str(lParam))
      SetGadgetText(2, Str(k\b[0])+"   "+Str(k\b[1])+"   "+Str(k\b[2])+"   "+Str(k\b[3]))
      GetKeyNameText_(lParam, key$,255)
      SetGadgetText(3,key$)
      SetGadgetText(4,"WM_KEYUP")
      SetGadgetText(5,Str(wParam))
     
      locale = GetKeyboardLayout_(GetCurrentThreadId_()) 
      ctrl$ = Space(100) 
      GetKeyNameText_(MapVirtualKeyEx_(k\l,1,locale), @ctrl$,  100) 
      SetWindowTitle(0,ctrl$)
     
      SetGadgetState(chk_ctrl, #PB_Checkbox_Unchecked)   
      SetGadgetState(chk_shft, #PB_Checkbox_Unchecked)
      SetGadgetState(chk_alt , #PB_Checkbox_Unchecked)
    Case  #WM_DEADCHAR
      k.L4B : k\l=lParam
     
      SetGadgetText(1, Str(lParam))
      SetGadgetText(2, Str(k\b[0])+"   "+Str(k\b[1])+"   "+Str(k\b[2])+"   "+Str(k\b[3]))
      GetKeyNameText_(lParam, key$,255)
      SetGadgetText(3,key$)
      SetGadgetText(4,"WM_DEADCHAR")
      SetGadgetText(5,Str(wParam))
    Case  #WM_SYSCHAR  ;hier opslaan van de ingevoerde toetsen
      k.L4B : k\l=lParam
     
      SetGadgetText(1, Str(lParam))
      SetGadgetText(2, Str(k\b[0])+"   "+Str(k\b[1])+"   "+Str(k\b[2])+"   "+Str(k\b[3]))
      GetKeyNameText_(lParam, key$,255)
      SetGadgetText(3,key$)
      SetGadgetText(4,"WM_SYSCHAR")
      SetGadgetText(5,Str(wParam))
      ;indien vooraf een WM_SYSKEYDOWN gebruikt werd (bvb. Alt)
      SetGadgetState(chk_ctrl, #PB_Checkbox_Unchecked)   
      SetGadgetState(chk_shft, #PB_Checkbox_Unchecked)
      SetGadgetState(chk_alt , #PB_Checkbox_Unchecked)
     
    Case  #WM_SYSKEYDOWN
      k.L4B : k\l=lParam
     
      SetGadgetText(1, Str(lParam))
      SetGadgetText(2, Str(k\b[0])+"   "+Str(k\b[1])+"   "+Str(k\b[2])+"   "+Str(k\b[3]))
      GetKeyNameText_(lParam, key$,255)
      SetGadgetText(3,key$)
      SetGadgetText(4,"WM_SYSKEYDOWN")
      SetGadgetText(5,Str(wParam))
      Select wParam
        Case #VK_CONTROL : SetGadgetState(chk_ctrl, #PB_Checkbox_Checked)   
        Case #VK_SHIFT   : SetGadgetState(chk_shft, #PB_Checkbox_Checked)
        Case #VK_MENU    : SetGadgetState(chk_alt,  #PB_Checkbox_Checked)
      EndSelect
     
  EndSelect
 
  ProcedureReturn #PB_ProcessPureBasicEvents
 
EndProcedure


OpenWindow(0,0,0,320,240,"Hotkey Test",#PB_Window_SystemMenu | #PB_Window_ScreenCentered |#PB_Window_MinimizeGadget)
chk_ctrl = CheckBoxGadget(#PB_Any,   5, 5, 40,  17,"Ctrl")
chk_shft = CheckBoxGadget(#PB_Any,  50, 5, 40,  17,"Shft")
chk_alt  = CheckBoxGadget(#PB_Any, 105, 5, 40,  17,"Alt")
TextGadget(1, 100,040,140,20, "")
TextGadget(2, 100,060,140,20, "")
TextGadget(3, 100,080,140,20,"")
TextGadget(4, 100,100,140,20,"")
TextGadget(5, 100,120,140,20,"")
SetWindowCallback(@WindowCallback())

Repeat
 
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      CloseWindow(0)
      End
  EndSelect
 
ForEver

Author:  IdeasVacuum [ Tue Jul 30, 2019 12:07 pm ]
Post subject:  Re: record keystrokes and playback

Hi Joris

I was stuck in a traffic jam this morning thinking about SendKeys etc, but not sure of the best way to record keystrokes - your sample code is exactly what I need to get my brain functioning again :mrgreen:

Author:  BarryG [ Tue Jul 30, 2019 12:40 pm ]
Post subject:  Re: record keystrokes and playback

Note that it only works if your app has the focus - it's not global. And it doesn't detect Alt+<Whatever> for me?

Author:  IdeasVacuum [ Thu Aug 01, 2019 1:26 pm ]
Post subject:  Re: record keystrokes and playback

OK, it works perfectly for the App Window that has focus, that's good for me, but unfortunately it does not work with an Editor Gadget on that Window :(

So, back to square 1 !

Author:  Sirius-2337 [ Thu Aug 01, 2019 1:48 pm ]
Post subject:  Re: record keystrokes and playback

Added code from this topic.
Code:
Structure L4B
  StructureUnion
    l.l
    b.b[4]
  EndStructureUnion
EndStructure
Global key$= Space(255)
Global chk_ctrl.l,chk_shft.l,chk_alt.l
Procedure WindowCallback(hWnd, uMsg, wParam, lParam)   
  Select uMsg
    Case #WM_CHAR
      k.L4B : k\l=lParam
     
      SetGadgetText(1, Str(lParam))
      SetGadgetText(2, Str(k\b[0])+"   "+Str(k\b[1])+"   "+Str(k\b[2])+"   "+Str(k\b[3]))
      GetKeyNameText_(lParam, key$,255)
      SetGadgetText(3,key$)
      SetGadgetText(4,"WM_CHAR")
      SetGadgetText(5,Str(wParam))
    Case #WM_KEYDOWN
      k.L4B : k\l=lParam
     
      SetGadgetText(1, Str(lParam))
      SetGadgetText(2, Str(k\b[0])+"   "+Str(k\b[1])+"   "+Str(k\b[2])+"   "+Str(k\b[3]))
      GetKeyNameText_(lParam, key$,255)
      SetGadgetText(3,key$)
      SetGadgetText(4,"WM_KEYDOWN")
      SetGadgetText(5,Str(wParam))
     
      Select wParam
        Case #VK_CONTROL : SetGadgetState(chk_ctrl, #PB_Checkbox_Checked)   
        Case #VK_SHIFT   : SetGadgetState(chk_shft, #PB_Checkbox_Checked)
      EndSelect
     
    Case #WM_KEYUP ;hier opslaan van de ingevoerde toetsen
      k.L4B : k\l=lParam
     
      SetGadgetText(1, Str(lParam))
      SetGadgetText(2, Str(k\b[0])+"   "+Str(k\b[1])+"   "+Str(k\b[2])+"   "+Str(k\b[3]))
      GetKeyNameText_(lParam, key$,255)
      SetGadgetText(3,key$)
      SetGadgetText(4,"WM_KEYUP")
      SetGadgetText(5,Str(wParam))
     
      locale = GetKeyboardLayout_(GetCurrentThreadId_())
      ctrl$ = Space(100)
      GetKeyNameText_(MapVirtualKeyEx_(k\l,1,locale), @ctrl$,  100)
      SetWindowTitle(0,ctrl$)
     
      SetGadgetState(chk_ctrl, #PB_Checkbox_Unchecked)   
      SetGadgetState(chk_shft, #PB_Checkbox_Unchecked)
      SetGadgetState(chk_alt , #PB_Checkbox_Unchecked)
    Case  #WM_DEADCHAR
      k.L4B : k\l=lParam
     
      SetGadgetText(1, Str(lParam))
      SetGadgetText(2, Str(k\b[0])+"   "+Str(k\b[1])+"   "+Str(k\b[2])+"   "+Str(k\b[3]))
      GetKeyNameText_(lParam, key$,255)
      SetGadgetText(3,key$)
      SetGadgetText(4,"WM_DEADCHAR")
      SetGadgetText(5,Str(wParam))
    Case  #WM_SYSCHAR  ;hier opslaan van de ingevoerde toetsen
      k.L4B : k\l=lParam
     
      SetGadgetText(1, Str(lParam))
      SetGadgetText(2, Str(k\b[0])+"   "+Str(k\b[1])+"   "+Str(k\b[2])+"   "+Str(k\b[3]))
      GetKeyNameText_(lParam, key$,255)
      SetGadgetText(3,key$)
      SetGadgetText(4,"WM_SYSCHAR")
      SetGadgetText(5,Str(wParam))
      ;indien vooraf een WM_SYSKEYDOWN gebruikt werd (bvb. Alt)
      SetGadgetState(chk_ctrl, #PB_Checkbox_Unchecked)   
      SetGadgetState(chk_shft, #PB_Checkbox_Unchecked)
      SetGadgetState(chk_alt , #PB_Checkbox_Unchecked)
     
    Case  #WM_SYSKEYDOWN
      k.L4B : k\l=lParam
     
      SetGadgetText(1, Str(lParam))
      SetGadgetText(2, Str(k\b[0])+"   "+Str(k\b[1])+"   "+Str(k\b[2])+"   "+Str(k\b[3]))
      GetKeyNameText_(lParam, key$,255)
      SetGadgetText(3,key$)
      SetGadgetText(4,"WM_SYSKEYDOWN")
      SetGadgetText(5,Str(wParam))
      Select wParam
        Case #VK_CONTROL : SetGadgetState(chk_ctrl, #PB_Checkbox_Checked)   
        Case #VK_SHIFT   : SetGadgetState(chk_shft, #PB_Checkbox_Checked)
        Case #VK_MENU    : SetGadgetState(chk_alt,  #PB_Checkbox_Checked)
      EndSelect
     
  EndSelect
 
  ProcedureReturn #PB_ProcessPureBasicEvents
 
EndProcedure

Global Gadget
Procedure GadgetCallback(hWnd, uMsg, wParam, lParam)
  WindowCallback(hWnd, uMsg, wParam, lParam)
  ProcedureReturn CallWindowProc_(Gadget, hWnd, uMsg, wParam, lParam)
EndProcedure


OpenWindow(0,0,0,720,240,"Hotkey Test",#PB_Window_SystemMenu | #PB_Window_ScreenCentered |#PB_Window_MinimizeGadget)
chk_ctrl = CheckBoxGadget(#PB_Any,   5, 5, 40,  17,"Ctrl")
chk_shft = CheckBoxGadget(#PB_Any,  50, 5, 40,  17,"Shft")
chk_alt  = CheckBoxGadget(#PB_Any, 105, 5, 40,  17,"Alt")
TextGadget(1, 100,040,140,20, "")
TextGadget(2, 100,060,140,20, "")
TextGadget(3, 100,080,140,20,"")
TextGadget(4, 100,100,140,20,"")
TextGadget(5, 100,120,140,20,"")

EditorGadget(6, 400, 0, 400, 400)

Gadget = SetWindowLong_(GadgetID(6), #GWL_WNDPROC, @GadgetCallback())

; SetWindowCallback(@WindowCallback())

Repeat
 
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      CloseWindow(0)
      End
  EndSelect
 
ForEver

Author:  IdeasVacuum [ Thu Aug 01, 2019 3:49 pm ]
Post subject:  Re: record keystrokes and playback

Thanks Sirius-2337, I would never have worked that one out!

Author:  Tenaja [ Sat Aug 03, 2019 2:57 am ]
Post subject:  Re: record keystrokes and playback

I know I'm late to this party, but scintilla gadget has macro recording and playback built in...

Author:  IdeasVacuum [ Sun Aug 04, 2019 4:25 pm ]
Post subject:  Re: record keystrokes and playback

Hi Tenaga

Yeah, I think Scintilla would be good in that area, a number of text editors out in the wild are using it, but my Project is bespoke and has text manipulation that probably wouldn't be useful to many people outside of a tiny industry :) To change over to Scintilla would I think make some of the stuff difficult to achieve.

Author:  skywalk [ Sun Aug 04, 2019 4:53 pm ]
Post subject:  Re: record keystrokes and playback

Yes, I find I am migrating many of my editors that do not need embedded graphics to Scintilla.
Tired of patching the rich edit gadget...
Many useful features are built-in to Scintilla and it is cross platform.

Author:  Tenaja [ Sun Aug 04, 2019 5:59 pm ]
Post subject:  Re: record keystrokes and playback

The more capabilities a library has, the bigger the learning curve. Once you do a little work with scintilla, though, it becomes second nature. A few years ago I even embedded it into a vb app (work choice) because it only took a few minutes to prototype in PB.

Page 1 of 1 All times are UTC + 1 hour
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/