Solved

Dynamic Control Creation VB5

Posted on 2000-03-10
21
415 Views
Last Modified: 2012-06-27
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
Comment
Question by:kevinstone
  • 7
  • 4
  • 3
  • +3
21 Comments
 
LVL 14

Expert Comment

by:mcrider
Comment Utility
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
 

Author Comment

by:kevinstone
Comment Utility
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
 
LVL 9

Expert Comment

by:samopal
Comment Utility
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
 
LVL 14

Expert Comment

by:mcrider
Comment Utility
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
 
LVL 9

Expert Comment

by:samopal
Comment Utility
I'm SORRY... I saw only VB6 at the end of this question...
0
 
LVL 2

Expert Comment

by:Bodya
Comment Utility
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
 
LVL 14

Expert Comment

by:mcrider
Comment Utility
Bodya,  It is not proper EE etiquette to steal another's comments and post them as your own answer.  Please remove your answer.
0
 
LVL 15

Expert Comment

by:ameba
Comment Utility
' 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
 
LVL 8

Expert Comment

by:stefanx
Comment Utility
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
 
LVL 15

Expert Comment

by:ameba
Comment Utility
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
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 15

Expert Comment

by:ameba
Comment Utility
>sublassing
subclassing :)
0
 
LVL 8

Expert Comment

by:stefanx
Comment Utility
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
 
LVL 15

Expert Comment

by:ameba
Comment Utility
>makes us feel old, hey ?
I use word 'experienced' instead, it sounds better :)
0
 

Author Comment

by:kevinstone
Comment Utility
Again this relies on the control already available
0
 
LVL 15

Expert Comment

by:ameba
Comment Utility
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
 
LVL 14

Expert Comment

by:mcrider
Comment Utility
Ameba, Your last example requires the the controls exist on form2...
0
 
LVL 8

Expert Comment

by:stefanx
Comment Utility
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
 
LVL 2

Expert Comment

by:Bodya
Comment Utility
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
 
LVL 15

Accepted Solution

by:
ameba earned 50 total points
Comment Utility
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
 

Author Comment

by:kevinstone
Comment Utility
I tried this and it does exactly what I wanted.  Many Thanks
0
 
LVL 15

Expert Comment

by:ameba
Comment Utility
Thanks for your points.
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now