SendKey ?
Re: SendKey ?
Last edited by WilliamL on Thu Feb 16, 2012 8:50 pm, edited 1 time in total.
MacBook Pro-M1 (2021), Sonoma 14.4.1, PB 6.10LTS M1
Re: SendKey ?
At first: welcome to the PureBasic Forum, Eidos...
What do you want to achieve?
If you want to simulate a key press into a StringGadget this can be
done very easily and cross-platform:
If you want to simulate a key press by generating an internal event,
things are becoming more complicated:
If you want to know how to detect the pressing of keys (and clicks onto
different mouse buttons) in a window (not as input into a StringGadget)
and display these actions in a TextGadget, then you might take a look
into this thread.
What do you want to achieve?
If you want to simulate a key press into a StringGadget this can be
done very easily and cross-platform:
Code: Select all
EnableExplicit
OpenWindow(0, 270, 100, 270, 70, "Simulate key press", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
StringGadget(0, 10, 10, WindowWidth(0) - 20, 20, "")
ButtonGadget(1, 30, 40, WindowWidth(0) - 60, 20, "Simulate pressing of <K> key")
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
If EventGadget() = 1
If EventType() = #PB_EventType_LeftClick
SetGadgetText(0, GetGadgetText(0) + "K")
EndIf
EndIf
EndSelect
ForEver
things are becoming more complicated:
Code: Select all
EnableExplicit
ImportC ""
CreateEvent(MemoryAllocatorRef.L, EventClass.L, EventKind.L, EventTime.D, EventAttributes.L, *EventRef)
SendEventToEventTargetWithOptions(EventRef.L, EventTargetRef.L, OptionBits.L)
EndImport
#kEventAttributeNone = 0
#kEventClassControl = 'cntl'
#kEventParamTextInputSendKeyboardEvent = 'tske'
Structure EventTypeSpec
EventClass.L
EventKind.L
EndStructure
ProcedureC ControlHandler(*NextEventHandler, EventRef.L, UserData.L)
Protected Result.L
If GetEventKind_(EventRef) = #kEventParamTextInputSendKeyboardEvent
SetGadgetText(0, GetGadgetText(0) + "K")
EndIf
EndProcedure
Dim EventTypes.EventTypeSpec(0)
Define EventRef.L
Define Result.L
OpenWindow(0, 270, 100, 270, 70, "Simulate key press", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
StringGadget(0, 10, 10, WindowWidth(0) - 20, 20, "")
ButtonGadget(1, 30, 40, WindowWidth(0) - 60, 20, "Simulate pressing of <K> key")
EventTypes(0)\EventClass = #kEventClassControl
EventTypes(0)\EventKind = #kEventParamTextInputSendKeyboardEvent
InstallEventHandler_(GetControlEventTarget_(GadgetID(0)), @ControlHandler(), 1, @EventTypes(), 0, 0)
If CreateEvent(0, #kEventClassControl, #kEventParamTextInputSendKeyboardEvent, 0, #kEventAttributeNone, @EventRef)
Debug "CreateEvent() failed!"
End
EndIf
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
If EventGadget() = 1
If EventType() = #PB_EventType_LeftClick
SendEventToEventTarget_(EventRef, GetControlEventTarget_(GadgetID(0)))
EndIf
EndIf
EndSelect
ForEver
different mouse buttons) in a window (not as input into a StringGadget)
and display these actions in a TextGadget, then you might take a look
into this thread.
Re: SendKey ?
Thank you for reply!
Actually, I'm writing a simple plugin for QuarkXpress and want to send key/word to edit window of QXP.
I've tried apple script, but that works too slowly and sometimes hanging the whole Qxp.
The solution was to make a simple application that stays on top and sending keystrokes to Quark on demand (pressing button)
The text is compiling inside the plugin and copied into the clipboard. Then switching to Qxp and simulating the APPLE + V (paste) operation. All wanted to do, is to simulate the Apple+V command.
here is the code where I'm trying to achieve this:
I hope that your second solution will fit my requirements.
Many thanks!
Actually, I'm writing a simple plugin for QuarkXpress and want to send key/word to edit window of QXP.
I've tried apple script, but that works too slowly and sometimes hanging the whole Qxp.
The solution was to make a simple application that stays on top and sending keystrokes to Quark on demand (pressing button)
The text is compiling inside the plugin and copied into the clipboard. Then switching to Qxp and simulating the APPLE + V (paste) operation. All wanted to do, is to simulate the Apple+V command.
here is the code where I'm trying to achieve this:
Code: Select all
Repeat
evt = WaitWindowEvent()
Select evt
Case #PB_Event_CloseWindow
quit = 1
Case #PB_Event_Gadget
eg = EventGadget()
If eg >=0 And eg <=11
SetClipboardText (GetGadgetText(eg)) ; put text into clipboard ...
DisableWindow (0, 1) ; remove sticky option for dialog
; <<---- Here, simulate Apple+V keystroke
DisableWindow (0, 0) ; back sticky option
EndIf
EndSelect
Until quit = 1
Many thanks!
Re: SendKey ?
Well, how about that!?
Anyway, we got two routines from shardik for sending and getting keystrokes.
Thanks again shardik!
Anyway, we got two routines from shardik for sending and getting keystrokes.
Thanks again shardik!
MacBook Pro-M1 (2021), Sonoma 14.4.1, PB 6.10LTS M1
Re: SendKey ?
Eidos,
thank you for the description of your intended project. Unfortunately I
have no QuarkXpress to code a customized solution, but I have tried to
find a similar solution which starts TextEdit and sends keystrokes to be
displayed in TextEdit (or each other application which currently has the
keyboard focus). You have to send the virtual key codes and the modifier
key mask (for example if you have the need to press the Shift key
simultaneously). Perhaps you should modify the SendKey() procedure to
accept a normal ANSI character which will then of course have to be
translated to the corresponding virtual key code. Since you can call
SendKey() multiple times, there is no need to use the clipboard anymore...
thank you for the description of your intended project. Unfortunately I
have no QuarkXpress to code a customized solution, but I have tried to
find a similar solution which starts TextEdit and sends keystrokes to be
displayed in TextEdit (or each other application which currently has the
keyboard focus). You have to send the virtual key codes and the modifier
key mask (for example if you have the need to press the Shift key
simultaneously). Perhaps you should modify the SendKey() procedure to
accept a normal ANSI character which will then of course have to be
translated to the corresponding virtual key code. Since you can call
SendKey() multiple times, there is no need to use the clipboard anymore...
Code: Select all
EnableExplicit
#kCGHIDEventTap= 0
; ----- Virtual keycodes (defined in Events.h)
#kVK_ANSI_E = $0E
#kVK_ANSI_H = $04
#kVK_ANSI_L = $25
#kVK_ANSI_O = $1F
#kVK_Return = $24
; ----- Modifier key masks (defined in IOLLEvent.h)
#kCGEventFlagMaskShift = $020000 ; = NX_SHIFTMASK
#kCGEventFlagMaskControl = $040000 ; = NX_CONTROLMASK
#kCGEventFlagMaskAlternate = $080000 ; = NX_ALTERNATEMASK
#kCGEventFlagMaskCommand = $100000 ; = NX_COMMANDMASK
ImportC ""
CFRelease(CFTypeRef.L)
CGEventCreateKeyboardEvent(CGEventSourceRef.L, CGVirtualKeyCode.U, KeyDown.L)
CGEventPost(CGEventTapLocation.L, CGEventRef.L)
CGEventSetFlags(CGEventRef.L, CGEventFlags.L)
EndImport
Procedure.L SendKey(VirtualKey.U, ModifierKey.L = 0)
Protected KeyEvent.L
KeyEvent = CGEventCreateKeyboardEvent(0, VirtualKey, #True)
If KeyEvent
; ----- Press key
CGEventSetFlags(KeyEvent, ModifierKey)
CGEventPost(#kCGHIDEventTap, KeyEvent)
CFRelease(KeyEvent)
KeyEvent = CGEventCreateKeyboardEvent(0, VirtualKey, #False)
CGEventSetFlags(KeyEvent, ModifierKey)
If KeyEvent
; ----- Release key
CGEventPost(#kCGHIDEventTap, KeyEvent)
CFRelease(KeyEvent)
EndIf
EndIf
ProcedureReturn KeyEvent
EndProcedure
Define Msg.S = "Hello!"
Define ProgramID.L
ProgramID = RunProgram("Open", "/Applications/TextEdit.app", "", #PB_Program_Open)
If ProgramID
; ----- Wait until TextEdit is running (increase delay if necessary)
Delay(100)
; ----- Send Keys to TextEdit
SendKey(#kVK_ANSI_H, #kCGEventFlagMaskShift)
SendKey(#kVK_ANSI_E)
SendKey(#kVK_ANSI_L)
SendKey(#kVK_ANSI_L)
SendKey(#kVK_ANSI_O)
SendKey(#kVK_Return)
CloseProgram(ProgramID)
EndIf
Re: SendKey ?
Hi Shardik,
Many thanks for code! That's really useful piece of code.
I came from Windows world and just started with Mac using PB.
I have faced with strange clipboard behavior in PB before implementing your senkey solution in mac.
It seems that SetClipboardText doesn't work properly on my Mac OSX.
The application can put into clipboard text and then read it back. SetClipboardText and GetClipboatdText works fine within the application, BUT SHOW Clipboard operation inside the FINDER doesn't show anything...
Simple text editor, safari and mac Word are showing my entries via APPLE+V (paste from clipboard).
Also, I've tried to copy the text from PB IDE and paste somewhere else: that worked! even showed up in SHOW Clipboard and QuarkXPress, but no luck when using Set/Get clipboard operations.
Can some try to run simple CLIPBOARD example on Mac OS (use only SetClipboardText) and check whether text visible or not in Show Clipboard window.
That's really strange and makes my development efforts useless....
Here is my mac configuration:
Powermac G4, MacOS X 10.4.9. (8p 135), Darwin 8.9.0
QuarkXpress v6.1 PPC
Many thanks for code! That's really useful piece of code.
I came from Windows world and just started with Mac using PB.
I have faced with strange clipboard behavior in PB before implementing your senkey solution in mac.
It seems that SetClipboardText doesn't work properly on my Mac OSX.
The application can put into clipboard text and then read it back. SetClipboardText and GetClipboatdText works fine within the application, BUT SHOW Clipboard operation inside the FINDER doesn't show anything...
Simple text editor, safari and mac Word are showing my entries via APPLE+V (paste from clipboard).
Also, I've tried to copy the text from PB IDE and paste somewhere else: that worked! even showed up in SHOW Clipboard and QuarkXPress, but no luck when using Set/Get clipboard operations.
Can some try to run simple CLIPBOARD example on Mac OS (use only SetClipboardText) and check whether text visible or not in Show Clipboard window.
That's really strange and makes my development efforts useless....
Here is my mac configuration:
Powermac G4, MacOS X 10.4.9. (8p 135), Darwin 8.9.0
QuarkXpress v6.1 PPC
Re: SendKey ?
Works ok for me. I've been using the clipboard copy/paste in a couple of apps and it has been working for me. When I look in 'Show clipboard', from the finder, it's there... ran example and cmd+V when in TextEdit and it pasted correctly. (only tried the text - canceled the pict load)
Code: Select all
; ------------------------------------------------------------
;
; PureBasic - Clipboard example file
;
; (c) Fantaisie Software
;
; ------------------------------------------------------------
;
; Paste text to the clipboard..
SetClipboardText("PureBasic pasted text example.")
; Display the contents of the clipboard...
MessageRequester("Info", "Text in the clipboard"+#LF$+"'"+GetClipboardText()+"'", 0)
; Now paste an image...
If LoadImage(0, OpenFileRequester("Load a picture","","Bitmap (*.bmp)|*.bmp",0))
If SetClipboardImage(0)
MessageRequester("Info", "Image correctly pasted to the clipboard."+Chr(10)+"Open 'Paint' to test it !", 0)
EndIf
EndIf
MacBook Pro-M1 (2021), Sonoma 14.4.1, PB 6.10LTS M1
Re: SendKey ?
Shardik,
Do you believe this code should still work under Catalina? I'm getting an "invalid memory access." That make sense?
Jonathan
Do you believe this code should still work under Catalina? I'm getting an "invalid memory access." That make sense?
Jonathan
Shardik wrote:Eidos,
thank you for the description of your intended project. Unfortunately I
have no QuarkXpress to code a customized solution, but I have tried to
find a similar solution which starts TextEdit and sends keystrokes to be
displayed in TextEdit (or each other application which currently has the
keyboard focus). You have to send the virtual key codes and the modifier
key mask (for example if you have the need to press the Shift key
simultaneously). Perhaps you should modify the SendKey() procedure to
accept a normal ANSI character which will then of course have to be
translated to the corresponding virtual key code. Since you can call
SendKey() multiple times, there is no need to use the clipboard anymore...Code: Select all
EnableExplicit #kCGHIDEventTap= 0 ; ----- Virtual keycodes (defined in Events.h) #kVK_ANSI_E = $0E #kVK_ANSI_H = $04 #kVK_ANSI_L = $25 #kVK_ANSI_O = $1F #kVK_Return = $24 ; ----- Modifier key masks (defined in IOLLEvent.h) #kCGEventFlagMaskShift = $020000 ; = NX_SHIFTMASK #kCGEventFlagMaskControl = $040000 ; = NX_CONTROLMASK #kCGEventFlagMaskAlternate = $080000 ; = NX_ALTERNATEMASK #kCGEventFlagMaskCommand = $100000 ; = NX_COMMANDMASK ImportC "" CFRelease(CFTypeRef.L) CGEventCreateKeyboardEvent(CGEventSourceRef.L, CGVirtualKeyCode.U, KeyDown.L) CGEventPost(CGEventTapLocation.L, CGEventRef.L) CGEventSetFlags(CGEventRef.L, CGEventFlags.L) EndImport Procedure.L SendKey(VirtualKey.U, ModifierKey.L = 0) Protected KeyEvent.L KeyEvent = CGEventCreateKeyboardEvent(0, VirtualKey, #True) If KeyEvent ; ----- Press key CGEventSetFlags(KeyEvent, ModifierKey) CGEventPost(#kCGHIDEventTap, KeyEvent) CFRelease(KeyEvent) KeyEvent = CGEventCreateKeyboardEvent(0, VirtualKey, #False) CGEventSetFlags(KeyEvent, ModifierKey) If KeyEvent ; ----- Release key CGEventPost(#kCGHIDEventTap, KeyEvent) CFRelease(KeyEvent) EndIf EndIf ProcedureReturn KeyEvent EndProcedure Define Msg.S = "Hello!" Define ProgramID.L ProgramID = RunProgram("Open", "/Applications/TextEdit.app", "", #PB_Program_Open) If ProgramID ; ----- Wait until TextEdit is running (increase delay if necessary) Delay(100) ; ----- Send Keys to TextEdit SendKey(#kVK_ANSI_H, #kCGEventFlagMaskShift) SendKey(#kVK_ANSI_E) SendKey(#kVK_ANSI_L) SendKey(#kVK_ANSI_L) SendKey(#kVK_ANSI_O) SendKey(#kVK_Return) CloseProgram(ProgramID) EndIf
Re: SendKey ?
Code is write for x86.
You mast change the var type long to integer ...
You mast change the var type long to integer ...
Code: Select all
EnableExplicit
#kCGHIDEventTap= 0
; ----- Virtual keycodes (defined in Events.h)
#kVK_ANSI_E = $0E
#kVK_ANSI_H = $04
#kVK_ANSI_L = $25
#kVK_ANSI_O = $1F
#kVK_Return = $24
; ----- Modifier key masks (defined in IOLLEvent.h)
#kCGEventFlagMaskShift = $020000 ; = NX_SHIFTMASK
#kCGEventFlagMaskControl = $040000 ; = NX_CONTROLMASK
#kCGEventFlagMaskAlternate = $080000 ; = NX_ALTERNATEMASK
#kCGEventFlagMaskCommand = $100000 ; = NX_COMMANDMASK
ImportC ""
CFRelease(CFTypeRef.i)
CGEventCreateKeyboardEvent(CGEventSourceRef.i, CGVirtualKeyCode.U, KeyDown.i)
CGEventPost(CGEventTapLocation.i, CGEventRef.i)
CGEventSetFlags(CGEventRef.i, CGEventFlags.i)
EndImport
Procedure.i SendKey(VirtualKey.U, ModifierKey.i = 0)
Protected KeyEvent.i
KeyEvent = CGEventCreateKeyboardEvent(0, VirtualKey, #True)
If KeyEvent
; ----- Press key
CGEventSetFlags(KeyEvent, ModifierKey)
CGEventPost(#kCGHIDEventTap, KeyEvent)
CFRelease(KeyEvent)
KeyEvent = CGEventCreateKeyboardEvent(0, VirtualKey, #False)
CGEventSetFlags(KeyEvent, ModifierKey)
If KeyEvent
; ----- Release key
CGEventPost(#kCGHIDEventTap, KeyEvent)
CFRelease(KeyEvent)
EndIf
EndIf
ProcedureReturn KeyEvent
EndProcedure
Define Msg.S = "Hello!"
Define ProgramID.i
ProgramID = RunProgram("Open", "/Applications/TextEdit.app", "", #PB_Program_Open)
If ProgramID
; ----- Wait until TextEdit is running (increase delay if necessary)
Delay(100)
; ----- Send Keys to TextEdit
SendKey(#kVK_ANSI_H, #kCGEventFlagMaskShift)
SendKey(#kVK_ANSI_E)
SendKey(#kVK_ANSI_L)
SendKey(#kVK_ANSI_L)
SendKey(#kVK_ANSI_O)
SendKey(#kVK_Return)
CloseProgram(ProgramID)
EndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: SendKey ?
Unfortunately my old code from 2012 doesn't work anymore on MacOS Mojave and Catalina. It still works up to High Sierra (for x64 compilation you have to make the changes proposed by mk-soft).jvzuck wrote:Shardik,
Do you believe this code should still work under Catalina? I'm getting an "invalid memory access."
In Catalina it seems not possible anymore to start TextEdit with RunProgram(). But it is still possible to start an application like TextEdit with launchApplication:. Unfortunately launchApplication: is deprecated in Big Sur but still working in Catalina. Therefore I have modified my old example from 2012 to also work in Catalina with PB 5.72 x64:
Code: Select all
EnableExplicit
#kCGHIDEventTap= 0
; ----- Virtual keycodes (defined in Events.h)
#kVK_ANSI_E = $0E
#kVK_ANSI_H = $04
#kVK_ANSI_L = $25
#kVK_ANSI_O = $1F
#kVK_Return = $24
; ----- Modifier key masks (defined in IOLLEvent.h)
#kCGEventFlagMaskShift = $020000 ; = NX_SHIFTMASK
#kCGEventFlagMaskControl = $040000 ; = NX_CONTROLMASK
#kCGEventFlagMaskAlternate = $080000 ; = NX_ALTERNATEMASK
#kCGEventFlagMaskCommand = $100000 ; = NX_COMMANDMASK
ImportC ""
CFRelease(CFTypeRef.I)
CGEventCreateKeyboardEvent(CGEventSourceRef.I, CGVirtualKeyCode.U, KeyDown.L)
CGEventPost(CGEventTapLocation.I, CGEventRef.I)
CGEventSetFlags(CGEventRef.I, CGEventFlags.L)
EndImport
Procedure.L SendKey(VirtualKey.U, ModifierKey.L = 0)
Protected KeyEvent.I
KeyEvent = CGEventCreateKeyboardEvent(0, VirtualKey, #True)
If KeyEvent
; ----- Press key
CGEventSetFlags(KeyEvent, ModifierKey)
CGEventPost(#kCGHIDEventTap, KeyEvent)
CFRelease(KeyEvent)
KeyEvent = CGEventCreateKeyboardEvent(0, VirtualKey, #False)
CGEventSetFlags(KeyEvent, ModifierKey)
If KeyEvent
; ----- Release key
CGEventPost(#kCGHIDEventTap, KeyEvent)
CFRelease(KeyEvent)
EndIf
EndIf
ProcedureReturn KeyEvent
EndProcedure
Define Msg.S = "Hello!"
Define ProgramID.I
If CocoaMessage(0, CocoaMessage(0, 0, "NSWorkspace sharedWorkspace"),
"launchApplication:$", @"TextEdit")
; ----- Wait until TextEdit is running (increase delay if necessary)
Delay(500)
; ----- Send Keys to TextEdit
SendKey(#kVK_ANSI_H, #kCGEventFlagMaskShift)
SendKey(#kVK_ANSI_E)
SendKey(#kVK_ANSI_L)
SendKey(#kVK_ANSI_L)
SendKey(#kVK_ANSI_O)
SendKey(#kVK_Return)
EndIf
Re: SendKey ?
So great! Thanks!
Where are the include files of which you speak: events.h and IOLLEvent.h
Presumably, if I wanted to do Command+Shit, I would just AND them, right?
Jonathan
Where are the include files of which you speak: events.h and IOLLEvent.h
Presumably, if I wanted to do Command+Shit, I would just AND them, right?
Jonathan
Re: SendKey ?
I found the include files online but it's strange I cannot find them on my Mac, having installed XCode and all.
Final question, your code bring the target application to the foreground. Is there a way to send keys to an application in the background. Let's say you're running a Keynote presentation and you want to log into TextEdit the timecodes each time you change slides. Ideally, you wouldn't bring TextEdit to the foreground to do it. That make sense?
Jonathan
Final question, your code bring the target application to the foreground. Is there a way to send keys to an application in the background. Let's say you're running a Keynote presentation and you want to log into TextEdit the timecodes each time you change slides. Ideally, you wouldn't bring TextEdit to the foreground to do it. That make sense?
Jonathan
Re: SendKey ?
jvzuck wrote:Where are the include files of which you speak: events.h and IOLLEvent.h
The Carbon framework (Events.h is a part of it) has been declared deprecated by Apple already for many years. Carbon was officially discontinued and removed entirely with the release of MacOS 10.15 Catalina. Nevertheless you still find the header files in the Xcode app:jvzuck wrote:I found the include files online but it's strange I cannot find them on my Mac, having installed XCode and all.
- Events.h:
/Applications/Xcode.app/Contents/Developer/Platform/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h
- IOLLEvent.h:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/IOKit/hidsystem/IOLLEvent.h
Alternatively you find them on opensource.apple.com
- IOLLEvent.h
and GitHub:
- Events.h
You may combine 2 modifier keys in the second parameter of SendKey() by using the OR operator "|", not the AND operator "&" which would clear each flag! Just tryjvzuck wrote:Presumably, if I wanted to do Command+Shit, I would just AND them, right?
Code: Select all
Debug 1 & 2 ; Displays 0
Debug 1 | 2 ; Displays 3
Re: SendKey ?
Yes, of course. Thanks. My programming skills are VERY rusty!