XAMLで始めるWPF入門:アルファチャンネル付き画像をコピー&ペースト

コンピュータ

Imageコントロールに対し、画像をCtrl+Vで貼り付け、Ctrl+Cでコピーを行うサンプルプログラムです。
扱う画像はアルファチャンネル(透明度)を維持します。

コピー&ペースト部分とショートカットキー(HotKey)部分をヘルパーとして切り出しています。また、
イベント関連ですのでコードビハインドで処理が完結するようにしてみました。

ソースコード

ファイル名:CutPest01.csproj


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

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

</Project>

ファイル名:MainWindow.xaml.cs


using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using NxLib.Helper;

namespace CutPest01;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        // Ctrl+C = Copy
        Wiring.Hotkey(this, Key.C, ModifierKeys.Control,
            () =>
            {
                if (Preview1.Source is BitmapSource bmp)
                    ClipBD.SetPNG((BitmapSource)Preview1.Source);
            },
            () => Preview1.Source is not null);
        
        // Ctrl+V = Paste
        Wiring.Hotkey(this, Key.V, ModifierKeys.Control,
            () =>
            {
                var bmp = ClipBD.GetPNG();
                if (bmp is not null)
                    Preview1.Source = bmp;
            },
            () =>
            {
                // img.Source is not null;
                return true;
            });
    }
}

ファイル名:Helpers\ClipBD.cs

// クリップボード

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

namespace NxLib.Helper;
public static class ClipBD
{
    public static void SetPNG(BitmapSource bmp)
    {
        var pngEnc = new PngBitmapEncoder();
        pngEnc.Frames.Add(BitmapFrame.Create(bmp));
        using var mem = new MemoryStream();
        pngEnc.Save(mem);
        Clipboard.SetData("PNG", mem);
    }

    public static BitmapSource? GetPNG()
    {
        var obj = (System.IO.MemoryStream)Clipboard.GetData("PNG");
        if (obj is null) return null;

        var bi = new BitmapImage();
        bi.BeginInit();
        bi.CacheOption = BitmapCacheOption.OnLoad;
        bi.StreamSource = obj;
        bi.EndInit();
        bi.Freeze();

        return bi;
    }
}

ファイル名:Helpers\Wiring.cs

using System.Windows;
using System.Windows.Input;

namespace NxLib.Helper;
public static class Wiring
{
    public static void Hotkey(Window w, Key key, ModifierKeys mods, Action action, Func<bool>? canExecute = null)
    {
        var cmd = new RoutedUICommand();
        ExecutedRoutedEventHandler exec = (_, __) => action();
        CanExecuteRoutedEventHandler can = (_, e) => e.CanExecute = canExecute?.Invoke() ?? true;

        var cb = new CommandBinding(cmd, exec, can);
        var kb = new KeyBinding(cmd, key, mods);

        w.CommandBindings.Add(cb);
        w.InputBindings.Add(kb);
    }
}

ファイル名:MainWindow.xaml

<Window x:Class="CutPest01.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:local="clr-namespace:CutPest01"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Image
            x:Name="Preview1"
            Stretch="Uniform"/>
    </Grid>
</Window>

コメント