שתף באמצעות


Duplicate a panel and its contents during runtime.

Question

Thursday, November 16, 2017 10:12 PM

Hi all,

I've got a panel in my form with a few buttons and stuff contained within it, I'd like to, upon button press, duplicate this panel on top of the other panel in the same location. I could then pres another button to alter which panel is on top and which is at the bottom. Do you have any idea how I could do this?

Thanks

PS: Acamar, Iron, Frank - I'm seriously covering ground with clicking on multiple forms simultaneously :D.

All replies (22)

Thursday, November 16, 2017 11:18 PM ✅Answered | 1 vote

Hi all,

I've got a panel in my form with a few buttons and stuff contained within it, I'd like to, upon button press, duplicate this panel on top of the other panel in the same location. I could then pres another button to alter which panel is on top and which is at the bottom. Do you have any idea how I could do this?

Thanks

PS: Acamar, Iron, Frank - I'm seriously covering ground with clicking on multiple forms simultaneously :D.

Do it all in code is one way but it's bear to deal with during design.

Explain why this approach appeals to you? Maybe there's a better way?

"A problem well stated is a problem half solved.” - Charles F. Kettering


Thursday, November 16, 2017 11:18 PM ✅Answered | 1 vote

This reply is to see if the question will pop into view in the VB.NET forums

Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
VB Forums - moderator


Thursday, November 16, 2017 11:25 PM ✅Answered | 1 vote

I've got a panel in my form with a few buttons and stuff contained within it, I'd like to, upon button press, duplicate this panel on top of the other panel in the same location.

Is there any reason for doing this in code rather than in the designer?  A common design task is to have multiple containers (eg, panels) of the same size and location on the form with different controls etc  and simply set the current one as the topmost, a bit like tab pages.  That is best done at design time.  To simplify the design process you lay the panels out wherever you want on the form, and in the form load procedure you update the panel Location properties to the same value, and make one of them topmost.

To do it in code, start simple.  Create a new instance of a panel object and co-locate it with the existing panel.  That is, copy the Location property of the existing panel to the same property of the new panel.  Also copy any other property that is not defaulted correctly, such as size and border style.

To make a panel created in code usable you need a reference to it, and that is most easily done using a List(Of Panel).  As you create each panel add it to the list.  Then reference each panel using an index into the list.  If you create the first panel in the designer it should be the first one in the list, for consistency.

To get a panel to display on your form you need to add it to the Controls collection of the form.

Then in the button click event decide which panel in the list of panels should be set as topmost.

If you have controls on the panel then you can create and add them in the same way, using the Controls collection of the existing panel to determine what they are and what properties should be set for each new control as you create it.  Add each controls to the Controls collection of the panel you are creating it for.

Do the methods for handling events for the new panel and its contained controls already exist?   Creating code to handle an event that does not already have a handler is very complex.  Adding an additional control to the handles list for an existing event handler is much easier, but of course you need code in the event handlers to determine which control (ie, a control on which panel) the event was raised by.


Thursday, November 16, 2017 11:30 PM ✅Answered | 1 vote

Hey Frank,

Typically I'd use a tab control. But to make things difficult, the "pages" will be panels instead and the panels will be navigated (i.e. brought to front - I know how to do this, by the way) through a menustrip drop-down. The real reason for this is because the tab control isn't practical for this purpose and it doesn't have a lot of options regarding merging the tab buttons into the menustrip while positioning the tabpages correctly. There are other reasons too, such as: clutters the form, etc.

Having the panels duplicated in the form designer and set to visible=false, and then programmatically, upon button press,  making the panels visible and bringforwarded is not practical in terms of performance and is not really possible considering the objects contained within the panel and all of the important codes relating to them.

I didn't mean to make it sound complicated (only to me it should be). :P

Thanks

But if they're identical then what's the point?

I'm going to guess that maybe it's so that you can programmatically enable/disable them? If so, then don't bother: One is all you need. Since a panel is a container control then if you set the .Enabled property, every control inside it is follows suit.

Is that why or am I off base entirely?

"A problem well stated is a problem half solved.” - Charles F. Kettering


Thursday, November 16, 2017 11:35 PM ✅Answered | 1 vote

Having the panels duplicated in the form designer and set to visible=false, and then programmatically, upon button press,  making the panels visible and bringforwarded is not practical in terms of performance and is not really possible considering the objects contained within the panel and all of the important codes relating to them.

