ACTIVEX.EXEで独自イベントを発生させ、標準EXEでイベント処理するには?

解決


sho  2005-08-27 02:52:54  No: 124528

ACTIVEX.EXEでのプロジェクトと標準EXEのプロジェクトを作成し、
標準EXEは「参照設定」で作成したACTIVEX.EXEを設定しました。
実行したところ、標準EXEプロジェクトから、ACTIVEXプロジェクト内のメソッドを呼び出し結果を得ることができましたが、ACTIVEXプロジェクト内にてRaiseEventでイベントを発生させても標準EXEプロジェクト内にてイベント発生を認識しません。

但しRaiseEventは確実に呼ばれており、VBエディタ上部のイベントボックスには正しくRaiseEventで呼び出すイベントが登録されています。

どなたか解決法ご存じでしたら教えて下さい。
よろしくお願いします。


030  2005-08-27 09:25:54  No: 124529

その現象を再現できる最小限のコードは書けますか?


sho  2005-08-29 19:31:35  No: 124530

書込ありがとうございます。

' 標準EXEプロジェクトのソース
' Formが1つ存在する
' ACTIVEX.EXEのプロジェクト(Prj)を参照設定している
Public WithEvents Test As Prj.ClassTest

Private Sub EvTest(Msg As String)
    Text1.Text = Msg
End Sub

Private Sub Form_Load()
    Set Test = New Prj.ClassTest
End Sub

' ACTIVEX.EXEプロジェクトの記述
' 1つのFormと1つのClassが存在する(Class名:ClassTest)

'ClassTestの記述
Public Event EvTest(Msg As String)

Private Sub Class_Initialize()
    Load Form1
End Sub

Public Sub EvTestON()
    RaiseEvent EvTest("イベント発生!")
End Sub

'Form1の記述
Public WithEvents Test As ClassTest          '通信クラス定義

Private Sub Form_Load()
    Set Test = New ClassTest
End Sub

Private Sub Button1_Click()
    Test.EvTestON
End Sub

にて再現できるかと思います。よろしくお願いします。


id_rsa+  2005-08-29 20:10:26  No: 124531

こんな感じです。。
Private WithEvents Test As Prj.ClassTest
Private Sub Form_Load()
    Set Test = New Prj.ClassTest
End Sub
Private Sub Test_EvTest(Msg As String)
    Text1.Text = Msg
End Sub

Public Event EvTest(Msg As String)
Private Sub Class_Initialize()
    Form1.DoOpen Me
End Sub
Public Sub EvTestON()
    RaiseEvent EvTest("イベント発生!")
End Sub

Private Test As ClassTest
Public Sub DoOpen(Cls As ClassTest)
    Set Test = Cls
    Me.Show
End Sub
Private Sub Button1_Click()
    Test.EvTestON
End Sub


id_rsa+  2005-08-29 20:19:24  No: 124532

ちなみに、イベントが発生しなかった理由は、
ACTIVEX.EXEの内でクラスのインスタンスを作ってたから。
Set Test = New ClassTestって書いちゃったから、インスタンスが2つできちゃったっぽいね。


魔界の仮面弁士  2005-08-29 20:46:13  No: 124533

一応、VB6という前提で回答しますね。

-----------------
(1) 標準EXE側の問題点。

> Public WithEvents Test As Prj.ClassTest
> Private Sub EvTest(Msg As String)
ではなく、
  Public WithEvents Test As Prj.ClassTest
  Private Sub Test_EvTest(Msg As String)
ですよね?

今回のようにWithEvents宣言した場合、コードウィンドウの左上にある
ドロップダウンリスト(オブジェクト ボックス)に、『Test』という項目が
表示されるはずなので、それを選択後、コードウィンドウの右上にある
ドロップダウンリスト(プロシージャ ボックス)から、『EvTest』を
選択することで、「Sub Test_EvTest」が自動生成されるはずです。

-----------------
(2) ActiveX EXE側の問題点。

> Private Sub Class_Initialize()
>     Load Form1
> End Sub
Form1 を Loadしてはいますが、Showしている部分がありませんよ。
このままでは、ActiveX EXEのフォームが非表示となってしまいます。

> Private Sub Button1_Click()
ん……。VB6標準の
  Command1_Click
という名前ではなく、VB.NETのように
  Button1_Click
という名前にしたのですね?

で、これはボタンのClickイベントだと思いますが、だとすると尚更、
Form1が表示されていなければなりませんよね。ボタンを押す事ができなければ、
いつまでも EvTestONイベントが発生しない事になってしまいますから。

> 'Form1の記述
> Public WithEvents Test As ClassTest          '通信クラス定義
> Private Sub Form_Load()
>     Set Test = New ClassTest
> End Sub
上記で作成している
    『Set Test = New ClassTest』
と、標準EXE側で作成している
    『Set Test = New Prj.ClassTest』
とが、別のインスタンスである事は理解されていますでしょうか?

まず、クラスの設計を整理してみましょう。

今回の場合、通信クラスのインスタンスを共有せねばならないので、
  案1. 標準EXE側でClassTestを生成し、それをActiveX EXE側でも使う。
  案2. ActiveX EXE側でClassTestを生成し、それを標準EXE側でも使う。
のいずれかの設計にする必要があるかと思います。

この場合のActiveX側の実装としては……。

たとえば前者の場合は、外部で生成されたインスタンスをForm1が使えるよう、
ClassTestを受け渡す為のメソッドを用意する、という手法があります。

後者の場合は、ClassTestが外部で誤って生成される事がないよう、クラスの
Instancingプロパティを、作成不可にしておいた方が良いでしょう。その上で、
クラスのインスタンスを標準EXEに返すためのメソッドかプロパティを用意します。

ActiveX EXEからのイベント通知について、具体的な例が欲しい場合には、
VB6ヘルプの下記項目を参照してください。

[Visual Studio 6.0 ドキュメント]
└[Visual Basic ドキュメント]
  └[Visual Basic の使用方法]
    └[コンポーネント ツール ガイド]
      └[ActiveX コンポーネントの作成方法]
        └[ActiveX EXE コンポーネントの作成方法]


sho  2005-08-29 20:58:44  No: 124534

教えて頂いた通り修正すると解決しました!
インスタンスについて十分理解できるよう勉強します。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加