みなさまこんばんわです。よろしくお願い申し上げます。

VB.NET 2008でコーディングしています。
CloseとDisposeの違いについて教えていただきたいのです。

これらのメソッドは、開いたファイルを閉じるときなどにも使いますが、今回お尋ねするのは、フォームを閉じるとき、しかも、自ら呼び出すとき(Me.Close() と、Me.Dispose() )のみに限ったこととしてお話しさせていただきます。

たとえば、ShowDialog() で呼び出したフォームは、そのフォーム内でMe.Close() しても、プロセスは残り、たとえば、タイマーコントロールのイベントに記述していますと、それは実行され続けます。

これを防ぐために、Me.Dispose() を使います。すると、きれいにプロセスは終了し、イベントは発生しない模様です。

そこで、「フォームを閉じる」意味のMe.Close() をすべてMe.Dispose() に変えてしまいました。確実にプロセスを破棄出来ると思ったからです。Webで調べると、違いは「再利用できる、できないの違い」という答えがありましたが、それはきっと、ファイルやオブジェクトのことで、フォームの場合は、再びShowまたはShowDialogで表示させることは可能でしたので、特に問題は感じていませんでした。

ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。Me.Close() に変えるとうまくいきました。

わけわからなくなってきました。。。

ちなみに、その残ったフォームは、スタートアップフォームであり、別のフォームからShowまたはShowDialogメソッドで呼び出したものではありません。

ここで4つの仮説を立ててみました。

1. ShowDialogで呼び出したフォームは、Me.Dispose()、Showで呼び出した、あるいは、スタートアップフォームは、Me.Close() すれば破棄できる

2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる

3. 呼び出し方ではなく、別の要因が存在する

4. 併記する必要がある場合がある

Me.Close()
Me.Dispose()

または、

Me.Dispose()
Me.Close()



どれが正しいのでしょうか?どなたがご存じの方がいらっしゃいましたら、ご教授いただけませんでしょうか? どうぞよろしくお願い申し上げます。ありがとうございました。

このQ&Aに関連する最新のQ&A

A 回答 (1件)

Me.Close()


Me.Dispose()
は根本的に違うものです。

formについて、Close()メソッドはフォームの表示を終了させるメソッドです。

ほかのクラスも同様。すべてのDispose()メソッドについて、これはインスタンスの破棄を明示的に行うものです。

>再利用できる、できないの違い

Dispose()はインスタンスが破棄されるため、再びコンストラクタを用いて、インスタンスを生成しないいけません。

一方Close()はインスタンスが残っているので、それを利用することができます。

>1. ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。
Me.Close() に変えるとうまくいきました。

通常はどちらでもうまくいきます。

>2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる

ShowDialogの場合は、メソッド内部で、ハンドルが破棄されているため、Close()メソッドの際にDispose()メソッドが呼び出されます。

>3. 呼び出し方ではなく、別の要因が存在する

そう思います。

>4. 併記する必要がある場合がある

インスタンスを明示的に破棄したほうがよい場合は多く存在します。
Disposeが使えるメンバはIDisposableをインターフェースとして持っているメンバです。
これらのメンバは、外部とのやり取りを行うものが多くあります。
たとえばSQLClientに含まれるようなメンバです。

外部とのコネクションを確実に破棄を保障してほしいなどという場合がありますよね、このようなときに使用します。

Using構文を使用するのとまったく同じ理由になります。
正確にはUsing構文を使用できるメンバには条件があります、IDisposableをインターフェースとして持っているメンバに限るというものです。

ほかにもガーベージコレクタによるファイナライズを伴うかどうかという違いがあります。
Disposeの場合はファイナライズが同時に行われるため、使用していたメモリ空間を開放することができます。

上記のような理由により、
Me.Close()
Me.Dispose()
は両方書いたほうがよいと思います。

蛇足ですが、
Me.Dispose()
Me.Close()
はエラーになります。
Me.Dispose()により、Me本体(インスタンス)は削除されてしまいます。
存在しないMeに対してCloseメソッドを要求することはできないためです。
    • good
    • 2
