Recreate a GUI control - vb.net

I'm using a video capturing control called VideoCapX and I've hit a bug, and after hours of debugging, I've determined that the only way to fix the glitch is to restart the program aka. reset the control.
I'm wondering is there any way to programmatically recreate a GUI control aka reset it to the way it was when the form opened.
I know this is a cheap fix, but at this point it's my only option.

In general, this would work:
Me.SomeControl1.Dispose()
Me.SomeControl1 = New SomeControl
'Configure SomeControl1 here.
Me.Controls.Add(Me.SomeControl1)
where SomeControl1 is the field created automatically when you add the control to the form at design-time. The first line removes the existing control from the form, the second line replaces the existing control with a new one of the same type and the last line adds the new control to the form. You need to set the appropriate properties of the new control in between, so you might want to keep the old one around to get the required property values from, e.g.
Dim newControl As New SomeControl
'Configure newControl here, e.g.
newControl.Location = Me.SomeControl.Location
Me.SomeControl1.Dispose()
Me.SomeControl1 = newControl
Me.Controls.Add(Me.SomeControl1)
Note that assigning the new control to the existing field will automatically connect any event handlers with a Handles clause.
That said, the fact that you're using what is likely to be a fairly complex custom control, it's hard to say whether there might be some other required steps too.

Related

Reset focus to control with lowest tab index

I have a form that is re-used. That is, instead of creating a new instance of the form each time, the form is kept hidden, and is made visible when needed. (A design I inherited; I presume this was a performance optimization.)
The problem: The second time that the form is used, the focus is on the OK or Cancel button, from the first use of the form.
The user wants the focus to start the way it did the first time the form appears - on the control with lowest tab index.
If there were just one such form, I would hack it: add a line of code hardwired to the desired control.
But there are many such forms, and the visibility logic is in a common base class.
So it would make more sense to do this right, and tell the form to focus on its first (lowest tabindex) control.
Is there an easy way to do so?
(I could iterate through all the controls, but then I have to correctly handle nested controls. Since the GUI has to do this the first time it shows a form, I am hoping there is some method I can call that does it for me.)
(Coded in VB.net, but a C# answer would be fine.)
It is a one-liner, the logic to find the next control is exposed as a method, SelectNextControl(). You should start at the Form object, the one that can never get the focus, and ask it to find the next one in the tabbing order. Which is the child with the lowest TabIndex, whatever value it might have.
So something like this:
public void ShowAgain() {
this.Show();
this.SelectNextControl(this, true, true, true, true);
}
And do consider that a Form object that isn't visible is a rather major resource hog, using up lots of operating system resources for a small convenience. Surely you can also Close/Dispose it and recreate it when needed. YMMV.
You can try to set ActiveControl property before making form visible:
_frm.ActiveControl = null;
This should clear the active control for the form and remove focus from its controls.

Making multiple forms appear as one in VB.NET

I am writing a Windows Forms application in VB.NET. I have three forms: the main form, which shows a list of accounts, the account form which allows the user to view/edit the information for a specific account, and the policy form which allows the user to view/edit the information on a specific policy for that account. I want the forms to appear as if they are all the same window. Example: when the application starts, the user clicks an account name in the list box on the main form and clicks "edit". What I want to happen is that the window stays in the exact same place and stays the same exact size, only the content of the main form appears to be replaced with the content of the account form. Same thing if the user then chooses to edit a policy from the account form. When the user finishes and clicks "save", the main form comes back up. Through this entire use case, it would appear to the user as if they were viewing the same window the entire time, with the content of that window changing.
How can I do this? I have tried something like:
Dim newForm as New AcctForm
newForm.Location = Me.Location
newForm.Show()
Me.Close()
The problem is that if the user moves the original window, the new window appears where the parent form originally appeared, not where it ended up.
I see this is already in the comments, but what I have done in this case in the past is build each "form" in the application as a custom control. Then I have one actual form, and navigation works by changing which custom control is currently loaded on the parent form. To move from one screen/view to another, you remove the current custom control from the form's controls collection and add the new custom control.
I believe this is superior to manually setting the startup position and size, because you can use the form's .SuspendLayout()/.ResumeLayout() methods to hide the interim state, where there is no control loaded, from the user. This is harder to do when you want one form to be completely replaced by another.
This also makes it easy to set certain form properties in one place and have them be consistent for the application. You can even have an area on the form with controls that will now show in every view.
When using this pattern, I typically have each of my custom controls inherit from a common base. You may not have anything specific you will do with that base at the outset, but it almost always comes in handy later.
Finally, switching to use this scheme is easier than you think. Just go to the code for the each of your current forms, and you will find that each class currently inherits from System.Windows.Forms.Form. Most of the time, all you really need to do is change them to inherit from System.Windows.Forms.Panel and you're most of the way there.
As others have said, it may be better to redesign your application using custom controls or panels etc.
However, to answer your question regarding the seemingly random location of your forms, the first thing to check is that each form has it's StartPosition property set to Manual.
If your main form is resizable, then I would also add code to adjust newForm to the same size too.
I hope that helps with your immediate issues; so that you can move on to redesigning the application!
good morning there is another way . set property for second form to (top most) and use also
from2.show();
that make you switch between forms and keep form2 top other
Thanks
try using ShowDialog()
Dim newForm as New AcctForm
newForm.Location = Me.Location
newForm.ShowDialog()
Me.Close() <-- removed this

Detecting if user has made changes to FontDialog object

I've got a FontDialog box called aFontDialog.
Can I detect changes made to this dialog box?
Initially my object creates the dialog using this code aFontDialog.ShowDialog, the user than makes changes, then if the user is happy with their changes then the application will receive Windows.Forms.DialogResult.OK:
Is it possible to detect any changes made to this dialog by the user? Will I need to record the state of the different aspects of the dialog before and then compare to how they are after - or are there some properties or methods built into this dialog box that help me find any changes?
The most important concern here is - why do you need to know the changes. See, font is usually not a transactional object, so you normally don't need to avoid excessive network traffic or minimize number of database roundtrips.
I would just look if user pressed OK. If yes, set the new font, regardless of how similar it is to your current one. It's just one line of code - simple as assigning this new font to the old one:
Me.Font = MyFontDialog.Font 'Me could be any control in this case
Besides, I think it is your only way, if the font is different. Meaning you cannot for example set Font.Bold = True, because it's read-only. And it would not take a lot of processing time either, so no point in optimizing it.
If you really want to, you can examine FontDialog.Font after checking DialogResult for OK, and compare to what you passed there, although I don't see where this would be useful.

How do I create a "wizard" style ui using vb.net?

The idea is that I would have a set of forms, users would click through a "forward" and "back" button, and the current form would change to a different one. My issue is that I can write code that just pops up a new form, but im not sure how to do a "replacement" of my current form. How is this usually done?
What I did recently was to create a form with buttons already in place and a large panel to contain each step. The dialog would accept an initial step in the form of a IWizStep instance, and the things would roll from there.
Each step was a class exposing a UserControl responsible for the visual aspect of the step, while the logic itself was handled by the class (it was a little more complicated that that, but that was the general idea).
The IWizStep interface, implemented by the step and accepted by the dialog, was on the lines of:
Interface IWizStep
Event StateChanged As EventHandler
ReadOnly Property Control As Control
ReadOnly Property Title As String
ReadOnly Property CanMovePrevious As Boolean
ReadOnly Property CanMoveNext As Boolean
Function MovePrevious As IWizStep
Function MoveNext As IWizStep
End Interface
To put everything together, a controller class would know how to compose the steps necessary for each given action. Therefore I had a controller for, say, "Emit Order", which needed some 10 steps, and a controller for "Emit Orders in Batch", which needed only a couple of steps.
Create a set of UserControls, and add and remove them from a Panel in a single form. (and set Dock to Fill)
You could define a user control which acts as a "wizard". It just needs the buttons you have and an array of content panels, just have it switch through the panels when the buttons are pressed assuming a certain condition is met within the controls on the panel. There's no real definitive "wizard" maker, since it's pretty easy to roll your own wizard.
You don't need to do a "replacement" of your current form really, you could just add a new one to the project. If you do need to for whatever reason, just grab the control collection with Me.Controls, copy that somewhere, and put the new controls up. When you don't need the wizard, swap them out again. It's generally best practice to make a new form however!

WPF User Control is causing Out of Memory Exception

Looking for a free spell checking solution, I thought I was so smart in doing this but I guess not.
I have created a windows form based application and I want the form to add a user specified amount of user controls (with textboxes) on to a panel. The user can then click some button and the controls on this panel are cleared and new ones are added. The user does something and the process is repeated. Now, I wanted these textboxes to support spell checking and looked all over for a free solution.
WPF textboxes support spell checking where the ones in regular win forms do not. I thought I would be able to use these WPF textboxes by adding them to an ElementHost object which is, in turn, within a panel. This panel would be a user control.
So, in my application, I would be able to add instances of these user controls onto the form and make use of .NET's spell checking goodness. This actually worked but after using the application for a while, found that the application would eventually freeze on me due to out of memory errors. I have pinpointed the memory errors to these WPF controls since this problem does not happen with normal textboxes.
When the window is opened and the number of controls is specified, this is pretty much how the controls are added:
Dim xOffset As Integer = 0
For i As Integer = 0 To theNumber
Dim myUserControl As New SpecialUserControl()
myPanel.Controls.Add(myUserControl)
myUserControl.Location = New Point(7, 7)
myUserControl.Location = New Point(xOffset, 7)
xOffset = xOffset + 207
Next
Note that:
myPanel is a panel on a form
SpecialUserControl is the user control with WPF textbox (within an ElementHost object)
When the user pressed a button, the panel is cleared:
myUserControl.Controls.Clear()
The user can then repeat the process.
There are a lot of results on the internet when I tried to find a solution and I'm thinking that the problem I am having is due to the fact that the WPF control is not going away even after clearing the panel. Following this conclusion, I have tried different solutions regarding disposing these controls or setting them to nothing but the memory problem keeps occurring. If someone could give me some advice or ideas here, I'd really appreciate it.
I've decided that this may just be due to the fact that these user controls are being created faster than they can be collected. I've changed the program so that it doesn't create any of these special user controls if it isn't necessary. The program works fine with a more manageable number of WPF controls.