XAMLを使わないWPF入門10「簡易イメージビューアー」

コンピュータ

画像をD&Dで画像表示、クリックすると次の画像が表示されます。

プロジェクトの作成

cd (mkdir NoXAML10)
dotnet new wpf -f net8.0
rm *.xaml
rm MainWindow.xaml.cs

ソースコード

ファイル名:NoXAML10.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UseWPF>true</UseWPF>
    <StartupObject>NoXAML10.App</StartupObject>
  </PropertyGroup>

</Project>

ファイル名:App.xaml.cs

using System.Data;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Windows.Media;

namespace NoXAML10;

public partial class App : Application
{
    // 対応画像フォーマットの拡張子一覧
    private static readonly string[] SupportedExtensions = new[]
    {
        ".bmp", ".jpg", ".jpeg", ".png", ".gif", ".tiff", ".tif"
    };
    // 画像ファイルの一覧を取得
    public static IEnumerable<string> GetImageFiles(string directoryPath)
    {
        if (!Directory.Exists(directoryPath))
            return Enumerable.Empty<string>();

        return Directory
            .EnumerateFiles(directoryPath)
            .Where(file => SupportedExtensions.Contains(Path.GetExtension(file).ToLower()));
    }
    // 画像をロード
    public static BitmapSource LoadImage(string file)
    {
        using var stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
        BitmapImage bitmapImage = new();

        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource = stream;
        bitmapImage.EndInit();
        bitmapImage.Freeze();

        return bitmapImage;
    }

    private static void App_Startup(object sender, StartupEventArgs e)
    {
        // 画像ファイルの一覧
        List<string> imageFiles = [];
        int currentIndex = -1;

        // ウィンドウ本体をコードで生成
        var window = new Window
        {
            Title = "SimpleImageViewer",
            Width = 800,
            Height = 450,
        };
        var image = new Image
        {
            Stretch = Stretch.Uniform,
        };
        var dockPanel = new DockPanel
        {
            Background = Brushes.Black,
            AllowDrop = true,            
        };
        dockPanel.Children.Add(image);

        window.Content = dockPanel;

        // ウィンドウロードイベント
        window.Loaded += (sender, e) =>
        {
            // コマンドライン引数を取得
            string[] args = Environment.GetCommandLineArgs();
            if (args.Length > 1)
            {
                string file = args[1];
                if (File.Exists(file) && SupportedExtensions.Contains(Path.GetExtension(file).ToLower()))
                {
                    var dir = Path.GetDirectoryName(file);
                    if (dir is not null)
                        imageFiles = GetImageFiles(dir).ToList();
                    currentIndex = imageFiles.IndexOf(file);

                    if (currentIndex >= 0)
                        image.Source = LoadImage(imageFiles[currentIndex]);
                }
            }
        };

        // 画面クリック
        dockPanel.MouseDown += (sender, e) =>
        {
            if (currentIndex < 0 || imageFiles.Count == 0) return;

            currentIndex++;
            if (currentIndex >= imageFiles.Count)
            {
                currentIndex = 0;
            }
            image.Source = LoadImage(imageFiles[currentIndex]);
        };

        // D&D
        dockPanel.DragEnter += (sender, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effects = DragDropEffects.Copy;
                e.Handled = true;
                return;
            }
            e.Effects = DragDropEffects.None;
            e.Handled = false;            
        };
        dockPanel.Drop += (sender, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop) == false) return;

            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            if (files.Length == 0) return;

            string file = files[0];
            if (File.Exists(file) && SupportedExtensions.Contains(Path.GetExtension(file).ToLower()))
            {
                imageFiles.Clear();
                currentIndex = -1;
                image.Source = null;

                var dir = Path.GetDirectoryName(file);
                if (dir is not null)
                    imageFiles = GetImageFiles(dir).ToList();
                currentIndex = imageFiles.IndexOf(file);

                if (currentIndex >= 0)
                    image.Source = LoadImage(imageFiles[currentIndex]);
            }

        };


        window.Show();  // ウィンドウを表示
    }

    [STAThread]
    public static void Main()
    {
        var app = new App();
        app.Startup += App_Startup;
        app.Run();
    }
}

コメント