この回答へのお礼

ご回答を賜り、ありがとうございました。そして、お返事が遅くなり、申し訳ございませんでした。

インスタンスの破棄の件につきましては、理解できました。とても勉強になりました。ありがとうございます。

フォームをCloseしたのに、タイマーイベントが実行され続ける意味も分かりました。そのフォームのクラスのインスタンスが残ってたんですね。このようにインスタンスを明示的に破棄する必要がある場合は、おっしゃるとおり、両方併記しなければならない件、よく理解できました。

どうしてもインスタンスを破棄したい場合は、併記をするようにしましたところ、問題は起こっていません。

丁寧なご説明をいただき、ありがとうございました! とても勉強になりました。心より感謝申し上げます。

お礼日時:2009/05/23 03:54

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QAccess2007のフォームウイザードでデータシートを作りたいが方法が分からない

Access2003では、フォームウイザードでデータシートを作れたが。
Access2007では、フォームウイザードでは単票のフォームしか作れない様だ。

どうやって、作るのだろうか。操作が分からない。

Aベストアンサー

どういう帳票が欲しいかわかりませんが一応例として....
まずAccess上部にある作成をクリックします。
フォームウィザードをクリックして使用するテーブルとフィールドを選択します。
次に表形式を選択すれば帳票形式でフォームが作成されます。

もう1つはその他のフォームから複数のアイテムを選択すれば帳票形式でフォームが作成されます。

Q[VB.NET]3つ以上のフォームを一つずつ表示し、最後のフォームを閉じた時に最初のフォーム以外のフォームを閉じる

VB.NETを学んでいるのですが、現在3つ以上のフォームを表示していくものを作ろうとして躓いたことがあったのでこちらに書き込みました。
内容としては、ボタンを押して次のフォームを表示していくものです。

動作の流れは以下のように考えています(フォームはA、B、Cの3つとする)
1.Aを表示
2.Aでボタンを押してBを表示し、Aは隠す
3.Bでボタンを押してCを表示し、Bは隠す
4.Cでボタンを押してBとCを閉じ、隠していたAを表示

隠すのはHideを用いてできたのですが、4.でCのボタンでBとCを一緒に閉じてAを表示させる方法がわかりませんでした。

1~4のように動作させるにはどうすればいいか教えてください

Aベストアンサー

まとめて考えるのではなく、分けて考えた方がコーディングもしやすくなります。

[ FormA の処理 ]
1. ボタンを押したら FormB を開き、自身を Hide する。
2. FormB が閉じられたら、自身を Show する。

[ FormB の処理 ]
3. ボタンを押したら FormC を開き、自身を Hide する。
4. FormC が閉じられたら、自身を Close する。

[ FormC の処理 ]
5. ボタンを押したら、自身を Close する。

ポイントは、親フォーム側で子フォームのFormCloseを捕らえるところです。FormBからFormAを、とか、FormCからFormAとFormBを・・・と考えるとややこしくなります。上記のように処理すれば、FormBはFormAの動作を気にする必要はありませんし、FormCもFormBやFormAの動作を気にする必要はありません。子フォームのFormCloseはWithEvents宣言すれば捕らえられます。

以下、簡単なコードを。ボタン配置が面倒だったので、フォームのクリックで動作します。


' [ FormA の処理 ]
Public Class FormA
Inherits Form

Public Sub New()
Me.Text = "FormA"
End Sub

Private WithEvents frmFormB As FormB

' 1. ボタンを押したら FormB を開き、自身を Hide する。
Private Sub FormA_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
frmFormB = New FormB
frmFormB.Text = "FormB"
frmFormB.Show()

Me.Hide()
End Sub

' 2. FormB が閉じられたら、自身を Show する。
Private Sub frmFormB_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles frmFormB.FormClosed
frmFormB = Nothing
Me.Show()
End Sub

End Class

