I'm considering porting my VB6 program to PB and there are obviously a number of challenges. One of them is that in my VB6 program I have a user control that I display on the screen multiple times (ie I have an array of this control). The user control contains many other controls, such as text fields, buttons, labels, images, and other user controls. And there's a lot of supporting code as well.
How do I build the equivalent of a VB6 User Control in PB?
PB equivalent of a VB6 User Control?
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
-
- Enthusiast
- Posts: 443
- Joined: Sun Apr 06, 2008 12:54 pm
- Location: Brisbane, Qld, Australia
- Contact:
A VB6 User Control is basically an object, even though VB6 is not object oriented. It contains (or may contain) a graphical component and also contains code. From my limited knowledge of PB I'd say the graphical component is like a Container Gadget.Trond wrote:I don't know what a user control is. Can you enlighten me?
Probably its best to show you an example. If you look at the screen shot here, the lower part of the screen contains three instances of a user control, and the program will create as many of these as necessary. The appearance of the control for Q3 is slightly different to that for Q1 and Q2, but it is the same User Control and buttons are displayed or hidden as required for the cue. Other code in the control performs relevant actions for the selected cue, such as playing or stopping the audio file, etc.
So the idea is to have a container control with all the necessary gadgets, procedures, etc, and be able to use it anywhere in the program, and as often as you like. The sliders in the screenshot are also user controls, so whenever I want to use one of my customised sliders (eg for audio levels) I just place an instance of that user control on the form or in another user control.
Well, PB is not VB of course (thank the Gods for that!
) However, I would agree with your assertion that a container gadget is perhaps the way to proceed. In terms of being able to reuse these controls and effectively create 'control arrays' - not a problem if you stick to using #PB_Any etc. You can 'wrap' your 'user controls' up into a single include file or even into a nice OOP class if you are comfortable with interfaces etc.
Yes, shouldn't be too difficult.

Yes, shouldn't be too difficult.

I may look like a mule, but I'm not a complete ass.
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
> even though VB6 is not object oriented. It contains (or may contain) a graphical component and also contains code.
VB is object oriented. the fact that an object contains code shows that.
in VB you can have subroutines .click in every single object,
in PB you have to handle this with Select from within the eventloop.
there is no way to make controls contain code, because PB is purely procedural.
VB is object oriented. the fact that an object contains code shows that.
in VB you can have subroutines .click in every single object,
in PB you have to handle this with Select from within the eventloop.
there is no way to make controls contain code, because PB is purely procedural.
oh... and have a nice day.
Blast from the past! 
A user control is a VB type of custom control and built partly out of other controls or completly custom drawn. you can assign your own event, properties and methods to it.
I'm not really very GUI knowledgeable though so I don't know how to do custom controls etc in PB.

A user control is a VB type of custom control and built partly out of other controls or completly custom drawn. you can assign your own event, properties and methods to it.
I'm not really very GUI knowledgeable though so I don't know how to do custom controls etc in PB.

Paul Dwyer
“In nature, it’s not the strongest nor the most intelligent who survives. It’s the most adaptable to change” - Charles Darwin
“If you can't explain it to a six-year old you really don't understand it yourself.” - Albert Einstein
“In nature, it’s not the strongest nor the most intelligent who survives. It’s the most adaptable to change” - Charles Darwin
“If you can't explain it to a six-year old you really don't understand it yourself.” - Albert Einstein
This is easy to duplicate, but not so easy to get your head around 
Take for instance, I have an address user control. This groups together address lines 1, 2 & 3, Town, County and Territory text boxes, and their labels.
To do the same in PB, I have to create an include file that contains the following procedures:
I prefix these with a unique label, so I know that I won't accidentally duplicate them, i.e.
Then I have a global array for all the controls, i.e.
Then you call the Address_SetNumberOfAddresses if you need more then one instance of the user control - BEFORE you call New.
Once that has been set, you can then call the New procedure:
Address_New(ContainerID, 100, 100, 0)
This will then draw all the controls into the specified container by using UseGadgetList before drawing
Then in your main event loop, you then pass in all the event variables:
Address_Event(Event, WindowID, GadgetID, EventType)
This in does any event processing as required in the control.
Finally, to destroy all the gadgets, you then call Address_Release() which frees all the gadgets. This is VERY important if you swap user controls.
Here is my Address example. To use it as a user control, just include the file with an XInclude and just use the calls in the example in the CompilerIf at the bottom:

Take for instance, I have an address user control. This groups together address lines 1, 2 & 3, Town, County and Territory text boxes, and their labels.
To do the same in PB, I have to create an include file that contains the following procedures:
Code: Select all
SetNumberOfInstances(Count.l)
New(pGadgetArea.l, pOffsetX.l, pOffsetY.l, pAddressNumber.l = 0)
Release()
Event(Event, WindowID, GadgetID, EventType)
Code: Select all
Address_SetNumberOfInstances
Address_New
Address_Release
Address_Event
Code: Select all
Global Dim lblCounty.l(0)
Global Dim lblTerritory.l(0)
Global Dim txtPostcode.l(0)
Global Dim txtLine1.l(0)
Once that has been set, you can then call the New procedure:
Address_New(ContainerID, 100, 100, 0)
This will then draw all the controls into the specified container by using UseGadgetList before drawing
Then in your main event loop, you then pass in all the event variables:
Address_Event(Event, WindowID, GadgetID, EventType)
This in does any event processing as required in the control.
Finally, to destroy all the gadgets, you then call Address_Release() which frees all the gadgets. This is VERY important if you swap user controls.
Here is my Address example. To use it as a user control, just include the file with an XInclude and just use the calls in the example in the CompilerIf at the bottom:
Code: Select all
EnableExplicit
; Addresses
Global __Address_TotalNumber.l = 0
Global Dim lblPostcode.l(0)
Global Dim lblLine1.l(0)
Global Dim lblLine2.l(0)
Global Dim lblLine3.l(0)
Global Dim lblTown.l(0)
Global Dim lblCounty.l(0)
Global Dim lblTerritory.l(0)
Global Dim txtPostcode.l(0)
Global Dim txtLine1.l(0)
Global Dim txtLine2.l(0)
Global Dim txtLine3.l(0)
Global Dim txtTown.l(0)
Global Dim txtCounty.l(0)
Global Dim txtTerritory.l(0)
Procedure Address_SetNumberOfAddresses(pCount.l)
__Address_TotalNumber = pCount - 1
ReDim lblPostcode.l(__Address_TotalNumber)
ReDim lblLine1.l(__Address_TotalNumber)
ReDim lblLine2.l(__Address_TotalNumber)
ReDim lblLine3.l(__Address_TotalNumber)
ReDim lblTown.l(__Address_TotalNumber)
ReDim lblCounty.l(__Address_TotalNumber)
ReDim lblTerritory.l(__Address_TotalNumber)
ReDim txtPostcode.l(__Address_TotalNumber)
ReDim txtLine1.l(__Address_TotalNumber)
ReDim txtLine2.l(__Address_TotalNumber)
ReDim txtLine3.l(__Address_TotalNumber)
ReDim txtTown.l(__Address_TotalNumber)
ReDim txtCounty.l(__Address_TotalNumber)
ReDim txtTerritory.l(__Address_TotalNumber)
EndProcedure
Procedure.l Address_New(pGadgetArea.l, pOffsetX.l, pOffsetY.l, pAddressNumber.l = 0)
UseGadgetList(pGadgetArea)
lblPostcode(pAddressNumber) = TextGadget(#PB_Any, pOffsetX + 0, pOffsetY + 0, 60, 20, "Postcode")
lblLine1(pAddressNumber) = TextGadget(#PB_Any, pOffsetX + 0, pOffsetY + 30, 70, 20, "Address Line 1")
lblLine2(pAddressNumber) = TextGadget(#PB_Any, pOffsetX + 0, pOffsetY + 60, 70, 20, "Address Line 2")
lblLine3(pAddressNumber) = TextGadget(#PB_Any, pOffsetX + 0, pOffsetY + 90, 70, 20, "Address Line 3")
lblTown(pAddressNumber) = TextGadget(#PB_Any, pOffsetX + 0, pOffsetY + 120, 70, 20, "Town")
lblCounty(pAddressNumber) = TextGadget(#PB_Any, pOffsetX + 0, pOffsetY + 150, 70, 20, "County")
lblTerritory(pAddressNumber) = TextGadget(#PB_Any, pOffsetX + 0, pOffsetY + 180, 70, 20, "County")
txtPostcode(pAddressNumber) = StringGadget(#PB_Any, pOffsetX + 80, pOffsetY + 0, 150, 20, "")
txtLine1(pAddressNumber) = StringGadget(#PB_Any, pOffsetX + 80, pOffsetY + 30, 150, 20, "")
txtLine2(pAddressNumber) = StringGadget(#PB_Any, pOffsetX + 80, pOffsetY + 60, 150, 20, "")
txtLine3(pAddressNumber) = StringGadget(#PB_Any, pOffsetX + 80, pOffsetY + 90, 150, 20, "")
txtTown(pAddressNumber) = StringGadget(#PB_Any, pOffsetX + 80, pOffsetY + 120, 150, 20, "")
txtCounty(pAddressNumber) = StringGadget(#PB_Any, pOffsetX + 80, pOffsetY + 150, 150, 20, "")
txtTerritory(pAddressNumber) = StringGadget(#PB_Any, pOffsetX + 80, pOffsetY + 180, 150, 20, "")
EndProcedure
Procedure Address_Release()
Protected i.l
For i = 0 To __Address_TotalNumber
FreeGadget(lblPostcode(i))
FreeGadget(lblLine1(i))
FreeGadget(lblLine2(i))
FreeGadget(lblLine3(i))
FreeGadget(lblTown(i))
FreeGadget(lblCounty(i))
FreeGadget(txtPostcode(i))
FreeGadget(txtLine1(i))
FreeGadget(txtLine2(i))
FreeGadget(txtLine3(i))
FreeGadget(txtTown(i))
FreeGadget(txtCounty(i))
Next
EndProcedure
Procedure.l Address(Event, WindowID, GadgetID, EventType)
If Event = #PB_Event_Gadget
Protected i.l
For i = 0 To __Address_TotalNumber
Select GadgetID
Case txtLine1(i)
SetGadgetText(txtLine3(i), Str(Event) + " " +Str(WindowID) + " " +Str(GadgetID) + " " +Str(EventType) + " ")
EndSelect
Next
EndIf
ProcedureReturn #True
EndProcedure
CompilerIf #PB_Compiler_Debugger
OpenWindow(0, 216, 0, 800, 600, "New window ( 0 )", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar | #PB_Window_WindowCentered )
Address_SetNumberOfAddresses(2)
Address_New(WindowID(0), 10, 10, 0)
Address_New(WindowID(0), 300, 10, 1)
;Address_New(WindowID(0), 10, 10)
Define Event
Define WindowID
Define GadgetID
Define EventType
Repeat ; Start of the event loop
Event = WaitWindowEvent() ; This line waits until an event is received from Windows
WindowID = EventWindow() ; The Window where the event is generated, can be used in the gadget procedures
GadgetID = EventGadget() ; Is it a gadget event?
EventType = EventType() ; The event type
Address(Event, WindowID, GadgetID, EventType)
Until Event = #PB_Event_CloseWindow
Address_Release()
CompilerEndIf