从浏览器或 AIR 中的模块化 Flex 应用程序捕获 Cmd-C(或 Ctrl-C)键盘事件
题
在浏览器中运行 Flex 应用程序或作为 AIR 应用程序运行时,似乎不可能捕获通常用于复制的键盘事件,大概是因为浏览器或操作系统首先拦截了它。
有没有办法告诉浏览器或操作系统让事件通过?
例如,在 AdvancedDataGrid 上,我将 keyUp 事件设置为 handleCaseListKeyUp(event),它调用以下函数:
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);
}
运行时,我永远无法在按下命令键(显示为 KeyboardEvent.ctrlKey)的同时释放“C”键。我得到以下跟踪结果:
charCode: 0
char:
keyCode: 17
ctrlKey: false
altKey: false
shiftKey: false
如您所见,我可以捕获的唯一事件是释放命令键,在按住命令键的同时释放“C”键甚至不会发送。
有人成功实现了标准的复制和粘贴键盘处理吗?
我是否注定只能单独使用“C”键(如代码示例所示)或提供复制按钮?
或者我是否需要在更高级别手动创建侦听器并将事件传递到我的模块化应用程序的内部?
解决方案
我做了一个测试,在舞台上监听按键事件,并注意到(在我的 Mac 上)我可以捕获 control-c、control-v 等。很好,但是任何涉及命令(键)的内容都没有被捕获,直到我释放命令键,然后 ctrlKey 为 false(即使文档说 ctrlKey 对于 Mac 上的命令键应该为 true),并且字符代码为 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 系统中发现了一个与此相关的 bug: https://bugs.adobe.com/jira/browse/FP-375
我根据捕获序列找到了一种解决方法。例如,当您按 Cmd+A 时,顺序为:
- 类型:KEY_DOWN,键码 15
- 类型:KEY_UP,键码 15
- 类型:KEY_DOWN,键码 65
因此,每次您向下然后向上输入 keyCode 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;
}
}