2016-05-30 1 views
0

Я столкнулся с очень странной проблемой при попытке получить снимок экрана TableLayoutPanel в моей форме.Мой код работает только при вставке случайного MsgBox

У меня есть этот код (взятый из другого вопроса (How to get a screenshot, only for a picturebox) код, предоставленный пользователем "Chase Rocker"):

Dim s As Size = TableLayoutPanel1.Size 
    Dim memoryImage = New Bitmap(s.Width, s.Height) 
    Dim memoryGraphics As Graphics = Graphics.FromImage(memoryImage) 
    Dim ScreenPos As Point = Me.TableLayoutPanel1.PointToScreen(New Point(0, 0)) 
    memoryGraphics.CopyFromScreen(ScreenPos.X, ScreenPos.Y, 0, 0, s) 
    Form3.PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize 
    Form3.PictureBox1.BringToFront() 
    Form3.PictureBox1.Image = memoryImage 

Теперь, вот идет моя проблема. Этот код дает мне пустую картинку. Похоже, это скриншот, но все, что я вижу, белое. Теперь я пытался выяснить, правильный ли размер, поэтому я возился с MsgBox. Добавить эту строку в код:

MsgBox("Random Message") 

Получение

Dim s As Size = TableLayoutPanel1.Size 
    MsgBox("Random Message") 
    Dim memoryImage = New Bitmap(s.Width, s.Height) 
    Dim memoryGraphics As Graphics = Graphics.FromImage(memoryImage) 
    Dim ScreenPos As Point = Me.TableLayoutPanel1.PointToScreen(New Point(0, 0)) 
    memoryGraphics.CopyFromScreen(ScreenPos.X, ScreenPos.Y, 0, 0, s) 
    Form3.PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize 
    Form3.PictureBox1.BringToFront() 
    Form3.PictureBox1.Image = memoryImage 

По некоторым причинам я не знаю, скриншот теперь работает. Я больше не вижу белого цвета, но фактический снимок экрана TableLayoutPanel. Для меня очень странно, что код работает только с MsgBox. Может быть, я что-то упустил. кто-нибудь знает, почему это произошло? Спасибо!

+0

В каком случае вы используете этот код? Надеюсь, что не в конструкторе, а в Форме. – Steve

+0

Private Sub Button1_Click (отправитель As Object, e As EventArgs) Ручки Button1.Click Простое событие кнопки. Это же событие также заполняет TableLayOutPanel всей информацией. –

+2

Если заполнение происходит в том же месте, где вы захватываете изображение, то у вас ничего нет в таблице tablelayoutpanel, пока вы не выйдете из обработчика события. Другими словами, механизм winforms не может ничего нарисовать до тех пор, пока вы не выйдете из обработчика события. – Steve

ответ

4

Как насчет того, если вы попытаетесь сделать вывод TableLayoutPanel в растровое изображение? Это можно сделать, используя метод Control.DrawToBitmap().

Dim s As Size = TableLayoutPanel1.Size 
Dim memoryImage As New Bitmap(s.Width, s.Height) 

TableLayoutPanel1.DrawToBitmap(memoryImage, New Rectangle(New Point(0, 0), s)) 
Form3.PictureBox1.Image = memoryImage 
+0

Ваш код работал без MsgBox. Спасибо! Хотя, мне все еще интересно о MsgBox в моем последнем коде. Я попробую другое предложение и посмотрю, что я получу в результате. –

+0

Очень хорошо - TLP больше не нужно рисовать, так что Refresh не требуется ни ..., ни больше утечки. – Plutonix

+0

Что вы подразумеваете под утечкой? –

2

Если заливка TableLayoutPanel происходит в тот же обработчик событий, где вы захватить изображение, а затем Windows, не сделать пользовательский интерфейс для элементов, добавляемых к TableLayoutPanel. Только когда вы выходите из обработчика событий, механизм winforms имеет возможность рисовать все.

Добавление MessageBox меняет все, потому что вызов Show (модальный вызов, который прерывает ваш код и передает управление обратно в окно) позволяет механизму Winform выводить ожидающие обновления и ваш код работает.

Вы можете добавить управление таймером и поместить код, который выполняет ScreenShoot в событии Timer.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
    ...... 
    ' code that fills the TableLayoutPanel 
    ...... 

    Dim tim1 = new System.Windows.Forms.Timer() 
    tim1.Interval = 1 
    AddHandler tim1.Tick, AddressOf tim1Ticked 
    tim1.Start() 
End Sub 
Private Sub tim1Ticked(sender As Object, e As EventArgs) 

    ...... 
    ' Code that execute the screenshoot. 
    ...... 

    Dim t = DirectCast(sender, System.Windows.Forms.Timer) 
    t.Stop() 
End Sub 
+0

Тогда мне любопытно, почему 'TabelLayoutPanel1.DrawToBitmap()', похоже, работает для OP. –

+0

Теперь мне тоже любопытно! Спасибо Стиву за объяснение, это то, что я искал. Не возражаете ли вы ответить на новый вопрос Visual Vincent и у меня? –

+2

Глядя на [источник ссылки DrawToBitmap] (http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Control.cs,4441da5479e7a6f8), кажется, что отправлено сообщение WM_PAINT в базовый элемент управления, заставляя немедленную перерисовку элемента управления, чтобы следующая функция BitBlt API имела необходимый контент для заполнения растрового изображения. Я не очень разбираюсь в этой области (графика), поэтому, возможно, есть другие моменты, которые нужно учитывать, так или иначе кажется, что DrawToBitmap - лучший выбор, чем весь код, требуемый моим ответом, и пользователем ChaseRocker – Steve

Смежные вопросы