我的代码仅在插入随机MsgBox时有效

时间:2016-05-30 15:24:37

标签: vb.net screenshot tablelayoutpanel

尝试在表单中获取TableLayoutPanel的屏幕截图时遇到了一个非常奇怪的问题。

我有这个代码(取自另一个问题(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。也许我错过了什么。有谁知道为什么会这样?谢谢!

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

如果TableLayoutPanel填充发生在您抓取图像的同一事件处理程序中,则Windows不会为添加到TableLayoutPanel的元素绘制UI。只有当您退出事件处理程序时,winforms引擎才有机会绘制所有内容。

添加MessageBox会更改所有内容,因为调用Show(中断代码并将控制权传递回窗口的模式调用)允许Winform引擎绘制待处理的更新并且代码可以正常工作。

您可以添加Timer控件并将执行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