' [ FormB の処理 ]
Public Class FormB
Inherits Form

Private WithEvents frmFormC As FormC

' 3. ボタンを押したら FormC を開き、自身を Hide する。
Private Sub FormB_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
frmFormC = New FormC
frmFormC.Text = "FormC"
frmFormC.Show()

Me.Hide()
End Sub

' 4. FormC が閉じられたら、自身を Close する。
Private Sub frmFormC_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles frmFormC.FormClosed
frmFormC = Nothing
Me.Close()
End Sub

End Class

' [ FormC の処理 ]
Public Class FormC
Inherits Form

' 5. ボタンを押したら、自身を Close する。
Private Sub FormC_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
Me.Close()
End Sub

End Class

※VB2005で書いたコードなので.NETでそのまま動くかは不明・・・。

なお、あくまで考え方のひとつなので、他にも方法はあります。

まとめて考えるのではなく、分けて考えた方がコーディングもしやすくなります。

[ FormA の処理 ]
1. ボタンを押したら FormB を開き、自身を Hide する。
2. FormB が閉じられたら、自身を Show する。

[ FormB の処理 ]
3. ボタンを押したら FormC を開き、自身を Hide する。
4. FormC が閉じられたら、自身を Close する。

[ FormC の処理 ]
5. ボタンを押したら、自身を Close する。

ポイントは、親フォーム側で子フォームのFormCloseを捕らえるところです。FormBからFormAを、とか、FormC...続きを読む

Q【Access】複数フォームを閉じる時の、選択処理について

Access Ver. : 2003
Windows Ver.: XP

Accessフォームの「閉じる時」処理で、下記のような工夫をした
いと考えております。

・フォームがひとつしか開かれていないとき、Accessを終了する
・複数のフォームが開かれている時、そのフォームのみを閉じる

そんなVBAコードがありましたら、教えてください。
何か参考になるページでも、かまいません。
どうぞ、宜しくお願いいたします。

Aベストアンサー

forms.count で開いているフォーム数を得て分岐
Application.quit

Access VBE のヘルプで、CurrentProject オブジェクト を見てみたら?

