Quickie question: Get key code for a particular character

It should be simple enough, but for some reason it isn’t. Quite simply, I’m trying to get the appropriate key code for a particular letter.

Example:

on clicked theObject
	set i to 1
	set theResult to "{"
	set myInput to the contents of text field "theInput" of window 1
	repeat (length of myInput) times
		set theResult to theResult & (get key code of (character i of myInput)) & " "
		set i to i + 1
	end repeat
	set contents of text field "theOutput" of window 1 to theResult
end clicked

Of course, I get an error. I tried “get key code of (keystroke(character i of myInput))”, thinking it required an event, but that didn’t work either. So, how would I go about getting the key code of a particular character?

Thanks,
-Rob

Do you really want the key code or just the ASCII code for it?

If ASCII:


set tChars to {}
set myInput to "Hello World!"
repeat with aChar in characters of myInput
	set end of tChars to ASCII number of aChar
end repeat
tChars --> {72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33}

I need the actual key code, as in here.

Obviously, I’m making a tiny app to just spit out the appropriate key codes for a string letters for use in the “key code” command. I could, of course, use a very large if-else routine and chug through every single character on the keyboard, but I was hoping I could use the “get key code” statement to achieve the same thing.

Thanks again,
-Rob

'Key code" is an event property, used to describe hardware… not represent actual glyphs, or letters, in a particular character set. Since keyboards and the keys on them can change, it’s not wise to assume that a particular key code ALWAYS represents a certain “letter”.

The best way to evaluate a keyCode, is to catch it from an appropriate object as it’s sent with an event… such as a key down event. To do this from a list of characters derived from a string, aside from focusing a control, sending it events, and recording the resulting key code of each event is not possible using the event class. Instead, you’ll have to manually make up a dictionary of chars and keycodes and access the list to find your matches. In your case, you have a finite list of letters and corresponding key codes, which you should adhere to. It seems to match typical key codes for basic keyboards, but since you’re looking for compatibility with a specific third-party specification, I’d go with their list to be sure. Either way, the process of getting a keycode out of a character is the same, regardless of the source of your key code dictionary. Below is a simple demonstration. I put the code that generates the dictionary of keys/values into a subroutines so you don’t have a huge dictionary declared in the head of your script file. It inserts a “-” in place of keycodes it knows not of. PS… I didn’t feel like typing in all of the keycodes into the list, so it only goes up to ‘e’… you’ll have to add the rest :wink:

on awake from nib theObject --> Connected to the FIle's Owner
	initKeyCodeList()
end awake from nib

on clicked theObject
	if name of theObject is "log" then
		set theInput to content of text field "input" of (window of theObject)
		
		set theKeyCodes to {} --> Output as a list
		--set theKeyCodes to "" --> Output as a string

		repeat with tmpChar in characters of theInput
			set tmpKeyCode to getKeyCodeForChar(tmpChar) --> Output as list
			copy tmpKeyCode to the end of theKeyCodes

			--set tmpKeyCode to tmpKeyCode & "." & getKeyCodeForChar(tmpChar) --> Output as string
		end repeat
		
		log theKeyCodes
	end if
	
end clicked

to getKeyCodeForChar(theChar)
	try
		set theKeyCode to run script "on run(theChar,keyCodeList)
return " & theChar & " of keyCodeList 
end run" with parameters {theChar, keyCodeList}
	on error
		set theKeyCode to "-"
	end try
	
	return theKeyCode
end getKeyCodeForChar

to initKeyCodeList()
	set keyCodeList to {a:"0", b:"11", c:"8", d:"2", e:"14"}
end initKeyCodeList

In a quick search on the interweb, all of the techniques I found that do this sort of thing use this same type of approach.

j

As I feared, I’ll have to make a list of every single character. :stuck_out_tongue: I had hoped there was a quick built-in function for it.

Thanks for the help,
-Rob

Found this the other day.

http://softwares.bajram.com/utilities/

here a small script (far from being perfect, but does it’s job) that gives you the keycode and the character when typing on the keyboard or by entering keycodes or characters in a dialog box (you can easily modify it to generate a keycode list by entering a repeat loop …):

You need a button (connect it to ‘on clicked’ and to ‘on keyboard up’)
and a text view (text view “tv” of scroll view “sv” of window “main”

property listeningToKeyboard : true

on keyboard up theObject event theEvent
	if (listeningToKeyboard) then
		tell window "main"
			tell text view "tv" of scroll view "sv"
				set modifierKeys to ""
				if (control key down of theEvent) then set modifierKeys to modifierKeys & "control+"
				if (option key down of theEvent) then set modifierKeys to modifierKeys & "option+"
				if (shift key down of theEvent) then set modifierKeys to modifierKeys & "shift+"
				set it's contents to it's contents & "Character: \"" & (character of theEvent) & "\"	Key(s): " & modifierKeys & "key code " & (key code of theEvent) & return
			end tell
		end tell
	end if
end keyboard up

on clicked theObject

	set listeningToKeyboard to false
	set input to (display dialog "enter key code or character(s)" default answer "" buttons {"key code", "character", "cancel"})
	
	if button returned of input = "key code" then
		set keyCode to text returned of input as integer
		try
			delay 0.1
			set listeningToKeyboard to true
			call method "MyKeyboardEvent:" of class "postKey" with parameter (keyCode)
		on error
			set listeningToKeyboard to true
		end try
		
	else if button returned of input = "character" then
		try
			delay 0.1
			set listeningToKeyboard to true
			tell application "System Events"
				tell process (my name)
					keystroke (text returned of input)
				end tell
			end tell
		on error
			set listeningToKeyboard to true
		end try
	end if
end clicked

And here the class ‘postKey’ files (for generating virtual keyboard events):


// file: postKey.h:
#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>

@interface postKey : NSObject {}
+(void)MyKeyboardEvent:(int)theKeyCode;
@end

// file: postKey.m:
#import "postKey.h"

@implementation postKey
+(void)MyKeyboardEvent:(int)theKeyCode{
	CGPostKeyboardEvent( 0, theKeyCode, YES);
	CGPostKeyboardEvent( 0, theKeyCode, NO );
}
@end

Thanks for feedback. I just ended up writing a utility that’ll break down a string into a series of “key code” statements. If, for example, you had a whacky case-sensitive registration key (something like: qlX92CDdk-dF#kd@#kaZfk0f2j-dns-LRt) that you needed to send to all the computers via Remote Desktop, you can feed that into the little utility, and it’ll spit out for you:

key code {12, 37}
key code {7} using shift
key code {92, 84}
key code {8, 2} using shift
key code {2, 40, 27, 2}
key code {3, 85} using shift
key code {40, 2}
key code {84, 85} using shift
key code {40, 0}
key code {6} using shift
key code {3, 40, 82, 3, 84, 38, 27, 2, 45, 1, 27}
key code {37, 15} using shift
key code {17}

Then just paste it between a tell “System Events” block, and you’re good to go.

-Rob

And then, upon remembering the keystroke statement, the utility was quickly followed by a resounding slap to the forehead.

-Rob

where’s the advantage/difference of your list of key code comands to:

tell application "System Events"
	keystroke "qlX92........"
end tell

it’s results seem to be identical … (using the keyboard settings your keycodes were made for)

Hence the resounding slap. It was a bunch of needlessly wasted time. :stuck_out_tongue:

[edit]

Okay, correction, it wasn’t a COMPLETE waste of time. I’ll find a use for it if I need to send sensitive things over the network (like admin password) and don’t want people who are hovering about the lab to know what exactly it is I’m sending.

-Rob