Imports System.Globalization Imports System.IO Imports Emgu.CV.Flann Public Class SetConfigForm Private Const IdCamEmpty As String = " --- " Private m_myImage As Image Private m_UpdatingDataSource As Boolean = False ' Indice della riga correntemente selezionata Private m_nCurrIndexRow As Integer = 0 ' Nome della configurazione corrente del programma Private m_sCurrAppliedIdCfg As String = 0 Private Enum ICO ERR_ = -1 WARNING_ = 0 OK_ = 2 End Enum Private Enum COLUMN ID_CFG = 0 CFG_ICO = 1 ID_CAM = 2 CAM_ICO = 3 SAVE_CMD = 4 APPLY_CMD = 5 End Enum ' Elementi che popolano la lista delle camere disponibili Private Structure EbnableCamItem ' Indica l'Id della camera Public IdCam As String ' Indica se l'Id è già stato assegnato ad una configurazione Public IsEnable As Boolean ' Indice se l'Id della camera è connessa Public IsConnected As Boolean ' Indica l'id della configurazione in cui è in uso Public IdCfg As List(Of String) End Structure ' Lista degli Id REALMENTE disponibili Private EnableCamList As New List(Of EbnableCamItem) Sub New() ' La chiamata è richiesta dalla finestra di progettazione. InitializeComponent() ' Aggiungere le eventuali istruzioni di inizializzazione dopo la chiamata a InitializeComponent(). End Sub ' OK: popolo la datagrid all'avvio del programma Private Sub LoadWindows() Handles Me.Load EnableCamList.Clear() ' Preparo lisra EnableCamList LoadListOfEnableCamItem() ' Popola la DataGridView e al caricamento seleziono la riga del'IdCfg impostato PopolateDataGrid(True) ' recupero il nome della configurazione impostata m_sCurrAppliedIdCfg = If(FrmMain.ComboBoxCameraCfg.SelectedItem.Equals("Default"), "0", FrmMain.ComboBoxCameraCfg.SelectedItem) End Sub #Region "METODI GESTIONE COMBOBOX" ' ------- INIZIO ------- gestione EnableCamList ---------------------------- ' OK: Costruisco la lista EnableCamList sulla base delle configurazioni salvate Private Sub LoadListOfEnableCamItem() Dim DirToReadCfg As String = FrmMain.sDataRoot ' Assegnno di defualt una camera VUOTA Dim NOCam As EbnableCamItem NOCam.IdCam = IdCamEmpty NOCam.IsEnable = True NOCam.IsConnected = False NOCam.IdCfg = New List(Of String) EnableCamList.Add(NOCam) ' Inizializzo la lista con le camere realmente disponibili (IsEnable=true) For Each CameraItem As String In FrmMain.ComboBoxCameras.Items Dim ItemCam As EbnableCamItem ItemCam.IdCam = CameraItem ItemCam.IsEnable = True ItemCam.IsConnected = True ItemCam.IdCfg = New List(Of String) EnableCamList.Add(ItemCam) Next ' Per ogni camera disponibile assegno l'ID della configuraione associata For Each CfgItem As String In FrmMain.ComboBoxCameraCfg.Items CfgItem = If(CfgItem = "Default", String.Empty, CfgItem) Dim NomeFileCfg As String = DirToReadCfg & CfgItem & "\CameraMng.cfg" ' Recupero l'Id della camera configurata nel file Cfg Dim IDCameraFromCgf As String = ReadIdCameraFromCfg(NomeFileCfg) ' Se esiste l'Id If Not String.IsNullOrEmpty(IDCameraFromCgf) Then ' Verifico se l'Id della camera è connessa Dim IndID As Integer = EnableCamList.FindIndex(Function(x) x.IdCam = IDCameraFromCgf) If IndID < 0 Then ' l'Id della camera non è nell'elenco delle camere connesse: lo aggiungo Dim ItemCam As EbnableCamItem ItemCam.IdCam = IDCameraFromCgf ItemCam.IsEnable = False ItemCam.IsConnected = False ItemCam.IdCfg = New List(Of String)({CfgItem}) EnableCamList.Add(ItemCam) Else ' Recupero l'oggetto associato alla camera corrente Dim CurrCam As EbnableCamItem = EnableCamList(IndID) ' l'Id della camera è connessa: aggiorno l'Id dalla configurazione CurrCam.IsEnable = False CurrCam.IdCfg.Add(CfgItem) ' Riassegno alla lista (solo la lista IdCfg viene aggiornata veramente...) EnableCamList(IndID) = CurrCam End If Else ' l'Id della camera non esiste (recupero la prima camera), ma una configurazione si Dim IndID As Integer = 0 Dim CurrCam As EbnableCamItem = EnableCamList(IndID) CurrCam.IdCfg.Add(CfgItem) End If Next End Sub ' OK: Data la config e il nuvo IDCam mi occupo di aggiornare la lista EnableCamList (NON DataGridView) Private Sub UpdateListOfEnableCamItem(CfgItem As String, NewIdCam As String) ' Recupero la camera assegnata alla configurazione Dim IndIDCam As Integer = GetCurrCamIndFromCfg(CfgItem) If IndIDCam > EnableCamList.Count - 1 Then Return Dim CurrCam As EbnableCamItem = EnableCamList(IndIDCam) If IsNothing(CurrCam) Then Return ' Verifico che sia presente in elenco If CurrCam.IdCfg.FindIndex((Function(x) x = CfgItem)) < 0 Then Return ' Rimuovo questo elemento dalla lista delle configurazioni (per rifereminto si aggiorna anche la lista) CurrCam.IdCfg.Remove(CfgItem) ' Se la camera non ha nessun assegnamento allora aggiorno lo stato If CurrCam.IdCfg.Count < 1 Then CurrCam.IsEnable = True EnableCamList(IndIDCam) = CurrCam End If IndIDCam = EnableCamList.FindIndex((Function(x) x.IdCam = NewIdCam)) If IndIDCam > -1 Then CurrCam = EnableCamList(IndIDCam) ' verifico che non sia già inserito in elenco (se la grafica non fosse allineata...) If CurrCam.IdCfg.FindIndex((Function(x) x = CfgItem)) < 0 Then CurrCam.IdCfg.Add(CfgItem) ' Aggiorno anche lo stato If CurrCam.IdCam <> IdCamEmpty And CurrCam.IsEnable Then CurrCam.IsEnable = False EnableCamList(IndIDCam) = CurrCam End If End If End If End Sub ' ------- FINE ------- gestione EnableCamList ---------------------------- ' OK: Carico gli elementi della tabella (n_CurrIndex: indice selezionato); bFirstRun: set la config applicata Private Sub PopolateDataGrid(Optional bFirstRun As Boolean = False) ' Ripulisco tutti i dati della datagrid DataGridView1.Rows.Clear() ' Per ogni configurazione genero una riga della datagrid For Each CfgItem As String In FrmMain.ComboBoxCameraCfg.Items CfgItem = If(CfgItem = "Default", String.Empty, CfgItem) ' Creo una nuova riga della tabella Dim riga As New DataGridViewRow() ' Crea le celle corrispondenti alle colonne riga.CreateCells(DataGridView1) ' Popolo text con configurazione: assegno Indice della configurazione riga.Cells(COLUMN.ID_CFG).Value = CfgItem ' Aggiorno le icone (leggendo la lista EnableCamList) RefreshIcoAndComboBox(riga) riga.Cells(COLUMN.SAVE_CMD).Value = "Save" riga.Cells(COLUMN.APPLY_CMD).Value = "Apply" ' Aggiungi la riga completa al DataGridView DataGridView1.Rows.Add(riga) ' Imposto la configurazione corrente come attiva If bFirstRun And CfgItem = FrmMain.ComboBoxCameraCfg.SelectedItem Then ' --> DataGridView1.ClearSelection() ' Recupero l'indice della riga corrente che deve rimanere selezionata Dim LastIndexRow As Integer = DataGridView1.Rows.Count - 1 ' --> DataGridView1.Rows(DataGridView1.Rows.Count - 1).Selected = True ' Imposto la selezione sulla riga corrente SelectCurrIndexRow(LastIndexRow) ' Indico in grassetto il comando Apply della configurazione corrente SetStatusApplyFont(LastIndexRow, True) End If Next ' Seleziono la riga associata alla configurazione impostata End Sub ' OK: Assegna le nuove combobox per ogni configurazione Private Sub UpdateDataGridView() ' Aggiorno le lista degli ID camera per ogni riga della tabella For IndexRow As Integer = 0 To DataGridView1.Rows.Count - 1 ' recupero la riga corrente della tabella Dim riga As DataGridViewRow = DataGridView1.Rows(IndexRow) ' Aggiorno la lista della combobox e le icone RefreshIcoAndComboBox(riga) Next End Sub ' OK: Recupero l'INDICE (della lista EnableCmaList) della camera associata a CfgItem Private Function GetCurrCamIndFromCfg(CfgItem As String) As Integer Dim IndIDCam As Integer = 0 For Ind As Integer = 0 To EnableCamList.Count - 1 If EnableCamList(Ind).IdCfg.FindIndex((Function(y) y = CfgItem)) > -1 Then IndIDCam = Ind Exit For End If Next Return IndIDCam End Function ' OK: Lettura dell'IDCam dal file di configurazione Private Function ReadIdCameraFromCfg(NomeFileCfg As String) As String Dim IDCamera As String = String.Empty Dim reader As New StreamReader(NomeFileCfg) Dim nfi As NumberFormatInfo = New CultureInfo("en-US", False).NumberFormat nfi.NumberDecimalSeparator = "." Dim TmpString As String = "" Try While (Not reader.EndOfStream) TmpString = reader.ReadLine() If TmpString.StartsWith("CameraID=") Then IDCamera = Mid(TmpString, 10) Exit While End If End While reader.Close() reader.Dispose() Catch ex As Exception MsgBox("Error in Cfg File " & TmpString) End Try Return IDCamera End Function ' OK: Restituisce l'immagine associata all'Enum indicato Private Function GetCurrIco(Index As Integer) As Image Select Case Index Case ICO.ERR_ m_myImage = My.Resources.cross Case ICO.WARNING_ m_myImage = My.Resources.warning Case Else m_myImage = My.Resources.accept End Select Return m_myImage End Function ' OK: Salva l'IDCam nella configurazione corrente Public Sub SaveIDCamera(IDConfing As String, IDCamera As String) Dim NomeFileCfg, TmpString As String Dim NomeFileTempCfg, DirToReadCfg As String Dim SaveFileCfg As String Dim nf As Integer Dim writer As StreamWriter Try If IDConfing.Contains("Default") Then IDConfing = "" DirToReadCfg = FrmMain.sDataRoot & IDConfing NomeFileCfg = DirToReadCfg & "\CameraMng.cfg" NomeFileTempCfg = DirToReadCfg & "\CameraMngTmp.cfg" SaveFileCfg = DirToReadCfg & "\CameraMng" & Format(Now, "yyyyMMddhhmmss") & ".cfg" If (File.Exists(NomeFileTempCfg)) Then File.Delete(NomeFileTempCfg) End If nf = FreeFile() FileOpen(nf, NomeFileCfg, OpenMode.Input) writer = New StreamWriter(NomeFileTempCfg) TmpString = "" While Not EOF(nf) TmpString = LineInput(nf) If Not TmpString.StartsWith("CameraID=") Then writer.WriteLine(TmpString, CultureInfo.InvariantCulture) End If End While writer.WriteLine("CameraID=" & If(IDCamera = IdCamEmpty, "", IDCamera), CultureInfo.InvariantCulture) FileClose(nf) writer.Close() File.Copy(NomeFileCfg, SaveFileCfg) If (File.Exists(NomeFileCfg)) Then File.Delete(NomeFileCfg) End If File.Copy(NomeFileTempCfg, NomeFileCfg) File.Delete(NomeFileTempCfg) MessageBox.Show("New ID succesfully written on '" & NomeFileCfg & "'.", "Avviso", MessageBoxButtons.OK, MessageBoxIcon.Information) Catch ex As Exception MsgBox("Error in Writing Cfg File " & ex.Message) End Try End Sub ' OK: Data la riga della DataGrid viene assegnato il font: bSet=True -> BOLD, bSet=False -> REGULAR Private Sub SetStatusApplyFont(IndexRowDataGrid As Integer, bSet As Boolean) If IndexRowDataGrid > -1 Then Dim ApplyCellButton As DataGridViewButtonCell = CType(DataGridView1.Rows(IndexRowDataGrid).Cells(COLUMN.APPLY_CMD), DataGridViewButtonCell) Dim CurrFont As Font = ApplyCellButton.Style.Font ' Crea un nuovo font basato su quello esistente, ma con stile Regular If IsNothing(CurrFont) Then CurrFont = Me.DataGridView1.Font ApplyCellButton.Style.Font = New Font(CurrFont, If(bSet, FontStyle.Bold, FontStyle.Regular)) End If End Sub ' OK: Aggiorno la DataGrid per visualizzare la configurazione attiva Private Function ApplyCurrCfg(CurrIdCfg As String, Optional bForce As Boolean = False) As Boolean ' Se il nome della configurazione corrente è già attivo allora esco If (m_sCurrAppliedIdCfg = CurrIdCfg And Not bForce) And String.IsNullOrEmpty(CurrIdCfg) Then Return False ' Recupero l'indice della DataGrid associato alla configurazione applicata: rimuovo il font BOLD Dim IndAppliedIdCfg As Integer = -1 For Index As Integer = 0 To DataGridView1.Rows.Count - 1 If DataGridView1.Rows(Index).Cells(COLUMN.ID_CFG).Value = m_sCurrAppliedIdCfg Then IndAppliedIdCfg = Index Exit For End If Next ' Ripristino il font Regular SetStatusApplyFont(IndAppliedIdCfg, False) ' Recupero l'indice della DataGrid associato alla configurazione Dim IndCurrIdCfg As Integer = -1 For Index As Integer = 0 To DataGridView1.Rows.Count - 1 If DataGridView1.Rows(Index).Cells(COLUMN.ID_CFG).Value = CurrIdCfg Then IndCurrIdCfg = Index Exit For End If Next ' Applico il font Bold SetStatusApplyFont(IndCurrIdCfg, True) ' Assegno come applicata cfg corrente m_sCurrAppliedIdCfg = CurrIdCfg Return True End Function #End Region ' Metodi gestione combobox ' OK: Aggiorna l'icone della riga corrente Private Function RefreshIcoAndComboBox(ByRef riga As DataGridViewRow) As Boolean 'Dim riga As DataGridViewRow = DataGridView1.Rows(IndexRow) Dim CfgItem As String = riga.Cells(COLUMN.ID_CFG).Value ' Recupero la camera assegnata alla configurazione Dim IndIDCam As Integer = GetCurrCamIndFromCfg(CfgItem) If IndIDCam > EnableCamList.Count - 1 Then Return False Dim CurrCam As EbnableCamItem = EnableCamList(IndIDCam) If IsNothing(CurrCam) Then Return False ' Configurazione delle icone della pagina If CurrCam.IdCam = IdCamEmpty Then ' CFG ICO riga.Cells(COLUMN.CFG_ICO).Value = GetCurrIco(ICO.ERR_) ' CAM ICO riga.Cells(COLUMN.CAM_ICO).Value = GetCurrIco(ICO.ERR_) Else ' CFG ICO If CurrCam.IdCfg(0) = CfgItem Then riga.Cells(COLUMN.CFG_ICO).Value = GetCurrIco(ICO.OK_) Else riga.Cells(COLUMN.CFG_ICO).Value = GetCurrIco(ICO.WARNING_) End If ' CAM ICO If CurrCam.IsConnected Then riga.Cells(COLUMN.CAM_ICO).Value = GetCurrIco(ICO.OK_) Else riga.Cells(COLUMN.CAM_ICO).Value = GetCurrIco(ICO.WARNING_) End If End If ' Creo la lista degli IdCam disponibili per la configurazione corrente Dim CamList As New List(Of String) ' Procedo alla creazione della lista delle camere libere For Each CameraItem As EbnableCamItem In EnableCamList If CameraItem.IsEnable Then CamList.Add(CameraItem.IdCam) End If Next ' Aggiungo la camera assegnata a questa configurazione If CurrCam.IdCam <> IdCamEmpty Then CamList.Add(CurrCam.IdCam) ' Se la camera non è in elenco tra le camere disponibili (Id già occupato) If CamList.IndexOf(CurrCam.IdCam) < 0 Then CamList.Add(CurrCam.IdCam) End If If m_nCurrIndexRow = riga.Index Then Dim Pippo As Boolean = True End If ' Assegno la lista alla cella ComboBox Dim comboBoxCell As DataGridViewComboBoxCell = TryCast(riga.Cells.Item(COLUMN.ID_CAM), DataGridViewComboBoxCell) If Not IsNothing(comboBoxCell) Then m_UpdatingDataSource = True ' Imposto l'ID della camera (sembra che questa assegnazione non generi nessun evento) comboBoxCell.Value = CurrCam.IdCam ' verifice che le due liste siano uguali Dim bAreSame As Boolean = False If Not IsNothing(comboBoxCell.DataSource) Then ' Ad ogni assegnazione della lista viene lanciato l'evento bAreSame = True If comboBoxCell.DataSource.Count <> CamList.Count Then ' Hanno numero di elementi differenti: quindi sicuramente diverse bAreSame = False Else ' Verifico che tutti gli elementi di una lista siano anche nell'altra For Each Item As String In comboBoxCell.DataSource If CamList.FindIndex(Function(x) x = Item) < 0 Then bAreSame = False Exit For End If Next End If End If ' Se le liste sono diverse anche per contenuto allora ricarico If Not bAreSame Then comboBoxCell.DataSource = CamList m_UpdatingDataSource = False End If Return True End Function ' Aggiorno la selezione della tabella e setto la riga corrente nella variabile m_nCurrIndexRow Private Sub SelectCurrIndexRow(IndexRow As Integer) ' Verifico che l'indice di riga sia valido If IndexRow < 0 Or IndexRow > DataGridView1.RowCount Then Return ' Se la selezione è la stessa riga che è in uso allora non aggiorno If IndexRow = m_nCurrIndexRow Then Return Me.Invalidate() DataGridView1.ClearSelection() DataGridView1.Rows(IndexRow).Selected = True m_nCurrIndexRow = IndexRow End Sub #Region "EVENTS" 'Private CMB As ComboBox ' Selezione ComboBox Private Sub DataGridView1_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing ' Seleziono la riga indicata SelectCurrIndexRow(DataGridView1.CurrentCell.RowIndex) ' Controlla se la cella corrente è nella colonna della ComboBox e se il controllo è una ComboBox If DataGridView1.CurrentCell.ColumnIndex = DataGridView1.Columns("ComboCamera").Index AndAlso TypeOf e.Control Is ComboBox Then Dim comboBox As ComboBox = TryCast(e.Control, ComboBox) If comboBox IsNot Nothing Then ' Salvo un riferimento alla combobox selezionata: viene cancellato il riferimento al termine della selezione 'CMB = comboBox ' Rimuovi i gestori precedenti per evitare agganci multipli RemoveHandler comboBox.SelectedIndexChanged, AddressOf DataGridViewComboBox_SelectedIndexChanged 'Aggiungo il gestore eventi per l'evento SelectedIndexChanged della ComboBox AddHandler comboBox.SelectedIndexChanged, AddressOf DataGridViewComboBox_SelectedIndexChanged End If End If End Sub ' Questo è il gestore eventi che si attiverà quando l'utente seleziona un elemento nella ComboBox -- Handles DataGridView1.EditingControlShowing Private Sub DataGridViewComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Dim comboBox As ComboBox = TryCast(sender, ComboBox) 'Dim comboBox As ComboBox = CMB If Not IsNothing(comboBox) AndAlso Not IsNothing(comboBox.SelectedItem) Then ' Nuovo valore Dim selectedValue As String = comboBox.SelectedItem.ToString() Dim currentRowIndex As Integer = DataGridView1.CurrentCell.RowIndex ' Precedente valore Dim IDCamera As String = If(Not IsNothing(DataGridView1.Rows(currentRowIndex).Cells("ComboCamera").Value), DataGridView1.Rows(currentRowIndex).Cells("ComboCamera").Value.ToString(), String.Empty) ' Id della configurazione corrente Dim IDCfg As String = DataGridView1.Rows(currentRowIndex).Cells("Config").Value.ToString() If IDCamera <> selectedValue Then ' Aggiorno l'elenco EnableCamList If Not m_UpdatingDataSource Then UpdateListOfEnableCamItem(IDCfg, selectedValue) Else UpdateListOfEnableCamItem(IDCfg, IDCamera) End If ' Ricostruisco la DataGrid UpdateDataGridView() ' Aggiorno il valore del bottone DataGridView1.Rows(currentRowIndex).Cells(COLUMN.SAVE_CMD).Value = "Save*" End If End If End Sub ' Selezione del valore di una cella: gestione dei bottoni SAVE & APPLY Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick ' Controlla che il click non sia sull'intestazione della colonna If e.RowIndex < 0 Then Return ' seleziona la riga indicata SelectCurrIndexRow(e.RowIndex) If e.ColumnIndex < 0 Then Return ' recupero l'Id della configurazione e l'Id della camera Dim sIDConfig As String = DataGridView1.Rows(m_nCurrIndexRow).Cells("Config").Value.ToString() Dim sIDCamera As String = If(Not IsNothing(DataGridView1.Rows(m_nCurrIndexRow).Cells("ComboCamera").Value), DataGridView1.Rows(e.RowIndex).Cells("ComboCamera").Value.ToString(), String.Empty) ' Controlla se il click è avvenuto nella colonna dei bottoni (Usa il nome che hai dato alla colonna) If Me.DataGridView1.Columns(e.ColumnIndex).Name = "SaveConfig" Then If Not String.IsNullOrEmpty(sIDConfig) Then SaveIDCamera(sIDConfig, sIDCamera) DataGridView1.Rows(m_nCurrIndexRow).Cells(COLUMN.SAVE_CMD).Value = "Save" '' Aggiorno l'elenco EnableCamList 'UpdateListOfEnableCamItem(sIDConfig, sIDCamera) '' Ricostruisco la DataGrid SENZA forzare la selezione della riga 'PopolateDataGrid(False) End If ' Se la configurazione è applicata allora procedo ad aggiornare anche il programma If m_sCurrAppliedIdCfg = sIDConfig Then If Not ApplyCurrCfg(sIDConfig, True) Then Return ' seleziona la riga indicata SelectCurrIndexRow(e.RowIndex) ' Aggiorno la camera in uso nel programma Dim IndCamera As Integer = FrmMain.ComboBoxCameras.Items.IndexOf(sIDCamera) If IndCamera > -1 Then FrmMain.ComboBoxCameras.SelectedIndex = IndCamera Dim IndCameraCfg As Integer = FrmMain.ComboBoxCameraCfg.Items.IndexOf(sIDConfig) If IndCameraCfg > -1 Then FrmMain.ComboBoxCameraCfg.SelectedIndex = IndCameraCfg End If ElseIf Me.DataGridView1.Columns(e.ColumnIndex).Name = "ApplyConfig" Then If Not String.IsNullOrEmpty(sIDConfig) And Not String.IsNullOrEmpty(sIDCamera) And sIDCamera <> IdCamEmpty Then ' Verifico che non ci sia una modifica attiva If DataGridView1.Rows(m_nCurrIndexRow).Cells(COLUMN.SAVE_CMD).Value.ToString().Contains("*"c) Then MessageBox.Show("Salvare la configurazione prima di applicarla.", "Informazione", MessageBoxButtons.OK, MessageBoxIcon.Asterisk) Return End If If Not ApplyCurrCfg(sIDConfig) Then Return ' seleziona la riga indicata SelectCurrIndexRow(e.RowIndex) ' Aggiorno la camera in uso nel programma Dim IndCamera As Integer = FrmMain.ComboBoxCameras.Items.IndexOf(sIDCamera) If IndCamera > -1 Then FrmMain.ComboBoxCameras.SelectedIndex = IndCamera Dim IndCameraCfg As Integer = FrmMain.ComboBoxCameraCfg.Items.IndexOf(sIDConfig) If IndCameraCfg > -1 Then FrmMain.ComboBoxCameraCfg.SelectedIndex = IndCameraCfg Else MessageBox.Show("Non è possibile applicare una configurazione di una camera non connessa.", "Avviso", MessageBoxButtons.OK, MessageBoxIcon.Asterisk) End If ElseIf Me.DataGridView1.Columns(e.ColumnIndex).Name = "ComboCamera" Then ' riconosco che è stata selezionata la combobox End If End Sub ' Chiusura della finestra Private Sub SetConfig_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing ' FORZA LA FINE DELLA MODALITÀ DI MODIFICA Me.Validate() Dim result As DialogResult Dim ListOfIndexModifiedCfg As New List(Of Integer) Dim bExit As Boolean = True For IndexRow As Integer = 0 To DataGridView1.Rows.Count - 1 ' Verifico se ci sia nessuna modifica attiva If DataGridView1.Rows(IndexRow).Cells(COLUMN.SAVE_CMD).Value = "Save*" Then ListOfIndexModifiedCfg.Add(IndexRow) bExit = False End If Next ' Se non ci sono modifiche allora esco subito If bExit Then Return ' Costruisco il messaggio in funzione del numero di elementi presenti Dim sMsg As String = "Vuoi salvare la modifica corrente?" If ListOfIndexModifiedCfg.Count > 1 Then sMsg = "Vuoi salvare le modifiche correnti?" End If result = MessageBox.Show(sMsg, "Attenzione", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning) Select Case result Case DialogResult.Yes ' Salvataggio For Each IndexRow As Integer In ListOfIndexModifiedCfg ' Salvataggio SaveIDCamera(DataGridView1.Rows(IndexRow).Cells(COLUMN.ID_CFG).Value, DataGridView1.Rows(IndexRow).Cells(COLUMN.ID_CAM).Value) Next Case DialogResult.No ' La finestra si chiuderà normalmente. Non fare nulla. Return Case DialogResult.Cancel ' L'utente ha annullato l'operazione. Annulla la chiusura della finestra. e.Cancel = True End Select ' Al termine la finestra viene chiusa End Sub #End Region ' Events End Class