QMessageBox.Show(Me,…の「Me」は何を意味する

VB.NETの勉強中です。

VB6などを今まで使っていたのですが、仕事上VB.NETを使用することになりました。
そこで、重要な事ではないとは思うのですが、.NETで作られた例題などを見ていると、MessageBox.Showメソッドを使用する際に第一引数に時々「Me」が指定されている事があります。
例に書くと、
MessageBox.Show(Me,"TEST1","Title")
のような感じです。
これを
MessageBox.Show("TEST1","Title")
としても、少なくとも見た目上は結果は同じに思えます。

私の勉強不足で、クラスの考え方がまだ少々おぼろげなので、これが理解できないのかも…と思うのですが、この「Me」をどのように考えたらよいか、ご存知の方、ご教授ください。

Aベストアンサー

Showメソッドには、何種類の呼び方があります。

1番目にオブジェクトを指定する使い方(この場合Meなので自分自身)は、指定されたオブジェクトの前にメッセージを表示します。
通常は、元のフォーム等の上に表示されるのであまり違いが分かりませんが、複数フォーム有る状態で、Meではなく別なフォームを指定してみると違いが分かります。

QACCESSフォームのボタン表示

ACCESSフォームのボタン表示

ACCESS2000で作成したフォームのボタンはACCESS2007でも変わりません。
ACCESS2007で一から作成したMDBは、ボタンの表示スタイルが異なります。
※ボタンの角が丸く、マウスカーソルをボタンの上に当てるだけで色が変わる。
ACCESS2000で作成したMDBをACCESS2007で上記のように表示させる設定は
あるのでしょうか?
いろいろ見ても、見当たらないのです。
よろしくお願いします。

Aベストアンサー

[Office ボタン] - [Accessのオプション] - [カレントデータベース] で
「フォーム上のコントロールに Windows のテーマを使用する」にチェック。

Q[ExcelVBA] Application.Dialogs(xlDialogPrint).Show とユーザーフォームについて

[環境] WinXpHomeSP2
Excel2002SP3

Excelのユーザーフォーム上にあるコマンドボタンをクリックすると、アクティブになっているシートを印刷するプログラムを作成しています。
印刷前に印刷ダイアログを表示し、プリンタの設定およびプレビューを可能にしたいため、
Application.Dialogs(xlDialogPrint).Show
を使用しています。
ユーザーフォームはその直前でいったんHideし、上記コードの直後に再度Showしています。

表示された印刷ダイアログの「プレビュー」ボタンをクリックすると、Hideしたはずのユーザーフォームがプレビュー画面の前面に表示されてしまい、プレビュー画面、ユーザーフォーム画面のどちらのボタンも効かなくなって制御不能となってしまいます。

プレビューしてもユーザーフォームが立ち上がってこなくなる方法を教えてください。

Aベストアンサー

再度の登場 onlyromです。

>UserForm1をいったんHideした後にまたShowするため、※1が実行され
その後は新しくUserForm1が立ち上がったのと同じ動作をします。

Showすれば必ずActivateイベントが発生します。
その処理は、
UserForm_Initializeイベントに書くと拙いのですか?
Initializeイベントであれば、HideしてShowしても
そこを通りませんので実行されません。

絶対Activateイベントに書かなければならないコードであり、
かつ、今回のように場合によっては、Activateイベントのコードを
実行させたくない時は

実行させるかさせないか判断させるための変数を
モジュール変数としてとっておきそれを利用する手もあります。


それから、
>このUserForm1が閉じられた後、※2を実行してしまうため、エラーになってしまいうまくいきません。

これは、Showの前で、※2を実行すればいいのではありませんか?


'--------------------------------------

  Dim MyFlag as Boolean

'--------------------------------------
Private UserForm_Activate()

  If MyFlag = True then Exit Sub

    ーーー処理ーーー

End Sub
'--------------------------------------


Private Sub CommandButton1_Click
  Dim blResponse AS Boolean
   :(帳票出力準備)

●● MyFlag = True  ●●

  UserForm1.Hide

  blResponse = Application.Dialogs(xlDialogPrint).Show
   :(帳票出力後始末)
  If blREsponse Then
    MsgBox "出力終了"
  End If


▲▲   : (※2)  ▲▲
  
   UserForm1.Show

●● MyFlag = False ●●


End Sub
'--------------------------------------------------

UserformActivateイベントで何をしてるのか
(※2) で何をしてるのか分かりませんので
これくらいのアドバイスしかできませんが、

さらに言うと
UserForm.Showの後に、(※2)のように何かの処理をさせるコードを書くことはありません。
書くとすれば、UserFormをYesNoのMsgBoxのように使う場合です。

また上記アドバイスでは、UserFormの使い方が不明でしたので
(※2)とShowを入れ替えていますが、
通常、UserFormが閉じられたときの処理は、
UserForm_QueryClose などに書きます。
 

Activateイベントの処理内容、(※2)の処理内容が分かれば
もっと的確な回答が寄せられるでしょう。
 

 
 

再度の登場 onlyromです。

>UserForm1をいったんHideした後にまたShowするため、※1が実行され
その後は新しくUserForm1が立ち上がったのと同じ動作をします。

Showすれば必ずActivateイベントが発生します。
その処理は、
UserForm_Initializeイベントに書くと拙いのですか?
Initializeイベントであれば、HideしてShowしても
そこを通りませんので実行されません。

絶対Activateイベントに書かなければならないコードであり、
かつ、今回のように場合によっては、Activateイベントのコードを
...続きを読む

QExcelで作成されたフォームをAccessにコンバージョンしたいので

Excelで作成されたフォームをAccessにコンバージョンしたいのですが、フォームのインポートはできないのでしょうか?
Accessのフォーム作成画面から、インポートを選択していって、Excelファイルを開くのですが、シートしか選択できません。
コントロールのコピペもできないみたいですが。。。
Excelで作成されたフォームはAccessにはインポートできないのですか?
コーディングをそっくり使用することはできなくても、せめてフォームのデザインはコピーしたいのですが。。。(> <)
よろしくお願いします。m(_ _)m

Aベストアンサー

質問者はプロかプロ経験者ですか。でないならこんな勉強は試みないほうが良いでしょう。
市販の書物や初心者向けの講習で説明される話題ではない。プロで会社にその辺の経験者がいたりすれば聞けるでしょうが。原理的には最熟練者の人は変換プログラムは組めるかもしれませんが、そのレベルの人は、この質問コーナーを読んでないでしょうし、無料で教えるスキルではないと思います。
WEBの記事も多分少ないでしょう。
Googleででも「エクセル フォーム アクセス 移行」で出てくる記事を参考にしてはどうでしょう。
http://www.accessclub.jp/bbs2/0080/beginter24987.html
同じ発想の人はいることはいるが。
ーー
VBAとVBのフォームはコードで扱う上で微妙に違うし、アクセスVBAとエクセルVBAでは違う点も多い。
またコントロールの生成もコードで行う方法は隠して、易しいD&Dやマウスによる移動、プロパティボックスでの入力にして易しくしています。
エクセルのUserForm1のフォームも本格的なものではないサービスのような気がする。エクセルで第3者を巻き込んだ業務の開発までは予定して無いように推測する(何でもエクセル的な過大期待が横行している)。
それにエクセルでのセルとの連携をつけた機能LinkedCell、FillいstRangweなどはエクセル特有で、RecordSourceのSQL指定やフォーム指定はアクセス特有と思います。
外観を決めるサイズや書式関係は(エクセルでフォームやコントロールの)プロパティーメモー(アクセスでのフォームやコントロールの)プロパティ設定でやや似せて移せるかもしれない。
エクセルバージョン内の相違、エクセル・アクセルで使えるコントロールの種類の相違などもあります。

質問者はプロかプロ経験者ですか。でないならこんな勉強は試みないほうが良いでしょう。
市販の書物や初心者向けの講習で説明される話題ではない。プロで会社にその辺の経験者がいたりすれば聞けるでしょうが。原理的には最熟練者の人は変換プログラムは組めるかもしれませんが、そのレベルの人は、この質問コーナーを読んでないでしょうし、無料で教えるスキルではないと思います。
WEBの記事も多分少ないでしょう。
Googleででも「エクセル フォーム アクセス 移行」で出てくる記事を参考にしてはど...続きを読む

Q【VB.NET2003】フォーム1を閉じてフォーム2を表示させたい

プログラミング初心者でVB.NET2003使用です。
検索したところ、それらしいものがあったのでチャレンジしましたがダメだった(ちょっと違う?)ので質問させていただきます。
http://oshiete1.goo.ne.jp/qa1757174.html

《やりたい事》
Form1に配置したボタン1をクリックするとForm1を閉じてForm2を表示
Form2に配置したボタンAをクリックするとForm2を閉じてForm1を表示する。

これをやりたいのですが、なかなかうまく行きません。

ボタン1をクリックしてForm1を閉じないでForm2をShowかShowDialogでモードレス表示
ボタンAをクリックしてForm2をCloseさせてForm1を表示させる事(元々閉じていないので)は出来ます。

可能ならばどちらかを必ず閉じる方法でやりたいと思います。
可能でしょうか?
解決策やヒント、良いサイトがありましたら回答をお願いします。

Aベストアンサー

Sub Mainでやるのは #1と同じですが オブジェクト『フォーム』の管理をModule1でやってみてはいかがですか

Module1に
  Dim oForm1 as Form1
  Dim oForm2 as Form2
  Sub Main
    ' Form1を表示
    oForm1 = new Form1
    oForm1.Show()
    Do While TRUE
      if oForm1.IsDisposed then
        ' Form1が閉じられた場合
        if oForm2 is Nothing then
          ' Form2が一度も表示されなかった場合
          Exit Sub
        else if oForm2.IsDisposed then
          ' Form2が1回以上表示された場合
          Exit Sub
        end if
      end if
      Application.DoEvents()
    Loop
  End Sub

フォーム1上のボタンイベント
if oForm2 is Notrhing OrElse oForm2.isDisposed then
  oForm2 = new Form2
end if
oForm2.Show()
me.Close()

フォーム2上のボタンイベント
if oForm1 is Notrhing OrElse oForm1.isDisposed then
  oForm1 = new Form1
end if
oForm1.Show()
me.Close()

といった具合で …

Sub Mainでやるのは #1と同じですが オブジェクト『フォーム』の管理をModule1でやってみてはいかがですか

Module1に
  Dim oForm1 as Form1
  Dim oForm2 as Form2
  Sub Main
    ' Form1を表示
    oForm1 = new Form1
    oForm1.Show()
    Do While TRUE
      if oForm1.IsDisposed then
        ' Form1が閉じられた場合
        if oForm2 is Nothing then
          ' Form2が一度も表示されなかった場合
          Ex...続きを読む

QVBからmdbファイル(Access2000)の特定のフォームを開きたい?

VisualBasicのフォームに配置したコマンドボタンをクリックすることで、特定のmdbファイルをAccess2000で開き、開くと同時に特定のフォームが表示されるようにしたいのですが、こんなことできますか?できるとすればどのようにすればよいのですか?

例えば、C:\商品管理\在庫一覧.mdbにフォーム商品があるとしたとき、
Form1のcommand1をクリックすると、C:\商品管理\在庫一覧.mdbがAccess2000で開き、フォーム商品が最初に表示されるようにしたいのですが・・・
ちなみに、Access2000の起動時の設定では他のフォームが最初に開くようになっています。
よろしくお願いします。

Aベストアンサー

オートメーションを使ってAccessを制御しましょう。
で、他のフォームが最初に開くようになっていることなので、最初に開くフォームを閉じてからAccessを表示するようにすればいいと思います。

Dim acs as Object

'AccessのApplicationオブジェクトを取得する。
Set acs = CreateObject("Access.Application")

'c:\test.mdbを開くacs.OpenCurrentDatabase "c:\test.mdb"

'起動時に開かれたフォームを閉じる
'2はacForm定数のこと
acs.Close 2,"フォーム名"

'Accessを表示させる
acs.Visible = True

'表示させたいフォームを開く
acs.OpenForm "フォーム名"


こんな感じで。

最後に、Accessを終わらせるときは

'オブジェクトの開放
Set acs = Nothing

で、オブジェクトを開放してください。

オートメーションを使ってAccessを制御しましょう。
で、他のフォームが最初に開くようになっていることなので、最初に開くフォームを閉じてからAccessを表示するようにすればいいと思います。

Dim acs as Object

'AccessのApplicationオブジェクトを取得する。
Set acs = CreateObject("Access.Application")

'c:\test.mdbを開くacs.OpenCurrentDatabase "c:\test.mdb"

'起動時に開かれたフォームを閉じる
'2はacForm定数のこと
acs.Close 2,"フォーム名"

'Accessを表示させる
acs.Visibl...続きを読む

Q継承クラスにdisposeを実装したいのですが...

スミマセン。教えて頂けますか?
VB2005初心者です。

pictureBoxの継承クラスにdisposeメソッドを実装したいのですが、

Protected Overrides Sub Dispose(ByVal disposing As Boolean)

Protected Overrides Sub Dispose()
どちらになるのでしょうか

宜しくお願いします。

Aベストアンサー

参考URLにある通り、Dispose()はDispose(true)を呼ぶだけですね。
同じ使用感にしたいならば両方書いて、めんどくさいなら、引数有りの方だけでいいのでは?

参考URL:http://msdn2.microsoft.com/ja-jp/library/bcss05x5(VS.80).aspx


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報