edit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.vs/
|
||||||
|
**/bin/
|
||||||
|
**/obj/
|
||||||
3
CLITPdfReader.slnx
Normal file
3
CLITPdfReader.slnx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<Solution>
|
||||||
|
<Project Path="CLITPdfReader/CLITPdfReader.csproj" />
|
||||||
|
</Solution>
|
||||||
7
CLITPdfReader/App.xaml
Normal file
7
CLITPdfReader/App.xaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<Application x:Class="CLITPdfReader.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
<Application.Resources>
|
||||||
|
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
||||||
22
CLITPdfReader/App.xaml.cs
Normal file
22
CLITPdfReader/App.xaml.cs
Normal file
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
10
CLITPdfReader/AssemblyInfo.cs
Normal file
10
CLITPdfReader/AssemblyInfo.cs
Normal file
@@ -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)
|
||||||
|
)]
|
||||||
15
CLITPdfReader/CLITPdfReader.csproj
Normal file
15
CLITPdfReader/CLITPdfReader.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net10.0-windows</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<UseWPF>true</UseWPF>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3856.49" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
78
CLITPdfReader/MainWindow.xaml
Normal file
78
CLITPdfReader/MainWindow.xaml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<Window x:Class="CLITPdfReader.MainWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="CLIT PDF Reader"
|
||||||
|
Width="1200"
|
||||||
|
Height="800"
|
||||||
|
MinWidth="760"
|
||||||
|
MinHeight="520"
|
||||||
|
Loaded="Window_Loaded"
|
||||||
|
AllowDrop="True"
|
||||||
|
DragOver="Window_DragOver"
|
||||||
|
Drop="Window_Drop">
|
||||||
|
<DockPanel>
|
||||||
|
<Border DockPanel.Dock="Top"
|
||||||
|
Background="#FFF4F4F5"
|
||||||
|
BorderBrush="#FFE2E8F0"
|
||||||
|
BorderThickness="0,0,0,1">
|
||||||
|
<ToolBarTray>
|
||||||
|
<ToolBar FontSize="14"
|
||||||
|
Padding="6,2"
|
||||||
|
MinHeight="34">
|
||||||
|
<Button Command="ApplicationCommands.Open"
|
||||||
|
Padding="10,3"
|
||||||
|
Margin="0,0,8,0">Открыть PDF</Button>
|
||||||
|
<Button Command="ApplicationCommands.Print"
|
||||||
|
Padding="10,3"
|
||||||
|
Margin="0,0,16,0">Печать</Button>
|
||||||
|
<Separator />
|
||||||
|
<TextBlock VerticalAlignment="Center"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Text="Файл:"
|
||||||
|
Margin="12,0,8,0" />
|
||||||
|
<TextBlock x:Name="CurrentFileTextBlock"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
TextTrimming="CharacterEllipsis"
|
||||||
|
Width="760"
|
||||||
|
Foreground="#FF334155"
|
||||||
|
Text="PDF не открыт" />
|
||||||
|
</ToolBar>
|
||||||
|
</ToolBarTray>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<StatusBar DockPanel.Dock="Bottom">
|
||||||
|
<StatusBarItem>
|
||||||
|
<TextBlock x:Name="StatusTextBlock" Text="Готово к открытию PDF." />
|
||||||
|
</StatusBarItem>
|
||||||
|
</StatusBar>
|
||||||
|
|
||||||
|
<Grid Background="#FFF8FAFC">
|
||||||
|
<wv2:WebView2 x:Name="PdfView" />
|
||||||
|
|
||||||
|
<Border x:Name="PlaceholderPanel"
|
||||||
|
Background="#FFF8FAFC"
|
||||||
|
Visibility="Visible">
|
||||||
|
<StackPanel MaxWidth="520"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<TextBlock x:Name="PlaceholderTitleTextBlock"
|
||||||
|
Text="Откройте PDF-файл"
|
||||||
|
FontSize="28"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Margin="0,0,0,12" />
|
||||||
|
<TextBlock x:Name="PlaceholderDescriptionTextBlock"
|
||||||
|
Text="Используйте кнопку «Открыть PDF», горячую клавишу Ctrl+O или просто перетащите файл в окно."
|
||||||
|
TextAlignment="Center"
|
||||||
|
Foreground="#FF475569"
|
||||||
|
FontSize="15"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</DockPanel>
|
||||||
|
</Window>
|
||||||
180
CLITPdfReader/MainWindow.xaml.cs
Normal file
180
CLITPdfReader/MainWindow.xaml.cs
Normal file
@@ -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<bool> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user