質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.10%

VB.netでexe側で読み取り可能な変数をdll側で作成する方法

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 749

ot2os

score 20

VB.netでコンボボックスの選択状態と押したボタンの内容を記録する簡単なプログラムを作っています。
ただし、ウィンドウのデザインは複数作成する必要があるので、dllファイルの差し替えでウィンドウのデザインを切り替えたり、同一のdll内でも切り替えボタンなどでコンボボックスの選択状態を保持したままウィンドウの切り替えを行う予定です。

そのため、dll側で持っている変数の内容をexe側で処理したいのですが、方法がわかりません。
下記のようなコードを組んでみましたが、exe側では変数の内容は反映されていないようです。

●exe側フォーム

Public Class Form1

    'ウィンドウ読み込み時
    Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
        'リスト読み込み
        Interface_Control_Form1.CtrlCombobox1.Items.Add("test1-1")
        Interface_Control_Form1.CtrlCombobox1.Items.Add("test1-2")
    End Sub


    'ボタン1
    Private Sub Button1_Click() Handles Interface_Control_Form1.CtrlButton1_Click
        Call Main(1)
    End Sub

    'ボタン2
    Private Sub Button2_Click() Handles Interface_Control_Form1.CtrlButton2_Click
        Call Main(2)
    End Sub

    'ボタン3
    Private Sub Button3_Click() Handles Interface_Control_Form1.CtrlButton3_Click
        Call Main(3)
    End Sub

    'メインの処理、押されたボタンから呼び出される
    Sub Main(BTN_num As Integer)
        '選択されたComboboxを検出する
        Dim MainClass As New interface_form.Main_Control
        Debug.Print("exe側:{0}", MainClass.CB1value) '★Combobox1の値を確認(3)
    End Sub

End Class

●dll側Class

Public Class Main_Control
    Public CB1value As Long

    ''変数参照?
    'Public ReadOnly Property Ctrl_CB1value() As Long
    '    Get
    '        Return CB1value
    '    End Get
    'End Property


    'Combobox変更用イベント
    Public Event ChangedConbobox1(ByVal sender As System.Object, ByVal e As System.EventArgs)
    'イベントトリガー
    Public Sub ModConbobox1(ByVal idx As Long)
        CB1value = idx
        RaiseEvent ChangedConbobox1(Me, New EventArgs)
    End Sub

End Class

●dll側ユーザーコントロール

Public Class Interface_Control_Form

    Public ReadOnly Property CtrlCombobox1() As System.Windows.Forms.ComboBox
        Get
            Return ComboBox1
        End Get
    End Property


    'Comboboxの値変更処理
    Dim WithEvents Cur_Control As New Main_Control
    'Dim WithEvents As New Main_Control
    Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
        Debug.Print("dll側イベント発生前:{0}", Cur_Control.CB1value) '★Combobox1の値を確認(1)
        Cur_Control.ModConbobox1(Me.ComboBox1.SelectedIndex)
    End Sub

    '他ウィンドウでComboboxが変更された時の連動
    Private Sub ChangedComboBox() Handles Cur_Control.ChangedConbobox1
        Debug.Print("dll側イベントヒット後:{0}", Cur_Control.CB1value) '★Combobox1の値を確認(2)
        Me.ComboBox1.SelectedIndex = Cur_Control.CB1value
    End Sub


    'ここから下はボタンのイベント処理。今回はあまり関係なし。
    Public Event CtrlButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        RaiseEvent CtrlButton1_Click(sender, e)
    End Sub

    Public Event CtrlButton2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
        RaiseEvent CtrlButton2_Click(sender, e)
    End Sub

    Public Event CtrlButton3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    Private Sub Button3_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button3.Click
        RaiseEvent CtrlButton3_Click(sender, e)
    End Sub


    Public ReadOnly Property CtrlButton1() As System.Windows.Forms.Button
        Get
            Return Button1
        End Get
    End Property

    Public ReadOnly Property CtrlButton2() As System.Windows.Forms.Button
        Get
            Return Button2
        End Get
    End Property

    Public ReadOnly Property CtrlButton3() As System.Windows.Forms.Button
        Get
            Return Button3
        End Get
    End Property

End Class

●イミディエイトウィンドウの内容("test1-2"を選択)

dll側イベント発生前:0
dll側イベントヒット後:1
exe側:0

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kenshirou

    2018/11/22 12:35

    「dll側で持っている変数の内容をexe側で処理したい」とは具体的にどのようなことでしょうか?どの変数をどうしたいのでしょうか?

    キャンセル

  • ot2os

    2018/11/22 13:20

    dllで定義した Main_Control クラス内の CB1value の変数をexe側のコメント「★Combobox1の値を確認(3)」の部分で読み出そうとしています。

    キャンセル

  • ot2os

    2018/12/03 18:04

    後からこの記事を見に来た方のために、要点をまとめます。 元々の質問の問題に関しては、 sugar_yasさん への 2018/11/27 17:56 の返信で記載したコードで解決しています。 今回の原因となっていたインスタンスが分断してしまう問題に関しては、 kenshirouさん への 2018/11/29 14:08 の返信で解決しています。 これでexe側でも正常にイベントを拾えるようになります。

    キャンセル

回答 3

checkベストアンサー

+1

まず整理させてほしいのですが、dll側ユーザーコントロール(Interface_Control_Form)は、exe側フォーム(Form1)上にあるという理解で良いでしょうか?
であれば、exe側フォームの

Dim MainClass As New interface_form.Main_Control

と、dll側ユーザーコントロールの

Dim WithEvents Cur_Control As New Main_Control

