I am trying to access a dynamically generated Control from a separate thread.
But I am always getting a "Stack Overflow Exception" with my code.
I am using following code:
Private _workerThread As Threading.Thread
Private Sub Main_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Dim Label As New Label
Label.Name = "Label1"
Label.Location = New System.Drawing.Point(12, 12)
Label.Text = String.Empty
Label.AutoSize = True
Controls.Add(Label)
_workerThread = New Threading.Thread(AddressOf DoWork)
_workerThread.Priority = Threading.ThreadPriority.BelowNormal
_workerThread.Start()
End Sub
Private Sub DoWork()
SetLabelText("Label1", "text")
End Sub
Delegate Sub SetLabelTextCallback(ByVal LabelName As String, ByVal text As String)
Private Sub SetLabelText(ByVal LabelName As String, ByVal text As String)
If CType(Me.Controls(LabelName), Label).InvokeRequired Then
Dim d As New SetLabelTextCallback(AddressOf SetLabelText)
d.Invoke(LabelName, text)
Else
CType(Me.Controls(LabelName), Label).Text = text
End If
End Sub
Apparently InvokeRequired never gets to False. But I can´t get it why.
Maybe someone can tell me what I´m doing wrong.
You are not calling the method SetLabelTextCallback on the thread of the Label,
thus you will recall again on the same thread and InvokeRequired is never false
Delegate Sub SetLabelTextCallback(ByVal LabelName As String, ByVal text As String)
Private Sub SetLabelText(ByVal LabelName As String, ByVal text As String)
Dim l as Label = CType(Me.Controls(LabelName), Label)
if l.InvokeRequired then
Dim d As New SetLabelTextCallback(AddressOf SetLabelText)
l.Invoke(d, new Object() {LabelName, text} )
Else
l.Text = text
End If
End Sub
Related
I have a first form (form_notice_hashtag) called like this:
Public Sub afficher_hashtag(hashtag As String, plateforme_hashtag As String)
Dim form_notice_hashtag_1 As New form_notice_hashtag
form_notice_hashtag_1.StartPosition = FormStartPosition.CenterScreen
form_notice_hashtag_1.Show()
End Sub
In form_notice_hashtag_1, i have a button calling a 2nd form (form_recherche_thesaurus) like this:
Private Sub hashtag_thesaurus_search_button_Click(sender As Object, e As EventArgs) Handles hashtag_thesaurus_search_button.Click
Dim form_recherche_thesaurus_1 As New form_recherche_thesaurus With {
.StartPosition = FormStartPosition.Manual,
.Location = New Point(Me.Left + Me.Width, Me.Top)
}
form_recherche_thesaurus_1.ShowDialog(Me)
End Sub
In form_recherche_thesaurus, i have a datagridview listing some words. The user can select one word, then by clicking a button in form_recherche_thesaurus, the word which will be added to a textbox in form_notice_hashtag
Private Sub thesaurus_ok_button_Click(sender As Object, e As EventArgs) Handles thesaurus_ok_button.Click
Dim list_terms_array As String()
Select Case Owner.Name.ToString
Case "form_notice_hashtag"
list_terms_array = Split(Remove_Duplicates_From_Strings_With_SemiColon(form_notice_hashtag.hashtag_descripteurs_txtbox.Text & ";" & selected_term), ";")
form_notice_hashtag.hashtag_descripteurs_txtbox.Text = (String.Join(";", list_terms_array.Where(Function(s) Not String.IsNullOrEmpty(s))))
End Select
End Sub
I used a select because this mechanism would be used in the same way with other forms than form_notice_hashtag.
Problem: the textbox in form_notice_hashtag is not filled with the selected keywords. I guess it's because of the way form_notice_hashtag is called.
I can't use the solution as explained here Send values from one form to another form because i understood (maybe badly) that this solution works only if the 2nd form (form_recherche_thesaurus in my case) is closed (i.e closing was the trigger) which i don't want.
How can I proceed?
Thanks to jmcilhinney and this page of his blog, here is the solution that allows to transfer several data from a called form (form_recherche_thesaurus) to a calling form (form_notice_hashtag) without closing the called form .
Public Class form_notice_hashtag
Private WithEvents form_recherche_thesaurus_1 As form_recherche_thesaurus
Private selected_thesaurus_term As String
Private Sub form_recherche_thesaurus_1_TextBoxTextChanged(sender As Object, e As EventArgs) Handles form_recherche_thesaurus_1.TextBoxTextChanged
Dim list_terms_array As String() = Split(Remove_Duplicates_From_Strings_With_SemiColon(Me.hashtag_descripteurs_txtbox.Text & ";" & form_recherche_thesaurus_1.selected_term), ";")
Me.hashtag_descripteurs_txtbox.Text = (String.Join(";", list_terms_array.Where(Function(s) Not String.IsNullOrEmpty(s))))
End Sub
Private Sub hashtag_thesaurus_search_button_Click(sender As Object, e As EventArgs) Handles hashtag_thesaurus_search_button.Click
Dim form_recherche_thesaurus_1 As New form_recherche_thesaurus With {
.StartPosition = FormStartPosition.Manual,
.Location = New Point(Me.Left + Me.Width, Me.Top)
}
If Me.form_recherche_thesaurus_1 Is Nothing OrElse Me.form_recherche_thesaurus_1.IsDisposed Then
Me.form_recherche_thesaurus_1 = New form_recherche_thesaurus With {
.StartPosition = FormStartPosition.Manual,
.Location = New Point(Me.Left + Me.Width, Me.Top)
}
Me.form_recherche_thesaurus_1.Show()
End If
Me.form_recherche_thesaurus_1.Activate()
End Sub
End Class
Public Class form_recherche_thesaurus
Public Event TextBoxTextChanged As EventHandler
Private term_thesaurus As String
Public Property selected_term() As String
Get
Return term_thesaurus
End Get
Set(ByVal value As String)
term_thesaurus = value
End Set
End Property
Private Sub thesaurus_ok_button_Click(sender As Object, e As EventArgs) Handles thesaurus_ok_button.Click
Dim list_terms_array As String()
Me.selected_term = Me.thesaurus_search_results_datagrid.Item(0, Me.thesaurus_search_results_datagrid.CurrentRow.Index).Value
Me.DialogResult = DialogResult.OK
RaiseEvent TextBoxTextChanged(Me, EventArgs.Empty)
End Sub
I am having trouble looping through my playlist of mp3 tracks.
Can anybody shed some light on where I am going wrong. This is the code. It play the first track, but then stops.
Code has been edited 011020
' The following Menu Item plays the full list of mp3s in the list box
Private Sub PlayListToolStripMenuItem_Click(sender As Object, e As EventArgs)
Handles PlayListToolStripMenuItem.Click
FromDictionary = False
PlaySongsFromListBox()
End Sub
Private Sub PlaySongsFromListBox()
'MsgBox("Index Counter = " & NextIndex)
'MsgBox("Total No of Tracks = " & ListBox1.Items.Count)
If NextIndex = ListBox1.Items.Count Then
NextIndex = 0
MessageBox.Show("All music has been played")
Exit Sub
End If
Dim item As KeyValuePair(Of String, String) =
DirectCast(ListBox1.Items(NextIndex), KeyValuePair(Of String, String))
Dim SongPath = Path.Combine(item.Value, item.Key)
PlayASong(SongPath)
End Sub
Private Sub PlayASong(SongPath As String)
MsgBox("Playing Track: " & SongPath)
CurrentMediaStreamName = SongPath
MediaPlayer1.URL = SongPath
MediaPlayer1.Ctlcontrols.play()
MsgBox("Playing Track: " & SongPath)
End Sub
Private Sub MediaPlayer1_PlayStateChange(sender As Object, e As
AxWMPLib._WMPOCXEvents_PlayStateChangeEvent) Handles
MediaPlayer1.PlayStateChange
If MediaPlayer1.playState = WMPLib.WMPPlayState.wmppsMediaEnded Then
NextIndex += 1
PlaySongsFromListBox()
End If
End Sub
At the class level (Form1) I declared 4 variables that are used in more than one method.
In the Form.Load I filled the MusicDictionary. You may be filling this from a database or text file. I also bound the ListBox to the dictionary. The ListBox.DataSource cannot take a Dictionary directly but a BindingSource can handle it.
PlayASong simply does what it says.
PlaySongsFromDictionary first checks if we have come to the end of the Dictionary. Note that I reset NextIndex back to 0. I used Path.Combine to get the path for the song. Notice that in one dictionary entry, I left out a back slash at the end of the directories and in the other entry I included the backslash. Path.Combine accepted both and added a back slash where necessary. Also notice that the index is applied to the Keys collection and the Values collection of the Dictionary not the Dictionary itself. If we tried to apply the index to the dictionary it would be trying to look for the Key inside the brackets. Default Public Property Item(key As TKey) As TValue
PlaySongsFromListBox casts the list box item (which is an object) back to its underlying type, KeyValuePair.
Finally, the important part! I used the MediaEnded event of the MediaPlayer1 to determine when to play the next song. Here I incremented the index and called the one of the PlaySongs... methods.
Private NextIndex As Integer
Private WithEvents MediaPlayer1 As New MediaPlayer
Private MusicDictionary As New Dictionary(Of String, String)
Private FromDictionary As Boolean
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
MusicDictionary.Add("2018-11-27_-_Track_A_-_FesliyanStudios.com_By_Stephen_Bennett.mp3", "C:\Users\maryo\Documents\Marys Music")
MusicDictionary.Add("file_example_MP3_700KB.mp3", "C:\Users\maryo\Documents\Marys Music\")
ListBox1.DataSource = New BindingSource(MusicDictionary, Nothing)
ListBox1.DisplayMember = "Key"
ListBox1.ValueMember = "Value"
End Sub
Private Sub PlayASong(SongPath As String)
MediaPlayer1.Open(New Uri(SongPath))
MediaPlayer1.Play()
End Sub
Private Sub PlaySongsFromDictionary()
If NextIndex = MusicDictionary.Count Then
NextIndex = 0
MessageBox.Show("All music has been played")
Exit Sub
End If
Dim SongPath = Path.Combine(MusicDictionary.Values(NextIndex), MusicDictionary.Keys(NextIndex))
PlayASong(SongPath)
End Sub
Private Sub PlaySongsFromListBox()
If NextIndex = ListBox1.SelectedItems.Count Then
NextIndex = 0
MessageBox.Show("All music has been played")
Exit Sub
End If
Dim item As KeyValuePair(Of String, String) = DirectCast(ListBox1.SelectedItems(NextIndex), KeyValuePair(Of String, String))
Dim SongPath = Path.Combine(item.Value, item.Key)
PlayASong(SongPath)
End Sub
Public Sub MediaPlayers1_MediaEnded() Handles MediaPlayer1.MediaEnded
NextIndex += 1
If FromDictionary Then
PlaySongsFromDictionary()
Else
PlaySongsFromListBox()
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
FromDictionary = False
PlaySongsFromListBox()
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
FromDictionary = True
PlaySongsFromDictionary()
End Sub
The problem with the MP3's not looping was solved using the following invoke method
If e.newState = WMPLib.WMPPlayState.wmppsStopped Then
Me.BeginInvoke(New Action(AddressOf NextSong))
End If
Found at the following location Function call only works when MessageBox.Show() is included?
So I've been fiddling with this for a while and I don't know if I'm not understanding how the BackgroundWorker works and/or I'm using it wrong or if I'm missing something.
Basically what I'm trying to do is call a BackgroundWorker from a DragDrop function where the user can drop a set of images into the form. The BackgroundWorder then copies the images to a temp location thumbnails are pulled and turned into PictureBoxes and the PictureBoxes are added to a collection. Once the BackgroundWorker is completed the function runs to add all the picture boxes to the form.
All of this is working properly except the progress. The progress function doesn't like to fire until near the end (after almost all the pictures have been copied) during this time the UI is locked (which I'm sure is why the progress function isn't firing) I just can't figure out why the UI is locking.
I've stepped through the code and the ReportProgress method is being called ever loop but the ProgressReported function isn't called until near the end.
HELP! LOL
this is the ControlClass for my copying and creating thumbnails
Imports System.ComponentModel
Imports System.IO
Namespace ThumbnailViewer
Public Class ThumbnailControl
Inherits FlowLayoutPanel
Private ImageExtensions As List(Of String) = New List(Of String) From {".JPG", ".JPE", ".BMP", ".GIF", ".PNG"}
Private tempStoragePath As String = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & "\tempPhotos"
Private WithEvents bkWPhotos As New BackgroundWorker
Public Property iThumbList As List(Of PictureBox)
Public Property sImageList As List(Of String(,))
Private PopupPrg As PopUpProgress.PopUpProgressControl
Public Sub New()
Me.AutoScroll = True
Me.AllowDrop = True
Me.DoubleBuffered = True
iThumbList = New List(Of PictureBox)()
sImageList = New List(Of String(,))()
AddHandler Me.DragDrop, AddressOf ThumbnailViewerControl_DragDrop
AddHandler Me.DragEnter, AddressOf ThumbnailViewerControl_DragEnter
If Not Directory.Exists(tempStoragePath) Then Directory.CreateDirectory(tempStoragePath)
bkWPhotos.WorkerReportsProgress = True
bkWPhotos.WorkerSupportsCancellation = True
End Sub
Public Sub BackGroundWorker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bkWPhotos.DoWork
AddImage(e.Argument)
End Sub
Public Sub BackGroundWorkder_Progress(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) Handles bkWPhotos.ProgressChanged
PopupPrg.SetProgress(e.ProgressPercentage)
End Sub
Public Sub BackGroundWorker_Complete(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles bkWPhotos.RunWorkerCompleted
For Each i As PictureBox In iThumbList
Me.Controls.Add(i)
Next
PopupPrg.Destory()
Me.Cursor = Cursors.Default
End Sub
Public Sub AddImage(ByVal files As String())
Dim fImage As Image
Dim prg As Integer = 0
For Each f As String In files
If ImageExtensions.Contains(Path.GetExtension(f).ToUpperInvariant()) Then
bkWPhotos.ReportProgress(prg)
fImage = Image.FromFile(f)
File.Copy(f, tempStoragePath & "\" & Path.GetFileName(f), True)
sImageList.Add({{tempStoragePath & "\" & Path.GetFileName(f), fImage.Size.Width, fImage.Size.Height}})
Dim t As PictureBox = MakeThumbnail(fImage)
prg = prg + 1
GC.GetTotalMemory(True)
End If
Next
End Sub
Public Function MakeThumbnail(ByVal inImage As Image) As PictureBox
Dim thumb As PictureBox = New PictureBox()
thumb.Size = ScaleImage(inImage.Size, 200)
thumb.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
thumb.SizeMode = PictureBoxSizeMode.Zoom
AddHandler thumb.MouseEnter, AddressOf thumb_MouseEnter
AddHandler thumb.MouseLeave, AddressOf thumb_MouseLeave
AddHandler thumb.DoubleClick, AddressOf thumb_DoubleClick
thumb.Image = inImage.GetThumbnailImage(thumb.Width - 2, thumb.Height - 2, Nothing, New IntPtr())
iThumbList.Add(thumb)
Return thumb
End Function
Private Sub thumb_DoubleClick(ByVal sender As Object, ByVal e As EventArgs)
Dim previewForm As Form = New Form()
Dim index As Integer = Me.Controls.GetChildIndex(CType(sender, PictureBox))
Dim img As Image = Image.FromFile(sImageList(index)(0, 0))
previewForm.FormBorderStyle = FormBorderStyle.SizableToolWindow
previewForm.MinimizeBox = False
previewForm.Size = ScaleImage(img.Size, Screen.GetWorkingArea(Me).Height / 4 * 3)
previewForm.StartPosition = FormStartPosition.CenterScreen
Dim view As PictureBox = New PictureBox()
view.Dock = DockStyle.Fill
view.Image = Image.FromFile(sImageList(index)(0, 0))
view.SizeMode = PictureBoxSizeMode.Zoom
previewForm.Controls.Add(view)
previewForm.ShowDialog()
End Sub
Private Sub thumb_MouseLeave(ByVal sender As Object, ByVal e As EventArgs)
CType(sender, PictureBox).Invalidate()
End Sub
Private Sub thumb_MouseEnter(ByVal sender As Object, ByVal e As EventArgs)
Dim rc = (CType(sender, PictureBox)).ClientRectangle
rc.Inflate(-2, -2)
ControlPaint.DrawBorder((CType(sender, PictureBox)).CreateGraphics(), (CType(sender, PictureBox)).ClientRectangle, Color.Red, ButtonBorderStyle.Solid)
ControlPaint.DrawBorder3D((CType(sender, PictureBox)).CreateGraphics(), rc, Border3DStyle.Bump)
End Sub
Private Sub ThumbnailViewerControl_DragEnter(ByVal sender As Object, ByVal e As DragEventArgs)
If e.Data.GetDataPresent(DataFormats.FileDrop) Then e.Effect = DragDropEffects.Copy Else e.Effect = DragDropEffects.None
End Sub
Private Sub ThumbnailViewerControl_DragDrop(ByVal sender As Object, ByVal e As DragEventArgs)
If e.Data.GetDataPresent(DataFormats.FileDrop) Then
Dim files As String() = CType(e.Data.GetData(DataFormats.FileDrop), String())
Me.Cursor = Cursors.WaitCursor
PopupPrg = New PopUpProgress.PopUpProgressControl(Me, files.Count)
bkWPhotos.RunWorkerAsync(files)
End If
End Sub
Public Function ScaleImage(ByVal oldImage As Size, ByVal TargetHeight As Integer) As Size
Dim NewHeight As Integer = TargetHeight
Dim NewWidth As Integer = NewHeight / oldImage.Height * oldImage.Width
NewHeight = NewWidth / oldImage.Width * oldImage.Height
Return New Size(NewWidth, NewHeight)
End Function
End Class
End Namespace
.... FacePalm.. I figured it out. Apparently during my testing (before I decided to use this control and a background worker, I had added another drag drop function in another area of my code that was being called first. It was taking all the dragged images and turning them into Image data types. The rest of the function was commented out which is why I didn't notice it before because I was only stepping though the classes functions not the functions in the main UI. but it makes perfect sense now, the backgroundworker and the UI function were kicking off at the same time but while the UI thread was processing the Image data typing the report progress calls were stacking up.
After removing that secondary function it works exactly as it should, UI remains fully functional Images and PictureBoxes are processed in the background and the Progressbar updates properly and remains functional as well.
I am new to visual basic so hopefully this is a simple question. I have a menu with buttons to call different forms. The forms are designed and have labels and text fields and buttons and so on. From the main menu I have tried calling the forms two different ways. One way the forms open and look correct and function. The other way the form opens as a small blank square with no fields. Ultimately I want to create a set of List objects when the main menu opens and pass them back and forth to the other forms for input and processing. I'm using parallel Lists as a temporary database for a simple school lab. I just don't see what is wrong with the way I am calling the form. I haven't even bothered worrying about passing the List objects properly yet.
Public Class frmMain
Dim arrGames As New List(Of String)
Dim arrDates As New List(Of String)
Dim arrPrices As New List(Of Decimal)
Dim arrSeats As New List(Of Integer)
Private Sub btnEnterGames_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEnterGames.Click
'NewEnter.Visible = True
Dim frmEnter As New NewEnter(arrGames, arrDates, arrPrices, arrSeats)
frmEnter.ShowDialog()
End Sub
Private Sub btnReports_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnReports.Click
'Reports.Visible = True
Dim frmReports As New Reports(arrGames, arrDates, arrPrices, arrSeats)
frmReports.Visible = True
End Sub
Private Sub btnSellTickets_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSellTickets.Click
'SellTickets.Visible = True
Dim frmSell As New SellTickets(arrGames, arrDates, arrPrices, arrSeats)
frmSell.Visible = True
End Sub
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
Close()
End Sub
End Class
This is the code for the form NewEnter. I have the New routine which accepts the 4 Lists and basically does nothing else. Doing the "'NewEnter.Visible = True" in the main menu will load the form correctly but I have to comment out the New sub routine in the forms or there is an error.
Public Class NewEnter
Private _arrGames As List(Of String)
Private _arrDates As List(Of String)
Private _arrPrices As List(Of Decimal)
Private _arrSeats As List(Of Integer)
Sub New(ByVal arrGames As List(Of String), ByVal arrDates As List(Of String), ByVal arrPrices As List(Of Decimal), ByVal arrSeats As List(Of Integer))
' TODO: Complete member initialization
' _arrGames = arrGames
' _arrDates = arrDates
' _arrPrices = arrPrices
' _arrSeats = arrSeats
End Sub
Private Sub btnSaveGame_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSaveGame.Click
Dim arrGames As New List(Of String)
Dim arrDates As New List(Of String)
Dim arrPrices As New List(Of Decimal)
Dim arrSeats As New List(Of Integer)
Dim strGame As String
Dim strPrice As String
Dim strSeats As String
Dim intSeats As Integer
Dim decPrice As Decimal
Dim bolGameErr As Boolean
Dim bolDateErr As Boolean
Dim bolPriceErr As Boolean
Dim bolSeatErr As Boolean
strGame = txtGame.Text
strPrice = txtPrice.Text
strSeats = txtSeats.Text
'~~~~~~~~~~~~verify a game is entered
If String.IsNullOrEmpty(strGame) Or String.IsNullOrWhiteSpace(strGame) Then
bolGameErr = True
Else
'~~~~~~~~~~~~verify price is numeric
If IsNumeric(strPrice) Then
decPrice = strPrice
'~~~~~~~~~~~~~~~verify seats are numeric
If IsNumeric(strSeats) Then
intSeats = Convert.ToInt32(strSeats)
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ add elements to array lists
arrGames.Add(New String(strGame))
arrDates.Add(dtpDate.Text)
arrPrices.Add(New Decimal(decPrice))
arrSeats.Add(intSeats)
lblSaveSuccessful.Visible = True
ClearInput()
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ add elements to array lists
Else
bolSeatErr = True
End If
Else
bolPriceErr = True
End If
End If
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Check flags for input errors
If bolDateErr = True Then
lblErr.Text = "Invalid date"
lblErr.Visible = True
End If
If bolGameErr = True Then
lblErr.Text = "Must enter a game name"
lblErr.Visible = True
txtGame.Focus()
End If
If bolDateErr = True And bolGameErr = True Then
lblErr.Text = "Must enter a game name and valid date"
lblErr.Visible = True
txtGame.Focus()
End If
If bolPriceErr = True Then
lblPriceErr.Visible = True
txtPrice.Text = ""
txtPrice.Focus()
End If
If bolSeatErr = True Then
lblSeatErr.Visible = True
txtSeats.Text = ""
txtSeats.Focus()
End If
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Check flags for input error
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Display output
Dim i As Integer
i = 0
lblData.Text = arrGames.Count.ToString
Do While i < arrGames.Count
lblData.Text = Convert.ToString(arrGames(i)) & " on " & Convert.ToString(arrDates(i)) & " Price: " & _
Convert.ToString(arrPrices(i)) & " Available Seats: " & Convert.ToString(arrSeats(i))
i += 1
Loop
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Display output
lblData.Visible = True
End Sub
Private Sub ClearInput()
'lblErr.Visible = False
'lblPriceErr.Visible = False
'lblSeatErr.Visible = False
txtGame.Text = ""
txtPrice.Text = ""
txtSeats.Text = ""
txtGame.Focus()
End Sub
Public Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Me.Visible = True
'Me.BackColor = Color.BurlyWood
'Me.ResumeLayout()
'Me.Activate()
'Me.Focus()
'Me.Show()
'Me.lblGameHdr.Visible = True
End Sub
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
Close()
End Sub
End Class
Add InitializeComponent() to your constructor class.
This is added by default to the New (constructor) function of all Visual Basic forms. It requires it to set-up the UI components on the form.
I'm trying to save a panel control as a bitmap using the following code (VB.net):
Private Sub SaveFileDialog1_FileOk(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles SaveFileDialog1.FileOk
filename = SaveFileDialog1.FileName
Dim CardImg As New Bitmap(Panel1.Width, Panel1.Height)
Panel1.DrawToBitmap(CardImg, Panel1.ClientRectangle)
CardImg.Save(filename, System.Drawing.Imaging.ImageFormat.Bmp)
End Sub
Everything works, except the Web browser control, which is docked in the panel. In the saved bitmap, this control appears as only white space, while everything else in the panel renders out fine. Any ideas?
When I saved snapshots from a WebBrowser I called .Focus() on it after navigating -- and somehow the white picture results magically disapperard. Don't know why, but it worked for me.
Download "ScreenCapture.vb" from http://www.vbforums.com/showthread.php?t=385497,
use CaptureDeskTopRectangle but you should not use the location of your panel because it's
referenced to panel parent you should use yourpanel.PointToScreen() to identify the correct
rectangle.
Regards..
UPDATE:
Check this out, you gon like it, i similute your case and it's working:
Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowse.Click
Try
Using fl As New SaveFileDialog
fl.Filter = "PNG images|*.png"
If fl.ShowDialog = Windows.Forms.DialogResult.OK Then
Dim sc As New screencapture
Dim pt = WebBrowser1.Parent.PointToScreen(WebBrowser1.Location)
Dim rec As New Rectangle(pt.X, pt.Y, WebBrowser1.Width, WebBrowser1.Height)
Application.DoEvents()
Threading.Thread.Sleep(500)
Using bmp As Bitmap = sc.CaptureDeskTopRectangle(rec, WebBrowser1.Width, WebBrowser1.Height)
bmp.Save(fl.FileName, System.Drawing.Imaging.ImageFormat.Png)
End Using
End If
End Using
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Update 2:
In Form:
Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowse.Click
Try
Using fl As New SaveFileDialog
fl.Filter = "PNG images|*.png"
If fl.ShowDialog = Windows.Forms.DialogResult.OK Then
JSsetTimeout.SetTimeout(Me, "TakeShot", 1500, fl.FileName)
End If
End Using
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Sub TakeShot(ByVal FilePath As String)
Try
Application.DoEvents()
Dim sc As New screencapture
Dim pt = WebBrowser1.Parent.PointToScreen(WebBrowser1.Location)
Dim rec As New Rectangle(pt.X, pt.Y, WebBrowser1.Width, WebBrowser1.Height)
Using bmp As Bitmap = sc.CaptureDeskTopRectangle(rec, WebBrowser1.Width, WebBrowser1.Height)
bmp.Save(FilePath, System.Drawing.Imaging.ImageFormat.Png)
End Using
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
To Create a time delay add the class below :
Public Class JSsetTimeout
Public res As Object = Nothing
Dim WithEvents tm As Timer = Nothing
Dim _MethodName As String
Dim _args() As Object
Dim _ClassInstacne As Object = Nothing
Public Shared Sub SetTimeout(ByVal ClassInstacne As Object, ByVal obj As String, ByVal TimeSpan As Integer, ByVal ParamArray args() As Object)
Dim jssto As New JSsetTimeout(ClassInstacne, obj, TimeSpan, args)
End Sub
Public Sub New(ByVal ClassInstacne As Object, ByVal obj As String, ByVal TimeSpan As Integer, ByVal ParamArray args() As Object)
If obj IsNot Nothing Then
_MethodName = obj
_args = args
_ClassInstacne = ClassInstacne
tm = New Timer With {.Interval = TimeSpan, .Enabled = False}
AddHandler tm.Tick, AddressOf tm_Tick
tm.Start()
End If
End Sub
Private Sub tm_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tm.Tick
tm.Stop()
RemoveHandler tm.Tick, AddressOf tm_Tick
If Not String.IsNullOrEmpty(_MethodName) AndAlso _ClassInstacne IsNot Nothing Then
res = CallByName(_ClassInstacne, _MethodName, CallType.Method, _args)
Else
res = Nothing
End If
End Sub
End Class