This my first post

Can you please tell, whether a SendKey analog exist in MAC OS?
Any OSX Api function to simulate keybd_event like in Windows?
Is it possible to do it in PureBasic for Mac?
Many thanks!
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
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
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
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
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
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
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
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."
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
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.
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