record keystrokes and playback

Windows specific forum
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

record keystrokes and playback

Post by IdeasVacuum »

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?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Joris
Addict
Addict
Posts: 885
Joined: Fri Oct 16, 2009 10:12 am
Location: BE

Re: record keystrokes and playback

Post by Joris »

I've got this sample code (don't know the origin ... me, don't think so ???) :)
Might be a start.

Code: Select all

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
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: record keystrokes and playback

Post by IdeasVacuum »

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:
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: record keystrokes and playback

Post by BarryG »

Note that it only works if your app has the focus - it's not global. And it doesn't detect Alt+<Whatever> for me?
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: record keystrokes and playback

Post by IdeasVacuum »

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 !
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Sirius-2337
User
User
Posts: 53
Joined: Sat May 14, 2011 10:39 am

Re: record keystrokes and playback

Post by Sirius-2337 »

Added code from this topic.

Code: Select all

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
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: record keystrokes and playback

Post by IdeasVacuum »

Thanks Sirius-2337, I would never have worked that one out!
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Tenaja
Addict
Addict
Posts: 1948
Joined: Tue Nov 09, 2010 10:15 pm

Re: record keystrokes and playback

Post by Tenaja »

I know I'm late to this party, but scintilla gadget has macro recording and playback built in...
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: record keystrokes and playback

Post by IdeasVacuum »

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.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: record keystrokes and playback

Post by skywalk »

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.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Tenaja
Addict
Addict
Posts: 1948
Joined: Tue Nov 09, 2010 10:15 pm

Re: record keystrokes and playback

Post by Tenaja »

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.
Post Reply