Solved

Need Help Disposing A Button in a .NET Dialog Popup

Posted on 2011-09-13
43
494 Views
Last Modified: 2012-05-12
Hello,

I am building a VB.NET PC application using VS 2008 and .NET Framework 3.5.

I am trying to dispose a control (a button) created programmatically in a dialog popup (by executing code connected to another button).

My code is: Me.Controls("btnMXReset").Dispose(), where btnMXReset is the name of the button.

My code compiles without error, but crashes on execution.  The error message tells me nothing of value ("Object reference not set to an instance of an object").

Oddly, I'm using exactly the same syntax to dispose of User Controls on the popup, and that code works.

Can anyone supply me with the correct syntax?

Thank you, Stu Engelman
0
Comment
Question by:stuengelman
  • 23
  • 10
  • 9
  • +1
43 Comments
 
LVL 12

Expert Comment

by:rgn2121
ID: 36528827
Although I haven't used this to dispose, the syntax is probably correct otherwise you would have gotten the error long before you tried to debug.  I am more interested in the code before this, more specifically dealing with "...executing code connected to another button"

It seems at some point your btnMXReset becomes Nothing...
0
 
LVL 40
ID: 36529536
The syntax is OK, it is probably the timing and the logic in the application that causes the error.

Is the error happening on the call to Dispose or after that? What is the line that causes the error?

If you call Dispose and the Control is no longer part of the Form (might have been removed by Me.Controls.Remove, set to Nothing or Dispose is in the FormClosed event), Dispose will crash.

If there is code later that tries to use the Control, that code will crash because the Control will have been disposed?
0
 

Author Comment

by:stuengelman
ID: 36529573
Hi Rgn2121,

After the dialog pops, the Load handler for the dialog populates the form with a variable number of User Controls (depending on how many records are on a DB table), and then renders two control buttons on the bottom.  What's strange is that I'm having no problem using the Dispose method to eliminate the User Controls, but the code crashes when I try to Dispose either of the buttons.

The basic idea is that when the "dispose button" is pressed, it's supposed to perform all the Dispose operations (including disposing the "dispose button" itself).

The code for creating one of the buttons is shown in the snippet (this code is in the Load handler for the dialog popup).

It seems strange that the buttons could become Nothing, as the Close button operates (its handler btnMXClose_Clicked closes the popup).  Also, the "dispose button" operates too, in the sense that it properly disposes the User Controls, before crashing on trying to Dispose either of the buttons.  Thus, it seems unlikely that the buttons could have a value of Nothing after being rendered.  I think it's more likely a syntax issue of some type.

Stu
Dim btnMXClose As New Button
Me.Controls.Add(btnMXClose)
btnMXClose.Text = "Close"
btnMXClose.BackColor = Color.White
btnMXClose.Left = (Me.Width / 2) - (btnMXClose.Width / 2)
btnMXClose.Top = resettop
AddHandler btnMXClose.Click, AddressOf btnMXClose_Clicked

Open in new window

0
 

Author Comment

by:stuengelman
ID: 36529666
Hi James,

Please see my 09/13/11 09:09 AM reply to Rgn2121.

The crash occurs on the invocation of the Dispose method (just for the native button objects; the Dispose method is working perfectly for the User Controls).

An example of a line that crashes is: Me.Controls("btnMXClose").Dispose()