は、確かにクラス(変数の型)は同じですが全くの別物(別インスタンス)です。
(例えば、「人」というクラスがあった場合、おそらく私も貴方も「人」クラスのインスタンスとなるわけですが、「私」と「貴方」は全くの別人ですよね。)
当然、別物であればそのメンバ変数の値(「人」クラスなら、例えば性別・年齢・身長・etc...)も違う可能性があるわけです。

具体的なやりたいことが不明のため、dll側Classの必要性は判りかねますが、exe側からdll側ユーザーコントロールのコンボボックスを参照できるような仕組みが必要、ということは理解しました。
しかしながら、exe側からユーザコントロールの型を特定できない(同様のユーザコントロールを複数用意し、場合によってはユーザコントロールを切り替えたい)が、特定のメンバ(例えばコンボボックス)は同じように扱いたい、ということであれば、インタフェースという仕組みを使います。
ただ、インタフェースを使うためには、しっかりとしたオブジェクト指向の知識が必要です。(当然、クラスのインスタンスの概念はしっかり理解する必要があります。)

「VB.NET インタフェース」でググると色々と出てきますが、VB中学校の解説は初級者に分かりやすいのでおススメです。
Visual Basic 中級講座
第2回 ポリモーフィズム
http://rucio.a.la9.jp/main/VBdotNet/Advance/Advance2old.htm

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/29 18:26 編集

    複数の同じようなフォームが開くことはあるんでしょうか?
    もしそのような場合があると、モジュールCtrl_ModuleのCB1valueは各フォームで共通に使えません。
    それならば、以前のMain_Controlクラスのインスタンスをフォーム毎に作成して、そのインスタンスの情報をそのフォーム上に載せたすべてのユーザコントロールに渡した方がより良いのではないかと思います。
    (これならば、同一フォーム上の各ユーザコントロール同士で、共通のパラメータを持つことができます。今までの私の回答は、インタフェースやら何やら等、元々の質問への回答からはズレていたかも知れませんが、これは元々の疑問を解消できることかも知れません。)
    ただし、今回の疑問が解消できても、このままの設計でいいかどうか、という点には疑問が残ります。

    キャンセル

  • 2018/12/03 15:44

    今後仕様が変更になるとどうなるかわかりませんが、今のところは同じユーザーコントロールを複数フォームで利用する予定はありません。

    今までこのようにユーザーコントロールを使用した使い方をしなかったので、今回のようにインスタンスが分断してしまうことはあまり考えずに使っていました。
    本来どのように設計するのが正しい作法なのかよくわからなかったのですが、もう少しインスタンスを意識して考えてみます。

    キャンセル

  • 2018/12/03 18:55

    ほらインスタンスが違うから。

    キャンセル

0

下記のようなコードを組んでみましたが、exe側では変数の内容は反映されていないようです。 

この文章は、
1「exe側で変数に値を設定したが、反映されていない」とも
2「別のところで変数に設定した値が、exe側から参照した場合に設定した値ではない」とも
読み取れますね。

まあ、2の場合として以下の変更で、
Interface_Control_FormクラスのCur_Control(Main_Control クラス)のCB1valueが参照できるのでは?

  • dll側ユーザーコントロール 
    'Comboboxの値変更処理
    Dim WithEvents Cur_Control As New Main_Control

   ↓

    Public Dim WithEvents Cur_Control As New Main_Control
  • exe側フォーム
    'メインの処理、押されたボタンから呼び出される
    Sub Main(BTN_num As Integer)
        '選択されたComboboxを検出する
        Dim MainClass As New interface_form.Main_Control
        Debug.Print("exe側:{0}", MainClass.CB1value) '★Combobox1の値を確認(3)
    End Sub

   ↓

    Sub Main(BTN_num As Integer)
        Debug.Print("exe側:{0}", Interface_Control_Form1.Cur_Control.CB1value)'★Combobox1の値を確認(3)
    End Sub

 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/27 17:56

    説明不足ですみません。
    現状、やりたいことは2です。(今後1が必要になるかもしれませんが、)

    いただいたコードを基に書き直してみましたが、下記のコンパイルエラーが出てしまいます。

    「エラー BC30456 'Cur_Control' は 'Interface_Control_Form1' のメンバーではありません。」

    そして、この時点で気づいたのですが、下記のようにパブリック変数を別のモジュールに移して、そちらを参照するように書き換えると正常にdll側の変数の読み取りができるようになりました。


    Module Ctrl_Module
    Public CB1value As Long
    End Module


    ●dllのユーザーコントロール(Interface_Control_Form) を下記変更

    Me.ComboBox1.SelectedIndex = Cur_Control.CB1value
       ↓
    Me.ComboBox1.SelectedIndex = Ctrl_Module.CB1value

    ●dll側Class(Main_Control) に下記追加

    Public ReadOnly Property Ctrl_CB1value() As Long
    Get
    Return Ctrl_Module.CB1value
    End Get
    End Property

    ●exe側フォーム(Form1) を下記変更

    Debug.Print("exe側:{0}", MainClass.CB1value) '★Combobox1の値を確認(3)
       ↓
    Debug.Print("exe側:{0}", MainClass.Ctrl_CB1value) '★Combobox1の値を確認(3)

    キャンセル

-2

BTN_num が使われていないからでは?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/22 12:05

    今回、BTN_numはまだ使っていないので無視してください。

    キャンセル

  • 2018/11/22 12:11

    では、new して直後に表示しているだけなのでこの結果は当然なのではないですか?

    キャンセル

  • 2018/11/26 11:55

    低評価がつくということは当然ではないと思っているわけですね?
    ではベストアンサーがどうなるかニヤニヤして待ちましょう。
    私のコメントも楽しみにしていてください。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.10%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる