vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Schützen Sie Ihre Software vor Software-Piraterie - mit sevLock 1.0 DLL!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

VB.NET - Fortgeschrittene
ComboBox für vorhandene Laufwerke 
Autor: Dikn
Datum: 21.05.19 17:18

Hallo!
Ich fülle in Load() eine ComboBox mit den aktuell vorhandenen Laufwerken.
Das erste Laufwerk wird ausgewählt.

Mit Protected Overloads Overrides Sub WndProc(ByRef msg As Message) kann ich erkennen, wenn ein Laufwerk hinzugefügt bzw. entfernt wird.

Jetzt möchte ich die Einträge in der ComboBox aktualisieren.

Mein Problem:
wenn ein neues Laufwerk hinzugefügt wird, soll sich die Ansicht der ComboBox nicht ändern.

wenn ein Laufwerk entfernt wird
-> Laufwerk ist nicht das aktuell ausgewählte Laufwerk -> Ansicht der ComboBox soll sich nicht ändern
-> Laufwerk ist das derzeit ausgewählte Laufwerk -> das erste Laufwerk der ComboBox soll angezeigt werden

Wie mache ich das?
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: ComboBox für vorhandene Laufwerke 
Autor: Manfred X
Datum: 21.05.19 17:31

Hallo!

Ich vermute, mit "Ansicht" meinst Du das aktuell selektierte Item.
Du kannst bei jeder Auswahl eines Laufwerks durch den Benutzer in der Combobox
den aktuell selektierten Eintrag (Value) in einer formularglobalen String-Variable
notieren.
Bei einer Änderung der Combobox-Liste prüfst Du, ob dieser Value noch
vorhanden ist und selektierst ihn, sonst das erste Item (index = 0).
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: ComboBox für vorhandene Laufwerke 
Autor: Dikn
Datum: 23.05.19 09:23

Hallo Manfred X!
Vielen Dank für Deine schnelle Antwort!

Mit „Ansicht“ meine ich:
Beim Hinzufügen/Entfernen eines Laufwerks soll im TreeView [trvFolders] die Markierung des ausgewählten Eintrags bestehen bleiben

Wie geht das?
Was kann vereinfacht verbesset werden?

Imports System.IO
 
Public Class Form1
  Dim strSelItem As String 
  Dim intTypArr(,) As String
 
  Const WM_DEVICECHANGE As Integer = &H219
  Const DBT_DEVICEARRIVAL As Integer = &H8000
  Const DBT_DEVICEREMOVECOMPLETE = &H8004
 
  Public Class TreeNode
    Inherits System.Windows.Forms.TreeNode
    Public Path As String
  End Class
 
  Public Declare Function LockWindowUpdate Lib "user32.dll" (ByVal hWndLock As _
    IntPtr) As Boolean  '???
 
 
Protected Overloads Overrides Sub WndProc(ByRef msg As Message)
  MyBase.WndProc(msg)
  If msg.Msg = WM_DEVICECHANGE AndAlso msg.WParam = CType(DBT_DEVICEARRIVAL, _
    IntPtr) Then
    frmInfo.TextBox1.Text = vbNewLine & "neuen Datenträger erkannt"
    frmInfo.intTime = 1
    frmInfo.Show
    Call setDrives()
    cbDrives.SelectedItem = strSelItem 
    strSelItem = Me.cbDrives.SelectedItem
  End If
  If msg.Msg = WM_DEVICECHANGE AndAlso msg.WParam = CType( _
    DBT_DEVICEREMOVECOMPLETE, IntPtr) Then 
    frmInfo.TextBox1.Text = vbNewLine & "Datenträger wurde entfernt"
    frmInfo.intTime = 1
    frmInfo.Show 
    Call setDrives()
    If InStr(strSelItem, "E:") Then
      cbDrives.SelectedIndex = 0
      strSelItem = Me.cbDrives.SelectedItem
      Call setFolders(strSelItem.Substring(strSelItem.Length-3, 2) & "\")
      trvFolders.Focus
    Else
      cbDrives.SelectedItem = strSelItem
    End If
  End If
  End Sub
 
 
Private Sub Me_Load(sender As Object, e As System.EventArgs) Handles Me.Load
  Call setDrives()
  cbDrives.SelectedIndex = 0
  strSelItem = Me.cbDrives.SelectedItem
  Call setFolders(Directory.GetLogicalDrives.First)
End Sub
 
 
 
Private Sub cbDrives_DrawItem (ByVal sender As Object, ByVal e As _
  System.Windows.Forms.DrawItemEventArgs) Handles cbDrives.DrawItem
  If Me.cbDrives.DroppedDown = True AND (e.State And DrawItemState.Selected) = _
  DrawItemState.Selected Then
    e.Graphics.FillRectangle(SystemBrushes.Control, e.Bounds)
  Else
    e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds)
  End If
 
  If intTypArr Is Nothing Then Exit Sub
 
  e.Graphics.DrawImage(ImageList2.Images.Item(CInt(intTypArr(e.Index,1))), 4, _
    e.Bounds.Top + 1)
  e.Graphics.DrawString(cbDrives.Items(e.Index).ToString, cbDrives.Font, _
  Brushes.Black, 20, e.Bounds.Top + 1)
  End Sub
 
Private Sub cbDrives_DropDownClosed (sender As Object, e As System.EventArgs) _
  Handles cbDrives.DropDownClosed
  Me.trvFolders.Nodes.Clear
  strSelItem =  Me.cbDrives.SelectedItem
  Call setFolders(strSelItem.Substring(strSelItem.Length-3,2) & "\")
  trvFolders.Focus
End Sub
 
Private Sub setFolders(strLW As String)
  Dim tn As TreeNode = Nothing
  Dim nodeInfo As DirectoryInfo = New DirectoryInfo(strLw)
 
  Try
    trvFolders.Nodes.Clear
    For Each di As DirectoryInfo In nodeInfo.GetDirectories
      If di.Attributes = FileAttributes.Directory Then
        tn = AddNode(trvFolders.Nodes, di.Name, di.FullName)
        If My.Computer.FileSystem.GetDirectories(tn.Path).Count > 0 Then 
          AddNode(tn.Nodes, ".", ".")
        End If
      End If
    Next
 
  Catch ex As Exception
  End Try
  End Sub
 
Private Function AddNode (ByVal nodeCollection As TreeNodeCollection, ByVal _
  Caption As String, ByVal path As String) As TreeNode
  Dim tn As New TreeNode()
 
  tn.Text = Caption
  tn.Path = path
  nodeCollection.Add(tn)
  Return tn
End Function
 
End Class
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: ComboBox für vorhandene Laufwerke 
Autor: Dikn
Datum: 23.05.19 09:24

Private Sub setDrives()
  Try
    Erase intTypArr
    cbDrives.Items.Clear
    ReDim Preserve intTypArr(DriveInfo.GetDrives.Length - 1, 1)
 
    Dim i As Integer = 0
    For Each d As DriveInfo In DriveInfo.GetDrives 
      Select Case d.DriveType
        Case DriveType.Unknown
          intTypArr(i,0) = " Unknown (" & d.Name.Substring(0, 2) & ")"
          intTypArr(i,1) = "1"
        Case  DriveType.Fixed
          If Asc(d.Name.Substring(0,1)) > 68 Then
            intTypArr(i,0) = " " & d.VolumeLabel & " (" & d.Name.Substring(0, _
              2) & ")"
            intTypArr(i,1) = "4"
          Else
            intTypArr(i,0) = " Laufwerk (" & d.Name.Substring(0, 2) & ")"
            intTypArr(i,1) = "3"
          End If
        Case DriveType.Network
          intTypArr(i,0) = " Netzlaufwerk (" & d.Name.Substring(0, 2) & ")"
          intTypArr(i,1) = "4"
        Case  DriveType.CDRom
          If d.IsReady = False Then Continue For
          intTypArr(i,0) = " DVD-RW-Laufwerk (" & d.Name.Substring(0, 2) & ")"
          intTypArr(i,1) = "5"
        Case DriveType.Ram
          intTypArr(i,0) = " Ram (" & d.Name.Substring(0, 2) & ")"
          intTypArr(i,1) = "5"
        Case  DriveType.Removable
          If d.IsReady = False Then Continue For 
          intTypArr(i,0) = " " & d.DriveType.ToString & " (" & d.Name.Substring( _
            0, 2) & ")"
          If d.Name = "A:\" OR d.Name = "B:\" Then
            intTypArr(i,1) = "2"
           Else
            intTypArr(i,1) = "6"
          End If
      End Select      
 
      Me.cbDrives.Items.Add(intTypArr(i,0))
      i += 1
    Next
 
  Catch ex As Exception
    MsgBox("Fehler: " & ex.ToString, MsgBoxStyle.Information, "Fehler in" & _
      "'setDrives()'")
  End Try
End Sub
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: ComboBox für vorhandene Laufwerke 
Autor: Manfred X
Datum: 23.05.19 13:38

Hallo!

Verwende: Option Strict On
Deine Programme arbeiten sonst nach dem Zufallsprinzip.

Die Zuweisung eines Objekts auf die String-Variable "strSelItem" ist
explizit zu konvertieren.

strSelItem = cbdrives.SelectedItem.ToString

"Instr"-Methode liefert einen Integer-Wert und keinen Boolean.
Also entweder eine korrekte Abfrage durchführen oder die Contains- bzw.
Startswith-Methode nutzen.

In der Gesamtheit habe ich den Code nicht getestet. Zu viele fehlende Angaben.
Der Code zur Reaktion auf das Entfernen eines Laufwerks sollte etwa so aussehen:

 If msg.Msg = WM_DEVICECHANGE AndAlso 
    msg.WParam = CType(DBT_DEVICEREMOVECOMPLETE, IntPtr) Then
 
    Call setDrives()
 
    If cbdrives.Items.Contains(strSelItem) Then
       If InStr(strSelItem, "E:") > 0 Then
          '???????????
          cbdrives.SelectedIndex = 0
          strSelItem = Me.cbdrives.SelectedItem.ToString            
       Else
          'Das in der Combo gewählte Item ist noch vorhanden
          cbdrives.SelectedItem = strSelItem
       End If
    Else
       'Das in der Combo gewählte Item ist entfernt worden
       cbdrives.SelectedIndex = 0
       strSelItem = cbdrives.SelectedItem.ToString                
    End If
 End If
Schau Dir Datenbindung an: Eine List(Of String) kann man an die Combobox binden.

Beitrag wurde zuletzt am 23.05.19 um 13:45:21 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: ComboBox für vorhandene Laufwerke 
Autor: Dikn
Datum: 25.05.19 09:59

Hallo Manfred X!
Vielen Dank für Deine Tipps! Werde sie zukünftig beachten.
Zu Deine Vorschlag: Muss es nicht If InStr(strSelItem, „E:“)) "=" 0 heißen?

