jonny1
@jonny1 (jonny)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

WindowsFormApp(C#)でコントロールの上に手書きしたい

解決したいこと

WindowsデスクトップアプリをWindowsForm(C#)で作成しています。
Panelの上に手書き用のイベント(MouseUpなど)を追加しており、その上にLabelを配置しています。
そうすると、Labelの表示領域には手書きが出来ずに困っています。

試したこと)
①Lableの上にPanelを配置して、Panelの背景を透過する
 →下にあるLabelも表示されない

②LabelのTextを線で描いて、表示領域を文字の線のみにする
 →技術不足により再現不可(意味不明。。。)

現状

下図のようにコントロールの表示領域が邪魔してきます。。。
理想はLabelの上にも手書きをしたいです。

image.png

解決方法を教えてほしいです。。。お願いします。。。

0

1Answer

Labelにもマウスイベントハンドラを設定すればいいんじゃないでしょうか。
下記の例では、panel1上に置いたlabel1をクリックしても、その位置に点が描画されます。
MouseEventArgsの座標が役に立たなくなるので、Control.MousePositionとpanel1.PointToClientでパネル上のマウス位置を算出するようにしています。

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
using System.Windows.Forms;

public partial class Form1 : Form
{
    private Bitmap _Image;
    private bool _Drawing;

    public Form1()
    {
        InitializeComponent();

        _Image = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height, PixelFormat.Format32bppArgb);
        panel1.BackgroundImage = _Image;
        panel1.BackgroundImageLayout = ImageLayout.None;
        panel1.GetType().InvokeMember(
           "DoubleBuffered",
           BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
           null,
           panel1,
           new object[] { true });

        using (var g = Graphics.FromImage(_Image))
        {
            g.Clear(Color.LightCyan);
        }

        SetMouseEvent(panel1);
        SetMouseEvent(label1);
    }

    private void SetMouseEvent(Control ctl)
    {
        ctl.MouseDown += Control_MouseDown;
        ctl.MouseMove += Control_MouseMove;
        ctl.MouseUp += Control_MouseUp;
    }

    private void PaintPanel()
    {
        if (!_Drawing)
            return;

        var posScreen = Control.MousePosition;
        var pos = panel1.PointToClient(posScreen);

        using (var g = Graphics.FromImage(_Image))
        {
            g.FillEllipse(Brushes.Black, pos.X - 5, pos.Y - 5, 10, 10);
        }
        panel1.Invalidate();
    }

    private void Control_MouseDown(object sender, MouseEventArgs e)
    {
        _Drawing = true;
        PaintPanel();
    }

    private void Control_MouseMove(object sender, MouseEventArgs e)
    {
        PaintPanel();
    }

    private void Control_MouseUp(object sender, MouseEventArgs e)
    {
        _Drawing = false;
    }
}

paintlabel.png

Label一つ二つなら大したことはないですが、コントロールの数が多くなると処理が重くなる可能性があるので、その場合はLabelを使わずに自分でテキストを管理して描画した方がよいかもしれません。

(2023/7/25)
サンプルソースのSetMouseEvent簡略化、メソッド名を若干修正。

2Like

Comments

  1. @jonny1

    Questioner

    @radian-jp さん
    丁寧なご回答ありがとうございます!!本当にありがとうございます。

    正直なところ、すぐには理解できそうにないですが、検証を重ねて理解したいと思います。
    自分が実装したいものは、Panel上に多数のコントロールが存在するので、最後に仰られているカスタムコントロール?もチャレンジしてみます!

    本当に助かりました!ありがとうございます!!

    image.png

Your answer might help someone💌