Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 449
  • Last Modified:

Dynamic Control Creation VB5

How do I create a control at runtime ie

place a label or textbox on a form

I know it can be done in VB 6
0
kevinstone
Asked:
kevinstone
  • 7
  • 4
  • 3
  • +3
1 Solution
 
mcriderCommented:
With VB5, you must have a control on the form already with the INDEX property set to 0.

For example add a textbox to a form an set the INDEX property to 0 and set the VISIBLE property to FALSE.

Then you can do this to have two new controls:

    Load Text1(1)
    With Text1(1)
         .Visible = True
         .Top = 0
         .Left = 0
    End With

    Load Text1(2)
    With Text1(2)
         .Visible = True
         .Top = 0
         .Left = Text1(1).Width + 120
    End With



Cheers!®©
0
 
kevinstoneAuthor Commented:
This requires that a control already exist on the form.  If this is the case a new instance of the control can be created with

DIM lable1 AS NEW LABEL1

where LABEL1 exist on the form

I can I achieve control creation where no other instance exist. ie blank form

on event create a control from scratch

0
 
samopalCommented:
This create a Dynamic Button
   Set cmdObject = Form1.Controls.Add("VB.CommandButton", "cmdOne")
   cmdObject.Visible = True
   cmdObject.Caption = "Dynamic CommandButton"

To create Label, use "VB.Label"

HTH
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
mcriderCommented:
samopal,

That does NOT work in VB5. Read the title of the question again.



kevinstone,

Your question title says "Dynamic Control Creation VB5"

"DIM lable1 AS NEW LABEL1" will NOT work in VB5.  This is VB6 only.

Like I said, the *ONLY* way to do it in VB5 is with objects that already exist on the form and have an INDEX set to 0.

If you want to be able to do "DIM lable1 AS NEW LABEL1" you MUST upgrade to VB6...


P.S. Dont shoot the messenger.  I did not write VB...



Cheers!®©


0
 
samopalCommented:
I'm SORRY... I saw only VB6 at the end of this question...
0
 
BodyaCommented:
In VB5 to create a control you must have a control array. That mean that if you want to create labela and TextBoxes, you should place on you form one Label with Index=0 (or more) and one TextBox with Index=0 (or more). The Index propery should be defined to explain to Basic that this is a controll array. Then you can write the following code (perhapes you name controls as 'MyLabel' and 'MyText' )

Load MyLabel(1)
Load MyText(1)

or

Load MyLabel(MyLabel.UBound+1)
Load MyText(MyText.UBound+1)

If you need to load a label from class  module where you have a reference to you form :

Load MyForm.MyLabel(1)

If you have to create other types of controls, you should place at least one instance of each type and set their Index property.

Note, that even in VB 6 controls, loaded in such a way works quiklier then those, loaded with Controls.Add()

best regards
0
 
mcriderCommented:
Bodya,  It is not proper EE etiquette to steal another's comments and post them as your own answer.  Please remove your answer.
0
 
amebaCommented:
' try this :)
Option Explicit
Private Declare Function CreateWindowEx Lib "user32.dll" Alias "CreateWindowExA" _
    (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, _
    ByVal dwStyle As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, _
    ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long
Private Declare Function DestroyWindow Lib "user32" (ByVal hWnd As Long) As Long
Private Const BS_PUSHBUTTON = &H0&
Private Const WS_CHILD = &H40000000
Private Const WS_VISIBLE = &H10000000
Private Const WS_EX_CLIENTEDGE = &H200&
Private Const LVS_REPORT = &H1
Private Const ES_MULTILINE = &H4&
Private Const ES_AUTOVSCROLL = &H40&
Private Const WS_DLGFRAME = &H400000
Private Const WS_BORDER = &H800000
Private m_hButton As Long
Private m_hWndLV As Long
Private m_hEdit As Long
Private m_hLabel As Long

Private Sub Form_Load()
    Dim lngStyle As Long
    ' Define style
    lngStyle = BS_PUSHBUTTON Or WS_CHILD Or WS_VISIBLE
    ' Create the button
    m_hButton = CreateWindowEx(0&, "BUTTON", "Click Me!", _
        lngStyle, 190, 10, 150, 50, Me.hWnd, 0&, App.hInstance, ByVal 0&)
       
    ' Define style
    lngStyle = WS_CHILD Or WS_VISIBLE Or LVS_REPORT
    ' Create the listview
    m_hWndLV = CreateWindowEx(WS_EX_CLIENTEDGE, "SysListView32", vbNullString, _
        lngStyle, 10, 10, 100, 100, Me.hWnd, 0, App.hInstance, ByVal 0&)

    ' Define style
    lngStyle = WS_DLGFRAME Or ES_AUTOVSCROLL Or ES_MULTILINE Or WS_CHILD Or WS_VISIBLE
    ' Create the textbox
    m_hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "TextBox", _
        lngStyle, 10, 120, 240, 100, Me.hWnd, 0&, App.hInstance, ByVal 0&)

    ' Define style
    lngStyle = WS_BORDER Or WS_CHILD Or WS_VISIBLE
    ' Create the label
    m_hLabel = CreateWindowEx(0&, "STATIC", "Label!", _
        lngStyle, 260, 170, 150, 30, Me.hWnd, 0&, App.hInstance, ByVal 0&)
