2011-10-27 9 views
0

私は写真をスキャンし、ファイルをクライアントのハードドライブの一時ファイルに保存して写真をアップロードするActiveXコンポーネントを持っています。ActiveXコンポーネントから呼び出されたJSコールバックが、メインコードフローに含まれていないとトリガーしない

私はスキャン部分を行い、スキャンが完了した後、 "ImageScanned"イベントをトリガする "TwainMan"インスタンスを持っています。これは私のメインのコードフローである:それを行う

scanner = new TwainMan(); 
scanner.ImageScanned += new ImageScannedEventHandler(Scanner_ImageScanned); 

コードは、イベントハンドラデリゲートメソッドに置かれている「Scanner_ImageScanned」:

TriggerJSCallback方法で
private void Scanner_ImageScanned(object Sender, ImageScannedEventArgs e) 
{ 
    this.tempFileName = scanner.ToTempFile(e.Image); 
    MessageBox.Show("Scanned picture stored on the following location:\n" + this.tempFileName); 

    Upload(this.tempFileName); // works just fine 

    TriggerJSCallback(); // here is where the problem appears!   
} 

私は私のJSコールバックをトリガ:

private void TriggerJSCallback() 
{ 
    EventHandler DataPreparingFinished = this.DataPreparingFinished; 
    if (null != DataPreparingFinished) { DataPreparingFinished(this.tempFileName); } 
} 

メインフロー内からJSCallback "DataPreparingFinished"をトリガーすると、JSコールバックリスナー(HTMLページで定義されています)はうまく動作しますが、probleトリガ「DataPreparingFinished」が「Scanner_ImageScanned」デリゲート内からトリガされ、メインコードフローからトリガされない場合は、mが表示されます。

私は間違っていますか?誰も助けることができますか?

タグ内のhtmlページ内のJSコールバック定義は次のとおりです。

<script for="AXTwain" event="DataPreparingFinished(args)" language="javascript" type="text/javascript"> 

    function AXTwain::DataPreparingFinished(args) {    
     alert("JS ALERT: SUCCESS!!! JS Callback working properly." + args); 
     // alert("The temp file is stored on: " + AXTwain.TempFileName); 
    } 

</script> 

私はより多くのコードを表示したい場合は、私の問題は、実際に何であるかの良いアイデアを得るでしょうので、多分それは、良いでしょう。

の上から行こう

...

以下は私のActiveXObjectをするinstantiatinとJSコールバック/リスナー関数を含んでいる私のHTMLページです。以下は

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 

    <title>ActiveX TWAIN test page</title> 

    <object id="AXTwain" name="AXTwain" classid="clsid:d8ea830e-38b0-4f3b-8be4-39c417c27583"></object> 

</head> 

<body onload="myload();"> 

    <h1 style="color:green;">AXTwain test page</h1> 

    <script type ="text/javascript"> 

     function myload() { 
      if (AXTwain != null) { 
       AXTwain.AcquireImage(); 
      }   
     } 

    </script> 

    <script for="AXTwain" event="DataPreparingFinished(args)" language="javascript" type="text/javascript"> 

     // The "for" attribute should be set to the name of instance of your COM component. 
     // The "event" attribute should be set to the JavaScript function signature for the event. 
     // The name of the JavaScript function is the instance name of your COM component, followed 
     // by double colons, followed by the JavaScript signature of the event. 

     function AXTwain::DataPreparingFinished(args) {    
      alert("JS ALERT: SUCCESS!!! JS Callback working properly." + args);    
     } 

    </script> 

</body> 
</html> 

あなたはより多くのコードを必要とする場合には

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Runtime.InteropServices; 

namespace AXImageAcquisition 
{ 
    #region ActiveX attributes 
    [ProgId("AXImageAcquisition.AXTwain_01")] 
    [Guid("d8ea830e-38b0-4f3b-8be4-39c417c27583")] 
    [ComVisible(true)] 
    [ClassInterface(ClassInterfaceType.None)] 
    [ComSourceInterfaces(typeof(IComEvents))] 
    #endregion 
    public class AXTwain 
    { 
     #region Class Properties and Settings 

     private TwainMan scanner; 
     private String tempFileName; 
     public String TempFileName 
     { 
      get { return this.tempFileName; } 
     } 

     [ComVisible(false)] 
     public delegate void EventHandler(string args); 
     public event EventHandler DataPreparingFinished; 

