Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

VB6 - Forms manipulation during run-time.

Status
Not open for further replies.

Endtime

Technical User
Nov 23, 2007
3
0
0
US
I have a form w/controls that I'm using as a generic "New Form" which I have hidden until needed. What I'm looking for is a way to manipulate that form with it's controls during run time, and save it under a different name, keeping the "New Form" generic. Basically, I would be adding the "New Form" to the program as "frmExample" during run-time. Thanks.
 
Why do you need to persist the resulting form beyond the run-time instance of your application?
 
I don't think it's possible to create a new class (which is essentially what you are asking) during run time.

If I had to do something like this, I would store the information about the form in a database (e.g. what controls it has, their positions on the form, other property values, etc.). Then when the user wants to use his custom form, I would initialize an existing "template" form, add all the controls as per my database settings, and then show the form.

Perhaps you could elaborate on what you want to do?


 
<I don't think it's possible ...

Well, I think it is, actually, given the following:

1. Each form file (or class file) is a text file.
2. Each .vbp file is a text file, and includes the list of forms (and/or classes) in the project.
3. Text files can be manipulated programmatically.
4. .vbp files can be compiled programmatically.

Given all of these, I believe the conclusion that it is possible is inescapable.
 
Bob said:
4. .vbp files can be compiled programmatically

When I release my EXE to my customer, assuming I go through the trouble of including the VBP and other source files in the install package, will the VB compiler be available to recreate the EXE? I suspect distributing the compiler would violate my license agreement to Microsoft.

Even if it doesn't, is it possible for the EXE to trigger it's own recompilation, shut down while it's new EXE is being compiled, then have the new EXE restart and take over from where the last EXE left off?

To answer my own question, theoretically I guess it's possible if you create some sort of "starter" EXE that monitors the main app and does all this work. (I hope the OP is not taking any of this as a practical solution.)

Besides, I said "during run time", and if you have to stop the original EXE to compile a new version, then it is no longer running.

 
Well, Joe, if you had said "I don't think it's possible for an application to create a new class on an instance of itself that isn't running on the machine where it was developed which doesn't have the source code on it either, and then recompile itself without interruption while it's still running, and all this on a machine that may not have the ability to compile VB programs without violating the Microsoft license" I'm sure I wouldn't have commented to the contrary at all.

Bob
 
Bob said:
"I don't think it's possible for an application to create a new class on an instance of itself that isn't running on the machine where it was developed which doesn't have the source code on it either, and then recompile itself without interruption while it's still running, and all this on a machine that may not have the ability to compile VB programs without violating the Microsoft license"
"during run time" seemed more concise.

 
It does now, too. Are you retracting all that other stuff then?
 
Yes, a Form in VB6 is a kind of class. People get confused because by default you get an implicit instance of the Form with the same name as the Form class.

It's easy enough to instantiate additional forms of that class however.

No, you can't "modify the Form" but of course you can add new controls to a Form instance's Controls collection as well as Load new instances into any control arrays.

How any of this is particularly useful in a typical program escapes me, but I suppose one could contrive some sort of scenario where it is desireable.
 
dilettante said:
How any of this is particularly useful in a typical program escapes me, but I suppose one could contrive some sort of scenario where it is desireable.
I once made a search form where the user could configure which search fields they wanted to see on the dialog box. For example, they could choose from a list fields such as:

First Name
Last Name
City
DOB
Job Title

If for example they configured it to include "First Name", "City", and "DOB", when the form opened it added three textboxes and corresponding labels to the form.

I'm assuming this is what the OP was after, so that the user could "customize" his form.

Incidentally, I don't think the users of my application ever changed the default settings of my customizable search screen, so I could have just as well hard coded it.

Oh well, it was a good coding excercise.

 
So, here's another good coding exercise, a way to create a class during runtime and then instantiate it from the same runtime context.

Write a piece of code that creates the following text files:
Code:
'.cls file, called myClass.cls
VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "myClass"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Option Explicit

Public Sub MyMethod()
MsgBox "Success!"
End Sub

'.vbp file, called MyComponent.vbp
Type=OleDll
Class=myClass; myClass.cls
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\WINDOWS\system32\STDOLE2.TLB#OLE Automation
Startup="(None)"
HelpFile=""
Command32=""
Name="MyComponent"
HelpContextID="0"
CompatibleMode="1"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
VersionCompanyName="Western United"
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=1
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1
ThreadingModel=1

[MS Transaction Server]
AutoRefresh=1
Of course, I didn't write this code; I simply created and saved (without compiling) an activeX DLL with the appropriate names and added the little myMethod method. I assume I don't have to go to the trouble to write this to prove my point.

Once this code is created, add the following:
Code:
Option Explicit

Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Const PROCESS_QUERY_INFORMATION = &H400
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Function IsProcessRunning(pid As Long) As Boolean
Dim hProcess As Long
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid)
CloseHandle hProcess
IsProcessRunning = hProcess
End Function

Private Sub Command1_Click()
Dim i As Integer
Dim ProcessID As Long
Dim x As Object
On Error Resume Next
ProcessID = Shell(Environ$("COMSPEC") & " /C " & "vb6 /make ""c:\bobrodes\activex dll\mycomponent.vbp""")
Do While IsProcessRunning(ProcessID)
    i = i + 1
    If i = 100 Then
        Err.Raise vbObjectError + 1000, "Shell Process", "Timeout"
    End If
    Sleep 100
Loop
Set x = CreateObject("mycomponent.myclass")
x.mymethod
'With CreateObject("mycomponent.myclass")
'    .mymethod
'End With
End Sub
All the IsProcessRunning logic (in other words, most of this code) is due to the shell command's running asynchronously. The code will on the CreateObject if we don't give the shell command a chance to close.

So, it seems to me that this is an example of creating a class at runtime without interrupting the runtime context. (I should point out that it's quite possible to put a Form in an ActiveX DLL as well...) Why anyone would want to do it...well, perhaps we'll find some post 2 years from now that explains how it was useful. And then again, perhaps not.

Bob
 
Why yes Bob, you've proven me wrong, it looks like that will work!

And it didn't occur to me until now that the EXE could be using objects from a separate DLL (I was thinking only of classes defined in the EXE itself).

One can't help but contemplate the new level of DLL Hell such a solution would spawn.

:)


 
Yes, indeed. One might refer to this as a "poisonous solution", in fact.
 
I may have missed something that EndTime is wanting to do, but I think EndTime is not wanting to truly save the new form. Just create a new instance during run time such as -

in a module-
Code:
Public frmExample1 As frmGeneric
Public frmExample2 As frmGeneric
Public frmExample3 As frmGeneric

Main form load
Code:
Set frmExample1 = New frmGeneric
Set frmExample2 = New frmGeneric
Set frmExample3 = New frmGeneric

frmExample1.BackColor = vbRed
frmExample2.BackColor = vbBlue
frmExample3.BackColor = vbGreen

Then show/hide the forms as needed

EndTime, Please elaborate as JoeAtWork suggested.

Tom
 
Tom - that's basically what I was suggesting. To add to your example, when the user wants to "save" his custom form, a new record in a database would be created where FormName="frmExample1", BackColor="vbRed", etc..

I think Bob and I scared the OP away with our "programming" discussion.


 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top