3

如果我有一个richTextBox 并在其上运行DrawToBitmap,它不会在richTextBox 内绘制任何文本。

Bitmap b = new Bitmap(rtb.Width, rtb.Height);
inputControl.DrawToBitmap(b, new Rectangle(0, 0, b.Width, b.Height));

有没有什么办法解决这一问题?

4

6 回答 6

5

我知道这是比较老的,但是我在http://www.windows-tech.info/3/8ffaf21eed5de2d4.php找到了一个可行的解决方案:

public static Bitmap RtbToBitmap(RichTextBox rtb)
{
    rtb.Update(); // Ensure RTB fully painted
    Bitmap bmp = new Bitmap(rtb.Width, rtb.Height);
    using (Graphics gr = Graphics.FromImage(bmp))
    {
        gr.CopyFromScreen(rtb.PointToScreen(Point.Empty), Point.Empty, rtb.Size);
    }
    return bmp;
}
于 2014-06-10T23:23:53.767 回答
4

该主题在 Google 中排名第二。似乎有你想要的。因为我想你在这个问题Accepting Form Elements As Method Arguments? ,最好做这样的事情。

if(inputControl is RichTextBox)
{
    //do specifc magic here
}
else
{
    //general case
}

您可以递归检查包含 RichTextBox 的控件

bool ContainsOrIsRichTextBox(Control inputControl)
{
    if(inputControl is RichTextBox) return true;
    foreach(Control control in inputControl.Controls)
    {
        if(ContainsOrIsRichTextBox(control)) return true;
    }
    return false;
}

我还没有编译这个,并且有一种方法可以做到这一点而不会冒 StackOverflowException 的风险,但这应该让你开始。

于 2011-02-11T21:34:51.210 回答
4

来自 RichTextBox.DrawToBitmap() 的 MSDN 库文章:

此方法与此类无关。

说本机 Windows Richedit 控件不支持 WM_PRINT 的糟糕方式。截屏是一种选择,诺维科夫给了你我答案的链接。

于 2011-02-11T21:38:38.950 回答
3

值得一提的是,RichTextBox 控件的更高版本正确地支持了 DrawToBitmap 方法;它还提高了性能并具有更多功能。

internal class RichTextBox5: RichTextBox
{
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr LoadLibrary(string lpFileName);

    protected override CreateParams CreateParams
    {
        get
        {
           CreateParams cparams = base.CreateParams; 
           if (LoadLibrary("msftedit.dll") != IntPtr.Zero)
           {
              cparams.ClassName = "RICHEDIT50W";
           }
           return cparams;
         }
    }
}
于 2015-06-05T19:32:53.393 回答
2

我在这里找到了一个相关的答案:如何以正确的格式在任何设备内容上打印富文本框内容?

我将其更改为将屏幕外 RichTextBox 渲染为位图。这样我就可以在屏幕外创建一个位图,然后将其发送到 OpenGL。

    // Convert the unit used by the .NET framework (1/100 inch) 
    // and the unit used by Win32 API calls (twips 1/1440 inch)
    private const double anInch = 14.4;

    [StructLayout(LayoutKind.Sequential)]
    private struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct CHARRANGE
    {
        public int cpMin;               // First character of range (0 for start of doc)
        public int cpMax;               // Last character of range (-1 for end of doc)
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct FORMATRANGE
    {
        public IntPtr    hdc;           // Actual DC to draw on
        public IntPtr    hdcTarget;     // Target DC for determining text formatting
        public RECT      rc;            // Region of the DC to draw to (in twips)
        public RECT      rcPage;        // Region of the whole DC (page size) (in twips)
        public CHARRANGE chrg;          // Range of text to draw (see earlier declaration)
    }

    private const int WM_USER        = 0x0400;
    private const int EM_FORMATRANGE = WM_USER + 57;

    [DllImport("USER32.dll")] private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);

    /// <summary>
    /// Render the specified RichTextBox onto the specified bitmap
    /// </summary>
    /// <param name="textBox">RichTextBox to render</param>
    /// <param name="bitmap">Bitmap to render the RichTextBox onto</param>
    public void RenderToBitmap(RichTextBox textBox, Bitmap bitmap)
    {
        // Set area to render to be entire bitmap
        RECT rect;
        rect.Left   = 0;
        rect.Top    = 0;
        rect.Right  = (int)(bitmap.Width  * anInch);
        rect.Bottom = (int)(bitmap.Height * anInch);

        Graphics g   = Graphics.FromImage(bitmap);
        IntPtr   hdc = g.GetHdc();

        FORMATRANGE fmtRange;
        fmtRange.chrg.cpMin = textBox.GetCharIndexFromPosition(new Point(0,0));
        fmtRange.chrg.cpMax = textBox.GetCharIndexFromPosition(new Point(bitmap.Width,bitmap.Height));
        fmtRange.hdc        = hdc;                  // Use the same DC for measuring and rendering
        fmtRange.hdcTarget  = hdc;
        fmtRange.rc         = rect;
        fmtRange.rcPage     = rect;

        IntPtr lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
        Marshal.StructureToPtr(fmtRange, lparam, false);

        // Render the control to the bitmap
        SendMessage(textBox.Handle, EM_FORMATRANGE, new IntPtr(1), lparam);

        // Clean up
        Marshal.FreeCoTaskMem(lparam);
        g.ReleaseHdc(hdc);
    }
于 2014-06-14T19:44:29.100 回答
0

我测试了上面的方法,每当我将保存的位图加载到 ImageViewer(Like Paint) 中时,SaveFileDialog-UI 都会淡入文本背景。幸运的是,我找到了一个简单的解决方法:

SaveFileDialog bfsd = new SaveFileDialog();       
var rtb = richTextBox1;

        bfsd.Filter = "Bitmap (*.bmp)|*.bmp|All Files (*.*)|*.*";
        bfsd.Title = "Save your text as a Bitmap File";

        rtb.Update(); // Ensure RTB fully painted
        Bitmap bmp = new Bitmap(rtb.Width, rtb.Height);
        using (Graphics gr = Graphics.FromImage(bmp))
        {
            gr.CopyFromScreen(rtb.PointToScreen(Point.Empty), Point.Empty, rtb.Size);
        }

        if (bfsd.ShowDialog()==DialogResult.OK)
        {
         Draw:
            try
            {
                bmp.Save(bfsd.FileName);

                bmp.Dispose();
            }
            catch (Exception)
            {
                DialogResult dr = MessageBox.Show("An error ocurred while attempting to save your Image...", "Error! Error!", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);

                if (dr == DialogResult.Retry)
                {
                    goto Draw;
                }
                else if (dr == DialogResult.Cancel)
                {
                    return;
                }
            }
  • 这样,它甚至会在您按下之前绘制图片Save别担心,在您按下之前它实际上不会保存图像Save

按下Cancel不会影响该过程,因为当您按下ButtonMenuStripItem保存它时,它将更新并重新绘制它:)

我实现了一个try-catch方法,以便在发生错误时捕获错误,而不仅仅是应用程序(Not Responding)

catch方法是一个Retry Button

它将捕获错误,并让您选择Cancel整体Operation,或Retry

我曾经goto能够倒带,并再次尝试保存文件,而不是SaveFileDialog再次出现。

我希望这可以帮助你 :)

于 2019-10-25T00:46:56.487 回答