There are no issues with Remove or setting to Nothing (I'm not doing either of these).

Do you think syntax like Me.Controls("controlname").Remove might work better?  If this works, will the control be wiped out of RAM (either immediately, or later by the Garbage Collector)?

Thanks, Stu
0
 
LVL 40
ID: 36529721
If I understand well, you call Dispose on the button inside of the Click event of the button?

This is not permitted.

If this is the case, set and start a Timer at the end of the event button. This will enable the event to terminate, and you will be able to dispose of the button when the event fires.

You do not absolutely have to Dispose of the Button however. It is a good practice, but Dispose simply releases a bit of memory (not much for a button) faster than it would be otherwise. And since the Button has been included in the form's Controls collection, it will be Disposed by the form when you close it. If you are curious, give a look at the Dispose method of the form in the usually hidden .Designer.vb file for the form. This method is called when you close the form, and it calls Dispose on all the controls on the form.
0
 

Author Comment

by:stuengelman
ID: 36529782
Hi James,

I follow what you're saying, but I tried commenting out the Dispose call on the "dispose button" itself.  The same crash occured when I tried to Dispose the other button.  I still think I have some type of a syntax issue.

Stu
0
 
LVL 40
ID: 36529926
How many buttons do you have to dispose of. As I told you, Dispose is a good practice, but is usually not necessary. Most people do not dispose of their controls otherwise.

Here is another one to try if you absolutely want to dispose of your controls.

You are disposing of the buttons while the form still has a reference to them through its Controls collection. Since we do not know what the form does under the hood, it is possible that the message comes indirectly from there.

Keep the reference to as a class member so that you still have it when disposing of your controls, and remove the control from the Controls collection before disposing of it:

Me.Controls.Remove(btnName)
btnName.Dispose()
0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 300 total points
ID: 36529994
You haven't set the Name() property of your Button when you create it.  Thus Me.Controls("btnMXClose") is returning Nothing because a match is not found.

Set the Name() property when you create it:   *The variable name is not the same thing!

    Dim btnMXClose As New Button
    btnMXClose.Name = "btnMXClose"

0
 

Author Comment

by:stuengelman
ID: 36530423
James - good ideas, will try them out.

Idle - I bet that's a BIG part of it (the User Controls ARE "named", which is why I can reference them). HAHAHAHA  - Thank you, will incorporate what you said.

To both - have been working about 10 hours, and I may not be able to reply again until late PM or early AM US EST (due to need to get some rest).  Sorry for the short delay, and thanks to both of you so much for your help.

Best regards, Stu
0
 
LVL 40
ID: 36530600
You do not have to name controls. If you keep a reference (variable) active, the 3 following lines do the same thing.
Me.Controls("btnMXClose").Dispose()
Me.Controls(btnMXClose).Dispose()
btnMXClose.Dispose()

Open in new window

If you use the second one, then you do not need to give a name to the control, and save the memory for 1 String.

Since a reference is only a pointer (32 bits), but a String is a reference PLUS 16 bits for every character, the reference takes less space in memory. Direct access to the button through its reference (btnMXClose.Visible as an example) is also faster than going through the collection (Me.Controls("btnMXClose").Visible)
0
 

Author Comment

by:stuengelman
ID: 36531097
Hi James,

Thanks, will take that into account.

Stu
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 36531172
While true James, the amount of memory being used and speed difference in the grand scheme of things is negligible.

The searching method can be quite useful for situations where you end up having to deal with many dynamic controls as you wouldn't need to keep a hard coded reference for each one (especially if you don't know how many might be created!).
0
 

Author Comment

by:stuengelman
ID: 36531200
Hi Idle,

Will keep your point in mid.

Thank you, Stu
0
 

Author Comment

by:stuengelman
ID: 36531204
*mid" s/b "mind"
0
 
LVL 40
ID: 36531247
Any approach can be good at that level. And I concur with you Idle, the amount of memory and speed difference would be negligible.

But in my way of thinking, negligible is not nothing. Performance issues are often an accumulation of those little negligible things. If you develop coding reflexes that automatically takes care of those negligible things, they wont accumulate. Thus, performance issues arise less often, and when you get one, you spend less time spent trying to point out possible sources of a performance issue. I value my own time more than performance, but my customers do not have the same idea.

For me, if I had many dynamic controls, I would simply add them to a collection, thus only one reference to keep. Over the best way to do things, we also all have our style :-).
0
 

Author Comment

by:stuengelman
ID: 36531629
Hi James,

Good points, I agree.

Stu
0
 

Author Comment

by:stuengelman
ID: 36534149
Hi Guys,

Making good progress.  Assigning the Name properties to the buttons eliminated the crash.  Now two additional issues popped up:

