USB angeschlossen, Form2 öffnen sonst Massagebox und Form2 nicht öffnen

  • VB.NET

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von mali.

    USB angeschlossen, Form2 öffnen sonst Massagebox und Form2 nicht öffnen

    So bin mal wieder an einem neuen Projekt. Habe im Sourcecodeaustausch einen Code von mikeb69 und Vatter gefunden:

    [VB.NET] Erkennen, wann ein Laufwerk hinzugefügt bzw. entfernt wurde (USB-Stick)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class ClsDrivewatcher
    3. Inherits System.Windows.Forms.NativeWindow
    4. 'Konstanten für Windowsmessages
    5. Private Const WM_DEVICECHANGE As Integer = &H219
    6. Private Const DBT_DEVICEARRIVAL As Integer = &H8000
    7. Private Const DBT_DEVICEREMOVECOMPLETE As Integer = &H8004
    8. 'Events
    9. Public Event WinProc(ByVal sender As ClsDrivewatcher, ByRef m As Message)
    10. Public Event Drive_Neu(ByVal DI As DriveInfo)
    11. Public Event Drive_entfernt(ByVal DN As String)
    12. Private allDrives As New List(Of DriveInfo)
    13. Public Sub New(ByVal Handle As IntPtr)
    14. 'übergibt dem NativeWindow das Handle
    15. MyBase.AssignHandle(Handle)
    16. 'Listet alle Laufwerke in allDrives
    17. allDrives = GetAllDrives()
    18. End Sub
    19. 'Ausgabemöglichkeit für Laufwerkliste
    20. Public Function Getdrives() As List(Of DriveInfo)
    21. Return allDrives
    22. End Function
    23. 'WinProc-Methode des übergebenen Handles
    24. Protected Overrides Sub WndProc(ByRef msg As Message)
    25. 'gibt die OriginalMessage an übergebenes Handles weiter
    26. MyBase.WndProc(msg)
    27. 'Event für externe Auswertung der Message
    28. RaiseEvent WinProc(Me, msg)
    29. 'Wenn ein Laufwerk gewechselt und ein neues Laufwerk erkannt wurde
    30. If msg.Msg = WM_DEVICECHANGE AndAlso msg.WParam = CType(DBT_DEVICEARRIVAL, IntPtr) Then
    31. 'alle laufwerke durchlaufen und in der liste suchen
    32. For Each s As String In Directory.GetLogicalDrives
    33. find_driveinfo_arg = s
    34. Dim d As DriveInfo = allDrives.Find(AddressOf find_driveinfo)
    35. If d Is Nothing Then
    36. d = New DriveInfo(s)
    37. 'laufwerk wurde in der liste nicht gefunden und ist somit neu
    38. 'MessageBox.Show("Neuer Datenträger erkannt = " & d.Name)
    39. 'laufwerk jetzt zur liste hinzufügen
    40. allDrives.Add(d)
    41. 'Event auslösen
    42. RaiseEvent Drive_Neu(d)
    43. End If
    44. Next
    45. End If
    46. 'Wenn ein Laufwerk gewechselt und ein Laufwerk entfernt wurde
    47. If msg.Msg = WM_DEVICECHANGE AndAlso msg.WParam = CType(DBT_DEVICEREMOVECOMPLETE, IntPtr) Then
    48. 'alle laufwerke aus der liste prüfen
    49. Dim temp As List(Of DriveInfo) = GetAllDrives()
    50. For Each d As DriveInfo In allDrives
    51. find_driveinfo_arg = d.Name
    52. Dim lost As DriveInfo = temp.Find(AddressOf find_driveinfo)
    53. If lost Is Nothing Then
    54. 'laufwerk wurde in der liste nicht mehr gefunden
    55. 'MessageBox.Show("Datenträger wurde entfernt = " & d.Name)
    56. 'Event auslösen
    57. RaiseEvent Drive_entfernt(d.Name)
    58. 'laufwerk aus der liste entfernen
    59. allDrives.Remove(d)
    60. 'schleife verlassen
    61. Exit For
    62. End If
    63. Next
    64. End If
    65. End Sub
    66. 'Funktion zum Auflisten der Laufwerke
    67. Private Function GetAllDrives() As List(Of DriveInfo)
    68. Dim ret As New List(Of DriveInfo)
    69. 'und wieder befüllen
    70. For Each d As String In Directory.GetLogicalDrives
    71. ret.Add(New DriveInfo(d))
    72. Next
    73. Return ret
    74. End Function
    75. 'suchfunktion zum finden der laufwerke in der collection
    76. Private find_driveinfo_arg As String
    77. Private Function find_driveinfo(ByVal d As DriveInfo) As Boolean
    78. If d.Name = find_driveinfo_arg Then
    79. Return True
    80. Else
    81. Return False
    82. End If
    83. End Function
    84. End Class


    Jetzt versuche ich mir alles etwas auf meine Bedürfnisse anzupassen.

    Folgendes Zenario: Form1 hat einen Button, dieser soll, solange kein USB Stick angeschlossen ist, keine Funktion und ein anderes Image als Hintergrund haben. Sobald ein USB Stick am PC hängt sollen diese Funktionen hinterlegt sein: anderes Image, Form2 öffnen und Laufwerksbuchstaben in Label ausgeben.

    Das ausgeben des Laufwerksbuchstaben in ein Label hab ich gelöst, indem ich die Private Sub aus dem Beispiel umgeschrieben habe. Jetzt happert es aber am Rest. Jetzt hoffe ich wieder auf eure hilfreichen Vorschläge.

    An dieser Stelle nochmal vielen Dank für den Sourcecode an mikeb69 und Vatter.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class Form1
    3. Private Drivewatcher As ClsDrivewatcher
    4. Private flagUsb As Boolean ' dies hier
    5. Private dlg As Form2 ' dies hier
    6. Public Sub New()
    7. InitializeComponent()
    8. flagUsb = False ' dies hier
    9. dlg = New Form2 ' dies hier
    10. Drivewatcher = New ClsDrivewatcher(Me.Handle)
    11. 'Events adden
    12. AddHandler Drivewatcher.Drive_Neu, AddressOf LW_erkannt
    13. AddHandler Drivewatcher.Drive_entfernt, AddressOf LW_entfernt
    14. End Sub
    15. 'Event Laufwerk neu
    16. Private Sub LW_erkannt(ByVal DI As DriveInfo)
    17. Debug.WriteLine(String.Format("Laufwerk {0}:\ wurde hinzugefügt, Label = {1} ", DI.Name, DI.VolumeLabel))
    18. Debug.WriteLine(String.Format("Type: {0};frei: {1} von {2}", DI.DriveType, DI.TotalFreeSpace, DI.TotalSize))
    19. flagUsb = True ' dies hier
    20. dlg.Show() ' dies hier
    21. End Sub
    22. 'Event Laufwerk entfernt
    23. Private Sub LW_entfernt(ByVal Name As String)
    24. Debug.WriteLine(String.Format("Laufwerk {0}:\ wurde entfernt ", Name))
    25. End Sub
    26. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    27. If Not flagUsb Then ' dies hier
    28. Return
    29. End If
    30. End Sub
    31. End Class

    Das Hintergrundbild für den Button schaffst Du alleine. :thumbup:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    wow, das war viel mehr als ich erwartet habe. Vielen Dank. :thumbsup: musste den code jedoch noch etwas umschreiben, weil sich die Form2 automatisch geöffnet hat, wenn der USB Stick angeschlossen wurde. Hab also den Button Event etwas geändert. Nur was ich nicht verstehe, wenn die Form2 mal geschlossen wurde, kann diese nicht mehr geöffnet werden und der Debuggen Modus wird mit der Fehlermeldung "auf das verworfene Objekt kann nicht zugegriffen werden" geschlossen.

    VB.NET-Quellcode

    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    2. If flagUsb = True Then ' dies hier
    3. dlg.Show()
    4. Else
    5. 'do nothing
    6. End If
    7. End Sub


    Weiss jemand, warum das so ist? ?( ?( ?(

    mali schrieb:

    Weiss jemand, warum das so ist? ?( ?( ?(
    Ist halt ein nicht modaler Dialog.

    VB.NET-Quellcode

    1. Private dlg As Form2
    2. Private Sub XXX()
    3. If dlg Is Nothing OrElse dlg.IsDisposed Then
    4. dlg = New Form2
    5. End If
    6. If Not dlg.Visible Then
    7. dlg.Show()
    8. End If
    9. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ok jetzt muss ich etwas genauer nachfragen, wolltest du den Code in den Sub Button1_Click? Wenn ja, dann öffnet sich die Form2 ja immer, auch wenn kein USB Stick angeschlossen ist. Wenn nein, dann gibt es keine Änderung. Hab jetzt die Form2 bei trennen des USB Sticks vom PC nur versteckt, also mit Hide, dann funktioniert das ganze. Aber sobald close geklickt wird is empty. Hab übrigens noch folgendes ergänzt

    VB.NET-Quellcode

    1. Private Sub LW_entfernt(ByVal Name as String)
    2. '....
    3. flagUsb = False
    4. End Sub


    Dachte mir, flagUsb muss ja wieder auf false gehen.
    Auch dir einen schönen 2 Advent. Ich beschäftige mich schon mit dem Code und probiere einiges aus. Aus meiner Sicht besteht das Problem, dass wenn Form2 geschlossen wird VB dlg nicht als neue Form2 setzt. Hab jetzt noch in dem LW_entfernt sub dieses mit reingeschrieben

    VB.NET-Quellcode

    1. dlg = New Form2


    und dann funktioniert das auch, dass die Form2 wieder aufrufbar ist, wenn der Stick getrennt wird. Nur wenn ich die Form2 schließe per Button gehts nicht. Aber ich werde weiter testen.

    Edit: Hab die Nacht so einiges durchdacht und den Code so geschrieben, ich hoffe Rod will mir jetzt nicht den Kopf abreisen.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class Form1
    3. Private Drivewatcher As ClsDrivewatcher
    4. Private flagUsb As Boolean ' dies hier
    5. Private dlg As Form2 ' dies hier
    6. Public Sub New()
    7. InitializeComponent()
    8. flagUsb = False ' dies hier
    9. dlg = New Form2 ' dies hier
    10. Drivewatcher = New ClsDrivewatcher(Me.Handle)
    11. 'Events adden
    12. AddHandler Drivewatcher.Drive_Neu, AddressOf LW_erkannt
    13. AddHandler Drivewatcher.Drive_entfernt, AddressOf LW_entfernt
    14. End Sub
    15. 'Event Laufwerk neu
    16. Private Sub LW_erkannt(ByVal DI As DriveInfo)
    17. dlg.Label1.Text = DI.Name
    18. flagUsb = True ' dies hier
    19. End Sub
    20. 'Event Laufwerk entfernt
    21. Private Sub LW_entfernt(ByVal Name As String)
    22. dlg.Close()
    23. dlg = New Form2
    24. flagUsb = False
    25. End Sub
    26. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    27. If flagUsb = True Then ' dies hier
    28. dlg = New Form2
    29. dlg.Show()
    30. End If
    31. End Sub
    32. End Class


    Damit kann die Form2 immer wieder geöffnet werden, solange der USB Stick am PC hängt. Das einzigste was jetzt nicht geht, ist dass im Label auf Form2 der DI.Name angezeigt wird. Ich denke das liegt am Button Sub, das ich da dlg = New Form2 integriet habe. Hier muss ich nochmal etwas grübeln.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „mali“ ()

    mali schrieb:

    Aus meiner Sicht besteht das Problem, dass wenn Form2 geschlossen wird VB dlg nicht als neue Form2 setzt.

    Form2 wird doch in der Klasse deklariert und in den Prozeduren greifst Du drauf zu.
    Beim Start ist Form2 = Nothing, nach dem Schließen über (X) ist die Form disposed. In diesen Fällen musst Du sie neu anlegen, wenn Du sie aufrufen willst.
    Wenn sie per Hide() nur unsichtbar (Not Visible) geschaltet wurde bzw. per New gerade instanziiert wurde, wird sie per Show() sichtbar gemacht. Fertig.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wie gesagt, bei mir funktioniert das so nicht. Hab jetzt den Code nochmal eins zu eins kopiert ohne meine Änderungen. Form2 öffnet sich automatisch, wenn der USB Stick angeschlossen wird. Wenn ich Form2 über X schließe kann ich sie nicht mehr öffnen per Button von Form1. Hab deinen Code auch verstanden, nur geht es halt nicht. Oder ich bin zu dumm. Wie in meinem letzten Post geschrieben habe ich es hinbekommen, dass die Form2 per Button immer geöffnet werden kann, nur dass jetzt das Label auf Form2 nicht mehr den Laufwerksbuchstaben anzeigt. Aber da arbeite ich noch dran.
    Mach Dir mal ein kleines Testprogramm mit dem Code.
    2 Forms, 1 Button, bei dem Du die 2. Form öffnest.
    Nimm Deinen Code und danach meinen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hab ich gemacht, das Ergebnis hab ich ja schon geschildert. Aber vielleicht hat ich einen Fehler dabei gemacht. Hier mal der zusammengetragene Code von dir:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class Form1
    3. Private Drivewatcher As ClsDrivewatcher
    4. Private flagUsb As Boolean ' dies hier
    5. Private dlg As Form2 ' dies hier
    6. Private Sub XXX()
    7. If dlg Is Nothing OrElse dlg.IsDisposed Then
    8. dlg = New Form2
    9. End If
    10. If Not dlg.Visible Then
    11. dlg.Show()
    12. End If
    13. End Sub
    14. Public Sub New()
    15. InitializeComponent()
    16. flagUsb = False ' dies hier
    17. dlg = New Form2 ' dies hier
    18. Drivewatcher = New ClsDrivewatcher(Me.Handle)
    19. 'Events adden
    20. AddHandler Drivewatcher.Drive_Neu, AddressOf LW_erkannt
    21. AddHandler Drivewatcher.Drive_entfernt, AddressOf LW_entfernt
    22. End Sub
    23. 'Event Laufwerk neu
    24. Private Sub LW_erkannt(ByVal DI As DriveInfo)
    25. Debug.WriteLine(String.Format("Laufwerk {0}:\ wurde hinzugefügt, Label = {1} ", DI.Name, DI.VolumeLabel))
    26. Debug.WriteLine(String.Format("Type: {0};frei: {1} von {2}", DI.DriveType, DI.TotalFreeSpace, DI.TotalSize))
    27. flagUsb = True ' dies hier
    28. dlg.Show() ' dies hier
    29. End Sub
    30. 'Event Laufwerk entfernt
    31. Private Sub LW_entfernt(ByVal Name As String)
    32. Debug.WriteLine(String.Format("Laufwerk {0}:\ wurde entfernt ", Name))
    33. End Sub
    34. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    35. If Not flagUsb Then ' dies hier
    36. Return
    37. End If
    38. End Sub
    39. End Class


    Was in dem Testprogramm noch fehlt, ist der Button auf Form2, der die Form2 schließt mit

    VB.NET-Quellcode

    1. Me.close()


    Aber auch wenn ich die Form2 über X schliesse, kann ich die Form2 nicht erneut per Button öffnen.

    Hier noch meiner, der funktioniert nur richtig, wenn ich dem Button auf Form2 den Befehl

    VB.NET-Quellcode

    1. Me.Hide()


    zuordne.

    EDIT: so jetzt gehts, ab und zu sieht mal den wald vor lauter Bäumen nicht. :rolleyes:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class Form1
    3. Private Drivewatcher As ClsDrivewatcher
    4. Private flagUsb As Boolean ' dies hier
    5. Private dlg As Form2 ' dies hier
    6. Public Sub New()
    7. InitializeComponent()
    8. flagUsb = False ' dies hier
    9. dlg = New Form2 ' dies hier
    10. Drivewatcher = New ClsDrivewatcher(Me.Handle)
    11. 'Events adden
    12. AddHandler Drivewatcher.Drive_Neu, AddressOf LW_erkannt
    13. AddHandler Drivewatcher.Drive_entfernt, AddressOf LW_entfernt
    14. End Sub
    15. 'Event Laufwerk neu
    16. Private Sub LW_erkannt(ByVal DI As DriveInfo)
    17. dlg.Label1.Text = DI.Name
    18. flagUsb = True ' dies hier
    19. End Sub
    20. 'Event Laufwerk entfernt
    21. Private Sub LW_entfernt(ByVal Name As String)
    22. dlg.Close()
    23. flagUsb = False
    24. End Sub
    25. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    26. If dlg Is Nothing OrElse dlg.IsDisposed Then
    27. dlg = New Form2
    28. End If
    29. If Not dlg.Visible And flagUsb = True Then
    30. dlg.Show()
    31. End If
    32. End Sub
    33. End Class


    Was ich noch nicht umsetzen konnte, ist der Part mit dem Label, welches den Laufwerksbuchstaben anzeigen soll. Habe das im Sub LW_ erkannt eingebaut, aber es wird nur beim ersten öffnen der Form2 der Laufwerksbuchstabe im Label angezeigt, danach nicht mehr. Aber das sollte ich alleine hinkriegen. Rod dir nochmal vielen Dank für die Hilfe bzw. Arbeit. :thumbsup:

    EDIT: so fertig, hab diese Zeile aus dem Sub LW_erkannt entfernt

    VB.NET-Quellcode

    1. dlg.label1.Text = DI.Name


    und dies in die Form2 Load reingeschrieben, und es geht :thumbsup:

    VB.NET-Quellcode

    1. For Each Laufwerk As IO.DriveInfo In My.Computer.FileSystem.Drives
    2. If Laufwerk.IsReady Then
    3. Label1.Text = Laufwerk.Name & vbNewLine
    4. End If
    5. Next

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „mali“ ()