Ich habe jetzt folgende Lösung:


Protected Overloads Overrides Sub WndProc(ByRef msg As Message)
  MyBase.WndProc(msg)
 
  If msg.Msg = WM_DEVICECHANGE AndAlso msg.WParam = CType(DBT_DEVICEARRIVAL, _
    IntPtr)
    LockWindowUpdate(CType(0, System.IntPtr))
    If cbDrives.DroppedDown = True Then
      cbDrives.DroppedDown = False
      Call setDrives()
      cbDrives.DroppedDown = True
    Else
      Call setDrives()
    End If
 
    cbDrives.SelectedItem = strSelItem
    LockWindowUpdate(CType(0, System.IntPtr))
  End If
 
  If msg.Msg = WM_DEVICECHANGE AndAlso msg.WParam = CType( _
    DBT_DEVICEREMOVECOMPLETE, IntPtr) Then
    LockWindowUpdate(CType(Me.Handle.ToInt32, System.IntPtr))
 
    If cbDrives.DroppedDown = True Then
      cbDrives.DroppedDown = False
      Call setDrives()
      cbDrives.DroppedDown = True
    Else
      Call setDrives()
    End If
 
    If cbDrives.Items.Contains(strSelItem) Then
      cbDrives.SelectedItem = strSelItem
    Else
      frmInfo.TextBox1.Text = "Das aktuell angezeigte Laufwerks wurde entfernt"
      frmInfo.intTime = 1
      frmInfo.Show
 
      cbDrives.SelectedIndex = 0
      strSelItem = cbDrives.SelectedItem.ToString
      Call setFolders(strSelItem.Substring(strSelItem.Length-3,2) & "\")
      LockWindowUpdate(CType(0, System.IntPtr))
    End If
  End If
End Sub
Bitte schau mal darüber… Ich bin dankbar für jeden Tipp.

Was für Angaben fehlen?
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: ComboBox für vorhandene Laufwerke 
Autor: Manfred X
Datum: 25.05.19 12:45

Hallo!

Die alte Instr-Funktion liefert 0 wenn der gesuchte String nicht gefunden wird,
sonst einen Wert > 0.

Ich würde die Management-Konsole nutzen, etwa so:
Imports System
Imports System.IO
Imports System.Management 'Verweis auf Assembly System.Management.DLL ist 
' erforderlich !!!! 
 
Public Class frmDrives2
 
    Dim WithEvents watcher As New ManagementEventWatcher
 
    Dim lstdrives As New List(Of String)
    Dim bsDrives As New BindingSource With {.DataSource = lstdrives}
    Dim WithEvents cboDrives As New ComboBox With
        {.Parent = Me, .Width = 200, .Left = 5, .Top = 5,
        .DropDownStyle = ComboBoxStyle.DropDown, .DataSource = bsDrives}
 
    Dim SelectedDrive As String = ""
 
 
    Public Enum USBAction
        inserted = 2
        removed = 3
    End Enum
 
 
    Private Sub frmDrives2_Load(sender As Object, e As EventArgs) Handles _
      MyBase.Load
 
        FillDrivelist()
 
        Dim query As WqlEventQuery = New
        WqlEventQuery("SELECT * FROM Win32_VolumeChangeEvent WHERE EventType =" & _
          "2 or EventType = 3")
 
        watcher.Query = query
        watcher.Start()
 
    End Sub
 
 
    Private Sub watcher_EventArrived(sender As Object, 
        e As EventArrivedEventArgs) Handles watcher.EventArrived
 
        Dim et As Short = CShort(e.NewEvent.Properties("EventType").Value)
        Dim driveName As String = e.NewEvent.Properties( _
          "DriveName").Value.ToString
        Dim eventName As String = [Enum].GetName(GetType(USBAction), et)
 
        If et = USBAction.inserted Then
            For Each drv As DriveInfo In IO.DriveInfo.GetDrives
                If drv.Name.StartsWith(driveName) Then
                    lstdrives.Add(driveName & "  " & drv.DriveType.ToString)
                End If
            Next drv
            lstdrives.Sort()
        Else
            For i As Integer = lstdrives.Count - 1 To 0 Step -1
                If lstdrives(i).StartsWith(driveName) Then lstdrives.RemoveAt(i)
            Next i
        End If
 
        cboDrives.Invoke(New MethodInvoker(AddressOf SetDriveBinding))
    End Sub
 
 
    Private Sub SetDriveBinding()
        bsDrives.ResetBindings(False)
        SetSelectedDrive()
    End Sub
 
 
    Private Sub FillDrivelist()
        lstdrives.Clear()
 
        For Each drv As DriveInfo In IO.DriveInfo.GetDrives
            lstdrives.Add(drv.Name & " " & drv.DriveType.ToString)
        Next drv
        lstdrives.Sort()
        bsDrives.ResetBindings(False)
    End Sub
 
 
    Private Sub SetSelectedDrive()
        Dim found As Boolean
        If String.IsNullOrEmpty(SelectedDrive) Then Exit Sub
        If lstdrives.Count = 0 Then Exit Sub
 
        For i As Integer = 0 To lstdrives.Count - 1
            If lstdrives(i).StartsWith(SelectedDrive) Then
                cboDrives.SelectedIndex = i : found = True
            End If
        Next i
        If Not found Then cboDrives.SelectedIndex = 0
    End Sub
 
 
    Private Sub cboDrives_SelectedIndexChanged(sender As Object,
                e As EventArgs) Handles cboDrives.SelectedIndexChanged
        If cboDrives.SelectedItem Is Nothing Then
            SelectedDrive = ""
        Else
            SelectedDrive = cboDrives.SelectedItem.ToString
        End If
    End Sub
End Class
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: ComboBox für vorhandene Laufwerke 
Autor: Dikn
Datum: 27.05.19 09:20

Hallo Manfred!
Vielen, vielen Dank für Deine Bemühung!

Ich hab‘s ausprobiert… funktioniert wunderbar
Die Management Konsole ist mir bisher völlig unbekannt

Ich hoffe, ich nerve nicht, noch folgende Fragen
- wie kann ich die Events einer vorhandenen ComboBox zuweisen?
- wenn ´ein Laufwerk entfernt wird und das DropDown geöffnet ist
wird die DropDown-Höhe nicht angepasst. Wie kann man das ändern?
- wenn das aktuell ausgewählte Laufwerk entfernt wird, soll das erste Laufwerk
in lstDrives ausgewählt werden.


Zu Deinem Script:
??? Notwendig ???
Dim eventName As String = [Enum].GetName(GetType(USBAction), et)

Ich habe
lstdrives.Add(driveName & " " & drv.DriveType.ToString)
ersetzt mit
lstdrives.Add(drv.Name & " " & drv.DriveType.ToString)
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: ComboBox für vorhandene Laufwerke 
Autor: Manfred X
Datum: 27.05.19 12:49

Was genau meinst Du, wenn Du Events einer vorhandenen Combobox
zuweisen möchtest? Eventhandler-Routinen werden von Windows immer für die
Klasseninstanzen aufgerufen, die entweder durch Handles-Klausel oder
Addhandler dem entsprechenden Klassen-Event im Code zugewiesen worden sind.

Bei mir (Windows10/64Bit, Visual Studio 2017, Framework 4.8, CPU-Typ x86)
wird das geöffnete Dropdown-Fenster der Combobox automatisch vergrößert,
wenn sich die Liste durch das Hinzufügen eines lokalen Laufwerks verlängert
(Basis: Reset der Datenbindung durch Bindingsource: neues Einlesen der Liste).

Beim Entfernen des in der Combobox selektierten Laufwerks wird in meinem
Beispiel das erste Laufwerk in der Liste (Index 0) gewählt. Das erledigt
die Routine "SetSelectedDrive".

Die Variable "Eventname" habe ich in das Beispiel aufgenommen, damit eine
Benachrichtigung des Users beim Hinzufügen/Entfernen eines lokalen Laufwerks
möglich wird:

MessageBox.Show("Drive " & eventName & ": " & driveName)
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: ComboBox für vorhandene Laufwerke 
Autor: Dikn
Datum: 27.05.19 17:43

Ich habe in meinem Formular „frmMain“ bereits eine ComboBox „cbDrives“.
Wie kann ich die mit deinem Vorschlag nutzen?

Das Dropdown-Fenster der Combobox wird auch bei mir automatisch vergrößert, wenn sich die Liste durch das Hinzufügen eines lokalen Laufwerks verlängert.
Aber:
Beim Herausnehmen eine Laufwerks wird der Eintrag gelöscht, aber das Dropdown-Fenster wird nicht verkleinert.

Beim Entfernen des in der Combobox selektierten Laufwerks wird
bei mir wird nicht das erste Laufwerk ausgewählt, sondern das vorige
z.B.:
C:\Fixed
D:\CDRom
E:\Removable

-> E:\Removable wird entfernt -> D:\CDRom wird ausgewählt
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: ComboBox für vorhandene Laufwerke 
Autor: Manfred X
Datum: 27.05.19 18:21

Was machst Du eigentlich?
Eine Combobox macht man auf, wählt den Eintrag und macht sie zu.
Man läßt diese Liste nicht offen.
Wieso soll die DropdownList direkt optisch auf Drive-Änderungen reagieren?

Setze die Dropdownstyle-Eigemschaft der Combobox auf DropDownlist und
ergänze folgenden Code:

    Private Sub SetDriveBinding()
        bsDrives.ResetBindings(False)
        Dim droppeddown As Boolean
        With cboDrives
            If .DroppedDown Then
                'Dropdown ggf. schließen
                .DroppedDown = False
                droppeddown = True
            End If
        End With
        SetSelectedDrive(droppeddown)
    End Sub
 
 
    Private Sub SetSelectedDrive(droppeddown As Boolean)
        Dim found As Boolean
        If String.IsNullOrEmpty(SelectedDrive) Then Exit Sub
        If lstdrives.Count = 0 Then Exit Sub
 
        For i As Integer = 0 To lstdrives.Count - 1
            If lstdrives(i).StartsWith(SelectedDrive) Then
                cboDrives.SelectedIndex = i : found = True
            End If
        Next i
        If Not found Then cboDrives.SelectedIndex = 0
 
        'Dropdown ggf. wieder öffnen 
        cboDrives.DroppedDown = droppeddown
    End Sub
Einbinden der Combobox:
Die Bindingsource der Datasource-Eigenschaft Deiner Combobox zuweisen.
Den Invoke-Aufruf auf die Eigenschaft Deiner Combo umsetzen.
Die Handles-Klausel der SelectedIndexChanged-HandlerRoutine auf Deine Combobox umsetzen.
Den obigen Code für Deine Combo umbenennen.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Sie sind nicht angemeldet!
Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.

Einloggen  |  Neu registrieren

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel