[RESOLVED] How to detect the environment's compile mode in a UserControl?
Hello!
I’ve developed several UserControls with VB6 and already learned a lot from this forum. Many thanks to all posters here!
But the search function couldn't help me for just one thing.
From MSDN:
- When the developer re-opens the project, and opens the form to work on it again, the control is reincarnated as a design-time instance. It receives Initialize, ReadProperties, Resize, Paint, and WriteProperties events.
- When compiling a project a control instance gets the Initialize, ReadProperties, and WriteProperties events.
I'm searching for a way to detect the compile mode from the code of the Initalize or ReadProperties events. Is there any way or trick to detect the compile mode?
Re: How to detect the environment's compile mode in a UserControl?
I'm not 100% sure what you're asking but if you're talking about telling the difference between design mode and when it's being executed you can use the Ambient.UserMode property. Example:-
Code:
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
If UserControl.Ambient.UserMode Then
Debug.Print "Run mode"
Else
Debug.Print "Design mode"
End If
End Sub
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by Niya
UserControl.Ambient.UserMode
Thanks for your fast reply. I already checked Ambient.UserMode but it's always false in design mode, also during compilation. Thus can't be used for detecing compilation mode.
When the environment compiles a project with user controls it raises for every control instance the Initialize, ReadProperties, and WriteProperties events to gather the property settings and store it in the exe file. Thus during compilation I need to skip some functions in ReadProperties (e.g. creating a window or asking for a resource file). In normal design mode, as well as run mode, that functions should be executed.
Re: How to detect the environment's compile mode in a UserControl?
Thank you very much.
I tested your IsCompileTime function but it seems to be a replacement for Ambient.UserMode only. If the environment compiles the project it also returns False. Any more ideas?
Re: How to detect the environment's compile mode in a UserControl?
I have an interesting question. Why would someone want to know whether it's the compiler or the designer that's executing UserControl code? What's the scenario that brought up this question?
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by Niya
I have an interesting question. Why would someone want to know whether it's the compiler or the designer that's executing UserControl code? What's the scenario that brought up this question?
I can answer that one. For instance, I've got an OptionButtonEx that allows Unicode, but I only want to allow it to be set during runtime. Therefore, I have the following property:
Code:
Public Property Get CaptionUnicode() As String ' Now we mess with the Unicode caption.
If RunTime Then
CaptionUnicode = UniCaption(opt.hWnd) ' Just for runtime.
Else
CaptionUnicode = "(Unicode, runtime only)" ' Just show this in the Properties Window.
End If
End Property
Public Property Let CaptionUnicode(ByVal s As String)
If Not RunTime Then Exit Property ' Only allowed in runtime, not from Properties Window.
UniCaption(opt.hWnd) = s
End Property
I do something similar in a few other places.
Last edited by Elroy; Dec 21st, 2021 at 02:17 PM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by Niya
I have an interesting question. Why would someone want to know whether it's the compiler or the designer that's executing UserControl code? What's the scenario that brought up this question?
Well, I see several reasons for this:
1. At the end of ReadProperties an initialization function is executed to create a window (e.g. to create a common control). This delays the compilation process and is unnecessary during compile time.
2. At the end of ReadProperties it could be necessary to read an image from an external resource file (e.g. to show a graphical part on the user control. If the user control finds multiple resource files it needs to ask the user to select the desired one. Blocking the compilation until the user has answered a messoage or input box is totally unnecessary during compilation.
3. The user control could be built so that a valid license must be present to build an exe, whil in the IDE (design time or run time) it runs without any license (trial mode).
Maybe I abuse the ReadProperties event a bit, but I think it is the best event to execute such initialization code.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by Elroy
I can answer that one. For instance, I've got an OptionButtonEx that allows Unicode, but I only want to allow it to be set during runtime. Therefore, I have the following property:
Code:
Public Property Get CaptionUnicode() As String ' Now we mess with the Unicode caption.
If RunTime Then
CaptionUnicode = UniCaption(opt.hWnd) ' Just for runtime.
Else
CaptionUnicode = "(Unicode, runtime only)" ' Just show this in the Properties Window.
End If
End Property
Public Property Let CaptionUnicode(ByVal s As String)
If Not RunTime Then Exit Property ' Only allowed in runtime, not from Properties Window.
UniCaption(opt.hWnd) = s
End Property
I do something similar in a few other places.
Actually it took me a while to realize he is not talking about the different between runtime and design time. When you attempt to compile a VB6 project, UserControl code is actually executed before the EXE is made. This is also a design time process. He wants to be able to tell when it's the VB6 compiler itself that's actually running the code.
Originally Posted by IO_X
Well, I see several reasons for this:
1. At the end of ReadProperties an initialization function is executed to create a window (e.g. to create a common control). This delays the compilation process and is unnecessary during compile time.
2. At the end of ReadProperties it could be necessary to read an image from an external resource file (e.g. to show a graphical part on the user control. If the user control finds multiple resource files it needs to ask the user to select the desired one. Blocking the compilation until the user has answered a messoage or input box is totally unnecessary during compilation.
3. The user control could be built so that a valid license must be present to build an exe, whil in the IDE (design time or run time) it runs without any license (trial mode).
Maybe I abuse the ReadProperties event a bit, but I think it is the best event to execute such initialization code.
Ah well I think this is the issue. Long ago in ancient times when was I writing custom controls in VB6, I seem to recall a very important guideline, which is to never to do anything complicated in events like ReadProperties. You shouldn't be creating windows or anything fancy like that from these events. I'd strongly suggest rethinking this design. I'm not sure it may even be possible to do what you're asking. Someone here may know how but still. You should rethink the design in my opinion.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by wqweto
Is this a Std-EXE project?
Can you make a small repro project in which IsCompileTime hack fails?
cheers,
</wqw>
Yes it is a Std-EXE project.
Just add the line
MsgBox Format$(IsCompileTime(Extender))
at the end of a ReadProperties Event of any user control.
Either compile the user control to an OCX or build a vbg from std-EXE vbp and user control vbp or add the user control directly to the std-EXE vbp.
Then open any form in the std exe project and place the user control directly on the form. Close the form and re-open it to ensure ReadProperties is fired. Watch what is shown in the message box (True or False).
In next step compile the exe (e.g. by pressing Alt+F, K). During compilation the ReadProperties event again is fired and the message box again is shown. Watch the content. Any difference?
Never run the exe in the ide or standalone. Runtime mode is a quite different story, not required here.
Code:
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
On Error Resume Next
'... read any properties, not required for this repro here
On Error GoTo 0
MsgBox Format$(IsCompileTime(Extender))
End Sub
Private Function IsCompileTime(Extender As Object) As Boolean
Dim oTopParent As Object
Dim oUserControl As UserControl
On Error GoTo QH
Set oTopParent = Extender.Parent
Set oUserControl = AsUserControl(oTopParent)
Do While Not oUserControl Is Nothing
If oUserControl.Parent Is Nothing Then Exit Do
Set oTopParent = oUserControl.Parent
Set oUserControl = AsUserControl(oTopParent)
Loop
Select Case TypeName(oTopParent)
Case "Form", "UserControl"
IsCompileTime = True
End Select
QH:
End Function
Private Function AsUserControl(oObj As Object) As UserControl
Dim pControl As UserControl
If TypeOf oObj Is Form Then
'--- do nothing
Else
Call CopyMemory(pControl, ObjPtr(oObj), 4)
Set AsUserControl = pControl
Call CopyMemory(pControl, 0&, 4)
End If
End Function
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by Niya
You should rethink the design in my opinion.
Well, I already started that redesign and will try to move that initalization to the resize event, which is not fired during compilation. But finding a function to detect the compiler run would save me a lot of redesign work. And for reason 3 (license checking) only InitProperties, ReadProperties and WriteProperties can be used. These are the only events raised during compilation run.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by wqweto
Compilation always happens in user-mode set.
No. Compilation happens in design mode (Ambient.UserMode=False)
With compilation I mean the process which generates the exe file on disk.
Originally Posted by wqweto
Here is the sample project I'm testing: IsCompileTime.zip
It says True when compiling Project1 to Project1.exe only.
I tested your sample and only see False. User-mode does not to change to True during compilation, at least not while the ReadProperties event is executing. Environment is the VB6 IDE, not VBA or whatever could compile that code.
How do you start compiling Project1 to Project1.exe? Did you also try commandline compile?
Path\VB6.EXE /Make SourcePath\Project1.vbp" /OutDir TargetPath
Re: How to detect the environment's compile mode in a UserControl?
I don't understand the expected behavior.
At the end of ReadProperties an initialization function is executed to create a window (e.g. to create a common control). This delays the compilation process and is unnecessary during compile time.
When a control was re-created it always gets Initialize/ReadProperties events. Let's admit you want to skip some functionality after compilation but then this control becomes incomplete. Is this behavior expected?
At the end of ReadProperties it could be necessary to read an image from an external resource file (e.g. to show a graphical part on the user control. If the user control finds multiple resource files it needs to ask the user to select the desired one. Blocking the compilation until the user has answered a messoage or input box is totally unnecessary during compilation.
Each time control was re-created you'll get this ask-message. There is almost no difference when your control is re-created after compilation or whatever else. So the proper method is to save external resource path to a property and use it instead asking everytime.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by The trick
I don't understand the expected behavior.
When a control was re-created it always gets Initialize/ReadProperties events. Let's admit you want to skip some functionality after compilation but then this control becomes incomplete. Is this behavior expected?
Yes. Completion is not necessary during compilation. The only purpose of ReadProperties/WriteProperties during compilation is to get the selected property values and compile them to the exe file. There are no Resize or Paint events to show the controls anywhere during compilation. Especially not when the commandline is used for compiling.
Originally Posted by The trick
Each time control was re-created you'll get this ask-message. There is almost no difference when your control is re-created after compilation or whatever else. So the proper method is to save external resource path to a property and use it instead asking everytime.
You are right, and in fact I do not ask every time. The control creates a shared memory which is used from all instances and main application. But this does not allow to remove the selection function at all. In some scenarios it's better to inform the user that there is a scenario which could lead to wrong or missing resources.
Re: How to detect the environment's compile mode in a UserControl?
I'm not sure I understand the question, but I think I do.
You want to tell the difference between "design mode" and "when you're compiling but before you're up and running mode" correct?
Here's an easy way to do it. Just start your project from a Sub Main, create a global boolean (probably in the same module as your Sub Main), and in your Sub Main, the first thing you do is set it to True. Let's call this variable Public gbImRunning As Boolean.
If it's in Sub Main, it'll be set to True before any of your custom UC's get a chance to raise their Initialize, ReadProperties, whatever events. And, when those events fire, you can check this gbImRunning variable to see if you're starting up or if you're in design mode.
In fact, in many ways, that'll be better than the UserControl.Ambient.UserMode property, as that property has several problems.
EDIT: The only downside I know of to that approach is that, if you have designer forms open with your custom UCs on them, and you simultaneously edit your module with the Sub Main in it, the custom UCs will get hatched out. To prevent that, I'd recommend making a module with your Sub Main in it and little else. That way, you shouldn't be tempted to open it very often.
Last edited by Elroy; Dec 21st, 2021 at 08:12 PM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: How to detect the environment's compile mode in a UserControl?
*furrows brow* That's some interesting code, wqweto:
Code:
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Function IsCompileTime(Extender As Object) As Boolean
Dim oTopParent As Object
Dim oUserControl As UserControl
On Error GoTo QH
Set oTopParent = Extender.Parent
Set oUserControl = AsUserControl(oTopParent)
Do While Not oUserControl Is Nothing
If oUserControl.Parent Is Nothing Then Exit Do
Set oTopParent = oUserControl.Parent
Set oUserControl = AsUserControl(oTopParent)
Loop
Select Case TypeName(oTopParent)
Case "Form", "UserControl"
IsCompileTime = True
End Select
QH:
End Function
Private Function AsUserControl(oObj As Object) As UserControl
Dim pControl As UserControl
If TypeOf oObj Is Form Then
'--- do nothing
Else
Call CopyMemory(pControl, ObjPtr(oObj), 4)
Set AsUserControl = pControl
Call CopyMemory(pControl, 0&, 4)
End If
End Function
Would you be up for adding some comments to that so we could trace through your thinking?
EDIT: And, doesn't just setting a global do the same thing?
Last edited by Elroy; Dec 21st, 2021 at 08:29 PM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by Elroy
You want to tell the difference between "design mode" and "when you're compiling but before you're up and running mode" correct?
When you compile a VB6 project, it seems part of the process involves restarting the designer which re-instantiate the UserControl in design mode. It's exactly the same thing that happens when you open a Form with a UserControl on it at design time only it's triggered by the compiler instead of the developer twiddling about in the designer. He wants to detect when the compiler does it.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by The trick
Why only during compilation? After compilation you still can work as usual so the control will broken.
ReadProperty is called after compilation. The runtime just terminate the form and re-create it with all the controls.
Not always. If you compile a project while all forms are closed in the designer, the compiler loads every form invisibly, instantiates every usercontrol, raises the events and unloads the form immediately. The same happens if you compile the project from command line. In these scenarios the limited UC functionality is desired.
For the commandline scenario I already found a possible way:
The batch file which creates the resource files and executes the compilation could start an extra application which creates a mutex and destroys it after the compilation is ready. If the UCs see that mutex the compilation scenario detection is successful.
Thus a way to detect the In-Ide-compilation scenario still is desired…
Re: How to detect the environment's compile mode in a UserControl?
@Elroy: When you compile a project which has a form with a MyControl on it the control's properties must be persisted in the final executable so the compiler re-spawns the form a couple of times in the process.
The idea is that when compiling the final executable for each form in the project the compiler recreates all the users controls as described by the source frm/frx which raises ReadProperties event on each and every sited control. Next the compiler instructs all controls to persist their properties by raising WriteProperties but this time the binary storage goes into the final executable.
So at compile-time the compiler is transfering control properties from source frm/frx into destination executable by for each control first raising ReadProperties to read data from frm/frx and immediately raising WriteProperties to write this (as binary data) into the exe.
The idea is that during exactly this ReadProperties which happens at compile-time you don't want to create custom comctl windows, don't want to subclass parent hwnd, don't want to show license dialogs and so on unnecessary "dangerous" activities which might bomb or stall the compiler.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by Elroy
I can answer that one. For instance, I've got an OptionButtonEx that allows Unicode, but I only want to allow it to be set during runtime. Therefore, I have the following property:
Code:
Public Property Get CaptionUnicode() As String ' Now we mess with the Unicode caption.
If RunTime Then
CaptionUnicode = UniCaption(opt.hWnd) ' Just for runtime.
Else
CaptionUnicode = "(Unicode, runtime only)" ' Just show this in the Properties Window.
End If
End Property
Public Property Let CaptionUnicode(ByVal s As String)
If Not RunTime Then Exit Property ' Only allowed in runtime, not from Properties Window.
UniCaption(opt.hWnd) = s
End Property
I do something similar in a few other places.
you can use main() sub for exe:
Code:
Option Explicit
Public RunInExe As Boolean
Sub Main()
RunInExe = True
Form1.Show
End Sub
in usercontrol:
Code:
Private Sub UserControl_Initialize()
Debug.Print Now & "RunInExe=" & RunInExe
End Sub
Code:
Public RunInExe As Boolean
Function CheckRunInVB6_EXE() As Boolean
'CHECK Process is vb6.exe
'put code here
CheckRunInVB6_EXE = True
End Function
Sub Main()
RunInExe = True
' RunInExe = CheckRunInVB6_EXE
Form1.Show
End Sub
Last edited by xiaoyao; Dec 22nd, 2021 at 05:16 AM.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by xiaoyao
in usercontrol:
Code:
Private Sub UserControl_Initialize()
Debug.Print Now & "RunInExe=" & RunInExe
End Sub
Not applicable. If the user control runs from an OCX file it has no chance to access variables located in a form or module of the exe.
Once again: Detecting the run time of exe (=Usermode) is not my question in this thread. The question is: How can a user control (usually with code in OCX) see, that the compiler in the IDE is building the main exe (and therefore is raising the ReadProperties Event in the user control)?
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by IO_X
In these scenarios the limited UC functionality is desired.
For this very limited functionality you can try to use this code:
Code:
Option Explicit
Private Declare Function GetModuleHandle Lib "kernel32" _
Alias "GetModuleHandleW" ( _
ByVal lpModuleName As Long) As OLE_HANDLE
Private Declare Sub GetMem4 Lib "msvbvm60" ( _
ByRef pAddr As Any, _
ByRef pDst As Any)
Private Declare Sub PutMem8 Lib "msvbvm60" ( _
ByRef pDst As Any, _
ByVal curVal As Currency)
Private Declare Sub PutMem4 Lib "msvbvm60" ( _
ByRef pDst As Any, _
ByVal curVal As Long)
Private Declare Sub PutArr Lib "msvbvm60" _
Alias "PutMem4" ( _
ByRef pDst() As Any, _
ByRef pSA As Any)
Private Sub UserControl_Initialize()
Debug.Print IsInExeMake
End Sub
Private Function IsInExeMake() As Boolean
Static s_pCio_fMakeExe As Long
Dim hVB6 As OLE_HANDLE
Dim pNTHdr As Long
Dim pStart As Long
Dim lLength As Long
Dim bSign(15) As Byte
Dim bSA(23) As Byte
Dim bData() As Byte
Dim lIndex1 As Long
Dim lIndex2 As Long
Dim lOffset As Long
If s_pCio_fMakeExe = 0 Then
hVB6 = GetModuleHandle(StrPtr("vb6.exe"))
If hVB6 = 0 Then Exit Function
GetMem4 ByVal hVB6 + &H3C, pNTHdr
pNTHdr = pNTHdr + hVB6
GetMem4 ByVal pNTHdr + &H104, pStart
pStart = pStart + hVB6
GetMem4 ByVal pNTHdr + &H108, lLength
PutMem8 bSign(0), 501175085014327.7256@
PutMem8 bSign(8), 385770353152893.3588@
PutMem8 bSA(0), 429503.2833@
PutMem4 bSA(12), pStart
PutMem4 bSA(16), lLength
PutArr bData(), ByVal VarPtr(bSA(0))
Do While lIndex1 < lLength - 16
If bData(lIndex1) = bSign(lIndex2) Then
lIndex2 = lIndex2 + 1
If lIndex2 >= 16 Then
lOffset = lIndex1 - 15 + pStart
Exit Do
End If
Else
If lIndex2 Then
lIndex1 = lIndex1 - lIndex2 + 1
lIndex2 = 0
End If
End If
lIndex1 = lIndex1 + 1
Loop
PutArr bData(), ByVal 0&
If lOffset = 0 Then
Stop ' // Not found
End If
GetMem4 ByVal lOffset + 16, s_pCio_fMakeExe
End If
GetMem4 ByVal s_pCio_fMakeExe, lIndex1
IsInExeMake = lIndex1 <> 0
End Function
Just close all the designer window and start to compile your project. However it won't work when you compile the project with the opened window but you told this mode is out of your needs.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by The trick
For this very limited functionality you can try to use this code:
Wow, that's real magic!
Now I understand why your name is "The trick".
Could you please enlight us a little bit so that we can understand what is being done here.
In the IDE in fact it works as expected.
In the commandline compiler it works for 50%. I saw that there are two runs. In the first run your function reports "False" in the second run it reports "True", as desired. But for commandline compiling I could add the Mutex solution.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by dday9
@wqweto - I've removed the link because it contained a download of an executable, which is against forum rules.
Sure!
There just was no way to provide sample ZIP file without including the OCX as in VB6 for binary compatibility target you have to point to a compiled version of the OCX (cannot use its TLB for no apparent reason)
But without binary compatibility set in Project2 the forms in Std-EXE Project1 couldn't contain user-controls from the OCX Project2 the way both are part of the same project group.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by wqweto
@Elroy: When you compile a project which has a form with a MyControl on it the control's properties must be persisted in the final executable so the compiler re-spawns the form a couple of times in the process.
The idea is that when compiling the final executable for each form in the project the compiler recreates all the users controls as described by the source frm/frx which raises ReadProperties event on each and every sited control. Next the compiler instructs all controls to persist their properties by raising WriteProperties but this time the binary storage goes into the final executable.
So at compile-time the compiler is transfering control properties from source frm/frx into destination executable by for each control first raising ReadProperties to read data from frm/frx and immediately raising WriteProperties to write this (as binary data) into the exe.
The idea is that during exactly this ReadProperties which happens at compile-time you don't want to create custom comctl windows, don't want to subclass parent hwnd, don't want to show license dialogs and so on unnecessary "dangerous" activities which might bomb or stall the compiler.
cheers,
</wqw>
Hi wqweto,
Thanks for that explanation. I already knew most of that, but never had thought about the mechanisms through which it happens.
For instance, I knew that, in the "source code", a UC's properties were in the frm/frx. I also knew that, once compiled, a copy of those original properties were in the compiled EXE (what you're calling persistent properties). I'm not sure I'd thought this through, but I guess it makes sense that it'd use ReadProperties to get them during compilation, and that it'd use a re-directed (to the EXE) of WriteProperties to write them into the EXE. However, that last part does seem a bit strange. I'd have thought that the compiler just directly wrote them.
Also, I suppose I've never totally thought through all these mechanisms. But, to my way of thinking, while in design mode, ReadProperties/WriteProperties is just IO into a PropertyBag (one PropertyBag per control, even for intrinsics, even for control arrays), and that it's actually the Save button that reads/writes it into the frm/frx (completely circumventing any ReadProperties/WriteProperties calls).
During a compile, I'm not at all sure where the compiler gets the properties. But, just guessing, I'd also say the PropertyBags of each/every control. I'm pretty sure this is true because you can compile without saving.
EDIT: You can also compile from the command line (in which case it certainly goes to the saved source code). But, I'm guessing, even in that case, it sets up PropertyBags and compiles using those.
-----
But, back to the OP's question. I guess he's asking for a way to distinguish between ReadProperties/WriteProperties during design vs during compiling. I guess that's what he said all along, and it's just taking a while to get into my head.
Also, now that (I think) I understand this, I'm back at Niya's question ... why would we need to know this? But, if there's a distinction, I'm definitely one for figuring out how to make it, even if there's not an immediate need.
Last edited by Elroy; Dec 22nd, 2021 at 10:48 AM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: How to detect the environment's compile mode in a UserControl?
After several test runs with Trick's IsInExeMake function I have two news:
The good news:
The function works very well in the IDE, regardless if designer windows are open or not. If a form designer window with user control is open, the compiler closes it and after the exe is created, it is reopened. In that moment the usercontrols are loaded again and IsInExeMake returns False, which is expected and desired.
The bad news:
If the IDE is restarted or the project re-opened, and immediately the compilation is started (without opening a form designer window with user controls) the IsInExeMake function returns False, which is not expected and not desired
I figured out, that in this scenario the IDE seems to execute a pre-compilation run, with loading/unloading all user controls. In that pre-compilation the IsInExeMake function returns False. After that the final compilation starts and all user controls will be loaded/unloaded again. Now IsInExeMake returns the desired True. The progress bar in the IDE's tool bar is shown only in that final compiler run.
This pre-compilation run seems to be that what I watched in the commandline compiler, which starts compiling immediately after loading the project.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by Elroy
... distinguish between ReadProperties/WriteProperties during design vs during compiling.
Exactly!
Originally Posted by Elroy
Also, now that (I think) I understand this, I'm back at Niya's question ... why would we need to know this? But, if there's a distinction, I'm definitely one for figuring out how to make it, even if there's not an immediate need.
Great! Immediate need I already have
Checkout also my recent comments for Trick's IsInExeMake function. Compilation seems to be not so straightforward as supposed.
Re: How to detect the environment's compile mode in a UserControl?
Do we need to know this when both compiling from command line and compiling from IDE?
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by wqweto
But without binary compatibility set in Project2 the forms in Std-EXE Project1 couldn't contain user-controls from the OCX Project2 the way both are part of the same project group.
It's complicated. Legacy problems
That happens only after you compile Project2 ocx at least once, because project1.vbp adds the CLSID of the ocx.
If you never compiled or manually change the reference in Project1.vbp, the ocx is not required.
An alternative solution is to change the extension of the reference file to something like Project2.cmp.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by Elroy
Do we need to know this when both compiling from command line and compiling from IDE?
The scenario "compiling in IDE" is the major goal. There is a high chance that the same function also works with commandline compiling, as this operates just with an invisible IDE.
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by Elroy
But, to my way of thinking, while in design mode, ReadProperties/WriteProperties is just IO into a PropertyBag (one PropertyBag per control, even for intrinsics, even for control arrays), and that it's actually the Save button that reads/writes it into the frm/frx (completely circumventing any ReadProperties/WriteProperties calls).
These are completely "spoofed" PropertyBags, not the original VB6 runtime ones.
Such PropertyBag object obviously reads/writes part of the properties into a textual frm file, while byte-arrays and serialized objects (like Pictures, StdFonts, etc.) are saved in binary to a frx file but the format has nothing to do with the Contents property of the regular MSVBVM60 provided PropertyBag (at least its not compatible if there are any similarities).
Re: How to detect the environment's compile mode in a UserControl?
Originally Posted by IO_X
The scenario "compiling in IDE" is the major goal. There is a high chance that the same function also works with commandline compiling, as this operates just with an invisible IDE.
When you compile a project after re-opening (before compilation) it setups an icon of the project so it requires loading the form resources and all the OCX/UC. I know how to check that but it requires more complex code with inline-asm. Is it applicable? You can test also current icon like GetCursor = LoadCursor(0, IDC_WAIT) but it also report true when your control is in design.
Re: How to detect the environment's compile mode in a UserControl?
To test, I just put a single UC (with no sub-controls) on a Form1.
The UC had the following code:
Code:
Option Explicit
Private Sub UserControl_Initialize()
MsgBox "Initialize"
End Sub
Private Sub UserControl_InitProperties()
MsgBox "InitProperties"
End Sub
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
MsgBox "ReadProperties"
End Sub
Private Sub UserControl_Terminate()
MsgBox "Terminate"
End Sub
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
MsgBox "WriteProperties"
End Sub
Now, here are the notes I took:
' On creation of UC on design form.
Initialize
InitProperties
' On close of design form after creation of UC or any properties changed.
WriteProperties
Terminate
' On close of design form if no properties have changed.
Terminate
' On open of design form with UC on it.
Initialize
ReadProperties
' There might also be WriteProperties calls if PropertyChanged was called.
' When project is saved and there have been changes to the form with the UC.
Initialize
ReadProperties
WriteProperties (sometimes called twice here)
Terminate
' When project is compiled from the IDE (with designer form closed).
Initialize
ReadProperties
WriteProperties
Terminate
' When compiled from command line, NONE of these events seem to be raised.
Here's a batch file I created for testing. You'll need to tweak it to use anywhere but on my computer:
I also did it with Debug.Print statements, but I wanted to use message boxes for compiling. That didn't seem to make any difference.
But what was notable to me was that I got no message boxes when compiling from the command line. Apparently this is a somewhat different process than compiling in the IDE.
Ohhh, and also, it's worth saying that all that happens upon execution of the EXE is an Initialize and ReadProperties, with a Terminate when the COM for the UC is uninstantiated. I'm thinking a call to WriteProperties wouldn't make any sense in the EXE.
Last edited by Elroy; Dec 22nd, 2021 at 05:01 PM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.