|
Thanks again. Can you help me understand this a bit more? How is WinForms slowing the graphics, and how can I skip it?
I think that I should not be using the form timer for animations this seems hacky, and there is not much control over speed or framerate.
I would love to get this working in an ideal way with VB. I already have a solid working example that I would love to post for critique. Is anyone willing to help me fine tune this program a bit? And how can I post an example project here (if that is allowed)?
|
|
|
|
|
Nate Schoonover wrote: How is WinForms slowing the graphics, and how can I skip it? The WinForm api is a set of controls, not designed with great graphics in mind - graphics cards didn't require dedicated coolers in those days. It doesn't use DirectX like WPF would, it would use the CPU for drawing.
Nate Schoonover wrote: there is not much control over speed or framerate. One doesn't control the framerate under Windows; Windows dictates how much CPU time your app will get, and then you go for the maximum amount of frames.
Now, you could draw yourself on a (base) WinForm, which means that it'll speed up a bit, since it requires one less picturebox is resources.
Nate Schoonover wrote: And how can I post an example project here (if that is allowed)? If you're planning to write an article on the subject, then that would be the place to upload the code. It'd be "in draft" and invisible, until it's working ofc
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Thanks Eddy! I will get rid of the picturebox as you suggested, one less thing to slow things down. I think writing up a draft would be a good idea. I will post it in a few days.
I have a few other things I need to sort out first. I am having trouble with loading settings using the base code I borrowed from Gertz. http://blogs.msdn.com/b/vbteam/archive/2009/01/23/an-updated-screensaver-example-matt-gertz.aspx?[^]
Most of the example code works great, but when I install the screensaver and use the config mode to define the source folder and other settings, the final settings are not used when the screen saver executes via Windows.
This is strange because the settings are used correctly in preview mode. However, when the Windows timer sets off the screensaver all the settings go back to default. This is the correct behavior if the screensaver does not detect any previous settings, but I can't figure out why it would load settings correctly in preview mode and not the regular mode.
The settings are being stored correctly in the User\AppData folder. There is nothing obviously wrong with the code, I am afraid I am missing something stupid.
For what it's worth I posted the code to the Options form below, but I recon you will have to see it all together to really understand it.
Options.vb
Option Strict On
Imports System.Collections.ObjectModel
Public Class Options
#Region "Member variables"
Private m_Speed As Integer = 3
Private m_ShowTags As Boolean = True
Private m_ShowDates As Boolean = True
Private m_UseSubdirectories As Boolean = True
Private m_Directory As String = ""
Private m_files As ReadOnlyCollection(Of String)
#End Region
#Region "Class Properties"
Public Property ShowDate() As Boolean
Get
Return m_ShowDates
End Get
Set(ByVal Value As Boolean)
m_ShowDates = Value
End Set
End Property
Public Property UseSubdirectories() As Boolean
Get
Return m_UseSubdirectories
End Get
Set(ByVal Value As Boolean)
m_UseSubdirectories = Value
End Set
End Property
Public Property ShowTags() As Boolean
Get
Return m_ShowTags
End Get
Set(ByVal Value As Boolean)
m_ShowTags = Value
End Set
End Property
Public Property Directory() As String
Get
Return m_Directory
End Get
Set(ByVal Value As String)
m_Directory = Value
End Set
End Property
Public Property Speed() As Integer
Get
Return m_Speed
End Get
Set(ByVal Value As Integer)
m_Speed = Value
End Set
End Property
#End Region
#Region "Class Methods"
Public Sub LoadOptions()
Me.Speed = 16
Me.ShowDate = My.Settings.ShowDate
Me.ShowTags = My.Settings.ShowTags
Me.Directory = My.Settings.Directory
Me.UseSubdirectories = My.Settings.UseSubdirectories
If String.IsNullOrEmpty(Me.Directory) Then
Me.Directory = My.Computer.FileSystem.SpecialDirectories.MyPictures
end If
If Me.UseSubdirectories = True Then
m_files = My.Computer.FileSystem.GetFiles(Me.Directory, FileIO.SearchOption.SearchAllSubDirectories, "*.jpg")
Else
m_files = My.Computer.FileSystem.GetFiles(Me.Directory, FileIO.SearchOption.SearchTopLevelOnly, "*.jpg")
End If
End Sub
Public Sub SaveOptions()
My.Settings.Speed = Me.Speed
My.Settings.ShowDate = Me.ShowDate
My.Settings.ShowTags = Me.ShowTags
If Not String.IsNullOrEmpty(Directory) Then
My.Settings.Directory = Me.Directory
My.Settings.Save()
End If
My.Settings.UseSubdirectories = Me.UseSubdirectories
My.Settings.Save()
If Me.UseSubdirectories = True Then
m_files = My.Computer.FileSystem.GetFiles(Me.Directory, FileIO.SearchOption.SearchAllSubDirectories, "*.jpg")
Else
m_files = My.Computer.FileSystem.GetFiles(Me.Directory, FileIO.SearchOption.SearchTopLevelOnly, "*.jpg")
End If
End Sub
#End Region
End Class
And here is where the screensaver form is supposed to load the saved settings using the form's Load event:
Option Strict On
Imports System.Windows.Media.Imaging
Imports System.IO
Imports System.Collections.ObjectModel
Imports System.Collections.Generic
Public Class frmScreenSaver
#Region "Variables"
Private m_Options As New Options()
Private m_Random As New Random()
Private m_IsActive As Boolean = False
Private m_MouseLocation As Point
Private m_files As ReadOnlyCollection(Of String)
Private m_fileCount As Integer = 0
#End Region
#Region "Events"
Private Sub frmSceenSaver_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Debug = False
m_Options.LoadOptions()
SetLabelLocation()
Me.tmrUpdateScreen.Interval = m_Options.Speed * 1000
Me.tmrUpdateScreen.Enabled = True
Me.AnimationTimer.Enabled = True
If m_Options.UseSubdirectories = True Then
m_files = My.Computer.FileSystem.GetFiles(m_Options.Directory, FileIO.SearchOption.SearchAllSubDirectories, "*.jpg")
Else
m_files = My.Computer.FileSystem.GetFiles(m_Options.Directory, FileIO.SearchOption.SearchTopLevelOnly, "*.jpg")
End If
If m_files IsNot Nothing Then
m_fileCount = m_files.Count
Else
Me.lblDescription.Text = "No pictures found!"
SetLabelLocation()
End If
Windows.Forms.Cursor.Hide()
If m_fileCount <> 0 Then
DrawPicture()
End If
End Sub
I left off the rest of the event handles that control the picture drawing and animation, but if you think it would be helpful I can throw that up here too.
Thanks again for your time here! Just let me know if you have any questions about the code. I just can't figure out why the saved settings won't load when executing the screensaver in regular mode.
Nate
|
|
|
|
|
Nate Schoonover wrote: I think writing up a draft would be a good idea. I will post it in a few days. Cool - loooking forward to the result
Nate Schoonover wrote: The settings are being stored correctly in the User\AppData folder. Your code looks good; if it were incorrect I'd expect it not to load in the preview-mode. I'm not sure whether a screensaver runs under the current users' credentials, or using a system-account. You could verify that by logging the Enivronment.UserName[^]. Next to that, there could be a difference in the current working-directory.
If you stay stuck, for say, a day or two, consider writing your own settings-class. Reading and writing that class to/from a file is fairly easy.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Thanks again Eddy. I am starting to think you are a one-man operation around here! I appreciate your patience!
Eddy wrote: I'm not sure whether a screensaver runs under the current users' credentials, or using a system-account. You could verify that by logging the Environment.UserName.
Good idea! I checked and the user name remains the same regardless of execution method. Both the preview mode, and the regular mode indicate my Windows user name (Nate). It seems that the application is running strictly under my user credentials. My user account is not an administrator, but this is my computer so the admin account is locked up tight. I almost never use it.
I did notice that when running the config mode, if I click the "..." to open the folder dialog, the default folder is C:\Users\Nate\Pictures\... This is defined by the default folder assignment:
Me.Directory = My.Computer.FileSystem.SpecialDirectories.MyPictures I can't navigate any higher than this with the dialog box that is given. I store my pictures under C:\Users\Public\Pictures\... and I can't navigate to this folder. I can't navigate beyond the My Pictures folder. This seems like a very restricted folder dialog box. I also couldn't find a Special.Directories assignment for a public folder via MSDN[^]. I know that I can access the public folders for the screensaver because when I hard code the folder location it works fine.
It looks like I may need to figure out my own settings file after all! I started digging around MSDN and found things like How to Persist User Settings[^]. As far as I can tell, this is exactly what Gertz used in his example screensaver.
Is there a better way to store basic application settings?
|
|
|
|
|
Nate Schoonover wrote: I store my pictures under C:\Users\Public\Pictures\... and I can't navigate to this folder. It should be accessible using the Explorer; if it's not, it won't be accessible from code either. It should be a writeable location under a default-installation. You can get the location with the snippet below;
Dim thePath As String = Environment.GetFolderPath(Environment.SpecialFolder.CommonPictures) Nate Schoonover wrote: Is there a better way to store basic application settings? The advantage of the "My Settings"-editor in Visual Studio is that it's clean, well-documented and has a nice UI. The advantage of writing your own is having a bit more control. I've included a small example that shows how to serialize/deserialize a POCO using a BinaryFormatter . There are more formatters available, one of them being for XML.
Imports System.Runtime.Serialization.Formatters.Binary
Module Module1
<Serializable()> _
Public Class MySettings
Public Property SomePath As String
Public Property SomeInt As Integer
End Class
Sub Main()
Dim thePath As String = Environment.GetFolderPath(Environment.SpecialFolder.CommonPictures)
Dim CurrentSettings As New MySettings
CurrentSettings.SomePath = thePath
CurrentSettings.SomeInt = 2
Dim formatter As New BinaryFormatter
Using s As New IO.FileStream(".\settings.bin", IO.FileMode.Create)
formatter.Serialize(s, CurrentSettings)
End Using
Dim PrevSavedSetting As MySettings
Using s As New IO.FileStream(".\settings.bin", IO.FileMode.Open)
PrevSavedSetting = formatter.Deserialize(s)
End Using
Console.WriteLine(PrevSavedSetting.SomePath)
Console.WriteLine(PrevSavedSetting.SomeInt)
Console.ReadKey()
End Sub
End Module This will save (and read) the contents of the MySettings object in a file called "settings.bin" in the current working-directory of the application.
Happy coding
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Hi,
I hope you all had a merry Christmas and nice holidays with your beloved ones!
I try to retrieve data from text files and show them in a Datagrieview control. Each of the files is represented in an instance of "SoundConfigFile", which are collected in a generic List(of SoundConfigFile). The problem is: Only one row (containing the data collected from the first file) shows up in the Datagridview!?!
In the forms constructor, I set
dgvList.AutoGenerateColumns = True
dgvList.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnValidation
. The longer task of extracting the required data from files is handled in a separate thread:
Private Sub ThreadFunction()
Try
SoundConfigFiles = New List(Of SoundConfigFile)
Dim dirs As String() = Directory.GetFiles(My.Settings.FSACDir, "sound.cfg", SearchOption.AllDirectories)
Dim max As Integer = dirs.Count()
Dim done As Integer = 0
Dim percent As Integer = 0
Dim msg As String = String.Empty
For Each configfile As String In dirs
SoundConfigFiles.Add(New SoundConfigFile(Me, configfile))
done += 1
percent = CInt(done / max * 100)
msg = String.Format("{0} finished ({1}%)", configfile, percent)
UpdateForm(configfile, percent, msg)
Next
Catch ex As Exception
End Try
End Sub
The UI thread is then updated in
Public Sub UpdateForm(ByVal myItem As String, ByVal percent As Integer, ByVal msg As String)
If Me.InvokeRequired Then
Dim d As UpdateDelegate = AddressOf UpdateForm
Me.Invoke(d, {myItem, percent, msg})
Else
Me.dgvList.DataSource = SoundConfigFiles
Me.dgvList.Refresh()
Me.ProgressBar1.Value = percent
Me.myLabel.Text = msg
Me.lblFinalMessage.Text = String.Format("{0} instances still open.", _
SoundConfigFile.instances)
End If
End Sub
I tried to find relevant information for hours now, but I can't get it to work. Does anyone of you have a good advice or can tell me what I'm doing wrong here?
Thank you,
Mick
|
|
|
|
|
Let's see; we add item to a collection, set the datasource to the collection, get the next item. You stated that you only saw the first one.
Try setting the datasource to "null" before assigning the collection
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
This works Thank you, Eddy!
But it's not enough to set the datasource to "Nothing" after startup (same result: only first row seen). I have do that (and afterwards assign the collection again) within the "UpdateUI" Sub. Doesn't that slow down the application massively? Is that a bug?
modified 29-Dec-13 13:41pm.
|
|
|
|
|
Sonhospa wrote: Doesn't that slow down the application massively? You're right, it does. It'd be recommended not to set the datasource until the list is completely populated.
If you want "smoother" loading using the DataGridView, you could implement a virtual mode[^]
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
What is the main use of LINQ(Language-integrated query) in visual basic?? I cant understand it properly when i read it from Msdn website.. Any other links??
|
|
|
|
|
|
|
Hi all,
I have a strange effect in a little test application which contains a ProgressBar control (set to 'continuous'), together with a list box and a label. All three of them are fed with values from a loop on a different thread (using a delegate) and updated within the same Sub (member of the main form). Just a very simple example from Micrsoft.
A funny effect now is that the progressbar seems to be updated with a delay: While the other controls show the value returned from the loop, the progressBar shows an approx. 10% lower value - i.e. when label and listbox show the 50% value, the progressbar stands at 40%, and when the loop is finished (label and listbox 100%) the progressbar still is at 90%. Just to mention it: The code updates the progressbar FIRST with the percentage (with Statusbar.Refresh), and after that updates the other controls.
In the application that I plan I didn't want to show the values in labels etc, so the progressbar should show progress more accurate. Compared with the other controls, it also seems to start a little bit delayed...
Are there any known issues with the accuracy of progress bar? Or am I dealing with something like 'race conditions'?
Thank you,
Mick
|
|
|
|
|
Without seeing your code, it's impossible to tell you what you did wrong.
|
|
|
|
|
Hi Dave,
it's basically the code from the Microsoft sample which I had linked to ('Control.Invoke Method'), just with an additional progressbar. But your answer sounds like it's not normal that the control lacks accuracy... The minor changes I made are in the following method:
Public Sub AddListItemMethod()
Dim myItem As String
Dim max As Integer = 50
Dim i As Integer
Dim percent As Integer
For i = 1 To max
myItem = "MyListItem" + i.ToString()
percent = CInt(i / max * 100)
ProgressBar1.Value = percent
StatusStrip1.Refresh()
myListBox.Items.Add(myItem)
myListBox.Update()
myLabel.Text = String.Format("{0} entries ({1}%) added.", CStr(i), percent)
myLabel.Update()
Thread.Sleep(30)
Next i
End Sub
I also reduced the Sleep time of the thread - that's why I asked if 'race conditions' might be involved. It seems as if the delay between label/listbox and progressBar is getting bigger with a lower value for 'Thread.Sleep' - very little delay with 800, much bigger delay with 20 or 30.
|
|
|
|
|
It doesn't work because you're hogging the UI thread with this code. The Thread.Sleep doesn't help.
What I mean by "hogging" is that you're not letting the UI thread process any messages from Windows, like WM_PAINT, that tells individual controls to update themselves. For a "quick fix" you can replace the line that says myLabel.Update() with Application.DoEvents() . This will process all pending messages in the application message pump, including drawing messages.
This is NOT the correct way to do this! This is a hack to get your example code working! The correct way to do this would be to move the long running code (you simulated this with the Thread.Sleep call) to a background thread and Invoke calls to update the UI controls on the UI thread.
|
|
|
|
|
ive seen all the post related to my problem.. but i have different code .. i've searching for the answer for almost 2weeks now .. but no luck .. this is my code i dont know what's happening .. it keeps prompting Verification Failure .. i dont know whats the problem in my code .. the bolded line's where i guess the problem occurs .. can someone kindly help me to fix this im using vb.net 2010 as my front and MySql as my back-end.. im using DigitalPersona 4000B
Sub OnComplete(ByVal Control As Object, ByVal FeatureSet As DPFP.FeatureSet, ByRef EventHandlerStatus As DPFP.Gui.EventHandlerStatus) Handles VerificationControl.OnComplete
Dim con As New MySqlConnection("Server = localhost; Username= root; Password =; Database = fesdata")
Dim cmd As New MySqlCommand("SELECT * FROM empdata", con)
con.Open()
Dim fpreader As MySqlDataReader = cmd.ExecuteReader
Dim byteTemplate As Byte()
Dim memStreamTemplate As MemoryStream
Dim ver As New DPFP.Verification.Verification()
Dim res As New DPFP.Verification.Verification.Result()
If fpreader.HasRows Then
While fpreader.Read
byteTemplate = fpreader.Item("Fingerprint")
memStreamTemplate = New MemoryStream(byteTemplate)
Dim templa8 As DPFP.Template = New DPFP.Template()
templa8.DeSerialize(memStreamTemplate)
If Not FeatureSet Is Nothing Then
ver.Verify(FeatureSet, templa8, res)
If res.Verified Then
Call SEARCH_EMPLOYEE()
End If
End If
End While
Else
MsgBox("Unknown Employee!")
End If
fpreader.Close()
End Sub
|
|
|
|
|
You're better off asking this question in a forum dedicated to the library you're using, usually the manufacturers own site.
You also don't describe what the problem is. "It doesn't work" does not suffice for a problem description. If you've taken 2 weeks to get nowhere, you're severely lacking in debugging skills. Stepping through the code in the debugger and looking at the values of variables should tell you a lot of about what you're code is actually doing compared to what you think it's doing.
|
|
|
|
|
What does exception.message , exception.stacktrace means? what details it gives??
|
|
|
|
|
|
For the past year, we have been running our VB 2010 data entry application for our 2 joint organizations. The main member form took about 5 seconds to display because there are 3 tabs to display (General, Organization 1, Organization 2) and the 2 Organization tabs have 4 tabs to them. Lots of data to display with lots of controls.
Starting around Thanksgiving, this form suddenly started taking up to 4 minutes to initially load; after the first load, any other member data displays (different members) were back to the 5 seconds. No changes to the program, so it has to be something else. Watching task manager in Windows 7 Pro, memory usage climbs slowly to 931 MB, then drops back to 19 MB and the form displays. Getting the memory is what takes so long. Running in the IDE, there is no memory problem - just when employees run the published program.
I put MSGBOX commands in the program to confirm where the slowdown was since debugging in the IDE wasn't an option:
msgbox("Starting New Form",MsgBoxStyle.Information)
dim frm as new frmCustomer"
msgbox("New Form Done",MsgBoxStyle.Information)
It is definitely the command creating the new form. 4 minutes and 931 MB of memory.
Anyone else experiencing something similar? Any ideas on how to fix this?
|
|
|
|
|
Not enough information. It's not that command slowing this down. There's a constructor in that frmCustomer class that is running code. What is so slow in that code?
|
|
|
|
|
I don't think this has anything to do with VB it self.
do you load data when you create this form? if so test to see how long that takes.
Every day, thousands of innocent plants are killed by vegetarians.
Help end the violence EAT BACON
|
|
|
|
|
What is the exact use of delegate?? Someone Tell me in simple way.
|
|
|
|
|