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 RichText Excel End Enum Private Enum FileLoadMode File Stream End Enum Private _ViewerMode As ViewerMode Private _currentSearchOccurence As Integer = 0 Private _toggleGamma As Boolean = True Private _licenseKey As String = String.Empty Private _licenseManager As New GdPicture14.LicenseManager() Private _logConfig As LogConfig Private _logger As Logger Private _email As Email2 Private _Config As ConfigManager(Of Config) Private _Annotations As Annotations Private _AnnotationsPending As Boolean = False 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 ' 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 UpdateMainUi() End Sub Public Property FileLoaded 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 Sub Init(pLogConfig As LogConfig, pLicenseKey As String) _logConfig = pLogConfig _logger = pLogConfig.GetLogger() _email = New Email2(pLogConfig) _licenseKey = pLicenseKey _licenseManager.RegisterKEY(_licenseKey) _Annotations = New Annotations(pLogConfig) Dim oConfigPath = ConfigPath() _Config = New ConfigManager(Of Config)(pLogConfig, oConfigPath) 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) FileLoaded = DoLoadFile(FilePath) SetViewerMode(_Fileinfo.Extension) UpdateMainUi() End Sub ''' ''' Load a file from a stream and display it ''' Public Sub LoadFile(FileName As String, Stream As Stream) FileLoaded = False If _licenseKey = String.Empty Then _logger.Warn("License key was not provided. File [{0}] not loaded.", FileName) Exit Sub End If 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 GdViewer.CloseDocument() 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 RichEditControl1_SizeChanged(sender As Object, e As EventArgs) Handles RichEditControl1.SizeChanged Dim oControlWidth = RichEditControl1.Width - 100 Dim oPageWidth = Units.DocumentsToPixelsF(RichEditControl1.Document.Sections(0).Page.Width, RichEditControl1.DpiX) RichEditControl1.Views.PrintLayoutView.ZoomFactor = oControlWidth / oPageWidth 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 If _ViewerMode = ViewerMode.GDPicture Then GdViewer.DisplayPreviousPage() ElseIf _ViewerMode = ViewerMode.RichText Then Dim oCmd As New PreviousPageCommand(RichEditControl1) oCmd.Execute() End If End Sub Private Sub btnNextPage_Click(ByVal sender As System.Object, ByVal e As EventArgs) Handles buttonNextPage.ItemClick If _ViewerMode = ViewerMode.GDPicture Then GdViewer.DisplayNextPage() ElseIf _ViewerMode = ViewerMode.RichText Then Dim oCmd As New NextPageCommand(RichEditControl1) oCmd.Execute() End If 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 If _ViewerMode = ViewerMode.GDPicture Then GdViewer.ZoomOUT() ElseIf _ViewerMode = ViewerMode.RichText Then Dim oCmd As New ZoomOutCommand(RichEditControl1) oCmd.Execute() End If End Sub Private Sub btnZoomIn_Click(sender As Object, e As EventArgs) Handles buttonZoomIn.ItemClick If _ViewerMode = ViewerMode.GDPicture Then GdViewer.ZoomIN() ElseIf _ViewerMode = ViewerMode.RichText Then Dim oCmd As New ZoomInCommand(RichEditControl1) oCmd.Execute() End If 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) Select Case Extension.ToUpper Case ".MSG" _ViewerMode = ViewerMode.RichText Case ".EML", ".DOC", ".DOCX", ".ODT", ".RTF", ".TXT" _ViewerMode = ViewerMode.RichText Case ".XLSX", ".XLS", "CSV" _ViewerMode = ViewerMode.Excel Case Else _ViewerMode = ViewerMode.GDPicture End Select 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.RichText _logger.Debug("Closing RichText Editor") RichEditControl1.CreateNewDocument() 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) As Boolean Try Dim oFileInfo = New FileInfo(FilePath) Dim oExtension As String = oFileInfo.Extension.ToUpper RichEditControl1.Visible = False RichEditControl1.Dock = DockStyle.None SpreadsheetControl1.Visible = False SpreadsheetControl1.Dock = DockStyle.None Select Case oExtension.ToUpper Case ".MSG" Dim oEmlPath As String = _email.Convert_ToEml(FilePath) _TempFiles.Add(oEmlPath) DoLoadFile(oEmlPath) Case ".EML", ".DOC", ".DOCX", ".ODT", ".RTF", ".TXT" RichEditControl1.LoadDocument(FilePath, GetDocumentFormat(oExtension)) RichEditControl1.Visible = True RichEditControl1.Dock = DockStyle.Fill Case ".XLSX", ".XLS", ".CSV" Dim oFormat = GetSpreadsheetFormat(oExtension) SpreadsheetControl1.LoadDocument(FilePath, oFormat) Dim oRange = SpreadsheetControl1.ActiveWorksheet.GetUsedRange() oRange.AutoFitColumns() SpreadsheetControl1.Visible = True SpreadsheetControl1.Dock = DockStyle.Fill Case Else GdViewer.ZoomMode = ViewerZoomMode.ZoomModeWidthViewer GdViewer.DocumentAlignment = ViewerDocumentAlignment.DocumentAlignmentTopCenter GdViewer.ForceTemporaryMode = True GdViewer.AnnotationDropShadow = True GdViewer.DisplayFromFile(FilePath) End Select UpdateMainUi() Return True Catch ex As Exception _logger.Error(ex) Return False End Try End Function Private Sub FitToPage() If _ViewerMode = ViewerMode.GDPicture Then GdViewer.ZoomMode = ViewerZoomMode.ZoomModeFitToViewer ElseIf _ViewerMode = ViewerMode.RichText Then Dim oCmd As New FitToPageCommand(RichEditControl1) oCmd.Execute() End If End Sub Private Sub FitToWidth() If _ViewerMode = ViewerMode.GDPicture Then GdViewer.ZoomMode = ViewerZoomMode.ZoomModeWidthViewer ElseIf _ViewerMode = ViewerMode.RichText Then Dim oCmd As New FitWidthCommand(RichEditControl1) oCmd.Execute() End If End Sub Private Function DoLoadFile(Stream As Stream, Extension As String) As Boolean Try RichEditControl1.Visible = False RichEditControl1.Dock = DockStyle.None SpreadsheetControl1.Visible = False SpreadsheetControl1.Dock = DockStyle.None Select Case Extension.ToUpper Case ".MSG" Dim oTempFileName = Path.Combine(IO.Path.GetTempPath(), Guid.NewGuid.ToString & ".msg") Using oFileStream As New FileStream(oTempFileName, FileMode.Create) Stream.Seek(0, SeekOrigin.Begin) Stream.CopyTo(oFileStream) Stream.Flush() End Using Dim oEmlPath As String = _email.Convert_ToEml(oTempFileName) DoLoadFile(oEmlPath) Case ".EML", ".DOC", ".DOCX", ".ODT", ".RTF", ".TXT" RichEditControl1.LoadDocument(Stream, GetDocumentFormat(Extension)) RichEditControl1.ActiveViewType = XtraRichEdit.RichEditViewType.PrintLayout RichEditControl1.Visible = True RichEditControl1.Dock = DockStyle.Fill Case ".XLSX", ".XLS", ".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 GdViewer.ForceTemporaryMode = True 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 Sub UpdateMainUi() Select Case _Config?.Config?.PageFit Case Config.PageFitSetting.FitPage FitToPage() Case Config.PageFitSetting.FitWidth FitToWidth() End Select Select Case _ViewerMode Case ViewerMode.GDPicture buttonPrint.Enabled = True buttonFitWidth.Enabled = True buttonFitPage.Enabled = True buttonZoomIn.Enabled = True buttonZoomOut.Enabled = True buttonRotateLeft.Enabled = True buttonRotateRight.Enabled = True buttonFlipX.Enabled = True buttonFlipY.Enabled = True buttonFirstPage.Enabled = True buttonPrevPage.Enabled = True buttonNextPage.Enabled = True buttonLastPage.Enabled = True buttonSettings.Enabled = True txtCurrentPage.Enabled = True Case ViewerMode.RichText buttonFitPage.Enabled = True buttonZoomIn.Enabled = True buttonZoomOut.Enabled = True buttonFitWidth.Enabled = True buttonNextPage.Enabled = True buttonPrevPage.Enabled = True buttonPrint.Enabled = False buttonRotateLeft.Enabled = False buttonRotateRight.Enabled = False buttonFlipX.Enabled = False buttonFlipY.Enabled = False buttonFirstPage.Enabled = False buttonLastPage.Enabled = False buttonSettings.Enabled = False txtCurrentPage.Enabled = False Case ViewerMode.Excel buttonPrint.Enabled = False buttonFitWidth.Enabled = False buttonFitPage.Enabled = False buttonZoomIn.Enabled = False buttonZoomOut.Enabled = False buttonRotateLeft.Enabled = False buttonRotateRight.Enabled = False buttonFlipX.Enabled = False buttonFlipY.Enabled = False buttonFirstPage.Enabled = False buttonPrevPage.Enabled = False buttonNextPage.Enabled = False buttonLastPage.Enabled = False buttonSettings.Enabled = False txtCurrentPage.Enabled = False End Select End Sub #End Region End Class