(1) The form takes a long time to dispose the User Controls; you actually see it flashing as it eliminates them one-by-one.  I use the following syntax to speed up initial rendering of controls:

Me.SuspendLayout()
'create controls programmatically
Me.ResumeLayout()
Me.PerformLayout()

The above logic does not speed up Dispose operations.  Would it help if I did a Remove before doing the Dispose?

(2) After running the dispose button handler, the popup is scolled to the bottom.  Apparently, Dialog Boxes don't have a ScrollTo method.  How do I get the scroller to go to the top?

Thanks, Stu
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 36535808
Use SendMessage() and WM_SETREDRAW to suppress repainting while you remove the controls:
http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_21963638.html#17368567

For scrolling, try something like:

    this.ScrollToControl(someControlReferenceHere);
0
 

Author Comment

by:stuengelman
ID: 36535877
Hello again,

Further to my last post:

(1) I tried using the Remove method instead of the Dispose method for the User Controls, but the clearing speed was the same.

(2) I tried Me.ScrollToControl(lblExpenseList), where lblExpenseList is a label near the top of the form.  As before, I am getting unpredictable results.  Sometimes after the "refresh" (dispose button is pressed), the form auto-scrolls to the top user control, or just remains at the bottom.  What I'm really looking for is something equivalent to the ScrollToTop Method (WPF has it, but dialog boxes don't appear to have this method).  The idea is to scroll all the way to the top of the dialog as the final step of the dispose button handler.

Stu
0
 

Author Comment

by:stuengelman
ID: 36535927
Hi Idle,

In regard to:

