richTextBox.DrawToBitmap не рисует содержащий текст? - PullRequest
2 голосов
/ 12 февраля 2011

Если у меня есть richTextBox и я запускаю DrawToBitmap, он не рисует текст внутри richTextBox.

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

Есть ли способ это исправить?

Ответы [ 5 ]

4 голосов
/ 11 июня 2014

Я знаю, что это относительно старое, но рабочее решение, которое я нашел по адресу 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;
}
3 голосов
/ 12 февраля 2011

Из статьи библиотеки MSDN для RichTextBox.DrawToBitmap ():

Этот метод не подходит для этого класса.

Неприличный способ сказать, что родной элемент управления Windows richedit не поддерживает WM_PRINT. Взять снимок экрана - вариант, Новиков дал вам ссылку на мой ответ.

2 голосов
/ 05 июня 2015

Несмотря на это, более поздняя версия элемента управления 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;
         }
    }
}
2 голосов
/ 12 февраля 2011

Эта тема заняла второе место в Google. Кажется, есть именно то, что вы хотите. Поскольку я полагаю, что вы используете это внутри своей функции из этого вопроса Принятие элементов формы в качестве аргументов метода? , вероятно, лучше сделать что-то подобное.

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, но это должно помочь вам начать.

1 голос
/ 14 июня 2014

Я нашел соответствующий ответ здесь: как напечатать содержимое текстового поля на любом устройстве с правильным форматированием?

Я изменил это, чтобы отобразить мой закадровый 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);
    }
...