1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RichTextBoxに画像を挿入

1
Last updated at Posted at 2022-01-12

画像データを WMF に埋め込んで Windows Forms の RichTextBox に挿入します。

概要

RichTextBox には画像を挿入するメソッドがありません。検索するとクリップボード経由で渡す方法がよく紹介されますが、今回は画像を含む RTF を生成して挿入します。

RTF の仕様には PNG など各種形式が含まれますが、RichTextBox が受け付けるのは WMF のみです。検索すると P/Invoke で WMF を生成する方法が見付かりますが、今回は直接 WMF を生成します。

実装

WMF に埋め込む DIB は BMP ファイルの 14 バイト以降です。画像を BMP に書き出して使用します。

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Text;

public class ImageToRtf
{
    public static void Write16(StringBuilder sb, params int[] args)
    {
        foreach (int w in args)
        {
            sb.AppendFormat("{0:X2}{1:X2}", w & 0xff, (w >> 8) & 0xff);
        }
    }

    public static string Convert(Image img, Color back)
    {
        int w = img.Width, h = img.Height;
        int picw = w * 2540 / 96, pich = h * 2540 / 96;
        int picwgoal = w * 1440 / 96, pichgoal = h * 1440 / 96;

        var sb = new StringBuilder();
        sb.AppendFormat(
            @"{{\rtf1{{\pict\wmetafile8\picw{0}\pich{1}\picwgoal{2}\pichgoal{3} ",
            picw, pich, picwgoal, pichgoal);

        byte[] bmp;
        using (var bitmap = new Bitmap(w, h))
        {
            using (var g = Graphics.FromImage(bitmap))
            {
                g.Clear(back);
                g.DrawImage(img, 0, 0, w, h);
            }
            using (var ms = new MemoryStream())
            {
                bitmap.Save(ms, ImageFormat.Bmp);
                bmp = ms.ToArray();
            }
        }

        int size1 = 14 + (bmp.Length - 14) / 2;
        int size2 = 9 + 5 + 5 + size1 + 3;

        Write16(sb,
            // META_HEADER Record
            1, 9, 0x300, size2, size2 >> 16, 0, size1, size1 >> 16, 0,
            // META_SETWINDOWORG Record
            5, 0, 0x20b, 0, 0,
            // META_SETWINDOWEXT Record
            5, 0, 0x20c, pich, picw,
            // META_STRETCHDIB Record
            size1, size1 >> 16, 0xf43, 0x20, 0xcc, 0, h, w, 0, 0, pich, picw, 0, 0
        );
        sb.Append(BitConverter.ToString(bmp, 14).Replace("-", ""));
        Write16(sb, 3, 0, 0); // META_EOF Record
        sb.Append("}}");

        return sb.ToString();
    }
}

使用例

透過色はサポートされないため、背景色を指定します。

var rtb = new RichTextBox();
using (var bmp = new Bitmap("test.png"))
{
    rtb.SelectedRtf = ImageToRtf.Convert(bmp, Color.White);
}

参考

WMF の仕様です。

同じ目的のコードです。これらをベースに整理しました。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?