【Winform】透過処理された画像の追加と重ね合わせ(複数の画像)

この資料では、Visual Studioを使用してWinFormsアプリケーションに透過処理された画像ファイルを追加し、それをフォーム上に重ね合わせて描画し、カーソルで画像を移動できるようにする方法を説明します。

ステップ 1: プロジェクトに画像ファイルを追加する

  1. プロジェクトを右クリック
    • ソリューションエクスプローラーでプロジェクト名を右クリックします。
    • 「追加」→「既存の項目」を選択します。
  2. ファイル種類を選択
    • 「項目追加」ダイアログが表示されます。
    • 画像ファイルの種類(*.png, *.jpg, *.gif など)を選択し、追加したい画像ファイルを選択します。
  3. 追加された画像ファイルのプロパティを変更
    • 追加された画像ファイルを右クリックし、「プロパティ」を選択します。
    • 「出力ディレクトリにコピー」の設定を「新しい場合はコピーする」に変更します。

ステップ 2: 画像オブジェクトの定義

まず、画像を管理するためのクラスを定義します。このクラスには画像の Bitmap とその位置情報、サイズを持たせます。

// DraggableImage クラスは、ドラッグ可能な画像を表すクラスです
public class DraggableImage
{
    // 画像を保持するプロパティ
    public Bitmap Image { get; set; }
    
    // 画像の位置を保持するプロパティ
    public Point Position { get; set; }
    
    // 画像のサイズを保持するプロパティ
    public Size Size { get; set; }
    
    // 画像がドラッグ中かどうかを示すフラグ
    public bool IsDragging { get; set; }
    
    // ドラッグ中のオフセットを保持するプロパティ
    public Point DragOffset { get; set; }

    // コンストラクタ
    // image: 表示する画像
    // position: 画像の初期位置
    // size: 画像のサイズ
    public DraggableImage(Bitmap image, Point position, Size size)
    {
        Image = image;          // 画像を設定
        Position = position;    // 位置を設定
        Size = size;            // サイズを設定
        IsDragging = false;     // 初期状態ではドラッグ中でないと設定
    }
}

ステップ 3: フォームで画像を管理する

次に、フォームで複数の DraggableImage オブジェクトを管理します。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace TransGraphic
{
    public partial class Form1 : Form
    {
        private List<DraggableImage> images;

        public Form1()
        {
            InitializeComponent();

            this.Text = "透過PNGイラストの重ね合わせと移動";
            this.Size = new Size(800, 600);

            // 画像リストの初期化
            images = new List<DraggableImage>
            {
                new DraggableImage(new Bitmap("dog.png"), new Point(70, 70), new Size(100, 100)),
                new DraggableImage(new Bitmap("cat.png"), new Point(100, 100), new Size(100, 100))
            };

            // ダブルバッファリングを有効にする
            this.DoubleBuffered = true;

            // イベントハンドラの登録
            RegisterEventHandlers();
        }

        private void RegisterEventHandlers()
        {
            this.MouseDown += Form1_MouseDown;
            this.MouseMove += Form1_MouseMove;
            this.MouseUp += Form1_MouseUp;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics;

            // 画像の描画
            foreach (var draggableImage in images)
            {
                g.DrawImage(draggableImage.Image, new Rectangle(draggableImage.Position, draggableImage.Size));
            }
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            foreach (var draggableImage in images)
            {
                if (IsMouseOnImage(draggableImage, e.Location))
                {
                    draggableImage.IsDragging = true;
                    draggableImage.DragOffset = new Point(e.Location.X - draggableImage.Position.X, e.Location.Y - draggableImage.Position.Y);
                    break;
                }
            }
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            foreach (var draggableImage in images)
            {
                if (draggableImage.IsDragging)
                {
                    draggableImage.Position = new Point(e.Location.X - draggableImage.DragOffset.X, e.Location.Y - draggableImage.DragOffset.Y);
                    this.Invalidate();
                }
            }
        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            foreach (var draggableImage in images)
            {
                draggableImage.IsDragging = false;
            }
        }

        private bool IsMouseOnImage(DraggableImage draggableImage, Point mousePosition)
        {
            Rectangle imageRect = new Rectangle(draggableImage.Position, draggableImage.Size);
            return imageRect.Contains(mousePosition);
        }

        protected override void OnFormClosed(FormClosedEventArgs e)
        {
            // リソースの解放
            foreach (var draggableImage in images)
            {
                draggableImage.Image.Dispose();
            }

            base.OnFormClosed(e);
        }
    }
}

説明

  1. DraggableImage クラスの定義
    • 画像 (Bitmap)、位置 (Point)、サイズ (Size) を保持します。
    • 画像がドラッグ中かどうかのフラグ (IsDragging) と、ドラッグのオフセット (DragOffset) も保持します。
  2. フォームの初期化
    • List<DraggableImage> を使用して複数の画像を管理します。
    • 画像をリストに追加し、それぞれの位置とサイズを設定します。
  3. イベントハンドラの登録
    • RegisterEventHandlers メソッドを作成し、ここでイベントハンドラを登録します。
    • MouseDownMouseMoveMouseUp イベントを登録します。
  4. 画像の描画
    • OnPaint メソッドをオーバーライドし、透過処理された画像をフォーム上に重ね合わせて描画します。
  5. 画像のドラッグ
    • Form1_MouseDown メソッド内で、クリック位置が画像上であればドラッグを開始します。
    • Form1_MouseMove メソッド内で、ドラッグ中の画像の位置を更新します。
    • Form1_MouseUp メソッド内で、ドラッグを終了します。
  6. リソースの解放
    • OnFormClosed メソッドをオーバーライドして、フォームが閉じられたときに画像リソースを解放します。

この方法により、複数の画像をオブジェクトとして管理し、それらをフォーム上に重ね合わせて描画し、カーソルで移動させることができます。