Imports System.IO Imports DevExpress Imports DevExpress.Spreadsheet Imports DevExpress.XtraRichEdit.Commands Imports DevExpress.Office.Utils Imports GdPicture14 Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Messaging Imports DigitalData.Modules.Config Public Class DocumentViewer Private Enum ZoomMode Zoom50 Zoom100 Zoom150 Zoom200 ZoomSelectedArea ZoomFitToViewer ZoomFitWidth ZoomFitHeight End Enum Private Enum ViewerMode GDPicture Excel Richtext End Enum Private Enum FileLoadMode File Stream End Enum Public ReadOnly Property PdfViewer As GdViewer Get Return GdViewer End Get End Property Private _logConfig As LogConfig Private _logger As Logger Private _Config As ConfigManager(Of Config) Private _email As Email2 Private _ViewerMode As ViewerMode Private _licenseKey As String = String.Empty Private _licenseManager As New GdPicture14.LicenseManager() Private _Search As Search Private _Annotations As Annotations Private _AnnotationsPending As Boolean = False Private _ToolbarSettings As New ToolbarSettings Private _hide_file_info_from_user As Boolean = False Private _FileStream As Stream Private _FilePath As String Private _FileInfo As FileInfo Private _FileLoadMode As FileLoadMode = FileLoadMode.File Private _ViewOverride As String = "" ' List of all created temp files when converting msg files Private _TempFiles As New List(Of String) Private Sub DocumentViewer_Load(sender As Object, e As EventArgs) Handles Me.Load ' Ensure search is initialized once the control (and GdViewer) exists EnsureSearchInitialized() UpdateMainUi() End Sub 'hallo Public Class ToolbarSettings Public Property ShowPrintButton As Boolean = True Public Property ShowFitWidthButton As Boolean = True Public Property ShowFitPageButton As Boolean = True Public Property ShowZoomButton As Boolean = True Public Property ShowRotateButton As Boolean = True Public Property ShowFlipButton As Boolean = True Public Property ShowSearchButton As Boolean = True Public Property ShowSettingButton As Boolean = True End Class Public Property FileLoaded As Boolean = False Public Property Viewer_ForceTemporaryMode As Boolean = False Public ReadOnly Property AnnotationsSaved As Boolean Get Return Not _AnnotationsPending End Get End Property ''' ''' Initialize the Viewer ''' ''' A LogConfig object ''' The GDPicture.NET License Key Public Function Init(pLogConfig As LogConfig, pLicenseKey As String, Optional pToolbarSettings As ToolbarSettings = Nothing) As Boolean _logConfig = pLogConfig _logger = pLogConfig.GetLogger() If pToolbarSettings Is Nothing Then pToolbarSettings = New ToolbarSettings End If Try _email = New Email2(pLogConfig) If pLicenseKey = String.Empty Then _logger.Warn("License key was not provided during init-process!") Return False End If _licenseKey = pLicenseKey _licenseManager.RegisterKEY(_licenseKey) _Annotations = New Annotations(pLogConfig) ' Defer creating Search until GdViewer is ready EnsureSearchInitialized() _ToolbarSettings = pToolbarSettings Dim oConfigPath = ConfigPath() _Config = New ConfigManager(Of Config)(pLogConfig, oConfigPath) Return True Catch ex As Exception _logger.Error(ex) Return False End Try End Function ' Create the Search helper only when both the log config and the GdViewer control exist Private Sub EnsureSearchInitialized() Try If _Search Is Nothing AndAlso _logConfig IsNot Nothing AndAlso GdViewer IsNot Nothing Then _Search = New Search(_logConfig, GdViewer) End If Catch ex As Exception _logger?.Error(ex) End Try End Sub ''' ''' Load a file from a path and display it ''' Public Sub LoadFile(FilePath As String) FileLoaded = False If _licenseKey = String.Empty Then _logger.Warn("License key was not provided. File {0} not loaded.", FilePath) Exit Sub End If If FilePath Is Nothing OrElse FilePath.Trim().Length = 0 Then _logger.Warn("FilePath was not provided. File not loaded.") Exit Sub End If _FilePath = FilePath _FileLoadMode = FileLoadMode.File _FileInfo = New FileInfo(FilePath) _logger.Info("Loading file [{0}] from Filesystem", FilePath) SetViewerMode(_FileInfo.Extension) FileLoaded = DoLoadFile(FilePath) UpdateMainUi() End Sub ''' ''' Load a file from a stream and display it ''' Public Sub LoadFile(FileName As String, Stream As Stream) FileLoaded = False Dim oExtension As String = FileName.Substring(FileName.LastIndexOf(".")) _FileStream = Stream _FileLoadMode = FileLoadMode.Stream _logger.Info("Loading file [{0}] from Stream", FileName) FileLoaded = DoLoadFile(Stream, oExtension) SetViewerMode(oExtension) UpdateMainUi() End Sub ''' ''' Terminate Viewer, freeing up resources and deleting temp files ''' Public Sub Done() Try _logger.Debug("Done: Deleting Temp Files") DeleteTempFiles() _logger.Debug("Done: Closing Documents") FreeFile() _logger.Debug("Done: Triggering GC") GC.Collect() Catch ex As Exception _logger.Warn("Error while cleaning up DocumentViewer") _logger.Error(ex) End Try End Sub Public Function AddAnnotation(pText As String) As Boolean Dim oFontStyle = FontStyle.Regular Dim oFontColor = Color.Black Dim oFontFamily = "Arial" Dim oFontSize = 8 Dim oBorderColor = Color.Red Dim oBackColor = Color.LightYellow Dim oOpacity = 1.0F Dim oRotation = 0.0F GdViewer.AddTextAnnotationInteractive(pText, oFontColor, oFontFamily, oFontStyle, oFontSize, Fill:=True, oBorderColor, oBackColor, oOpacity, oRotation) _AnnotationsPending = True Return True End Function Public Function Save() As Boolean Dim oSaveResult As GdPictureStatus = GdPictureStatus.OK If GdViewer.BurnAnnotationsToPage(True, False) = GdPictureStatus.OK Then If _FileLoadMode = FileLoadMode.Stream Then oSaveResult = GdViewer.SaveDocumentToPDF(_FileStream) Else oSaveResult = GdViewer.SaveDocumentToPDF(_FilePath) End If End If If oSaveResult = GdPictureStatus.OK Then _AnnotationsPending = False Return True Else Return False End If End Function Public Sub CloseDocument() Try ' Null-sicher schließen If GdViewer IsNot Nothing Then Try GdViewer.CloseDocument() Catch exInner As Exception _logger?.Warn("Fehler beim Schließen von GdViewer") _logger?.Error(exInner) End Try Else _logger?.Debug("CloseDocument: GdViewer ist Nothing – nichts zu schließen") End If _FileInfo = Nothing _FilePath = Nothing _FileStream = Nothing UpdateMainUi() Catch ex As Exception _logger.Error(ex) End Try End Sub ''' ''' Configures the viewer to hide the file path to the end-user. ''' ''' ''' True means that all file info should be hidden from the end-user ''' False means the end user may see the filepath or other info about the file ''' Public Sub SetViewOnly(ViewOnly As Boolean) If ViewOnly Then buttonPrint.Visibility = XtraBars.BarItemVisibility.Never Else buttonPrint.Visibility = XtraBars.BarItemVisibility.Always End If _hide_file_info_from_user = ViewOnly End Sub Public Sub SetAllowAnnotations(AllowAnnotations As Boolean) End Sub ''' ''' DEPRECATED: Use SetViewOnly ''' Public Sub RightViewOnly(ViewOnly As Boolean) SetViewOnly(ViewOnly) End Sub ''' ''' DEPRECATED: Use SetViewOnly ''' Public Sub RightOnlyView(ViewOnly As Boolean) SetViewOnly(ViewOnly) End Sub #Region "Form Events" Private Sub btnFitWidth_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonFitWidth.ItemClick FitToWidth() _Config.Config.PageFit = Config.PageFitSetting.FitWidth _Config.Save() End Sub Private Sub btnFitPage_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonFitPage.ItemClick FitToPage() _Config.Config.PageFit = Config.PageFitSetting.FitPage _Config.Save() End Sub Private Sub btnOpen_Click(sender As Object, e As EventArgs) GdViewer.ZoomMode = ViewerZoomMode.ZoomModeWidthViewer GdViewer.DocumentAlignment = ViewerDocumentAlignment.DocumentAlignmentTopCenter If OpenFileDialog.ShowDialog() = DialogResult.OK Then GdViewer.DisplayFromFile(OpenFileDialog.FileName) End If GdViewer.Focus() UpdateMainUi() End Sub Private Sub BtnFirstPage_Click(ByVal sender As System.Object, ByVal e As EventArgs) Handles buttonFirstPage.ItemClick GdViewer.DisplayFirstPage() End Sub Private Sub BtnPreviousPage_Click(ByVal sender As System.Object, ByVal e As EventArgs) Handles buttonPrevPage.ItemClick GdViewer.DisplayPreviousPage() End Sub Private Sub BtnNextPage_Click(ByVal sender As System.Object, ByVal e As EventArgs) Handles buttonNextPage.ItemClick GdViewer.DisplayNextPage() End Sub Private Sub BtnLastPage_Click(ByVal sender As System.Object, ByVal e As EventArgs) Handles buttonLastPage.ItemClick GdViewer.DisplayLastPage() End Sub Private Sub TbCurrentPage_Leave(ByVal sender As System.Object, ByVal e As EventArgs) Handles txtCurrentPage.EditValueChanged Dim page As Integer = 0 If Integer.TryParse(txtCurrentPage.EditValue, page) Then If page > 0 And page <= GdViewer.PageCount Then GdViewer.DisplayPage(page) UpdateaNavigationToolbar() End If End If End Sub Private Sub GdViewer1_PageChanged() Handles GdViewer.PageChanged UpdateaNavigationToolbar() End Sub Private Sub GdViewer1_AfterZoomChange() Handles GdViewer.AfterZoomChange UpdateaNavigationToolbar() If GdViewer.MouseMode = ViewerMouseMode.MouseModeAreaZooming Then GdViewer.MouseMode = ViewerMouseMode.MouseModePan End If End Sub Private Sub btnZoomOut_Click(sender As Object, e As EventArgs) Handles buttonZoomOut.ItemClick GdViewer.ZoomOUT() End Sub Private Sub btnZoomIn_Click(sender As Object, e As EventArgs) Handles buttonZoomIn.ItemClick GdViewer.ZoomIN() End Sub Private Sub btnPrint_Click(sender As Object, e As EventArgs) Handles buttonPrint.ItemClick If GdViewer.PageCount = 0 Then Return End If GdViewer.PrintDialog() End Sub Private Sub BtnRotateLeft_Click(sender As Object, e As EventArgs) Handles buttonRotateLeft.ItemClick GdViewer.Rotate(RotateFlipType.Rotate270FlipNone) End Sub Private Sub BtnRotateRight_Click(sender As Object, e As EventArgs) Handles buttonRotateRight.ItemClick GdViewer.Rotate(RotateFlipType.Rotate90FlipNone) End Sub Private Sub btnFlipX_Click(sender As Object, e As EventArgs) Handles buttonFlipX.ItemClick GdViewer.Rotate(RotateFlipType.RotateNoneFlipX) End Sub Private Sub btnFlipY_Click(sender As Object, e As EventArgs) Handles buttonFlipY.ItemClick GdViewer.Rotate(RotateFlipType.RotateNoneFlipY) End Sub Private Sub GdViewer1_TransferEnded(ByVal status As GdPictureStatus, ByVal download As System.Boolean) Handles GdViewer.TransferEnded GdViewer.Focus() UpdateMainUi() End Sub Private Sub AddSearchRegion(ByVal occurence As Integer, ByVal leftCoordinate As Single, ByVal topCoordinate As Single, ByVal regionWidth As Single, ByVal regionheight As Single, ByVal ensureVisibility As Boolean) Dim searchRegion As Integer = GdViewer.AddRegionInches("SearchResult" & occurence, leftCoordinate, topCoordinate, regionWidth, regionheight, ForegroundMixMode.ForegroundMixModeMASKPEN, Color.Yellow) GdViewer.SetRegionEditable(searchRegion, False) If ensureVisibility Then GdViewer.EnsureRegionVisibility(searchRegion) End If End Sub Private Sub BtnSettings_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonSettings.ItemClick Using frmSettings As New frmViewerSettings(GdViewer) frmSettings.ShowDialog(Me) End Using UpdateaNavigationToolbar() End Sub #End Region #Region "Private Functions" Private Function ConfigPath() As String Return Path.Combine(Application.UserAppDataPath, "DocumentViewer") End Function Private Sub UpdateaNavigationToolbar() Try Dim oCurrentZoom As Double = GdViewer.Zoom Dim oCurrentPage As Integer = GdViewer.CurrentPage Dim oPageCount As Integer = GdViewer.PageCount txtCurrentPage.EditValue = oCurrentPage labelPageCount.Caption = $"/ {oPageCount}" If oCurrentPage = oPageCount Then buttonLastPage.Enabled = False buttonNextPage.Enabled = False buttonPrevPage.Enabled = True buttonFirstPage.Enabled = True ElseIf oCurrentPage = 1 Then buttonPrevPage.Enabled = False buttonFirstPage.Enabled = False buttonLastPage.Enabled = True buttonNextPage.Enabled = True Else buttonPrevPage.Enabled = True buttonFirstPage.Enabled = True buttonLastPage.Enabled = True buttonNextPage.Enabled = True End If Catch ex As Exception _logger.Error(ex) End Try End Sub Public Sub DeleteTempFiles() For Each oFile In _TempFiles Try _logger.Debug("Deleting temp file [{0}]", oFile) File.Delete(oFile) Catch ex As Exception _logger.Warn("Could not delete temp file [{0}]", oFile) End Try Next End Sub Private Sub SetViewerMode(Extension As String) If _ViewOverride = "Richtext" Then _ViewerMode = ViewerMode.Richtext Else Select Case Extension.ToUpper Case "CSV" _ViewerMode = ViewerMode.Excel 'Case ".EML", ".DOC", ".DOCX", ".ODT", ".RTF", ".TXT" ' _ViewerMode = ViewerMode.RichText Case Else _ViewerMode = ViewerMode.GDPicture End Select End If End Sub Private Sub FreeFile() Try If Len(_FilePath) = 0 OrElse _FileInfo Is Nothing Then Exit Sub End If Dim oExtension As String = _FileInfo.Extension.ToUpper Select Case _ViewerMode Case ViewerMode.Excel _logger.Debug("Closing Excel Editor") SpreadsheetControl1.CreateNewDocument() Case Else _logger.Debug("Closing GDPicture Viewer") GdViewer.CloseDocument() End Select Catch ex As Exception _logger.Warn($"Unexpected error in FreeFile: {ex.Message}") End Try End Sub Private Function DoLoadFile(FilePath As String, Optional ViewOverride As String = "") As Boolean Try ' Ensure the embedded GdViewer control exists before using it If Not EnsureViewerReady() Then _logger?.Warn("GdViewer control is not initialized yet. Delaying load.") Return False End If lblInfo.Visible = False Dim oFileInfo = New FileInfo(FilePath) Dim oExtension As String = oFileInfo.Extension.ToUpper lbFileNotLoaded.Visible = False SpreadsheetControl1.Visible = False RichEditControl1.Visible = False SpreadsheetControl1.Dock = DockStyle.None RichEditControl1.Dock = DockStyle.None If ViewOverride = "Richtext" Then RichEditControl1.LoadDocument(FilePath, GetDocumentFormat(oExtension)) RichEditControl1.Visible = True GdViewer.Visible = False RichEditControl1.Dock = DockStyle.Fill _ViewOverride = "Richtext" _ViewerMode = ViewerMode.Richtext lblInfo.Visible = True lblInfo.Text = "This docx-file contains a generic error and will be displayed in a reduced viewer. Please try to open the file in WORD" Else _ViewOverride = "" Select Case oExtension.ToUpper Case ".CSV" Dim oFormat = GetSpreadsheetFormat(oExtension) SpreadsheetControl1.LoadDocument(FilePath, oFormat) Dim oRange = SpreadsheetControl1.ActiveWorksheet.GetUsedRange() oRange.AutoFitColumns() SpreadsheetControl1.Visible = True GdViewer.Visible = False SpreadsheetControl1.Dock = DockStyle.Fill Case Else Select Case oExtension.ToUpper Case ".EML", ".DOC", ".DOCX", ".XLS", ".XLSX", ".ODT", ".RTF", ".TXT" GdViewer.ForceTemporaryMode = False End Select GdViewer.ZoomMode = ViewerZoomMode.ZoomModeWidthViewer GdViewer.DocumentAlignment = ViewerDocumentAlignment.DocumentAlignmentTopCenter If Viewer_ForceTemporaryMode = True Then GdViewer.ForceTemporaryMode = True End If GdViewer.AnnotationDropShadow = True GdViewer.BackColor = Color.White Dim oGDPState As GdPicture14.GdPictureStatus = GdViewer.DisplayFromFile(FilePath) If oGDPState <> GdPictureStatus.OK Then _logger.Warn($"GdPictureStatus is [{oGDPState}]") If oExtension.ToUpper = ".DOCX" And oGDPState = GdPictureStatus.GenericError Then DoLoadFile(FilePath, "Richtext") Else Dim oFileName = IO.Path.GetFileName(FilePath) lbFileNotLoaded.Text = String.Format("Datei konnte nicht geladen werden:{0}{1}", vbCrLf, oFileName) lbFileNotLoaded.Visible = True End If Else If GdViewer.Visible = False Then GdViewer.Visible = True End If End If End Select End If If _ViewOverride = "Richtext" Then _ViewerMode = ViewerMode.Richtext End If Return True Catch ex As Exception _logger.Error(ex) Return False End Try End Function ' Ensures the embedded GdViewer control exists and is added to the visual tree Private Function EnsureViewerReady() As Boolean Try ' If the control field is Nothing (e.g., designer not yet created), try to lazy-create and add it If GdViewer Is Nothing Then ' Attempt to find an existing instance by name in Controls collection Dim existing = Me.Controls.OfType(Of GdPicture14.GdViewer)().FirstOrDefault() If existing IsNot Nothing Then ' Assign the designer field via reflection if needed, otherwise use it directly GdViewer = existing Else ' Last resort: create a new viewer and add it Dim viewer = New GdPicture14.GdViewer() viewer.Dock = DockStyle.Fill Me.Controls.Add(viewer) GdViewer = viewer End If End If Return GdViewer IsNot Nothing Catch ex As Exception _logger?.Error(ex) Return False End Try End Function Private Sub FitToPage() GdViewer.ZoomMode = ViewerZoomMode.ZoomModeFitToViewer End Sub Private Sub FitToWidth() GdViewer.ZoomMode = ViewerZoomMode.ZoomModeWidthViewer End Sub Private Function DoLoadFile(Stream As Stream, Extension As String) As Boolean Try SpreadsheetControl1.Visible = False SpreadsheetControl1.Dock = DockStyle.None Select Case Extension.ToUpper Case ".CSV" SpreadsheetControl1.LoadDocument(Stream, GetSpreadsheetFormat(Extension)) Dim oRange = SpreadsheetControl1.ActiveWorksheet.GetUsedRange() oRange.AutoFitColumns() SpreadsheetControl1.Visible = True SpreadsheetControl1.Dock = DockStyle.Fill Case Else GdViewer.ZoomMode = ViewerZoomMode.ZoomModeWidthViewer GdViewer.DocumentAlignment = ViewerDocumentAlignment.DocumentAlignmentTopCenter If Viewer_ForceTemporaryMode = True Then GdViewer.ForceTemporaryMode = True End If GdViewer.AnnotationDropShadow = True GdViewer.DisplayFromStream(Stream) End Select UpdateMainUi() Return True Catch ex As Exception _logger.Error(ex) Return False End Try End Function Private Function GetSpreadsheetFormat(Extension) As Spreadsheet.DocumentFormat Dim oFormat As Spreadsheet.DocumentFormat = Spreadsheet.DocumentFormat.Undefined Select Case Extension.ToUpper Case ".XLSX" : oFormat = Spreadsheet.DocumentFormat.Xlsx Case ".XLS" : oFormat = Spreadsheet.DocumentFormat.Xls Case ".CSV" : oFormat = Spreadsheet.DocumentFormat.Csv End Select Return oFormat End Function Private Function GetDocumentFormat(Extension) As XtraRichEdit.DocumentFormat Dim oFormat As XtraRichEdit.DocumentFormat = XtraRichEdit.DocumentFormat.Undefined Select Case Extension.ToUpper Case ".EML" : oFormat = XtraRichEdit.DocumentFormat.Mht Case ".DOC" : oFormat = XtraRichEdit.DocumentFormat.Doc Case ".DOCX" : oFormat = XtraRichEdit.DocumentFormat.OpenXml Case ".ODT" : oFormat = XtraRichEdit.DocumentFormat.OpenDocument Case ".RTF" : oFormat = XtraRichEdit.DocumentFormat.Rtf Case ".TXT" : oFormat = XtraRichEdit.DocumentFormat.PlainText End Select Return oFormat End Function Private Function ToVisibility(pBoolean As Boolean) As XtraBars.BarItemVisibility If (pBoolean = True) Then Return XtraBars.BarItemVisibility.Always Else Return XtraBars.BarItemVisibility.Never End If End Function Private Sub UpdateMainUi() Select Case _Config?.Config?.PageFit Case Config.PageFitSetting.FitPage FitToPage() Case Config.PageFitSetting.FitWidth FitToWidth() End Select If _FileStream Is Nothing And _FilePath Is Nothing Then lbFileNotLoaded.Visible = False End If Select Case _ViewerMode Case ViewerMode.GDPicture ToolbarDocumentViewer.Visible = True buttonPrint.Visibility = ToVisibility(_ToolbarSettings.ShowPrintButton) buttonFitWidth.Visibility = ToVisibility(_ToolbarSettings.ShowFitWidthButton) buttonFitPage.Visibility = ToVisibility(_ToolbarSettings.ShowFitPageButton) buttonZoomIn.Visibility = ToVisibility(_ToolbarSettings.ShowZoomButton) buttonZoomOut.Visibility = ToVisibility(_ToolbarSettings.ShowZoomButton) buttonRotateLeft.Visibility = ToVisibility(_ToolbarSettings.ShowRotateButton) buttonRotateRight.Visibility = ToVisibility(_ToolbarSettings.ShowRotateButton) buttonFlipX.Visibility = ToVisibility(_ToolbarSettings.ShowFlipButton) buttonFlipY.Visibility = ToVisibility(_ToolbarSettings.ShowFlipButton) buttonSettings.Visibility = ToVisibility(_ToolbarSettings.ShowSettingButton) txtSearch.Visibility = ToVisibility(_ToolbarSettings.ShowSearchButton) btnSearch2.Visibility = ToVisibility(_ToolbarSettings.ShowSearchButton) btnNextHighlight.Visibility = ToVisibility(_ToolbarSettings.ShowSearchButton) btnPrevHighlight.Visibility = ToVisibility(_ToolbarSettings.ShowSearchButton) buttonFirstPage.Visibility = ToVisibility(True) buttonPrevPage.Visibility = ToVisibility(True) buttonNextPage.Visibility = ToVisibility(True) buttonLastPage.Visibility = ToVisibility(True) txtCurrentPage.Visibility = ToVisibility(True) Case ViewerMode.Excel ToolbarDocumentViewer.Visible = False buttonPrint.Visibility = ToVisibility(False) buttonFitWidth.Visibility = ToVisibility(False) buttonFitPage.Visibility = ToVisibility(False) buttonZoomIn.Visibility = ToVisibility(False) buttonZoomOut.Visibility = ToVisibility(False) buttonRotateLeft.Visibility = ToVisibility(False) buttonRotateRight.Visibility = ToVisibility(False) buttonFlipX.Visibility = ToVisibility(False) buttonFlipY.Visibility = ToVisibility(False) buttonFirstPage.Visibility = ToVisibility(False) buttonPrevPage.Visibility = ToVisibility(False) buttonNextPage.Visibility = ToVisibility(False) buttonLastPage.Visibility = ToVisibility(False) buttonSettings.Visibility = ToVisibility(False) txtCurrentPage.Visibility = ToVisibility(False) txtSearch.Visibility = ToVisibility(False) btnSearch2.Visibility = ToVisibility(False) btnNextHighlight.Visibility = ToVisibility(False) btnPrevHighlight.Visibility = ToVisibility(False) Case Else ToolbarDocumentViewer.Visible = False End Select End Sub Private Sub btnSearch2_ItemClick(sender As Object, e As XtraBars.ItemClickEventArgs) Handles btnSearch2.ItemClick EnsureSearchInitialized() If _Search IsNot Nothing AndAlso Not String.IsNullOrEmpty(txtSearch.EditValue) Then _Search.SearchAll(txtSearch.EditValue?.ToString) End If End Sub Private Sub btnPrevHighlight_ItemClick(sender As Object, e As XtraBars.ItemClickEventArgs) Handles btnPrevHighlight.ItemClick EnsureSearchInitialized() _Search?.PrevHighlight() End Sub Private Sub btnNextHighlight_ItemClick(sender As Object, e As XtraBars.ItemClickEventArgs) Handles btnNextHighlight.ItemClick EnsureSearchInitialized() _Search?.NextHighlight() End Sub Private Sub txtSearch_EditValueChanged(sender As Object, e As EventArgs) Handles txtSearch.EditValueChanged If String.IsNullOrEmpty(txtSearch.EditValue) Then btnPrevHighlight.Enabled = False btnNextHighlight.Enabled = False Else btnPrevHighlight.Enabled = True btnNextHighlight.Enabled = True End If End Sub #End Region End Class