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

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

新規登録して質問してみよう
ただいま回答率
85.50%
VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

3回答

2730閲覧

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

ot2os

総合スコア23

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2018/11/22 02:33

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

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

●exe側フォーム

lang

1Public Class Form1 2 3 'ウィンドウ読み込み時 4 Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown 5 'リスト読み込み 6 Interface_Control_Form1.CtrlCombobox1.Items.Add("test1-1") 7 Interface_Control_Form1.CtrlCombobox1.Items.Add("test1-2") 8 End Sub 9 10 11 'ボタン1 12 Private Sub Button1_Click() Handles Interface_Control_Form1.CtrlButton1_Click 13 Call Main(1) 14 End Sub 15 16 'ボタン2 17 Private Sub Button2_Click() Handles Interface_Control_Form1.CtrlButton2_Click 18 Call Main(2) 19 End Sub 20 21 'ボタン3 22 Private Sub Button3_Click() Handles Interface_Control_Form1.CtrlButton3_Click 23 Call Main(3) 24 End Sub 25 26 'メインの処理、押されたボタンから呼び出される 27 Sub Main(BTN_num As Integer) 28 '選択されたComboboxを検出する 29 Dim MainClass As New interface_form.Main_Control 30 Debug.Print("exe側:{0}", MainClass.CB1value) '★Combobox1の値を確認(3) 31 End Sub 32 33End Class

●dll側Class

lang

1Public Class Main_Control 2 Public CB1value As Long 3 4 ''変数参照? 5 'Public ReadOnly Property Ctrl_CB1value() As Long 6 ' Get 7 ' Return CB1value 8 ' End Get 9 'End Property 10 11 12 'Combobox変更用イベント 13 Public Event ChangedConbobox1(ByVal sender As System.Object, ByVal e As System.EventArgs) 14 'イベントトリガー 15 Public Sub ModConbobox1(ByVal idx As Long) 16 CB1value = idx 17 RaiseEvent ChangedConbobox1(Me, New EventArgs) 18 End Sub 19 20End Class

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

lang

1Public Class Interface_Control_Form 2 3 Public ReadOnly Property CtrlCombobox1() As System.Windows.Forms.ComboBox 4 Get 5 Return ComboBox1 6 End Get 7 End Property 8 9 10 'Comboboxの値変更処理 11 Dim WithEvents Cur_Control As New Main_Control 12 'Dim WithEvents As New Main_Control 13 Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged 14 Debug.Print("dll側イベント発生前:{0}", Cur_Control.CB1value) '★Combobox1の値を確認(1) 15 Cur_Control.ModConbobox1(Me.ComboBox1.SelectedIndex) 16 End Sub 17 18 '他ウィンドウでComboboxが変更された時の連動 19 Private Sub ChangedComboBox() Handles Cur_Control.ChangedConbobox1 20 Debug.Print("dll側イベントヒット後:{0}", Cur_Control.CB1value) '★Combobox1の値を確認(2) 21 Me.ComboBox1.SelectedIndex = Cur_Control.CB1value 22 End Sub 23 24 25 'ここから下はボタンのイベント処理。今回はあまり関係なし。 26 Public Event CtrlButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 27 Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click 28 RaiseEvent CtrlButton1_Click(sender, e) 29 End Sub 30 31 Public Event CtrlButton2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 32 Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click 33 RaiseEvent CtrlButton2_Click(sender, e) 34 End Sub 35 36 Public Event CtrlButton3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 37 Private Sub Button3_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button3.Click 38 RaiseEvent CtrlButton3_Click(sender, e) 39 End Sub 40 41 42 Public ReadOnly Property CtrlButton1() As System.Windows.Forms.Button 43 Get 44 Return Button1 45 End Get 46 End Property 47 48 Public ReadOnly Property CtrlButton2() As System.Windows.Forms.Button 49 Get 50 Return Button2 51 End Get 52 End Property 53 54 Public ReadOnly Property CtrlButton3() As System.Windows.Forms.Button 55 Get 56 Return Button3 57 End Get 58 End Property 59 60End Class

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

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kenshirou

2018/11/22 03:35

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

2018/11/22 04:20

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

2018/12/03 09:04

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

回答3

0

ベストアンサー

まず整理させてほしいのですが、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/22 06:12

編集2018/11/22 06:14
kenshirou

総合スコア772

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ot2os

2018/11/22 08:56 編集

わかりやすい解説ありがとうございます。 リンクも拝見しました。 なんとなく理解した気になっていたのですが、やはりインスタンスが別になっているからダメなんですね。 その検証のため、Debug.Printでdll内のCB1value値の変化とexe内から見たCB1value値をチェックしていたのですが、dll内(★印の(1)~(2))では変更されたCB1value値は保持されているようですが、exe内(★印の(3))ではCB1value値は0のままです。 > まず整理させてほしいのですが、dll側ユーザーコントロール(Interface_Control_Form)は、exe側フォーム(Form1)上にあるという理解で良いでしょうか? はい、その通りです。 同じForm1上に複数のユーザーコントロールを張り付けて、それぞれVisibleを切り替えてウィンドウデザインを変更する方法を検討しています。 その際、デザインは変わりますが、コンボボックスやボタンの数や役割は同じです。 > 具体的なやりたいことが不明のため、dll側Classの必要性は判りかねますが、exe側からdll側ユーザーコントロールのコンボ > ボックスを参照できるような仕組みを用意することが必要かと思います。 例えばexe側のForm1で下記のようにすれば実際にユーザーコントロールで選択されているコンボボックスの値を読み取ることはできますが、複数のユーザーコントロールを作ったり、ボタンやコンボボックスの数が異なる別のdllを作ったりする可能性を考えると、できるだけexe側でこのような処理はせず、dll内部でCB1valueのような変数を持たせて、その変数をexe側で読み取るほうが良いのではないかと考えました。 Debug.Print("exe側から読み取ったCombobox1:{0}", Interface_Control_Form1.CtrlCombobox1.SelectedIndex)
kenshirou

2018/11/22 13:26

> その際、デザインは変わりますが、コンボボックスやボタンの数や役割は同じです。 これこそが、インタフェースを使用する大きなメリットとなります。 インタフェースを実装するクラスの中身(UIを担うコントロール等についてはデザインも含めて)はそれぞれ全く異なっていても構いません。ただし、インタフェースを実装するクラスには必ずインタフェースに定義したメンバを用意します。これにより、全く異なるクラスであっても定義したメンバを(例えばユーザコントロール1の指定コンボボックスでも、ユーザコントロール2の指定コンボボックスでも)同じように扱うことができます。 とは言え、インタフェースの概念はなかなかうまく説明できません。ゴメンナサイ。 ここは、専門サイトの解説にお任せしたいと思います。
ot2os

2018/11/27 08:50

ありがとうございます。 dll側Classを下記のように変更することで、インターフェイスからChkCB1の戻り値を得ることができるようになりました。 ただ、このインターフェイスを走らせるためにexe側でインスタンス化(Dim MainClass As New interface_form.Main_Control)した時に別インスタンスになるので、結局結果は0になってしまいます。 ただこれ、使い方によっては複数のユーザーコントロールを一括で制御できそうで、もう少し調べてみます。 Public Class Main_Control ↓ Public Class Main_Control : Implements IPlugin Public Interface IPlugin Function ChkCB1() As Long End Interface Public Function ChkCB1() As Long _ Implements IPlugin.ChkCB1 Return CB1value End Function Public CB1value As Long
kenshirou

2018/11/27 09:33 編集

私の理解では、デザインの異なる(ただしコンボボックス・ボタンの機能は同じ)ユーザコントロールが複数あるけれど、フォーム上のこれらユーザコントロールの切り替えを行ったとしても、それを区別なく各ユーザコントロールの変数にアクセスしたい(実際にはユーザコントロール内変数にアクセスするためには、そのユーザコントロールのクラス名を知る必要がある)ということなのですが、この私の理解は合っていますでしょうか? もし違っていたらゴメンナサイ。 また、理解が合っている場合、私であればMain_Controlは使用せず、各ユーザコントロールのクラスにインタフェースを実装します。(例示したいのですが、今は時間がないのでお時間をください。)
ot2os

