Page 1 of 2 12 LastLast
Results 1 to 40 of 71

Thread: [RESOLVED] How to detect the environment's compile mode in a UserControl?

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Resolved [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?

  2. #2
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    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
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    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

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by Niya View Post
    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.
    Last edited by IO_X; Dec 21st, 2021 at 12:43 PM.

  4. #4

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    ....
    Last edited by IO_X; Dec 21st, 2021 at 12:41 PM.

  6. #6

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    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?
    Last edited by IO_X; Dec 21st, 2021 at 11:58 AM.

  7. #7
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: How to detect the environment's compile mode in a UserControl?

    Is this a Std-EXE project?

    Can you make a small repro project in which IsCompileTime hack fails?

    cheers,
    </wqw>

  8. #8
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    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?
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    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

  9. #9
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,852

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by Niya View Post
    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.

  10. #10

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by Niya View Post
    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.

  11. #11
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by Elroy View Post
    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.

    Quote Originally Posted by IO_X View Post
    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.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    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

  12. #12

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by wqweto View Post
    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

  13. #13

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by Niya View Post
    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.

  14. #14
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: How to detect the environment's compile mode in a UserControl?

    Try MsgBox Format$(Ambient.UserMode And IsCompileTime(Extender)) and this works as expected here.

    In the linked thread there was this sample usage:

    Code:
            If Ambient.UserMode And Not IsCompileTime(Extender) Then
                SubClass m_uSubclassCtl, m_hWndCtl, ObjPtr(Me), AddressOf RedirectDTControlWndProc
            End If
    i.e the control does not use subclassing when run in the IDE or when compiling a form which has the control placed (sited) on it.

    Here is the sample project I'm testing: removed by moderator

    It says True when compiling Project1 to Project1.exe only.

    It says False when opening Form1 designer, when running the project in the IDE or when running the compiled Project1.exe

    Let me summarize its usage again: you should call IsCompileTime only when Ambient.UserMode is set i.e. when not run in the IDE.

    When run in the IDE (Ambient.UserMode is not set) you can be sure the control is not placed on a form/control that is being compiled.

    cheers,
    </wqw>

  15. #15

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by wqweto View Post
    Try MsgBox Format$(Ambient.UserMode And IsCompileTime(Extender)) and this works as expected here.
    I'll try. But how can it produce a different ouput, if in both cases Ambient.UserMode is False ???
    False and True = False
    False and False = False


    Quote Originally Posted by wqweto View Post
    you should call IsCompileTime only when Ambient.UserMode is set i.e. when not run in the IDE.
    Not possible. The compile run is executed in design mode only!
    Last edited by IO_X; Dec 21st, 2021 at 03:32 PM.

  16. #16
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by IO_X View Post
    I'll try. But how can it produce a different ouput, if in both cases Ambient.UserMode is False ???
    False and True = False
    False and False = False
    I summarized usage above in an edit.

    Yes, makes no sense to call IsCompileTime when not in user-mode because it's 100% certain there is no compilation happening when ide-mode is signaled.

    Compilation always happens in user-mode set.

    Try linked minimal repro project above too (if uncertain).

    Quote Originally Posted by IO_X View Post
    Not possible. The compile run is executed in design mode only!
    I'll be leaving this thread now. Good luck!

    cheers,
    </wqw>

  17. #17

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by wqweto View Post
    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.

    Quote Originally Posted by wqweto View Post
    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
    Last edited by IO_X; Dec 21st, 2021 at 04:12 PM.

  18. #18
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    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.

  19. #19

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by The trick View Post
    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.

    Quote Originally Posted by The trick View Post
    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.

  20. #20
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by IO_X View Post
    Yes. Completion is not necessary during compilation.
    Why only during compilation? After compilation you still can work as usual so the control will broken.

    Quote Originally Posted by IO_X View Post
    The only purpose of ReadProperties/WriteProperties during compilation is to get the selected property values and compile them to the exe file.
    ReadProperty is called after compilation. The runtime just terminate the form and re-create it with all the controls.

  21. #21
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,852

    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.

  22. #22
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,852

    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.

  23. #23
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by Elroy View Post
    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.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    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

  24. #24

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by The trick View Post
    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…

  25. #25
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    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.

    cheers,
    </wqw>

  26. #26
    PowerPoster
    Join Date
    Jan 2020
    Posts
    3,746

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by Elroy View Post
    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.

  27. #27

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by xiaoyao View Post
    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)?

  28. #28
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by IO_X View Post
    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.

  29. #29

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by The trick View Post
    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.

  30. #30
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,711

    Re: How to detect the environment's compile mode in a UserControl?

    @wqweto - I've removed the link because it contained a download of an executable, which is against forum rules.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  31. #31
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by dday9 View Post
    @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.

    It's complicated. Legacy problems. You did good.

    cheers,
    </wqw>

  32. #32
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,852

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by wqweto View Post
    @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.

  33. #33

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    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.

  34. #34

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by Elroy View Post
    ... distinguish between ReadProperties/WriteProperties during design vs during compiling.
    Exactly!

    Quote Originally Posted by Elroy View Post
    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.

  35. #35
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,852

    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.

  36. #36
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,995

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by wqweto View Post
    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.
    Attached Files Attached Files

  37. #37

    Thread Starter
    Junior Member
    Join Date
    Dec 2021
    Location
    Austria
    Posts
    22

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by Elroy View Post
    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.

  38. #38
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by Elroy View Post
    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).

    cheers,
    </wqw>

  39. #39
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    Re: How to detect the environment's compile mode in a UserControl?

    Quote Originally Posted by IO_X View Post
    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.

  40. #40
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,852

    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:
    Code:
    "C:\Program Files (x86)\Microsoft Visual Studio\VB98\VB6" /MAKE "C:\Users\Elroy\Desktop\New\Project1.vbp" /outdir "C:\Users\Elroy\Desktop\New"
    pause
    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.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width