That is not so.  It is perfectly practical and effective.


Thursday, November 16, 2017 11:39 PM ✅Answered | 1 vote

...therefore not affect this external MdiChild.

You didn't mention this was MDI; I assumed it to be SDI.

I can't really imagine what you're doing but I suspect there's a better way of going about it. ;-)

"A problem well stated is a problem half solved.” - Charles F. Kettering


Thursday, November 16, 2017 11:51 PM ✅Answered | 1 vote

Oops, my mistake, it's not MDI - it's just conventional setting child:

SetParent(ClientProcess.MainWindowHandle, Panel.Handle)

The reason for the confusion was that I was experimenting with MDI's earlier on.

They appear to do the same thing as simply setting a window as child, I wonder how they're different.

Good luck on maintaining that -- so far, it looks like a lot of controls and a lot of handles and a real headache when you modify it down the road.

"A problem well stated is a problem half solved.” - Charles F. Kettering


Friday, November 17, 2017 12:02 AM ✅Answered | 1 vote

I just thought, maybe I could, like Acamar said, put multiple panels in my form via designer, but I could use If statements to determine when a process is started and set as child to the panel.

So:

If panel23.visible = true then
Dim process As Process = Process.Start(New ProcessStartInfo("C:\..."))
        process.WaitForInputIdle()
'Chunk of code to set as child and other stuff
Else
Panel1.visible = false
End If


' Then some more code that basically does this: if the panel isn't visible then the process related to that panel is terminated - in order to preserve system resources.

I've just thought of that, so don't judge the poor quality of code too much. But, fundamentally, would that work? I read something the other day about garbage disposal (or something like that)- is this relevant?

Thanks

Who are you talking to?

"A problem well stated is a problem half solved.” - Charles F. Kettering


Friday, November 17, 2017 12:10 AM ✅Answered | 1 vote

I which case, I've misinterpreted your response. Just to clarify: are the panels all running their components/child windows if they are in the form?

That would depend entirely on what you mean by 'running'.  Components or child windows are simply design time elements.  They take up negligible code (you can see it in the designer) and whatever resources you have created for them.   I would take the usual meaning of 'running' to imply that you have started some procedure associated with these components.  So whether or not they are 'running' depends on whether or not you have started those processes, and starting a process is not typically something that you configure in the designer.


Friday, November 17, 2017 12:17 AM ✅Answered | 1 vote

I hoped I had edited my failure to address in time xD. I'm talking to you.

I wish I knew more about the overall picture; I'm pretty sure that none of us here really do.

Right now I think there are "too many cooks in the kitchen" so I'll back out and make a convenient exodus stage left for the night. ;-)

I still stand by saying this: It looks like it's going to be a real {expletive removed} to modify the first time around, let alone to maintain and modify later down the road.

If you want, we'll talk more tomorrow. :)

"A problem well stated is a problem half solved.” - Charles F. Kettering


Friday, November 17, 2017 12:21 AM ✅Answered | 1 vote

If panel23.visible = true then
Dim process As Process = Process.Start(New ProcessStartInfo("C:\..."))
        process.WaitForInputIdle()

That seems backwards.  How did that panel become visible?  Whatever event made it visible is the event where the code to start the process associated with the panel would be located.


Friday, November 17, 2017 6:42 AM ✅Answered | 1 vote

Consider the next way too: design a separate User Control, move your panel’s controls here. It will then appear in Toolbox, and you can drag it to your form. Use ‘New MyUserControl’ and Controls.Add to add it to your form programmatically. See BringToFront and Visible too.


Friday, November 17, 2017 7:11 AM ✅Answered | 1 vote

By running, I mean an application that utilizes 15% CPU and 800mb memory per instance.

Then you have to consider that you might be tying to do something which simply isn't practical for a typical PC.


Thursday, November 16, 2017 11:27 PM

Hey Frank,

Typically I'd use a tab control. But to make things difficult, the "pages" will be panels instead and the panels will be navigated (i.e. brought to front - I know how to do this, by the way) through a menustrip drop-down. The real reason for this is because the tab control isn't practical for this purpose and it doesn't have a lot of options regarding merging the tab buttons into the menustrip while positioning the tabpages correctly. There are other reasons too, such as: clutters the form, etc.

Having the panels duplicated in the form designer and set to visible=false, and then programmatically, upon button press,  making the panels visible and bringforwarded is not practical in terms of performance and is not really possible considering the objects contained within the panel and all of the important codes relating to them.