2018/11/29 00:14

イメージとしては大体そんな感じです。 ただ、ウィンドウのデザインが異なるだけで変数の役割は一緒なので、変数は各ユーザーコントロール内には置いていません。 質問文ではdll側Class(Main_Control)に変数を配置し、各ユーザーコントロールで共通で扱おうとしていました。 新規で作成したモジュールにこれを配置したところうまく行きました。 お手間をとらせてすみません。 どうやればスマートに機能するか、こちらもいろいろ試しています。
kenshirou

2018/11/29 01:07

もう少し質問させてください。 今回の複数のユーザコントロールを使い分けるタイミングとしては、以下のどれに当てはまるでしょうか? ・フォーム表示時(インスタンス化のタイミング)、そのフォームの用途に応じてフォームに適用するユーザコントロールが決まる。 (この用途にはUserControl1をForm1で使う、この用途にはUserControl2をForm1で使う、など) ・フォーム表示時には任意のユーザコントロールを使用しているが、ユーザ操作により、適用しているユーザコントロールの入れ替えが発生する。 (例えば、UserControl1をForm1上に表示しているが、ボタン押下やメニュー選択でこれをUserControl2に切り替える、等) 遠征先のため、私のレスポンスが遅くなるかも知れません。ご了承ください。m(__)m
ot2os

2018/11/29 05:08

まずご質問の内容についてですが「フォーム表示時」です。 私自身、ユーザーコントロールのうまい切り替え方法がわからず、一旦フォームに全部のユーザーコントロールを置いて、用途によってユーザーコントロールのVisbleをTrue/False切り替えています。 かなり力技ですが、一番楽だったのでこうしているだけで、特にこうでないといけないというわけではありません。 そしてインスタンスが別になってしまう問題については下記の通り。 sugar_yasさんへの返信でちょこっと記載したのですが、dll側に適当なモジュールを追加して、そこで変数を持たせることによって今回の掲題の問題は回避できたようです。 そして、kenshirouさんにヒントを頂いたインスタンスが分断する問題も、同様にdll側に下記のようにモジュールを追加することによって解消できました。 ●dll側モジュール Module Ctrl_Module 'Comboboxの値 Public CB1value As Long 'Main_Controlクラス用のインスタンス Public WithEvents Cur_Module_Control As New Main_Control End Module ●dll側Class(Main_Control)に下記を追加 'Main_Control(自分)用に作成されたインスタンスの場所を取得する Public ReadOnly Property Main_Control_instance() As Main_Control Get Return Ctrl_Module.Cur_Module_Control End Get End Property ●dll側ユーザーコントロール(Interface_Control_Form)に下記行を追加 Dim WithEvents Cur_Control As Main_Control = Cur_Module_Control ●exe側に下記を追加 Dim CtrlMainClass As New interface_form.Main_Control WithEvents CtrlMain_instance As interface_form.Main_Control = CtrlMainClass.Main_Control_instance これで、dll側の各ユーザーコントロールは「Cur_Control」で、exe側は「CtrlMain_instance」で同一のMain_Controlクラスのインスタンスを取得できているようです。 さらにMain_Control側でイベントを出すようにした場合も、「CtrlMain_instance」でexe側でイベントを拾えます。
kenshirou

2018/11/29 09:29 編集

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

2018/12/03 06:44

今後仕様が変更になるとどうなるかわかりませんが、今のところは同じユーザーコントロールを複数フォームで利用する予定はありません。 今までこのようにユーザーコントロールを使用した使い方をしなかったので、今回のようにインスタンスが分断してしまうことはあまり考えずに使っていました。 本来どのように設計するのが正しい作法なのかよくわからなかったのですが、もう少しインスタンスを意識して考えてみます。
Zuishin

2018/12/03 09:55

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

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 03:41

sugar_yas

総合スコア135

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ot2os

2018/11/27 08: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)
guest

0

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

投稿2018/11/22 03:01

Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ot2os

2018/11/22 03:05

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

2018/11/22 03:11

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

2018/11/26 02:55

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問