Захват события клавиатуры с помощью команды Cmd-C (или Ctrl-C) из приложения modular Flex в браузере или AIR
Вопрос
Похоже, что невозможно зафиксировать событие клавиатуры, обычно используемое для копирования при запуске приложения Flex в браузере или в качестве приложения AIR, предположительно потому, что браузер или операционная система перехватывают его первыми.
Есть ли способ сообщить браузеру или операционной системе пропустить событие?
Например, в AdvancedDataGrid я установил событию keyUp значение handleCaseListKeyUp(событие), которое вызывает следующую функцию:
private function handleCaseListKeyUp(event:KeyboardEvent):void
{
var char:String = String.fromCharCode(event.charCode).toUpperCase();
if (event.ctrlKey && char == "C")
{
trace("Ctrl-C");
copyCasesToClipboard();
return;
}
if (!event.ctrlKey && char == "C")
{
trace("C");
copyCasesToClipboard();
return;
}
// Didn't match event to capture, just drop out.
trace("charCode: " + event.charCode);
trace("char: " + char);
trace("keyCode: " + event.keyCode);
trace("ctrlKey: " + event.ctrlKey);
trace("altKey: " + event.altKey);
trace("shiftKey: " + event.shiftKey);
}
При запуске я никогда не могу отпустить клавишу "C", одновременно нажимая клавишу command (которая отображается как KeyboardEvent.ctrlKey).Я получаю следующие результаты трассировки:
charCode: 0
char:
keyCode: 17
ctrlKey: false
altKey: false
shiftKey: false
Как вы можете видеть, единственное событие, которое я могу зафиксировать, - это отпускание командной клавиши, отпускание клавиши "C" при удержании командной клавиши даже не отправляется.
Кто-нибудь успешно внедрил стандартную обработку копирования и вставки с клавиатуры?
Суждено ли мне просто использовать клавишу "C" самостоятельно (как показано в примере кода) или сделать доступной кнопку копирования?
Или мне нужно создать прослушиватель вручную на более высоком уровне и передать событие в нутро моего модульного приложения?
Решение
Я провел тест, в котором прослушивал ключевые события на сцене и заметил, что (на моем Mac) я могу захватывать control-c, control-v и т.д.просто отлично, но все, что связано с command (клавиша ), не было захвачено, пока я не отпустил клавишу command, и тогда ctrlKey было false (хотя в документах говорится, что ctrlKey должен быть true для командной клавиши на Mac), а код символа был равен 0.Короче говоря, довольно бесполезно.
Другие советы
Еще одна невероятно раздражающая вещь, которую я только что осознал, - это то, что ctrl-c не может быть захвачен event.ctrlKey && event.keyCode = Keyboard.C
(или ...event.charCode == 67
), вместо этого вы должны проверить на charCode
или keyCode
быть 3
.Это в некотором роде имеет смысл для charCode
поскольку ctrl-c является 3
в таблице ASCII, но это не имеет смысла для keyCode
, который должен представлять клавишу на клавиатуре, а не введенный символ.То же самое относится ко всем остальным комбинациям клавиш (поскольку каждая комбинация ctrl имеет эквивалент ASCII).
Редактировать Обнаружена ошибка в системе Flex bug по этому поводу: https://bugs.adobe.com/jira/browse/FP-375
Я нашел одно обходное решение для этого, основанное на последовательности захвата.Например, когда вы нажимаете Cmd + A, последовательность выглядит следующим образом:
- Тип:KEY_DOWN, код ключа 15
- Тип:KEY_UP, код ключа 15
- Тип:KEY_DOWN, код ключа 65
Таким образом, каждый раз, когда вы нажимаете код ключа 15 вниз, а затем вверх и происходит следующий захват, вы можете предположить, что пользователь нажал комбинацию клавиш.Моя реализация заканчивается примерно так:
protected var lastKeys:Array;
this.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyHandler, false, 0, true);
this.stage.addEventListener(KeyboardEvent.KEY_UP, keyHandler, false, 0, true);
private function getCmdKey(ev:KeyboardEvent):Boolean {
this.lastKeys.push(ev);
this.lastKeys = this.lastKeys.splice(Math.max(0, this.lastKeys.length-3), 3);
if (this.lastKeys.length < 3) return false;
if (ev.keyCode != 15 && ev.type == KeyboardEvent.KEY_UP) {
var firstKey:KeyboardEvent = this.lastKeys[0] as KeyboardEvent;
var secondKey:KeyboardEvent = this.lastKeys[1] as KeyboardEvent;
if (firstKey.keyCode == 15 && firstKey.type == KeyboardEvent.KEY_DOWN &&
secondKey.keyCode == 15 && secondKey.type == KeyboardEvent.KEY_UP) {
return true;
}
}
return false;
}
private function keyHandler(ev:KeyboardEvent):void {
var cmdKey:Boolean = this.getCmdKey(ev.clone() as KeyboardEvent);
var ctrlKey:Boolean = ev.ctrlKey || cmdKey;
if (ctrlKey) {
if (ev.keyCode == 65) {
// ctrl + "a"-- select all!
}
}
}
Для меня работает следующее:
private var _ctrlHoldFlag:Boolean = false;
// Do something if CTRL was held down and C was pressed
// Otherwise release the ctrl flag if it was pressed
public function onKey_Up(event:KeyboardEvent):void {
var keycode_c:uint = 67;
if (_ctrlHoldFlag && event.keyCode == keycode_c)
{
//do whatever you need on CTRL-C
}
if (event.ctrlKey)
{
_ctrlHoldFlag = false;
}
}
// Track ctrl key down press
public function onKey_Down(event:KeyboardEvent):void
{
if (event.ctrlKey)
{
_ctrlHoldFlag = true;
}
}