MTSkull Posted July 23, 2003 Posted July 23, 2003 I wrote a simple screen saver app that cycles through all the pictures in a folder. I have 1 question and 2 bugs that I need help with. Public bFirstMove As Boolean Public Pics() As String Public position As Int16 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) ; Handles MyBase.Load Me.CenterToScreen() picBox.Height = Me.Height picBox.Width = Me.Width bFirstMove = True Pics = Directory.GetFiles("C:\Fractals") position = 0 picBox.Image = Drawing.Bitmap.FromFile(Pics(position)) End Sub Private Sub Form1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) ; Handles MyBase.KeyUp Me.Close() End Sub Private Sub picBox_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) ; Handles picBox.MouseMove If Not bFirstMove Then Me.Close() Else bFirstMove = False End If End Sub Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) ; Handles Timer1.Tick position += 1 If position = UBound(Pics) Then position = 0 picBox.Image = Drawing.Bitmap.FromFile(Pics(position)) End Sub 1. How do I pass the capture of the mouse move to the underlying form? Since the pic box is sized to = the form I have to put the mouse move event in the picBox control. This probably does not matter but I am curious how it is done. 2. If I hit run (F5) from inside the .net developer, it always picks up a mouse move event and shuts down the program. That is the reason for the bFirstMove form global. Is there a way to flush the mouse move buffer? 3. I compiled this and tested it out and it works as a screen saver (changed .exe to .scr). After about a 1/2 hour of continuous running I get a "System out of Memory" fault that crashes the program. Do I need to set the picBox.image to nothing to flush memory or something? Thanks Brian Quote "Beer is proof that God loves us and wants us to be happy." -Benjamin Franklin
*Experts* Volte Posted July 23, 2003 *Experts* Posted July 23, 2003 1) Look at the [api]SetCapture[/api] API. 2) Not that I'm aware of (though I don't totally understand why you would need this... if you just ignore the event it will go away on its own). 3) Not sure why that is happening... Perhaps you should try loading all the images into an array of Image objects at load, and simply cycling through those, rather than continuously loading the images from the HDD. Also, instead of UBound(Pics) you should use the .NET CLR way Pics.GetUpperBound(0) Quote
reanjr Posted July 26, 2003 Posted July 26, 2003 In short, the answers to your questions are: 1. As far as I know, you have to use something outside of the .NET framework to do so. 2. I do not believe there is a way to do this. Windows sends mouse messages whether you want them or not. 3. Use the Bitmap's Dispose method before it goes out of scope or is set to a new Bitmap. At length, the answers to your questions are: The following should give you something else to think about: Remove the PictureBox Set Form1.FormBorderStyle to None Try this: Private Pics() As String Private position As Int16 Private bmpCurrent, bmpOld As Bitmap Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.CenterToScreen() Pics = System.IO.Directory.GetFiles("C:\Fractals") position = 0 bmpCurrent = Bitmap.FromFile(Pics(position)) End Sub Private Sub Form1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyUp Me.Close() End Sub Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove Static bCaughtMove As Boolean If bCaughtMove Then Me.Close() Else bCaughtMove = True End If End Sub Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint e.Graphics.DrawImage(bmpCurrent, 0, 0) End Sub Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick position += 1 If position = Pics.GetUpperBound(0) Then position = 0 bmpOld = bmpCurrent bmpCurrent = Bitmap.FromFile(Pics(position)) bmpOld.Dispose() Me.Refresh() End Sub This is what I did: I changed the global variables to Private instead of Public. Just a good habit. 1. I moved all of the Painting/Pictures directly to the form. No need to worry about mouse events on the PictureBox anymore. 2. Put the MouseChecking variable into the Mouse Event Handler. It's a bit cleaner that way. As far as I know there is no way to flush it. 3. Now the bitmap is drawn during the Form's Paint event. When updating the picture what I did was set bmpOld to whichever bitmap was currently being used. I then set bmpCurrent to the new pic about to be displayed. I then call Dispose on bmpOld. This is why you had a memory leak. Any Class that implements the IDisposable Interface (quickest way to check is to just see if it has a Dispose Method) does not clean itself up automatically. You have to call the Dispose method to get it to clean up internal resources (in this case an HBITMAP Windows API Structure). The reason I didn't simply call bmpCurrent.Dispose and then set it to the new one is because that might cause problems if the form's Paint event went off while it was loading the new one. 4. Sorry if I was a bit lengthy, but I like to espouse good coding practices whenever possible. The more people who code in a clean, structured (possibly Object Oriented) manner, the more code there will be around for others to see and understand. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.