午後わてんのブログ

ベランダ菜園とWindows用アプリ作成(WPFとC#)

WPF、PDFファイルをロックしないで開く

昨日の

gogowaten.hatenablog.com

続き

PDFファイルをロックしないで画像として表示したい

表示しているPDFファイルは

農林水産省 トマトの種類と見分け方

http://www.maff.go.jp/j/pr/aff/1708/pdf/1708_04.pdf

 より引用

f:id:gogowaten:20200103113849p:plain

開いている間はファイルがロックされていて削除できない

アプリを終了すれば削除できるけどめんどくさい、これを解決したい

 

//ロックな開き方
private async void ButtonLock_Click(object sender, RoutedEventArgs e)
{
    Windows.Storage.StorageFile file = await Windows.Storage.StorageFile.GetFileFromPathAsync(@"D:\ブログ用\1708_04.pdf");
    //ここから
    Windows.Data.Pdf.PdfDocument MyPdfDocument = await Windows.Data.Pdf.PdfDocument.LoadFromFileAsync(file);
    //ここまで
    using (Windows.Data.Pdf.PdfPage page = MyPdfDocument.GetPage(0))
    {
        using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
        {
            await page.RenderToStreamAsync(stream);
            var image = new BitmapImage();
            image.BeginInit();
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.StreamSource = stream.AsStream();
            image.EndInit();
            MyImage.Source = image;
        }
    }
}

 

//ロックじゃない開き方
private async void ButtonFree_Click(object sender, RoutedEventArgs e)
{
    Windows.Storage.StorageFile file = await Windows.Storage.StorageFile.GetFileFromPathAsync(@"D:\ブログ用\1708_04.pdf");
    //ここから
    using (Windows.Storage.Streams.IRandomAccessStream RAStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
    {
        Windows.Data.Pdf.PdfDocument MyPdfDocument = await Windows.Data.Pdf.PdfDocument.LoadFromStreamAsync(RAStream);
        //ここまで
        using (Windows.Data.Pdf.PdfPage page = MyPdfDocument.GetPage(0))
        {
            using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
            {
                await page.RenderToStreamAsync(stream);
                var image = new BitmapImage();
                image.BeginInit();
                image.CacheOption = BitmapCacheOption.OnLoad;
                image.StreamSource = stream.AsStream();
                image.EndInit();
                MyImage.Source = image;
            }
        }
    }
}

 違うのは太字のところだけで、ストリームで開けばいいみたい、そのためには

StorageFile.OpenAsyncでストリームにしたのを

Windows.Data.Pdf.PdfDocument.LoadFromStreamAsyncで読み込めばいいみたい

 

 

ストリームまでの道のり

画像ファイルをロックしないで開くときもストリームを使っていたから、PDFもおなじようにできないかなあって思っていて

f:id:gogowaten:20200103120758p:plain

ファイルからPdfDocumentを作成するところでLoadFromStreamAsyncってそれっぽいのがあったので

たまによく使うFileStreamで試してみたら

f:id:gogowaten:20200103121336p:plain

できない

 

f:id:gogowaten:20200103121633p:plain

なんでも型が違うからできないって言われる

このWindows.Storage.Streams.IRandomAccessStreamってのにすればいいみたいだけど、コレガワカラナイ

 

ようやく見つけたのがStrageFileのOpenAsyncメソッド

f:id:gogowaten:20200103123025p:plain

使用法のところを見るとWindows.Storage.Streams.IRandomAccessStreamってある!

 

使ってみるとアクセスモードを指定するみたいで

f:id:gogowaten:20200103125326p:plain

ReadとReadWriteのどちらか、書き込みはしないのでRead指定

 

f:id:gogowaten:20200103125714p:plain

あとはさっきのLoadFromStreamAsyncに渡したら期待通りの動きにできたわけ

 

今回のロックされないPdfDocument取得

  1. Windows.Storage.StorageFile.GetFileFromPathAsyncにファイルパスを渡して、StorageFile作成
  2. StorageFile.OpenAsyncでWindows.Storage.Streams.IRandomAccessStream(ストリーム)作成
  3. Windows.Data.Pdf.PdfDocument.LoadFromStreamAsyncにストリームを渡して、PdfDocument作成

 

前回のロックされてしまうPdfDocument取得

  1. Windows.Storage.StorageFile.GetFileFromPathAsyncにファイルパスを渡して、StorageFile作成
  2. Windows.Data.Pdf.PdfDocument.LoadFromFileAsyncにStorageFileを渡して、PdfDocument作成

 

f:id:gogowaten:20200103130554p:plain

開いている状態でも削除(ゴミ箱へ移動)できた

 

 

<Grid>
<StackPanel>
<Button Content="Free" Click="ButtonFree_Click"/>
<Button Content="Lock" Click="ButtonLock_Click"/>
<Image Name="MyImage"/>
</StackPanel>
</Grid>

 

 

using System;
using System.Windows;
using System.Windows.Media.Imaging;

using System.IO;

//下の2つを参照に追加する必要がある
//"C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Annotated\Windows.winmd"
//"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll"

//参照したところ
//.NET Core デスクトップアプリケーションで PDF 帳票を画面表示する - rksoftware
//https://rksoftware.hatenablog.com/entry/2019/01/31/032913
//【UWP】UWPアプリでインターネット上のPDFファイルを表示する - Qiita
//https://qiita.com/ryo-ta/items/81edc024fa70c2e5ed99
//PdfDocument.LoadFromStreamAsync - Google 検索
//https://www.google.com/search?q=PdfDocument.LoadFromStreamAsync



namespace _20200102_PDFファイルをロックしないで開く
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        Windows.Data.Pdf.PdfDocument MyPdfDocument;
        string MyPdfFilePath;


        public MainWindow()
        {
            InitializeComponent();

            MyPdfFilePath = @"D:\ブログ用\1708_04.pdf";
        }

        //ロックじゃない開き方
        private async void ButtonFree_Click(object sender, RoutedEventArgs e)
        {            
            Windows.Storage.StorageFile file = await Windows.Storage.StorageFile.GetFileFromPathAsync(MyPdfFilePath);            
            //ここから
            using (Windows.Storage.Streams.IRandomAccessStream RAStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
            {
                MyPdfDocument = await Windows.Data.Pdf.PdfDocument.LoadFromStreamAsync(RAStream);
                //ここまで
                using (Windows.Data.Pdf.PdfPage page = MyPdfDocument.GetPage(0))
                {
                    using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
                    {
                        await page.RenderToStreamAsync(stream);
                        var image = new BitmapImage();
                        image.BeginInit();
                        image.CacheOption = BitmapCacheOption.OnLoad;
                        image.StreamSource = stream.AsStream();
                        image.EndInit();
                        MyImage.Source = image;
                    }
                }
            }            
        }

        //ロックな開き方
        private async void ButtonLock_Click(object sender, RoutedEventArgs e)
        {
            Windows.Storage.StorageFile file = await Windows.Storage.StorageFile.GetFileFromPathAsync(MyPdfFilePath);            
            //ここから
            MyPdfDocument = await Windows.Data.Pdf.PdfDocument.LoadFromFileAsync(file);
            //ここまで
            using (Windows.Data.Pdf.PdfPage page = MyPdfDocument.GetPage(0))
            {
                using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
                {
                    await page.RenderToStreamAsync(stream);
                    var image = new BitmapImage();
                    image.BeginInit();
                    image.CacheOption = BitmapCacheOption.OnLoad;
                    image.StreamSource = stream.AsStream();
                    image.EndInit();
                    MyImage.Source = image;
                }
            }
        }

    }
}

ギットハブ

wpf_test2/20200102_PDFファイルをロックしないで開く



 

 

 

f:id:gogowaten:20200103131726p:plain

ファイルを開いた状態でもファイル削除できるようになった、いいかどうかはわからないけどねえ、jpegに変換したら元のPDFファイルは要らなーい

ダウンロード

PDFtoJPEG_1.2.zip

 

 

 関連記事

続きは翌日

gogowaten.hatenablog.com