End Sub

Private Sub Form_Unload(Cancel As Integer)
    ' Cleanup
    Call DestroyWindow(m_hButton)
    Call DestroyWindow(m_hWndLV)
    Call DestroyWindow(m_hEdit)
    Call DestroyWindow(m_hLabel)
End Sub
0
 
stefanxCommented:
Ameba - that's pretty cool (reminds me of my straig C days). Now how does one process the events? Also, how do you figure out what a legal window (control) type ?

Just for interest's sake....
0
 
amebaCommented:
Hehe, sometimes you don't need events, e.g. user enters text and you just read content of edit box.
For events, you'll need sublassing (btw, I hate sublassing) to catch messages.
This (Win API controls) is all very complicated, especially for us comfortable VB programmers, but performance is much better than with normal VB controls - I have seen very fast implementations of ListView32 and RichEdit controls.
But, the 'full code' to use events and properties is very large, e.g. see:

http://www.mvps.org/btmtz/enumdeskvb/
"Dynamically create both the treeview and listview common controls at runtime
 
This example is busy. Not only does it create both the treeview and listview common controls at runtime through the API (no Comctl32.ocx); subclass the controls' parent window, a VB Form, allowing the receipt of control window notification messages; ..."
0
 
amebaCommented:
>sublassing
subclassing :)
0
 
stefanxCommented:
Heh, I was hoping it was as simple as registering your event to the parent window with an AddressOf(Procedure) operator ;). I remember this kind of stuff from the early Turbo pascal for Windows stuff though...makes us feel old, hey ?
0
 
amebaCommented:
>makes us feel old, hey ?
I use word 'experienced' instead, it sounds better :)
0
 
kevinstoneAuthor Commented:
Again this relies on the control already available
0
 
amebaCommented:
You requested code that will add controls to a blank form, so here it is:

' Form1, no controls on *this* form (i.e. blank form)
Option Explicit
Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long

Private Sub Form_Load()
    Dim ctl As Control
    On Error Resume Next
   
    Show
    Load Form2
    For Each ctl In Form2.Controls
        ' SetParent doesn't work for lightweight controls (controls without hwnd)
        If TypeOf ctl Is Label Then
            ' this is replacement for Label control (it's not perfect)
            Me.CurrentX = ctl.Left
            Me.CurrentY = ctl.Top
            Print ctl.Caption
        Else
            SetParent ctl.hWnd, Me.hWnd
        End If
    Next
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Unload Form2
End Sub
0
 
mcriderCommented:
Ameba, Your last example requires the the controls exist on form2...
0
 
stefanxCommented:
That may well be, but I think ameba's suggestion is pretty brilliant. Sure, the controls need to be on form2, but if form2 is unloaded, the controls in the "control pool" do not waste any resources. Smart move - I like it !
0
 
BodyaCommented:
mcrider ,
Sorry I have looked through comments but don't pay attantion to a rejected answer. :(

Kevinstone, I don't understand why do you insist on creating from a scratch ? Finally, all the code you write for this will take more memory then a control on a form. Or, may be, you like programming on pure C ? :)))



0
 
amebaCommented:
stefanx, thanks

I just wanted to show what is possible.

I don't know if my samples will be used by kevinstone in real world app, or they are only for discussion, but I used both.

For Bodya,
>Kevinstone, I don't understand why do you insist on creating from a scratch ?

Here is one possible scenario:
You have a form with, e.g. 50 misc controls. All controls are with index 0.

You have to present preview of some dialog (e.g. defined in .dlg file).

If your form with all controls has the same style as the dialog you have to show, then no problem.
But if you have to show different form style (different form properties: BorderStyle, ControlBox, MaxButton, MinButton, MDIChild, etc) you cannot change this properties - they are read-only. For changing some properties it is possible to use APIs, like SetWindowLong, to change Form style, but not for all. To cover all combinations (there are 64) you'll have to use many (~16) forms:

    ' TForm1 is UDT, it is filled by reading .dlg file
    fn = selform(TForm1.BORDERSTYLE, TForm1.MaxButton, TForm1.MinButton, TForm1.ControlBox, TForm1.MDIChild)

Function selform(bs As Integer, mx As Integer, mn As Integer, cb As Integer, mdc As Integer) As Integer
    Dim fnum As Integer
    fnum = cb + 2 * mn + 4 * mx + 8 * bs + 16 * mdc
    Select Case fnum
    Case 0 To 7
        Load Form0
    Case 24, 26, 28, 30
        Load Form1
    Case 25, 27, 29, 31
        Load Form2
    Case 8
        Load Form3
    ...
    Case 63
        Load Form15
    End Select
End Function

You can prefill all 16 forms with controls, but having controls on *only one* form means:
- smaller .exe
- easy maintenance (imagine you have to add one more control to your set of supported controls)
0
 
kevinstoneAuthor Commented:
I tried this and it does exactly what I wanted.  Many Thanks
0
 
amebaCommented:
Thanks for your points.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 7
  • 4
  • 3
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now