问题
I work for a medical transcription company and our medical transcription test we administer to our applicants is an older flash forms app that stops copy and paste by emptying the clipboard when you enter the form. This worked great in IE 7, but recently it has come to my attention that it does not work so well in Firefox. Or perhaps it is the version of flash, since flash should be browser independent. I'm not by any means a flash developer, in fact I'm quite terrible at it. So what I need to know is how to stop the copy and paste using action script.
Based on the comments apparently some additional information is necessary. What the test actually does it plays a voice file (Basic MP3) that they have to transcribe as the listen to it. The copy and paste problem comes in when their transcriptionist buddy has already taken the test and just emails it to their friend so they can skip over it.
回答1:
You might not be able to "disable paste" as such (without hosting the Flash control somehow yourself, say, in a Windows app, or in a browser extension of some sort), but you can certainly make a pretty good guess about the way someone's using the app with a little timer-based math. Here's a (super-)rough example of a Flex app illustrating what I mean:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:local="*" creationComplete="this_creationComplete(event)">
<mx:Script>
<![CDATA[
private var timer:Timer;
import flash.events.Event;
private function this_creationComplete(event:Event):void
{
timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER, timer_tick);
timer.start();
}
private function timer_tick(event:TimerEvent):void
{
var elapsedTimeInMinutes:Number = timer.currentCount / 60;
var averageWordLength:Number = 4;
var humanlyPossible:Number = 200;
var thisPersonsSpeed:Number = (txtTest.text.length / averageWordLength) / elapsedTimeInMinutes;
if (thisPersonsSpeed > humanlyPossible)
{
txtSpeed.text = "Wait, " + Math.floor(thisPersonsSpeed).toString() + " words per minute? This clown is probably cheating.";
txtTest.enabled = false;
timer.stop();
}
else
{
txtSpeed.text = "Currently typing " + Math.floor(thisPersonsSpeed).toString() + " wpm. Hurry up! Faster!";
}
}
]]>
</mx:Script>
<mx:VBox>
<mx:TextArea id="txtTest" width="600" height="300" />
<mx:Text id="txtSpeed" />
</mx:VBox>
</mx:Application>
Essentially, it's just a timer that calculates words per minute; if that number exceeds a certain threshold, the timer stops, and the form disables.
Sure, it's not iron-clad, and if I were implementing it myself, I'd layer in some additional timing-oriented safeguards (e.g., stopping the timer after periods of inactivity, etc.), but it should illustrate the point. I'm sure there are other solutions, but something simple like this may work out well-enough for you.
Update: A couple of folks have mentioned Event.PASTE, which would work, but doesn't exist in ActionScript 2 / Flash Player 9. Provided you were able to ensure Flash Player 10 and could script in ActionScript 3, that'd be another option.
回答2:
I assume since this is a trascription test, you're displaying some source document side by side with a form you want the user to fill in based on said source document. Instead of emptying the clipboard, wouldn't it be easier to prevent them from copying the source document? If the source document is also under the control of your flash object, it should be simple to set it as readonly and unselectable. This has the added benefit of allowing them to copy between form fields, as that may be their normal usage during transcription and allow them to test faster.
Note that no solution like this is ever going to stop someone who is determined and has a little bit of time -- if you're trying to do anything beyond preventing them from cheating on this test, you're getting into DRM territory, which is both very difficult and very futile.
回答3:
Recently Flash updates have made it tougher to access the clipboard. As a general rule of thumb, programmatic clipboard accesses will often fail to work when not initiated by the user. So, clipboard-clearing code is more likely to work if you place it inside a button call. This really doesn't help you, but it does tell you what is wrong, and why the the thing you are trying to fix cannot be fixed. I'd suggest making use of rmeador's suggestion.
If that is not practical, take a screenshot of the text and use a graphic for the text. Someone stubborn could still copy and paste with a bit of effort, but this is a rather simple way to stop it from being done casually without using a flash form.
Internally to flash, you might want to look into a paste event handler.
回答4:
Couldn't you register an event handle to capture the past event on the textfield?
function onPasteMessage(event:Event){ ... }
...
myTextField.addEventListener(Event.PASTE, onPasteMessage)
onPasteMessage could either be a simple alert to the user that past is not allowed or something that undoes the paste action depending on when the event is fired and when/how the textfield is modified. Chances are if you capture the event at this level you'll prevent the default eventHandler from copying the text from the clipboard to the textfield.
回答5:
In the absence of event.paste in earlier versions of flash you could probably set up something like an onKeyUp listener that checked for pressing the V key with the control/command key pressed. I guess it would go something like:
var listening_object = new Object();
Key.addListener(listening_object);
listening_object.onKeyUp(){
if ( Key.getCode() == whatevercodeforVis && Key.isDown(Key.CONTROL)){
freakout();
}
}
Where freakout() did something like clear out the text field or pop up a warning dialog. It wouldn't help for right-click pasting, but you might be able to disable the context menu - you can for most parts of flash but whether it works in text-fields I am uncertain.
Is it completely out of scope to prepare a number of slightly different readings that get randomised at runtime to catch out people who might be inclined to cheat?
回答6:
package {
import flash.desktop.Clipboard;
import flash.desktop.ClipboardFormats;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.ui.ContextMenu;
public class PasteExample extends MovieClip {
public function PasteExample():void {
//make a movie
var pasteTarget:Sprite = addChild(new Sprite()) as Sprite;
pasteTarget.graphics.beginFill(0);
pasteTarget.graphics.drawRect(0, 0, 100, 100);
pasteTarget.endFill();
var contextMenu:ContextMenu = new ContextMenu();
contextMenu.clipboardMenu = true;
contextMenu.clipboardItems.paste = true;
pasteTarget.contextMenu = contextMenu;
pasteTarget.addEventListener(Event.PASTE,pasteHandler)
}
private function pasteHandler(e:Event):void {
var clipboadStr:String = Clipboard.generalClipboard.getData(ClipboardFormats.TEXT_FORMAT) as String;
trace(clipboadStr)
}
}
来源:https://stackoverflow.com/questions/485072/how-do-you-stop-copy-paste-in-a-flash-form