     public bool imageScanned = false; 

     #endregion 

     #region Class Constructors 
     public AXTwain() 
     {} 
     #endregion 

     #region Class Methods 

     [ComVisible(true)] 
     public void AcquireImage() 
     { 
      this.DataPreparingFinished += new EventHandler(Delegate_DataPreparingFinished); 

      this.scanner = new TwainMan(); 
      this.scanner.ImageScanned += new ImageScannedEventHandler(Scanner_ImageScanned);    

      TriggerJSCallback(); // HERE IN THE MAIN CODE FLOW THE MESSAGE GETS TO JS!!! 
     } 

     /// <summary> 
     /// Delegate that defines functionality for the ImageScanned event, defined in TwainMan class. 
     /// </summary> 
     /// <param name="Sender"></param> 
     /// <param name="e"></param> 
     public void Scanner_ImageScanned(object Sender, ImageScannedEventArgs e) 
     { 
      this.tempFileName = scanner.ToTempFile(e.Image); 
      Upload(this.tempFileName);    

      TriggerJSCallback(); // HERE (NOT IN THE MAIN CODE FLOW) THE MESSAGE NEVER GETS TO JS!!! WHYYYY? :(
     } 

     /// <summary> 
     /// TODO!!! 
     /// </summary> 
     /// <param name="tempFileName"></param> 
     private void Upload(string tempFileName) 
     { 
      // TODO 
     } 

     /// <summary> 
     /// Test method for the DataPreparingFinished trigger. 
     /// </summary> 
     public void TriggerJSCallback() 
     {   
      EventHandler DataPreparingFinished = this.DataPreparingFinished; 
      if (null != DataPreparingFinished) DataPreparingFinished(this.tempFileName); 
     } 

     /// <summary> 
     /// Delegate that defines functionality for the DataPreparingFinished event, which is defined in IComEvents. 
     /// </summary> 
     /// <param name="msg">Arguments passing from C# to JS.</param> 
     void Delegate_DataPreparingFinished(string msg) 
     { 
      // MessageBox.Show("Delegate_DataPreparingFinished message! (C# code).\n Input message: " + msg); 
     } 

     #endregion 
    } 
} 

...私の私のActiveXラッパークラスで、私も/コードの残りの部分をコピー&ペーストすることができ、それはTwainManクラスであり、それはです依存関係。しかし、すべてはcodeprojectチュートリアルhereから取られています。 Btw、作者のおかげです。

答えて

1

私はC#からActiveXコンポーネントを書きませんが、C++では、メインスレッド以外のスレッドからコールされた場合のようなコールバックが可能です。 ActiveXは、通常、すべての呼び出しがメインスレッド上で発生することを期待しています。ただし、ActiveXで他のスレッドを動作させる方法はありますが、C#ではこれが自動的に実行される可能性があるので、C#では常に正確ではない場合があります。

メインスレッドでこの関数をトリガする方法を見つけることをお勧めします。私はDispatcherTimerを使ってSilverlightでこれを行う方法があることを知っています。おそらくあなたは何か類似したものを見つけることができますとにかく、それは私が試みるものです。

+0

タキソール、お返事ありがとうございました。私が "コードフロー"に言及したとき、私はスレッドを気にしませんでした。だから、「メインコードフロー」と言うと、私はメインスレッドを意味するものではありません。 :)しかし、おそらく私は間違った用語を使用しました。 :) – AlexRebula

+0

あなたはそれを実現せずにC#が別のスレッドを使用していないことは間違いありませんか?とにかく、それは私の唯一のアイデアでしたが、私はFYIとしてそこに投げ捨てると思っていました。DispatcherTimerやそれに類するものがある場合は、それを試してみてください。いずれにせよ、幸運 – taxilian

+0

正直言って私は同じことを考えていたし、後ろに別のスレッドがあるかどうかまだ分かりません。 IMHOはありません、私に利用可能なコードでexplixitスレッドの開始を見ないので、実際には私はいくつかのさらなる研究をしなければならないと確信している...そうすることを見つける方法を見つける。しかし、それでも、別のテストコードでは、私は新しいスレッドからイベントをトリガしようとしましたが、JSコールバックはイベントを正しく捕捉しました。私がする必要があることは、すべてのメッセージをキャッチして、メッセージが実際にトリガされ、どこが失われるかを確認する方法を見つけることです。 – AlexRebula

関連する問題