(1) Could you please provide some VB sample code (I can't read C#)?  What I'm doing now is shown in the code snippet.

(2) As mentioned, I tried the ScrollToControl method, but it didn't work.  If dialog boxes don't have a ScrollToTop method, is there any method provided so I can scroll to stated coordinates (i.e., (0,0))?

Stu
Me.SuspendLayout()
For i = 1 To ctlcounter
    Me.Controls("mxrow" & CStr(i)).Dispose()
Next
Me.Controls("btnMXReset").Dispose()
Me.Controls("btnMXClose").Dispose()
Me.ResumeLayout()
Me.PerformLayout()

Open in new window

0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 36535987
Sorry about the C# code...I switch back and forth so often I forget where I am and it all looks the same to me!

VB Code would look something like:  
Public Class Form1

    Private Const WM_SETREDRAW As Integer = &HB

    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal handle As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        SendMessage(Me.Handle, WM_SETREDRAW, False, 0) ' Turn OFF updates

        ' ... do some stuff in here ...

        SendMessage(Me.Handle, WM_SETREDRAW, True, 0) ' Turn ON updates
        Me.Refresh()
    End Sub

End Class

Open in new window


>> "If dialog boxes don't have a ScrollToTop method"

How is your form a "dialog"?...how was it created and shown...and how did you make it scrollable?
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 40
ID: 36536913
I tried using the Remove method instead of the Dispose method for the User Controls, but the clearing speed was the same.

Let's clarify something, because I see that you do not understand what Dispose does.

I repeat, although it is a good practice, you do not have to call Dispose on controls, any controls. It will eventually be done automatically by the system.

You manipulate a variable through a variable. You do not always see it that way, but when you name a Button something like btnClose, a variable called btnClose is created. When you add the control (Me.Controls.Add(btnMXClose)) to the collection of Controls, you are simply passing this pointer to a collection that sometimes works will all controls.

The button itself is somewhere in memory. That pointer is only the location of the button. The pointer exists as long as you still have your variable OR the controls is part of the collection.

If you lose your variable (End Sub for a local variable / Setting the variable to Nothing), the pointer still exists in the Controls collection.

If you Remove the control from the collection, you simply remove that copy of the variable. You do not destroy the Object.

When you have both removed the control and lost the variable, the pointer is lost. This is not much, this is only the address in memory (4 bytes on 32-bits computers). You do not see the control anymore, but the Object itself, all the properties of the Control are still in memory. They are managed by something called the Garbage Collector. It's role is to optimize the use of memory.

So, losing a variable and calling Remove does not do much, it clears up 4 bytes.

Dispose does something completely different. But it still does not clear up the memory used by the control. It calls the object and tells it to clean up the ressources it could be using. If the object opened a file, started a timer in Windows, those will be closed. But the object will still be in memory. .NET used Managed code. The Garbage Collector is the manager. The memory used by the object will be cleared only when the GC decides so. You have no control over that (yes you have, but you should not do it, otherwise you obliterate the usefullness of a Garbage Collector, so I won't tell you how). If you did not call Dispose while you had the pointer to the object, the Garbage Collector will do it when it decides to reclaim the memory used up by the object.

What happens when you call Dispose on a Control then? Almost Nothing for most controls.

What happens if you do not call Dispose? If you look at the code hidden in the .designer.vb file that is hidden under your Form, you will see that it contains a Dispose method. This method is automatically called when you close the form. This Dispose method loops through all the controls on your form and call their Dispose method.

You do not need to implicitely call Dispose, it is done for you by the code generator by the Form Designer.

What happens if the application crashes? The Gargage Collector knows it because he (or she?) is aware of everything that happens in the framework memory space. It does nothing though.

When it will need some memory, it will look through the useless objects lying there, select one, call its Dispose and then clean up that space in memory.

When you shutdown Windows, the Garbage Collector calls Dispose on all the objects still lying in its memory space, to make sure that all files, network connections, database connections, you name it, has been take care of.

So all that discussion about having problem disposing of a simple Button is over the head. Dispose will be called when needed.

I repeat. This is a good practice, but not necessary. There are a few cases where it can help, but its hard to tell because we do not know the inner workings of all those 9000+ classes in the framework. When it can help, usually the documentation suggests calling Dispose before losing the reference (the pointer / the variable). It could help if you had 2000 buttons to dispose of, because it would give the GC a better choice when come time to reclaim memory with as little impact as possible on the performance of running applications.

But all this discussion because you are not able to dispose of one Button is greatly overrated. Don't call Dispose on those Buttons. The system will do it for you when you close the form, when the garbage collector decides that it's time to do so, or when you shutdown windows.
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 36537079
In this case, calling Dispose() also removes the control from the form:  
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Button2.Dispose()
    End Sub

End Class

Open in new window

Idle-Mind-500007.flv
0
 

Author Comment

by:stuengelman
ID: 36537476
Idle,

Your code for suppressing the very lengthy "flickering" as my logic disposes the User Controls does not help.  I get exaclty the same long flickering as when I do no layout suspension, or I suspend layout using:

Me.SuspendLayout()
'Dispose of multiple User Controls via FOR Loop
Me.ResumeLayout()
Me.PerformLayout()

I tried my logic shown just above using the Remove method, but it makes no difference.  In both cases I get the long flickering.

I also tried your suppression code using Remove instead of Dispose, but the result is the same.

I feel really stumped here.  My logic shown just above does a beautiful job speeding up the rendering of my User Controls when I instantiate them programmatically.  The issue is that I need the ability to refresh the entire dialog (purge and reinstantiate all the User Controls) via a "Refresh" button.  I simply can't get the "purge" portion of the logic to operate quickly.

Stu
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 36537497
Can you show your attempt with WM_SETREDRAW?....
0
 

Author Comment

by:stuengelman
ID: 36537549
Hi James,

Thanks so much for the lesson on Dispose and Remove.  Please tell me if this understanding is correct:

(1) Remove eliminates an object from a collection, but in some cases it may still be accessible directly or as part of a different collection.
(2) Dispose completely eliminates all access to an object.
(3) In both cases above, RAM used by the object is not cleared until the GC does this for you.

Stu
0
 

Author Comment

by:stuengelman
ID: 36537592
Hi Idle,

Please see code snippet.

Thanks, Stu
At Popup's Class Level:
-----------------------
Private Const WM_SETREDRAW As Integer = &HB
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal handle As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

Within Handler For Reset Button
-------------------------------
SendMessage(Me.Handle, WM_SETREDRAW, False, 0)
For i = 1 To ctlcounter
    Me.Controls("mxrow" & CStr(i)).Dispose()
Next
Me.Controls("btnMXReset").Dispose()
Me.Controls("btnMXClose").Dispose()
SendMessage(Me.Handle, WM_SETREDRAW, True, 0)
Me.Refresh()
mdgExpListMgr_Load(Nothing, Nothing)

Note: the final line above calls the dialog's Load handler to recreate the controls on the form.

Open in new window

0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 36537716
What else is being added to the form?...what other code is there?...what is in the UserControls?

How many controls are we talking about?

I'm not getting any flickering at all...
0
 
LVL 40
ID: 36537789
Almost right for (1), confused for (2), right on the spot for (3). These concepts can be hard to grasp because they involve things that happens under the hood, things that we do not see unless we have special tools to examine the computer memory while the application is running. So let's clarify, you were almost there.

 -----

(1) Almost, because it can be something else than a Collection, but for the purpose of your previous discussion, lets stick to the collection.

You lose the access when you lose all reference. In you original code, you had two references. The variable btnMXClose, as well as the Controls collection once the button was added to the collection.

Assuming that it is a local variable, when you get out of your procedure, you lose btnMXClose. But since the Controls collection is managed by the Form and you still have access to it, there is one reference left. When you Remove the button from the collection, you cannot access it throuh Controls. You have lost your second reference, none is left. The control is not accessible, but still in memory.

Probably no big deal for a Button.

But if you had used an object that "works" with the system, let's say a FileStream object that opens a file in Windows. And let's say that you forgot to Close the file before losing all your references. Who will close the file?

This one is easy to grasp, a file left opened and probably locked. But since we do not know the inner working of classes, it is not always evident that you might need to force some kind of cleanup before losing a reference to an object. And even when you know you should do it, you could forget (not closing the file).

That's were Dispose comes into play.

-----
(2) Dispose does not eliminates the access to an object, this is done when you lose all references (variables and properties) that would enable you to manipulate the object.

Dispose is a safeguard. A standard method that Microsoft has designed so that it will be called at some point no matter what, as explained in my previous post.

Not all classes need a Dispose, and most do not have one.

But a programmer who knows how to program a class in .NET and who knows that his class uses external resources outside of .NET will provide a Dispose method. This method will clean up everything that was started by the class and could cause problems if it is not stopped (opened files and database connections, timers, and a few others).

That is the sole role of Dispose.

It can be called by you, by the garbage collector when it needs to free memory, by Windows that is closing. A form automatically calls Dispose on it's controls when you close it. The thing is that except for a power failure on the computer, Dispose will be called at some point in time to make sure that everything is terminated properly.

-----

(3) You got just right.
0
 

Author Comment

by:stuengelman
ID: 36537922
Hi James,

Thanks, I follow now.

Stu
0
 

Author Comment

by:stuengelman
ID: 36537968
Hi Idle,

There are about 200 User Controls.  Each User Control contains a combobox, two textboxes, a checkbox, and three buttons.

The only other things on the form are the background, a label, and two buttons.

The Reset button's handler disposes the 200 User Controls and the two buttons, and then calls the dialog's Load handler to recreate them.  The recreate process is just as fast as the original load.  The problem is the time required to dispose the 200 User Controls.  The system flickers as it disposes each User Control, and the process takes about 30-60 seconds.

Stu
0
 
LVL 40

Assisted Solution

by:Jacques Bourgeois (James Burger)
Jacques Bourgeois (James Burger) earned 200 total points
ID: 36538020
I have seen "background". Very bad word.

It is very hard if not impossible to prevent flickering when you use an intricate background such as a bitmap or a gradient. The Paint event is called for every control that gets added to the form. Since in intricate background takes some time to redraw itself, it produces flickering.

That problem arose in another post that was closed today.

Your solution is to use a plain background.
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 36538030
This combo seemed to work for me...
Public Class Form1

    Private Const WM_SETREDRAW As Integer = &HB
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal handle As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        SendMessage(Me.Handle, WM_SETREDRAW, False, 0)
        Me.SuspendLayout()

        For i As Integer = 1 To 200
            Dim uc1 As New UserControl1
            uc1.Name = "UserControl1" & i
            uc1.TextBox1.Text = "Instance #" & i
            uc1.Location = New Point(25, 25 + (uc1.Height + 7) * i)
            Me.Controls.Add(uc1)
        Next

        Me.ResumeLayout()
        SendMessage(Me.Handle, WM_SETREDRAW, True, 0)
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        SendMessage(Me.Handle, WM_SETREDRAW, False, 0)

        For i As Integer = 1 To 200
            Me.Controls("UserControl1" & i).Dispose()
        Next

        SendMessage(Me.Handle, WM_SETREDRAW, True, 0)
        Form1_Load(Nothing, Nothing)
    End Sub
End Class

Open in new window

0
 

Author Comment

by:stuengelman
ID: 36541714
Hi Idle,

Have already tried the method in your last post.

Will try the idea James put forward (have a short background at the top, followed by a solid background color).

Stu
0
 

Author Comment

by:stuengelman
ID: 36543607
Idle and James,

I tried two additional tests, each time invoking the line Me.BackgroundImage = Nothing before doing anything else in the Reset button handler.  The first test used the SuspendLayout strategy, and the second used Idle's SendMessage strategy.  In both cases I got the long flickering.

Stu
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 36543682
In my last submission, I'm using both SuspendLayout and SendMessage...lines #7 and #8.
0
 

Author Comment

by:stuengelman
ID: 36543963
Idle,

I'm having no speed issue on User Control instatntiation and rendering; the sole issue is the disposal speed.  Should I try the layered SuspendLayout and SendMessage within the Reset handler logic that performs the disposal?

Thanks, Stu
0
 
LVL 40
ID: 36543997
Ideas are running out.

If you try to add the controls to a brand new form, with nothing else in it, do you still get the problem? If so the problem could be in the UserControl itself.
0
 
LVL 40
ID: 36544019
I come back to it.

If the problem is with disposal, and knowing that disposal is not required, why don't you just skip the dispose. It will be done eventually by the Garbage Collector when it will need resources.
0
 

Author Comment

by:stuengelman
ID: 36553763
Hi James,

The disposal is required.  The point of the Reset button is to eliminate all the User Controls and refresh them from the database.  The popup itself is not closed on this operation, so the GC does not enter into the issue.

Stu
0
 

Author Comment

by:stuengelman
ID: 36553788
Hello guys,

See the code in the code snippet (the handler for the Reset button).  You'll see I turned the background image off.  I tried it as shown, and also with the order of the SendMessage and SuspendLayout strategies nested in reverse.  In both cases, the long flickering occured.

Stu
Me.BackgroundImage = Nothing
SendMessage(Me.Handle, WM_SETREDRAW, False, 0)
Me.SuspendLayout()
For i = 1 To ctlcounter
    Me.Controls("mxrow" & CStr(i)).Dispose()
Next
Me.Controls("btnMXReset").Dispose()
Me.Controls("btnMXClose").Dispose()
SendMessage(Me.Handle, WM_SETREDRAW, True, 0)
Me.ResumeLayout()
Me.PerformLayout()
mdgExpListMgr_Load(Nothing, Nothing)

Open in new window

0
 

Author Comment

by:stuengelman
ID: 36553869
James,

Some good news.  Your solution on the other ticket regarding the background image leaving traces of itself as I scroll provided a solution to the "scroll to top" issue in this ticket.  I simply added the line "Me.ScrollControlIntoView(pbExpListBackground)" at the bottom of the Reset button handler, where pbExpListBackground is the PictureBox containing the upper background image.

So all we have left is the flickering issue.

Stu
0
 

Author Closing Comment

by:stuengelman
ID: 36553958
Hi James and Idle.  Closing this ticket out and awarding points to both of you.  Idle resolved the dispose issue, and James pointed me to the solution of the "scroll to top" issue.  Will set up a separate ticket for the flickering problem that still remains.  Thanks so much to both of you for your help.  Stu
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now