Сделать недействительным собственное растровое изображение - PullRequest
11 голосов
/ 15 декабря 2011

Я хочу за пределами экрана визуализировать элемент управления для некоторого растрового изображения, чтобы у меня был быстрый доступ к нему.

К сожалению, Control.DrawToBitmap, кажется, рисует весь элемент управления, на котором он вызывается, включая все его дочерние элементы управления.Внутренне он выдает сообщение WM_PRINT с самодостаточным DC в растровое изображение.Это временное растровое изображение затем добавляется в предоставленное пользователем растровое изображение.Для меня неприемлемо, я бы предпочел обновить это растровое изображение по мере необходимости, чтобы свести к минимуму снижение производительности при необходимости растрового изображения.

В идеальном случае я бы хотел, чтобы форма работала так, как если бы она была видна наэкран (но это не может быть).Это означало бы, что если, скажем, у некоторого элемента управления свойство Text изменилось, форма будет частично аннулирована.После перехвата соответствующих сообщений / событий я мог бы либо указать свой собственный DC для формы, которую нужно нарисовать, либо просто привязать DC формы к своему.

Некоторые направления, в которых я смотрел:

  • Параметр PaintEventArgs в OnPaint, кажется, содержит член saveGraphicsState, возможно, его можно использовать для определения того, что не требует аннулирования
  • Наличие формы видимой, но внеплощадь экрана.Тогда элементы управления не будут окрашены.
  • Ручной вызов RedrawWindow () для окна, та же история

Ответы [ 3 ]

1 голос
/ 21 января 2012

Я думаю, что есть две проблемы:

  1. обнаружение неверной области элемента управления (без помощи окон)
  2. рендеринг только недействительной части.

По первому вопросу, я думаю, вы в значительной степени сами по себе. Вы должны следить за тем, какие элементы управления меняются, и вести учет, который нуждается в обновлении.

Для второго вопроса вы можете попытаться отправить сообщение WM_PRINT самостоятельно и предоставить DC, ссылающийся только на маленькую битовую карту. Оригинальный DC API позволял вам смещать и обрезать действительную область рисования HDC. Если вам очень повезет, окна выведут область рендеринга из HDC, а если нет, большинство команд рендеринга, которые полностью выпадают из растрового изображения, должны быть довольно дешевыми, поскольку нет пикселей, которые нужно менять.

Вы сможете проверить это, напечатав в растровое изображение 1x1, и проверить, быстрее ли оно, и / или проверить, уменьшена ли область клипа, отправленная в WM_PAINT, до размера растрового изображения.

0 голосов
/ 21 декабря 2011

Я сделал пример проекта для вас, где я показал некоторые события onPaint. Если вы не видите, как это решается таким образом, просто обновите пример.

Привет! OnPaint example

Скачать здесь: http://www.goldengel.ch/temp/OnPaintExample.zip

Private Sub Button1_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles Button1.Paint
    Dim bm As New Bitmap(Me.Button1.Width, Me.Button1.Height, PixelFormat.Format32bppRgb)

    Button1.DrawToBitmap(bm, New Rectangle(0, 15, bm.Width -5, bm.Height+2))
    Using gr As Graphics = Graphics.FromImage(bm)
        gr.DrawString(DateTime.Now.ToLongTimeString, Me.Font, Brushes.Lime, 0, 0)
    End Using
    Me.PictureBox1.BackgroundImageLayout = ImageLayout.Tile
    Me.PictureBox1.BackgroundImage = bm

End Sub
    Public Class myTextBox
        Inherits System.Windows.Forms.TextBox


        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            MyBase.OnPaint(e)
            e.Graphics.Clear(Color.Yellow)
            e.Graphics.DrawString(DateTime.Now.ToLongTimeString, Me.Font, Brushes.Gray, 0, 0)
        End Sub

        Public Sub New()
            SetStyle(ControlStyles.UserPaint, True)
        End Sub
    End Class
0 голосов
/ 18 декабря 2011

Я думаю, что это будет работать, если клонировать элемент управления, так что вы получите элемент управления, который не находится на форме и не имеет дочерних элементов управления:

Control ctrl = ControlFactory.CloneCtrl(this.button3);
Bitmap bmp = new Bitmap(ctrl.Width, ctrl.Height);
ctrl.DrawToBitmap(bmp, new Rectangle(0, 0, ctrl.Width, ctrl.Height));
bmp.Save(@"C:\Users\Oli\Desktop\test.bmp");

Я использовал ControlFactory , написанный lxwde, найденный в Код проекта .

ControlFactory не идеален, но достаточно прост и может быть легко улучшен.

...