.
Let me help:
1. Create a new ActiveX dll project called SingletonProj
2. Change the name of Class1 to SingletonClass
3. Change the instancing to Public Not Creatable
4. Paste in this code:
Option Explicit
Public VoltVal As Double
5. Add a standard module to the project
6. Paste in this code:
Option Explicit
Dim mSingleton As SingletonClass
Public Function Singleton() As SingletonClass
If mSingleton Is Nothing Then Set mSingleton = New SingletonClass
Set Singleton = mSingleton
End Function
7. Add another class module to the project
8. Change the name of the class to GMUClass
9. Change the instancing to Global Multi Use
10. Paste in this code:
Option Explicit
Public Property Get Singleton() As SingletonClass
Set Singleton = Module1.Singleton
End Property
Now you reference SingletonProj in your main project and in your ActiveX EXE project, and access the VoltVal like this:
SingletonProj.Singleton.Vo
HTH-Jon
HTH-Jon
Be seen. Boost your question’s priority for more expert views and faster solutions
1. Create a new VB ActiveX exe project (name it, say, ElectTestProj)
2. Set the thread pool to 1 thread
3. Add the file mStart.bas from the VBAccelerator demo to it
4. Create a class module (name it, say, cElectTest)
5. Copy the code from cAsync.cls from the VBAccelerator demo into it
6. Copy the code from Elect_Test_Part into the Runnable_Start sub
7. Compile it
In the main program, go into Project | References and add the ElectTestProj component. If you don't care when the async procedure finishes (which is what it sounds like), you can ignore the stuff with the Complete and Cancelled events, and declaring the object WithEvents at the module level. To just launch the process in its own thread your code would be roughly:
Dim objElectTest As ElectTestProj.cElectTest
...
If PhotoEye3 = True Then
Set objElectTest = New ElectTestProj.cElectTest
objElectTest.Start
End If
...
Each time an ElectTestProj.cElectTest object is created it will run in its own thread.
HTH-Jon
I created an ActiveX exe and called it TestProject. TestProject consisted of a small amount of code to append Date and Time to a file 100,000 times. I used the objTest.Start in my Mainproject to run the TestProject ActiveX. While the ActiveX was doing it's thing, my MainProject was adding Date and Time to a list on my main form. Everything was asynchronous. It worked great.
Here is the problem though. My ElectTestProject is very large and shares many global variables with my Mainproject. I also show a lot of test data to the main form in my Mainproject, which I lose. I could spend a lot of time making my Main project completely seperate from the ElecTestProject, which might be worthwhile, but I don't think so.
The problem with having seperate exe's with my application is that I use a I/O handler that my Main project and ElectTestProject both use. Because my Main project uses I/O on the same computer relay card that the ElectTestProject uses, the I/O handler software must reside in an exe that contains all my code. I've tried putting the I/O handler in 2 different exe's and shelling an exe from my Main project and it doesn't work out. The only way to get around this is to have a dedicated I/O card to Main project completely seperate from I/O card to ElectTestProject. This would reguire an upgraded computer since I'm out of slots, not to mention a lot rewiring. Not the best option.
The ActiveX exe seems much more effecient than shelling a seperate exe, But in regards to not sharing variables it seems the same.
Let me know if I'm off base. My unfamilarity with ActiveX exe's could easily make me spew ignorance.
Of course this would represent a lot of rewriting. Another possible solution (which I am unfamiliar with) is described in this thread I found on Google:*vb*&rnum=1&hl=en#d81ef9a66fc4d0cb
Sorry but any way you slice it, it seems you're staring down a lot of revision.
You mention an easy way using a Create Event API and an I/O wait API. If you would like to expound, I'm listening. I'm all for easy.
Since your main project will need a reference to the singleton project, create an interface class in the singleton project that defines the properties and methods that you'll want the singleton to access on the main form. For example:
(class IParent)
Public Property Get Something() As String
End Property
Public Property Let Something(ByVal NewValue As String)
End Property
Public Sub DoSomething()
End Sub
(etc.)
Then in your main form put this in the declarations section:
Implements IParent
Private mSomething As String
Then you can drop down the object selector in the code view of the main form and select IParent, and define the implementation of this interface, e.g.:
Private Sub IParent_DoSomething()
'implementation of the DoSomething method
End Sub
Private Property Let IParent_Something(ByVal RHS As String)
mSomething = RHS
End Property
Private Property Get IParent_Something() As String
IParent_Something = mSomething
End Property
In the singleton object, include a parameter of type IParent on the procedures that you want to access the main form, e.g.:
(in the singleton class)
Public Sub SomeAction(ByVal Parent AS IParent)
'now you can access these properties and methods defined on the main form
Parent.Something = "blah"
Parent.DoSomething
End Sub
And in the main project when you want to execute the SomeAction method on the singleton:
'lets assume you have a global variable named gMainForm to reference your main form
'and a global variable named gSingleton to reference your singleton object
gSingleton.SomeAction gMainForm
Good luck.
Jon
I've been trying to create a singleton object and need some clarification. This is what I'm working with, just don't know how to piece everything together.
1. I have a MainProject
2. I have a GlobVar.bas in Mainproject (assume similar to myModule.bas in article)
3. Globvar.bas contains over 200 global variables. I'm just try work with 1 global variable called 'public VoltVal as double'.
4. I have a TestProject which is an ActiveX exe.
I think I need MainProject and TestProject to be able to access global variables in GMU class.
Where does GMU class go? In Mainproject? or TestProject? or a 3rd Project?
In the article under 'My way', he refers to myClass in his code. What would myClass be in my code.
Once I get this singleton object understood, I'll pursue the Mainform sharing.
thanks
In my Main Project I set SingletonProj.Singleton.Vo
When I activate my ActiveX EXE project I have a procedure that prints SingletonProj.Singleton.Vo
If I set SingletonProj.Singleton.Vo
It appears that I can set the VoltVal in each project, but if the variable changes in one of the projects it doesn't reflect in the other project.
Thanks so much
I think I found a solution for both problems. I should have dug into this deeper, before submitting a question. I got a little lazy, I guess.
1. To know that "ElectTest" ActiveX program is done, I just created a ElectTestDone variable in the Singleton ActiveX. I set the ElectTestDone variable to false in my MainProject just before I activate "ElectTest". In "ElectTest", I set the variable to true when the test is complete.
2. As far as the ActiveX programs always running in the background, it appears that it doesn't matter when I call the ActiveX program "ElectTest" multiple times. So I don't have duplicate ActiveX programs running in the task manager, which is what I thought would happen. All I did was use API functions "FindWindow(ElectTest)", "PostMessage(WM_close), and "WaitforSingleObject" to close the ActiveX programs when I unload the MainProject. When "ElectTest" closes the "Singleton" activeX closes also.
Last Issue, before I start rewriting my project.
I'm gonna tackle using the I/O handler in the Singleton class. Before I accept the "Singleton" answer, I would like to keep this question open in case I run into problems with the I/O handler stuff in the Singleton class.
You've been a great help
thanks
The I/O handler uses Type Definitions and some constants. The Singleton class module won't compile a Public Type Def or Constant. When I make them private it compiles, but can't see variables as objects in MainProject or ElectTest project. Am I screwed? or is there a way around this?
My constants are numeric. I think I need further explananation though. I tried some things to no avail. Here is what I'm working with:
SingletonClass
Public VoltVal as double ' shows up ok in other projects
Type D_IO ' stands for digital i/o ' compiling error
Board as integer
Port as integer
Bit as integer
On as boolean
end Type
Public Const Estop = 1 'compiling error
Public Const Alarm= 2
Public Const Running=3
Not sure what you mean by defining a public class that has public properties matching the type numbers.
Also not clear on how to use the Enum. I've tried some things using help, but didn't work out.
(declarations section of the class)
Public Enum IOStateEnum
Estop = 1
Alarm = 2
Running = 3
End Enum
This should compile and then you can access these in the main project as though they were constants.
For defining a class to replace the type, so something like:
(in the singleton class, add a new multi-use class named, say, clsIO)
Private mBoard As Integer
Private mPort As Integer
Private mBit As Integer
Private mOn As Boolean
Public Property Get Board() As Integer
Board = mBoard
End Property
Public Property Let Board(ByVal NewValue As Integer)
mBoard = NewValue
End Property
(etc...)
Then wherever you would declare a variable of type D_IO, declare a varaible of type clsIO instead:
Dim objIO As clsIO
Set objIO = New clsIO
With objIO
.Board = 1
'etc....
End With
Enum still can't access in main project. It's about the end of my day. I'll check back tommorrow.
The last thing I'm trying to figure out is whether I can use a component (I/O Device) in the Singleton Project and access it in both the MainProject and ElectTest Project to turn Outputs On/OFF through either project. Any advice?
SingletonFrm.Output_BD(0).
SingletonFrm.Output_BD(0).
SingletonFrm.Output_BD(0).
How do I do this from MainProject and ElectTestProject? I thought possible SingletonProj.SingletonFrm
This isn't correct. Maybe have to transfer to another class in SingletonProj and reference this class from MainProject?
I defined a class to replace the DAQDevice and DAQDO (component)
(in the singleton class, I add a new multi-use class named, say, DAQIO)
Private IO_CARD(0 to 1) As DAQDevice
Private Ouput_BD(0 to 1) As DAQDO
Then tried to use the Public Property functions.
I couldn't get anything to compile. I'm obviously doing something wrong. I don't think I can treat the component like the Type Def in clsIO.
If you're there, I'm still struggling to access a component in Singleton ActiveX and define ClsIO variables in main project. These are the problems I've run into.
1. In Mainproject I'm trying to initialize I/O variables. These I/O variables are in Singleton class and defined as a clsIO. For instance:
Singleton Class
Conveyor_Motor as ClsIO
Mainproject
SingletonProj.Singleton.Co
SingletonProj.Singleton.Co
*When I run main project I get an "Object variable or with Block Not Set"
2. I have a DAQclass in singleton project. This class contains a procedure to Turn On an Output. OUTPUT_BD(0 to 1) is DAQ output board on form.
DAQclass (GLobal multiuse)
Public Sub TurnOn_Output(Outputsig as ClsIO)
singletonfrm.OUTPUT_BD(out
singletonfrm.OUTPUT_BD(out
singletonfrm.OUTPUT_BD(out
end sub
When I run main project to TurnOn_Output I get an 'Object Required' error. This probably has something to do with "Object variable or with Block Not Set", when I try to initialize IO variables, Since I'm passing in a ClsIO to TurnOn_Output.
singletonproj.daqclass.Tur
Private Sub Class_Initialize()
Set Conveyor_Motor = New clsIO
End Sub
I think that will address the "Object variable not set" error.
When you call a sub, you should avoid parentheses, or use the Call statement:
Instead of:
singletonproj.daqclass.Tur
Use:
singletonproj.daqclass.Tur
Or:
Call singletonproj.daqclass.Tur
When you use the following:
singletonproj.daqclass.Tur
VB actually interprets this as:
singletonproj.daqclass.Tur
(note the space in between "Output" and the open paren)
Then VB evaluates the expression in parentheses, and passes the result of that evaluation as the parameter to TurnOn_Output. So, that might have something to do with the "Object required" error too.
I noticed you did a similar thing here:
singletonfrm.OUTPUT_BD(out
Again this should be:
singletonfrm.OUTPUT_BD(out
Or:
Call singletonfrm.OUTPUT_BD(out
So OUTPUT_BD is an array 0 To 1 of a class? Note that each array element that is a class must be initialized (probably in form_load) with a Set statement, much like the Set statement I described in the Class_Initialize procedure for the Conveyor_Motor member. E.g.:
Private Sub Form_Load()
Set OUTPUT_BD(0) = New <whateverclassitis>
Set OUTPUT_BD(1) = New <whateverclassitis>
End Sub
Since points have already been awarded for this specific question, I wonder if the admins here at E.E. would permit my offering dve01 my email address for the remaining follow-up questions that are not related to this specific solution?
Jon