PB equivalent of a VB6 User Control?

Just starting out? Need help? Post your questions and find answers here.
ozzie
Enthusiast
Enthusiast
Posts: 443
Joined: Sun Apr 06, 2008 12:54 pm
Location: Brisbane, Qld, Australia
Contact:

PB equivalent of a VB6 User Control?

Post by ozzie »

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?
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

I don't know what a user control is. Can you enlighten me?

Most likely you can't port that part straight over. Instead, you must use an alternative approach.

But I can't give a definite answer until I know what it is.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

I did a google image search on VB user control, looks like this means a complex user designed requester.

for PB I would recommend a new Window with an extra eventloop,
maybe started from a thread would be good.
oh... and have a nice day.
ozzie
Enthusiast
Enthusiast
Posts: 443
Joined: Sun Apr 06, 2008 12:54 pm
Location: Brisbane, Qld, Australia
Contact:

Post by ozzie »

Trond wrote:I don't know what a user control is. Can you enlighten me?
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.

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.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Well, PB is not VB of course (thank the Gods for that! :wink: ) 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. :)
I may look like a mule, but I'm not a complete ass.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

> 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.
oh... and have a nice day.
User avatar
pdwyer
Addict
Addict
Posts: 2813
Joined: Tue May 08, 2007 1:27 pm
Location: Chiba, Japan

Post by pdwyer »

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. :?
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
Foz
Addict
Addict
Posts: 1359
Joined: Tue Nov 13, 2007 12:42 pm
Location: Manchester, UK

Post by Foz »

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:

Code: Select all

SetNumberOfInstances(Count.l)
New(pGadgetArea.l, pOffsetX.l, pOffsetY.l, pAddressNumber.l = 0)
Release()
Event(Event, WindowID, GadgetID, EventType)
I prefix these with a unique label, so I know that I won't accidentally duplicate them, i.e.

Code: Select all

Address_SetNumberOfInstances
Address_New
Address_Release
Address_Event
Then I have a global array for all the controls, i.e.

Code: Select all

Global Dim lblCounty.l(0)
Global Dim lblTerritory.l(0)

Global Dim txtPostcode.l(0)
Global Dim txtLine1.l(0)
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:

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
ozzie
Enthusiast
Enthusiast
Posts: 443
Joined: Sun Apr 06, 2008 12:54 pm
Location: Brisbane, Qld, Australia
Contact:

Post by ozzie »

That's excellent Foz :D That's given me a good guide for converting my user controls - many thanks.
Post Reply