commit a62252a181766d2bd95b313aa86a4be3f3288512 Author: Курнат Андрей Date: Wed Apr 1 20:48:48 2026 +0300 edit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f9195be --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vs/ +**/bin/ +**/obj/ diff --git a/CLITPdfReader.slnx b/CLITPdfReader.slnx new file mode 100644 index 0000000..127ea70 --- /dev/null +++ b/CLITPdfReader.slnx @@ -0,0 +1,3 @@ + + + diff --git a/CLITPdfReader/App.xaml b/CLITPdfReader/App.xaml new file mode 100644 index 0000000..0750b3d --- /dev/null +++ b/CLITPdfReader/App.xaml @@ -0,0 +1,7 @@ + + + + + diff --git a/CLITPdfReader/App.xaml.cs b/CLITPdfReader/App.xaml.cs new file mode 100644 index 0000000..4cab52f --- /dev/null +++ b/CLITPdfReader/App.xaml.cs @@ -0,0 +1,22 @@ +using System.IO; +using System.Windows; + +namespace CLITPdfReader; + +public partial class App : Application +{ + protected override void OnStartup(StartupEventArgs e) + { + base.OnStartup(e); + + string? initialPdfPath = null; + + if (e.Args.Length > 0 && File.Exists(e.Args[0])) + { + initialPdfPath = e.Args[0]; + } + + MainWindow = new MainWindow(initialPdfPath); + MainWindow.Show(); + } +} diff --git a/CLITPdfReader/AssemblyInfo.cs b/CLITPdfReader/AssemblyInfo.cs new file mode 100644 index 0000000..cc29e7f --- /dev/null +++ b/CLITPdfReader/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly:ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/CLITPdfReader/CLITPdfReader.csproj b/CLITPdfReader/CLITPdfReader.csproj new file mode 100644 index 0000000..b9b7bbf --- /dev/null +++ b/CLITPdfReader/CLITPdfReader.csproj @@ -0,0 +1,15 @@ + + + + WinExe + net10.0-windows + enable + enable + true + + + + + + + diff --git a/CLITPdfReader/MainWindow.xaml b/CLITPdfReader/MainWindow.xaml new file mode 100644 index 0000000..13533d4 --- /dev/null +++ b/CLITPdfReader/MainWindow.xaml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CLITPdfReader/MainWindow.xaml.cs b/CLITPdfReader/MainWindow.xaml.cs new file mode 100644 index 0000000..af264f5 --- /dev/null +++ b/CLITPdfReader/MainWindow.xaml.cs @@ -0,0 +1,180 @@ +using System.IO; +using System.Windows; +using System.Windows.Input; +using Microsoft.Web.WebView2.Core; +using Microsoft.Win32; + +namespace CLITPdfReader; + +public partial class MainWindow : Window +{ + private const string AppTitle = "CLIT PDF Reader"; + private readonly string? _initialPdfPath; + private bool _isBrowserReady; + private string? _currentPdfPath; + + public MainWindow(string? initialPdfPath = null) + { + _initialPdfPath = initialPdfPath; + InitializeComponent(); + + CommandBindings.Add(new CommandBinding(ApplicationCommands.Open, OpenCommand_Executed)); + CommandBindings.Add(new CommandBinding(ApplicationCommands.Print, PrintCommand_Executed, PrintCommand_CanExecute)); + InputBindings.Add(new KeyBinding(ApplicationCommands.Open, new KeyGesture(Key.O, ModifierKeys.Control))); + InputBindings.Add(new KeyBinding(ApplicationCommands.Print, new KeyGesture(Key.P, ModifierKeys.Control))); + } + + private async void Window_Loaded(object sender, RoutedEventArgs e) + { + await EnsureBrowserReadyAsync(); + + if (_isBrowserReady && !string.IsNullOrWhiteSpace(_initialPdfPath)) + { + OpenPdf(_initialPdfPath); + } + } + + private async Task EnsureBrowserReadyAsync() + { + if (_isBrowserReady) + { + return true; + } + + try + { + await PdfView.EnsureCoreWebView2Async(); + PdfView.CoreWebView2.Settings.HiddenPdfToolbarItems = CoreWebView2PdfToolbarItems.None; + _isBrowserReady = true; + UpdateCommandState(); + return true; + } + catch (WebView2RuntimeNotFoundException) + { + ShowPlaceholder( + "WebView2 Runtime не найден", + "Установите Microsoft Edge WebView2 Runtime, после чего приложение сможет отображать PDF." + ); + StatusTextBlock.Text = "Не найден Microsoft Edge WebView2 Runtime."; + return false; + } + catch (Exception ex) + { + ShowPlaceholder( + "Не удалось инициализировать просмотр", + ex.Message + ); + StatusTextBlock.Text = "Ошибка инициализации WebView2."; + return false; + } + } + + private async void OpenCommand_Executed(object sender, ExecutedRoutedEventArgs e) + { + if (!await EnsureBrowserReadyAsync()) + { + return; + } + + var openFileDialog = new OpenFileDialog + { + Title = "Выберите PDF-файл", + Filter = "PDF files (*.pdf)|*.pdf|All files (*.*)|*.*", + Multiselect = false + }; + + if (openFileDialog.ShowDialog(this) == true) + { + OpenPdf(openFileDialog.FileName); + } + } + + private void PrintCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) + { + e.CanExecute = _isBrowserReady && !string.IsNullOrWhiteSpace(_currentPdfPath); + } + + private void PrintCommand_Executed(object sender, ExecutedRoutedEventArgs e) + { + if (!_isBrowserReady || PdfView.CoreWebView2 is null) + { + return; + } + + PdfView.CoreWebView2.ShowPrintUI(CoreWebView2PrintDialogKind.Browser); + } + + private void Window_DragOver(object sender, DragEventArgs e) + { + e.Effects = HasSinglePdfFile(e.Data) ? DragDropEffects.Copy : DragDropEffects.None; + e.Handled = true; + } + + private async void Window_Drop(object sender, DragEventArgs e) + { + if (!HasSinglePdfFile(e.Data)) + { + StatusTextBlock.Text = "Поддерживаются только PDF-файлы."; + return; + } + + if (!await EnsureBrowserReadyAsync()) + { + return; + } + + var droppedFiles = e.Data.GetData(DataFormats.FileDrop) as string[]; + + if (droppedFiles is { Length: 1 }) + { + OpenPdf(droppedFiles[0]); + } + } + + private static bool HasSinglePdfFile(IDataObject dataObject) + { + if (!dataObject.GetDataPresent(DataFormats.FileDrop)) + { + return false; + } + + var files = dataObject.GetData(DataFormats.FileDrop) as string[]; + return files is { Length: 1 } && + File.Exists(files[0]) && + string.Equals(Path.GetExtension(files[0]), ".pdf", StringComparison.OrdinalIgnoreCase); + } + + private void OpenPdf(string pdfPath) + { + if (!File.Exists(pdfPath)) + { + ShowPlaceholder("Файл не найден", pdfPath); + StatusTextBlock.Text = "Не удалось открыть файл."; + return; + } + + _currentPdfPath = pdfPath; + PdfView.CoreWebView2.Navigate(new Uri(pdfPath).AbsoluteUri); + PlaceholderPanel.Visibility = Visibility.Collapsed; + CurrentFileTextBlock.Text = pdfPath; + Title = $"{Path.GetFileName(pdfPath)} - {AppTitle}"; + StatusTextBlock.Text = "PDF открыт. Для печати нажмите Ctrl+P."; + UpdateCommandState(); + } + + private void ShowPlaceholder(string title, string description) + { + PlaceholderTitleTextBlock.Text = title; + PlaceholderDescriptionTextBlock.Text = description; + PlaceholderPanel.Visibility = Visibility.Visible; + CurrentFileTextBlock.Text = "PDF не открыт"; + Title = AppTitle; + _currentPdfPath = null; + UpdateCommandState(); + } + + private void UpdateCommandState() + { + CommandManager.InvalidateRequerySuggested(); + } +}