I didn't mean to make it sound complicated (only to me it should be). :P

Thanks


Thursday, November 16, 2017 11:33 PM

I've got a panel in my form with a few buttons and stuff contained within it, I'd like to, upon button press, duplicate this panel on top of the other panel in the same location.

Is there any reason for doing this in code rather than in the designer?  A common design task is to have multiple containers (eg, panels) of the same size and location on the form with different controls etc  and simply set the current one as the topmost, a bit like tab pages.  That is best done at design time.  To simplify the design process you lay the panels out wherever you want on the form, and in the form load procedure you update the panel Location properties to the same value, and make one of them topmost.

To do it in code, start simple.  Create a new instance of a panel object and co-locate it with the existing panel.  That is, copy the Location property of the existing panel to the same property of the new panel.  Also copy any other property that is not defaulted correctly, such as size and border style.

To make a panel created in code usable you need a reference to it, and that is most easily done using a List(Of Panel).  As you create each panel add it to the list.  Then reference each panel using an index into the list.  If you create the first panel in the designer it should be the first one in the list, for consistency.

To get a panel to display on your form you need to add it to the Controls collection of the form.

Then in the button click event decide which panel in the list of panels should be set as topmost.

If you have controls on the panel then you can create and add them in the same way, using the Controls collection of the existing panel to determine what they are and what properties should be set for each new control as you create it.  Add each controls to the Controls collection of the panel you are creating it for.

Do the methods for handling events for the new panel and its contained controls already exist?   Creating code to handle an event that does not already have a handler is very complex.  Adding an additional control to the handles list for an existing event handler is much easier, but of course you need code in the event handlers to determine which control (ie, a control on which panel) the event was raised by.

Acamar,

Thank you very much for your reply! Unfortunately there are an abundance of handlers within the panel that I am trying to duplicate on runtime. Having them already existing within the form, when they are not at that particular moment required, uses up a lot of system resources.

However, thanks for the reply and, if it appears that direct duplication is not possible, I will attempt to implement your method.

Thanks for taking the time to help :)


Thursday, November 16, 2017 11:35 PM

Hi Frank,

The controls within the form summon an external program and embeds it within the form, hopefully you now understand the scale of resources that would be used if multiple panels were to co-exist on start-up.

Panel.Enabled = False will therefore not affect this external MdiChild.

Thanks.


Thursday, November 16, 2017 11:43 PM

Oops, my mistake, it's not MDI - it's just conventional setting child:

SetParent(ClientProcess.MainWindowHandle, Panel.Handle)

The reason for the confusion was that I was experimenting with MDI's earlier on.

They appear to do the same thing as simply setting a window as child, I wonder how they're different.


Thursday, November 16, 2017 11:45 PM

Hi Acamar,

I which case, I've misinterpreted your response. Just to clarify: are the panels all running their components/child windows if they are in the form?

Thanks.


Friday, November 17, 2017 12:00 AM

[edit] To Frank,

I just thought, maybe I could, like Acamar said, put multiple panels in my form via designer, but I could use If statements to determine when a process is started and set as child to the panel.

So:

If panel23.visible = true then
Dim process As Process = Process.Start(New ProcessStartInfo("C:\..."))
        process.WaitForInputIdle()
'Chunk of code to set as child and other stuff
Else
Panel1.visible = false
End If


' Then some more code that basically does this: if the panel isn't visible then the process related to that panel is terminated - in order to preserve system resources.

I've just thought of that, so don't judge the poor quality of code too much. But, fundamentally, would that work? I read something the other day about garbage disposal (or something like that)- is this relevant?

Thanks


Friday, November 17, 2017 12:09 AM

I hoped I had edited my failure to address in time xD. I'm talking to you.


Friday, November 17, 2017 12:21 AM

Acamar,

By running, I mean an application that utilizes 15% CPU and 800mb memory per instance. :( Unfortunately, even if the application is idle, it's taking up a tonne of resources. I must go now, I'll work on it tomorrow based off of all of your suggestions. I'll mark as answer tomorrow once I've used your suggestions to solve the problem.

Thanks for all of your help!


Saturday, November 18, 2017 7:18 PM

To Everyone who contributed help,

It's all sorted now :) - My solution was mainly based on Acamar's solution (the one that I said wasn't practical) - so thank you! :D