Captura de evento de teclado Cmd-C (o Ctrl-C) desde la aplicación modular Flex en el navegador o AIR
Pregunta
Parece que es imposible capturar el evento de teclado que normalmente se usa para copiar cuando se ejecuta una aplicación Flex en el navegador o como una aplicación AIR, presumiblemente porque el navegador o el sistema operativo lo intercepta primero.
¿Hay alguna manera de decirle al navegador o al sistema operativo que deje pasar el evento?
Por ejemplo, en AdvancedDataGrid configuré el evento keyUp para manejarCaseListKeyUp (evento), que llama a la siguiente función:
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);
}
Cuando lo ejecuto, nunca puedo soltar la tecla "C" mientras presiono la tecla de comando (que aparece como KeyboardEvent.ctrlKey).Obtengo los siguientes resultados de seguimiento:
charCode: 0
char:
keyCode: 17
ctrlKey: false
altKey: false
shiftKey: false
Como puede ver, el único evento que puedo capturar es la liberación de la tecla de comando, la liberación de la tecla "C" mientras se mantiene presionada la tecla de comando ni siquiera se envía.
¿Alguien ha implementado con éxito el manejo estándar del teclado para copiar y pegar?
¿Estoy destinado a usar la tecla "C" sola (como se muestra en el ejemplo de código) o a tener disponible un botón de copia?
¿O necesito crear el oyente manualmente en un nivel superior y pasar el evento a las entrañas de mi aplicación modular?
Solución
Hice una prueba en la que escuché los eventos clave en el escenario y noté que (en mi Mac) podía capturar control-c, control-v, etc.está bien, pero todo lo relacionado con el comando (la tecla ) no se capturó hasta que solté la tecla de comando, y luego ctrlKey era falso (aunque los documentos dicen que ctrlKey debería ser verdadero para la tecla de comando en Mac), y el El código de caracteres era 0.Bastante inútil, en definitiva.
Otros consejos
Otra cosa increíblemente molesta de la que me acabo de dar cuenta es que Ctrl-c no puede ser capturado por event.ctrlKey && event.keyCode = Keyboard.C
(o ...event.charCode == 67
), en su lugar tienes que probar charCode
o keyCode
ser 3
.Tiene sentido para charCode
ya que Ctrl-c es 3
en la tabla ASCII, pero no tiene sentido para keyCode
, que se supone que representa la tecla del teclado, no el carácter escrito.Lo mismo ocurre con todas las demás combinaciones de teclas (porque cada combinación Ctrl tiene un equivalente ASCII).
Editar Encontré un error en el sistema de errores Flex sobre esto: https://bugs.adobe.com/jira/browse/FP-375
Encontré una solución para esto basada en la secuencia de captura.Cuando presionas Cmd+A, por ejemplo, la secuencia es:
- tipo:KEY_DOWN, código de clave 15
- tipo:KEY_UP, código clave 15
- tipo:KEY_DOWN, código clave 65
Entonces, cada vez que baja y luego sube el Código de tecla 15 y la siguiente captura es hacia abajo, puede asumir que el usuario presionó la combinación de teclas.Mi implementación termina así:
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!
}
}
}
Para mí, lo siguiente funciona:
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;
}
}