在格式文本框插入图像在光标位置 [英] Insert Image at Cursor Position in Rich Text box

查看:159
本文介绍了在格式文本框插入图像在光标位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有这样的各种各样的问题,但我这么问是因为我无法理解所有的答案给的。我有的RichTextBox ,我希望用户能够插入在当前光标所在位置的图像。

I know there are various questions like this but i'm asking because i couldn't understand all the answers give. I have RichTextBox and i want the user to be able to insert an image at the current cursor position.

我使用剪贴板来设置图像,然后在格式文本框粘贴都试过了。这工作,但因为它改变了cliboard数据不通知用户的情况我已经告诉它的坏习惯。

I have tried using the Clipboard to set the Image and then pasting it in the rich textbox. This works but i've been told its bad practice as it change data in a cliboard without notifying the user.

这是我曾尝试

    private bool CheckIfImage(string filename)
    {
        if (filename.EndsWith(".jpeg")) { return true; }
        else if (filename.EndsWith(".jpg")) { return true; }
        else if (filename.EndsWith(".png")) { return true; }
        else if (filename.EndsWith(".ico")) { return true; }
        else if (filename.EndsWith(".gif")) { return true; }
        else if (filename.EndsWith(".bmp")) { return true; }
        else if (filename.EndsWith(".emp")) { return true; }
        else if (filename.EndsWith(".wmf")) { return true; }
        else if (filename.EndsWith(".tiff")) { return true; }
        else { return false; }
    }

    private void openFileDialog2_FileOk(object sender, CancelEventArgs e)
    {
        if (CheckIfImage(openFileDialog2.FileName.ToLower()) == true)
        {
            Image img = Image.FromFile(openFileDialog2.FileName);
            string setData = (String)Clipboard.GetData(DataFormats.Rtf);

            Clipboard.SetImage(img);
            rtbType.Paste();

            Clipboard.SetData(DataFormats.Rtf, setData);
        }
        else
        {
            MessageBox.Show("Invalid Image File Selected");
        } 
    }



PLS是有没有更好的方式来做到这一点?

Pls is there any better way to do this?

推荐答案

我已经为你准备了贴使用该解决方案功能齐全的例子的此处剥削RTF力量。

I've prepared a fully functional example for you using the solution posted here exploiting the RTF power.

由于汉斯帕桑特写道:该解决方案是相当棘手的,有一些有效的替代品来实现它。

As Hans Passant wrote: the solution is quite tricky and there are some valid alternatives to achieve it.

顺便说一句,这是你的代码(rewrited)

BTW, this is your code (rewrited):

private bool CheckIfImage(string filename)
{
        var valids = new[] {".jpeg", ".jpg", ".png", ".ico", ".gif", ".bmp", ".emp", ".wmf", ".tiff"};
        return valids.Contains(System.IO.Path.GetExtension(filename));
}

private void openFileDialog2_FileOk(object sender, CancelEventArgs e)
{
    if (CheckIfImage(openFileDialog2.FileName.ToLower()) == true)
        embedImage(Image.FromFile(openFileDialog2.FileName));
    else
        MessageBox.Show("Invalid Image File Selected");
}

这是 embedImage 方法:

    private void embedImage(Image img)
    {
        var rtf = new StringBuilder();

        // Append the RTF header
        rtf.Append(@"{\rtf1\ansi\ansicpg1252\deff0\deflang1033");
        // Create the font table using the RichTextBox's current font and append
        // it to the RTF string
        rtf.Append(GetFontTable(this.Font));
        // Create the image control string and append it to the RTF string
        rtf.Append(GetImagePrefix(img));
        // Create the Windows Metafile and append its bytes in HEX format
        rtf.Append(getRtfImage(img));
        // Close the RTF image control string
        rtf.Append(@"}");
        richTextBox1.SelectedRtf = rtf.ToString();
    }



在这里有所有必要的方法:

Here there are all the necessary methods:

    private enum EmfToWmfBitsFlags
    {
        EmfToWmfBitsFlagsDefault = 0x00000000,
        EmfToWmfBitsFlagsEmbedEmf = 0x00000001,
        EmfToWmfBitsFlagsIncludePlaceable = 0x00000002,
        EmfToWmfBitsFlagsNoXORClip = 0x00000004
    };

    private struct RtfFontFamilyDef
    {
        public const string Unknown = @"\fnil";
        public const string Roman = @"\froman";
        public const string Swiss = @"\fswiss";
        public const string Modern = @"\fmodern";
        public const string Script = @"\fscript";
        public const string Decor = @"\fdecor";
        public const string Technical = @"\ftech";
        public const string BiDirect = @"\fbidi";
    }

    [DllImport("gdiplus.dll")]
    private static extern uint GdipEmfToWmfBits(IntPtr _hEmf,
      uint _bufferSize, byte[] _buffer,
      int _mappingMode, EmfToWmfBitsFlags _flags);


    private string GetFontTable(Font font)
    {
        var fontTable = new StringBuilder();
        // Append table control string
        fontTable.Append(@"{\fonttbl{\f0");
        fontTable.Append(@"\");
        var rtfFontFamily = new HybridDictionary();
        rtfFontFamily.Add(FontFamily.GenericMonospace.Name, RtfFontFamilyDef.Modern);
        rtfFontFamily.Add(FontFamily.GenericSansSerif, RtfFontFamilyDef.Swiss);
        rtfFontFamily.Add(FontFamily.GenericSerif, RtfFontFamilyDef.Roman);
        rtfFontFamily.Add("UNKNOWN", RtfFontFamilyDef.Unknown);

        // If the font's family corresponds to an RTF family, append the
        // RTF family name, else, append the RTF for unknown font family.
        fontTable.Append(rtfFontFamily.Contains(font.FontFamily.Name) ? rtfFontFamily[font.FontFamily.Name] : rtfFontFamily["UNKNOWN"]);
        // \fcharset specifies the character set of a font in the font table.
        // 0 is for ANSI.
        fontTable.Append(@"\fcharset0 ");
        // Append the name of the font
        fontTable.Append(font.Name);
        // Close control string
        fontTable.Append(@";}}");
        return fontTable.ToString();
    }

    private string GetImagePrefix(Image _image)
    {
        float xDpi, yDpi;
        var rtf = new StringBuilder();
        using (Graphics graphics = CreateGraphics())
        {
            xDpi = graphics.DpiX;
            yDpi = graphics.DpiY;
        }
        // Calculate the current width of the image in (0.01)mm
        var picw = (int)Math.Round((_image.Width / xDpi) * 2540);
        // Calculate the current height of the image in (0.01)mm
        var pich = (int)Math.Round((_image.Height / yDpi) * 2540);
        // Calculate the target width of the image in twips
        var picwgoal = (int)Math.Round((_image.Width / xDpi) * 1440);
        // Calculate the target height of the image in twips
        var pichgoal = (int)Math.Round((_image.Height / yDpi) * 1440);
        // Append values to RTF string
        rtf.Append(@"{\pict\wmetafile8");
        rtf.Append(@"\picw");
        rtf.Append(picw);
        rtf.Append(@"\pich");
        rtf.Append(pich);
        rtf.Append(@"\picwgoal");
        rtf.Append(picwgoal);
        rtf.Append(@"\pichgoal");
        rtf.Append(pichgoal);
        rtf.Append(" ");

        return rtf.ToString();
    }

    private string getRtfImage(Image image)
    {
        // Used to store the enhanced metafile
        MemoryStream stream = null;
        // Used to create the metafile and draw the image
        Graphics graphics = null;
        // The enhanced metafile
        Metafile metaFile = null;
        try
        {
            var rtf = new StringBuilder();
            stream = new MemoryStream();
            // Get a graphics context from the RichTextBox
            using (graphics = CreateGraphics())
            {
                // Get the device context from the graphics context
                IntPtr hdc = graphics.GetHdc();
                // Create a new Enhanced Metafile from the device context
                metaFile = new Metafile(stream, hdc);
                // Release the device context
                graphics.ReleaseHdc(hdc);
            }

            // Get a graphics context from the Enhanced Metafile
            using (graphics = Graphics.FromImage(metaFile))
            {
                // Draw the image on the Enhanced Metafile
                graphics.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height));
            }

            // Get the handle of the Enhanced Metafile
            IntPtr hEmf = metaFile.GetHenhmetafile();
            // A call to EmfToWmfBits with a null buffer return the size of the
            // buffer need to store the WMF bits.  Use this to get the buffer
            // size.
            uint bufferSize = GdipEmfToWmfBits(hEmf, 0, null, 8, EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
            // Create an array to hold the bits
            var buffer = new byte[bufferSize];
            // A call to EmfToWmfBits with a valid buffer copies the bits into the
            // buffer an returns the number of bits in the WMF.  
            uint _convertedSize = GdipEmfToWmfBits(hEmf, bufferSize, buffer, 8, EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
            // Append the bits to the RTF string
            foreach (byte t in buffer)
            {
                rtf.Append(String.Format("{0:X2}", t));
            }
            return rtf.ToString();
        }
        finally
        {
            if (graphics != null)
                graphics.Dispose();
            if (metaFile != null)
                metaFile.Dispose();
            if (stream != null)
                stream.Close();
        }
    }



我建议你换到自己的这个用户控件

这篇关于在格式文本框插入图像在光标位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