dcsimg
Page 2 of 4 FirstFirst 1234 LastLast
Results 41 to 80 of 126

Thread: The 1001 questions about vbRichClient5 (2019-08-19)

  1. #41

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: The 1001 questions about vbRichClient5 (2019-02-19)

    Quote Originally Posted by lolovj View Post
    dreammanor could share the examples, post #34 and post #37 to study them and learn a little more about RC5. Thank you.
    The cwSpread is a control we use internally. It's not a stand-alone product. It has more than 20,000 lines of code (more than 30,000 lines in the future) and is a very complex heavyweight control.

    When Windows desktop-apps are getting less and less, developing a heavyweight controls like Spread is not a smart move. We had to develop a Spread control for some special reasons, because we needed to completely replace the FarPoint Spread control in all of our software.

    Olaf once said that nothing is a VirtualList with OwnerDraw-Events can not be achieved. In other words, The VList with OwnerDraw-Events is often a more concise and effective solution than a Spread control.

    If you need a stable and reliable open source Grid control that can be used in a production environment, then Krool's VBFlexGrid is a good choice.

    If you need a very powerful open source Grid control, then you should look at the source code of vhGrid.

    If you want to learn how to develop a themed Grid control, maybe you can look at the source code of LynxGrid, and the source code of vbAccelerator SGrid is also worth learning.

    If you have already checked the source code of the above grid controls, then you will find that it takes a lot of time and effort to develop a Spread control. (Our Spread control is much more complicated than all of the above Grid controls)

    Therefore, I suggest that you first try to develop a PropertyGrid control with RC5(vbWidgets) VList, and you will learn a lot of RC5 knowledge.
    Last edited by dreammanor; Feb 22nd, 2019 at 10:11 PM.

  2. #42

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: Qustion 010: Are there components similar to FontDialog and ColorDialog in RC5?

    Quote Originally Posted by DaveDavis View Post
    I just tested HMS's code, it is slow to response while scrolling. I hope your borrow Grid is not slow than that. BTW, when can you post your "Spread"?
    Our Spread is used to process millions of data, which means that even if my ProperGrid has a million property items, it can scroll smoothly and quickly.

    Quote Originally Posted by DaveDavis View Post
    BTW, when can you post your "Spread"?
    What kind of Spread control do you want? Free Spread, open-source Spread, or paid Spread?
    Last edited by dreammanor; Feb 22nd, 2019 at 08:29 PM.

  3. #43
    Addicted Member
    Join Date
    Aug 2016
    Posts
    174

    Re: The 1001 questions about vbRichClient5 (2019-02-19)

    If you have already checked the source code of the above grid controls, then you will find that it takes a lot of time and effort to develop a Spread control. (Our Spread control is much more complicated than all of the above Grid controls)
    I remembered you said you only took few weeks to develop 70% Spread Grid control. Why you said "a lot of time and effort" now?
    What kind of Spread control do you want? Free Spread, open-source Spread, or paid Spread?
    I remembered you promised you will post your 'spread grid' in few weeks, but after few month, we didn't see it at all.

    I remembered you mentioned on VBForums that you have borrowed codes from many people, why not contribute some codes to our VB6 community?

  4. #44

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: The 1001 questions about vbRichClient5 (2019-02-19)

    Quote Originally Posted by DaveDavis View Post
    I remembered you said you only took few weeks to develop 70% Spread Grid control. Why you said "a lot of time and effort" now?
    You always seem to misunderstand what others mean. I can develop 70% of Farpoint Spread in a few weeks and it doesn't mean you can do the same. I'm very familiar with Spread, and you might not.

    In addition, I've already said that I could develop Spread in a short time because I have accumulated a lot of Spread knowledge and code in the past (more than 16 years).

    Quote Originally Posted by DaveDavis View Post
    I remembered you promised you will post your 'spread grid' in few weeks, but after few month, we didn't see it at all.

    I remembered you mentioned on VBForums that you have borrowed codes from many people, why not contribute some codes to our VB6 community?
    I'll certainly contribute some very valuable code to the VB6 community in the future, but not now. Because I have a lot of important things to do now, the difficulty and workload of these things is almost 20 times that of Farpoint Spread. Only when I finish my main job, I have time to consider contributing some source code to the VB6 community.

    Our Spread control is used in some commercial software and cannot be open sourced due to corporate confidentiality restrictions.

    Edit:
    In addition, I think the problem the VB6 community faces is not to contribute source code (there is already too much source code here), but how to make the dying VB6 reborn.
    Last edited by dreammanor; Feb 22nd, 2019 at 10:19 PM.

  5. #45
    Hyperactive Member
    Join Date
    Jul 2013
    Posts
    372

    Re: The 1001 questions about vbRichClient5 (2019-02-03)

    @dreammanor, sorry to pull in to ask my own question to Olaf but it's somewhat related.

    @Olaf,

    I don't want to argue again about your vision of a global ImageList but I too would like to be able to create some kind of local one, even by using cCollection. The point is that I would like to create independent UCs and be able to assign keys "1", "2",... This would fatally generate collisions between UCs if using the global Imagelist.

    However, I can see that by using Cairo.Imagelist I have some advantages like the "automagically" detection of the image type. Implementing my own methods to distinguish between them would, at least, duplicate the necessary code. And certainly in a less efficient way.

    So, my questions are:
    How to solve potential collisions with image keys?
    What's the best approach to detect the image type without relying on file extension (if using cCollection)?

    Thanks
    Carlos

  6. #46

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: The 1001 questions about vbRichClient5 (2019-02-25)

    Hi Carlos, You are welcome, I've put your questions on the list of new questions on the post #1.

    For the local-ImageList, my suggestion is to use cCollection to simulate a local-ImageList based on the interface (properties and functions) of the global-ImageList, so there is no collisions with image keys.
    Last edited by dreammanor; Feb 26th, 2019 at 10:04 PM.

  7. #47
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: The 1001 questions about vbRichClient5 (2019-02-03)

    Quote Originally Posted by Carlos Rocha View Post
    I don't want to argue again about your vision of a global ImageList but I too would like to be able to create some kind of local one, even by using cCollection.
    The point is that I would like to create independent UCs and be able to assign keys "1", "2",...
    You can always use a local cCollection to hold cCairoSurface-References of course... as e.g. (under your own "local ImageKeys of choice"):
    MyImgCol.Add Cairo.ImageList.AddImage("", PathToImage1), "1"
    MyImgCol.Add Cairo.ImageList.AddImage("", PathToImage2), "2"

    Quote Originally Posted by Carlos Rocha View Post
    However, I can see that by using Cairo.Imagelist I have some advantages like the "automagically" detection of the image type. Implementing my own methods to distinguish between them would, at least, duplicate the necessary code. And certainly in a less efficient way.
    Sure, the Cairo.ImageList.Addxxx-Functions offer a bit more functionality, compared to "direct, ImageLoading via Cairo.CreateSurface"...
    The above 2 lines show already, how one can use the Cairo.ImageList as a "Surface-returning load-function" (via passing the ImageKey "" along)...
    All the Cairo.ImageList.Addxxx-functions will return the just loaded Surface as a function-result ...
    (and the always constant ""-empty ImageKey ensures, that ImageList-Contents do not "add up" in the global List)

    Quote Originally Posted by Carlos Rocha View Post
    So, my questions are:
    How to solve potential collisions with image keys?
    What's the best approach to detect the image type without relying on file extension (if using cCollection)?
    I hope the above was answering your questions, although I still do not understand the need for "local ImageLists" entirely...

    As for "context" (regarding "global ImageList vs. local ones"...

    In my own Apps, I often use e.g. a ToolBar-Widget "multiple times" (e.g. in up-popping modal Dialogs which show a toolbar-control as well) -
    and these toolbars and their different ToolBar-Buttons are fed (Icon-wise) from the global ImageList -
    which makes sense, since this way they can share the same "globally cached" Icon-ImageSurface,
    even if the multiple toolbars have different ToolBar-Buttons to show...
    - e.g. ToolbarMain could show Buttons with ImageKeys: "Close, Open, Copy, Cut, Paste, Save, Help"
    - and another ModalForm-ToolBar could e.g. just show Buttons: "Close, Save, Help"
    Both ToolBar-Control-instances (their Button-Images) are nevertheless fed via the same global ImageListKeys -
    though the Buttons sit at different "index-positions" within the ToolBar-instance in question of course...

    In my ToolBar-Button-Click-Event-Routines, I'm not identifying them over the Index-Position of these Buttons though,
    but instead use the ToobarButtonKey (which mostly is identical to the ImageKey-Name of the Buttons Icon) -
    so I don't need "position-dependent Keys" like "1" or "2" - in case that's the problem on your end...

    Perhaps describing in more detail, what you would do with "Control-local Images which have ImageKeys like "1", "2", etc. would clear things up for me.

    HTH

    Olaf

  8. #48
    Hyperactive Member
    Join Date
    Jul 2013
    Posts
    372

    Re: The 1001 questions about vbRichClient5 (2019-02-03)

    Quote Originally Posted by Schmidt View Post
    MyImgCol.Add Cairo.ImageList.AddImage("", PathToImage1), "1"
    MyImgCol.Add Cairo.ImageList.AddImage("", PathToImage2), "2"

    Sure, the Cairo.ImageList.Addxxx-Functions offer a bit more functionality, compared to "direct, ImageLoading via Cairo.CreateSurface"...
    The above 2 lines show already, how one can use the Cairo.ImageList as a "Surface-returning load-function" (via passing the ImageKey "" along)...
    All the Cairo.ImageList.Addxxx-functions will return the just loaded Surface as a function-result ...
    (and the always constant ""-empty ImageKey ensures, that ImageList-Contents do not "add up" in the global List)
    Perfect, thanks

    In my own Apps, I often use e.g. a ToolBar-Widget "multiple times"...
    I also use a global image list for menus and toolbar buttons with Codejock commandbars and it's handy for this matter when one knows what will be needed in the whole app.

    Perhaps describing in more detail, what you would do with "Control-local Images which have ImageKeys like "1", "2", etc. would clear things up for me.
    I would like to be able to add/remove UCs (mostly made with your widgets engine) to different programs without worries about unique keys in the global imagelist of each program, making these UCs as independent as possible, working in their own "black boxes" with no chance of braking anything.

    But your idea of empty keys in the imagelist seems to solve it and still keeping it's facilities. A perfect solution, as always.

    Thanks again
    Carlos

  9. #49

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Qustion 013: Store object to database fields: XML or JSON?

    Qustion 013: Store object to database fields: XML or JSON?

    I need to save the properties of some objects in a database field using XML or JSON. I'd like to know which one of XML or JSON would be better?

    I thought JSON would be cleaner and clearer than XML, but it doesn't seem to be the case, for example:

    XML
    Code:
    <Employees>
        <Person firstName='Brett' lastName='McLaughlin' age='23' />
        <Person firstName='Jason' lastName='Hunter' age='35' />
        <Person firstName='Elliotte' lastName='Harold' age='27' />
        <Person firstName='Frank' lastName='Peretti' age='28' />
    </Employees>
    JSON (Pretty JSON)
    Code:
    {
      "Employees": {
        "Person": [
          {
            "firstName": "Brett",
            "lastName": "McLaughlin",
            "age": "23"
          },
          {
            "firstName": "Jason",
            "lastName": "Hunter",
            "age": "35"
          },
          {
            "firstName": "Elliotte",
            "lastName": "Harold",
            "age": "27"
          },
          {
            "firstName": "Frank",
            "lastName": "Peretti",
            "age": "28"
          }
        ]
      }
    }
    JSON
    Code:
    {"Employees":{"Person":[{"firstName":"Brett","lastName":"McLaughlin","age":"23"},{"firstName":"Jason","lastName":"Hunter","age":"35"},{"firstName":"Elliotte","lastName":"Harold","age":"27"},{"firstName":"Frank","lastName":"Peretti","age":"28"}]}}
    That is to say, when storing "objects", JSON does not seem to be more concise than XML. However, if RC5 handles JSON more easily than XML, I would also like to use JSON. Is it more convenient for RC5 to handle JSON than XML?

  10. #50

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Qustion 014: What objects in RC5 can be used to process XML? Is it cElement?

    Qustion 014: What objects in RC5 can be used to process XML? Is it cElement?

    I need to save the properties of some objects in a database field using XML or JSON. I'd like to know if cElement is a tool for working with XML? What objects in RC5 can be used to process XML? Thanks.

  11. #51
    Frenzied Member
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    1,360

    Re: Qustion 013: Store object to database fields: XML or JSON?

    Quote Originally Posted by dreammanor View Post
    That is to say, when storing "objects", JSON does not seem to be more concise than XML. However, if RC5 handles JSON more easily than XML, I would also like to use JSON. Is it more convenient for RC5 to handle JSON than XML?
    I think JSON is the way to go - vbRichClient5 has JSON Array and Object support, and SQLite has a JSON extension (AFAIK it is enabled in RC5, but I haven't tried it out): https://www.sqlite.org/json1.html

  12. #52

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: Qustion 013: Store object to database fields: XML or JSON?

    Quote Originally Posted by jpbro View Post
    I think JSON is the way to go - vbRichClient5 has JSON Array and Object support, and SQLite has a JSON extension (AFAIK it is enabled in RC5, but I haven't tried it out): https://www.sqlite.org/json1.html
    Hi jpbro, what you said is very reasonable, I've decided to use JSON as my data storage format. Thank you very much.

  13. #53

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Qustion 015: Is cWidgetBase suitable as a UI element model for web-pages ?

    Qustion 015: Is cWidgetBase suitable as a UI element model for web-pages ?

    I want to build a generic UI component (element) model for web-pages, mobile-apps and win-apps. I wonder if cWidgetBase is suitable as a UI element model for web-pages? Thanks.

  14. #54

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: Qustion 015: Is cWidgetBase suitable as a UI element model for web-pages ?

    Quote Originally Posted by dreammanor View Post
    Qustion 015: Is cWidgetBase suitable as a UI element model for web-pages ?

    I want to build a generic UI component (element) model for web-pages, mobile-apps and win-apps. I wonder if cWidgetBase is suitable as a UI element model for web-pages? Thanks.
    It seems that HTML5 elements are the best choice.

  15. #55

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: The 1001 questions about vbRichClient5 (2019-01-29)

    Quote Originally Posted by dreammanor View Post

    Quote Originally Posted by Schmidt View Post
    And a Win10-compatible Theme can be implemented without using the WinAPI as well (directly in a cThemeWin10.cls) -
    see, the Win7-compatible Themes were implemented completely with Cairo-Drawing -
    and compared to the Win7-Themes both: the (flat) Win10-Scrollbars - as well as the (flat) Win10-ButtonFaces are quite simple
    (it's basically only flat Rectangle-Filling and Rectangle-Stroking with the right Colors and LineWidths, depending on the different ButtonStates.
    Using a cThemeWin10.cls is indeed the best solution and I've made some progress. Thank you, Olaf
    Finally, I used DrawThemeBackground and CreateWin32Surface instead of cThemeWin10.cls. Because I found that if I want to make vbWidgets have Win10 Theme, I not only have to develop cThemeWin10.cls, but also modify many other cw*.cls.

    I only implemented the Win10 theme for cwButton in the cThemeWin10.cls, and the rest of the development work needs to wait until there is free time in the future. I'll post the source code later.
    Last edited by dreammanor; Mar 2nd, 2019 at 08:25 PM.

  16. #56

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: The 1001 questions about vbRichClient5 (2019-03-01)

    The cThemeWin10.cls in the attached example only implements the Win10 theme for cwButton. Others could continue to complete the Win10 theme for CheckBox, OptionButton and ScrollBar if they are interested.

    Note:
    In the cThemeWin10.cls, the colors of Win10 theme are what I grabbed from my computer screen, maybe they are very slightly different from Microsoft's standard theme colors.
    Attached Images Attached Images  
    Attached Files Attached Files
    Last edited by dreammanor; Mar 3rd, 2019 at 08:09 PM.

  17. #57

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Qustion 016: How to quickly release a large number of objects in a collection?

    Qustion 016: How to quickly release a large number of objects in a collection?

    I need a lightweight grid control instead of my heavyweight Spreads in one of my projects. This lightweight grid control is mainly used to replace ListBox and ListView.

    In this lightweight GridView control, I use collections and objects(classes) instead of arrays and types to store data. But now I have a problem, that is, it takes a long time to release a large number of objects(classes) in the collection. I tested the VB collection and the RC5 collection, and the results were the same.

    I'd like to know if there is a way to quickly release a large number of objects(classes) in the collection? Thanks!
    Attached Images Attached Images  
    Attached Files Attached Files

  18. #58
    Frenzied Member
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    1,360

    Re: Qustion 016: How to quickly release a large number of objects in a collection?

    Quote Originally Posted by dreammanor View Post
    Qustion 016: How to quickly release a large number of objects in a collection?
    ...I'd like to know if there is a way to quickly release a large number of objects(classes) in the collection? Thanks!
    It's an known "issue" with VB6 objects that they are slow to destroy in large numbers. Check out this thread by Olaf on lightweight COM objects that are much faster, but will take a fair bit more work to write:

    http://www.vbforums.com/showthread.p...BaseInterfaces

  19. #59

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: Qustion 016: How to quickly release a large number of objects in a collection?

    Quote Originally Posted by jpbro View Post
    It's an known "issue" with VB6 objects that they are slow to destroy in large numbers. Check out this thread by Olaf on lightweight COM objects that are much faster, but will take a fair bit more work to write:

    http://www.vbforums.com/showthread.p...BaseInterfaces
    Hi jpbro, thank you for your reminder. Just now Arnoutdv also told me the same link. I downloaded that thread last year, but I forgot it. Now I'm testing it. Thank you, jpbro.

  20. #60

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: The 1001 questions about vbRichClient5 (2019-03-26)

    I studied Olaf's LightCOM and vbFriendly-BaseInterfaces, which is really great. But vbFriendly-BaseInterfaces complicates the code and reduces the readability of the code. After careful consideration, I decided to abandon the use of collections and classes and reuse arrays and types.

  21. #61
    New Member
    Join Date
    May 2018
    Posts
    11

    Re: The 1001 questions about vbRichClient5 (2019-03-26)

    I have a question about how to convert vbrichclient5.cRecordset into ADODB.Recordset in RC5. Because all the output of my perfect partial function is ADODB.Recordset, I need RC5 to process DB data without changing the original program structure. Otherwise, it will be too heavy. Thank you for your help.

  22. #62
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: The 1001 questions about vbRichClient5 (2019-03-26)

    Quote Originally Posted by yinxiaodan View Post
    I have a question about how to convert vbrichclient5.cRecordset into ADODB.Recordset in RC5. Because all the output of my perfect partial function is ADODB.Recordset, I need RC5 to process DB data without changing the original program structure. Otherwise, it will be too heavy.
    What's your goal in the end?
    For the moment, I assume you just want to switch from a JET-mdb to an SQLite-db?

    Well, there is a built-in method on a cRecordset, which will produce a copy of its content in an ADO-Rs:
    Set RsADO = cRecordset.GetADORsFromContent

    Though, what's now contained in RsADO is a disconnected (free standing) ADO-Rs, which has no underlying Connection to any DB.

    In a well-designed, larger DB-App (which took "scaleability" into account from the beginning),
    one usually does not mind about such "true disconnected ADO-Rs" with no underlying connection
    (because these are the norm, when the Rs could come also from a Web- or other Application-Server).

    So, when you now hand out such freestanding, connectionless ADO-Rs to your Application (from your "partial function", which I guess is not related to the math-term),
    you will have to check, what methods of the ADO-Rs you are using later on, "down in the depths of your App-Code".

    Because with connectionless Rs - all the Methods for the "write-direction" (AdoRs.Update/UpdateBatch - just make a scan for them in your App via Find-Dialogue)
    would have to be replaced by appropriate alternatives in a *.bas Module - for example: UpdateBatch(Rs As Ado.Recordset)

    Olaf

  23. #63
    New Member
    Join Date
    May 2018
    Posts
    11

    Re: The 1001 questions about vbRichClient5 (2019-03-26)

    Because we need to use translation tools, so the expression is not clear, the actual function I want is GetADORs FromContent, has been tested successfully, thank you very much. In order to achieve this function, I have written a silly conversion code, as follows:
    Code:
    Public Function ConvertRC5Rst_TO_ADORst(tCRst_RC5 As vbrichclient5.cRecordset) As ADODB.Recordset
    
        Dim i As Long, tRst As New ADODB.Recordset
    
        If ObjPtr(tCRst_RC5) > 0 Then
            
            If tCRst_RC5.Fields.Count = 0 Then Set ConvertRC5Rst_TO_ADORst = Nothing: Exit Function
    
            'tCRst_RC5.Fields(0).n
            For i = 0 To tCRst_RC5.Fields.Count - 1
                tRst.Fields.Append tCRst_RC5.Fields(i).OriginalColumnName, adVariant '    ', tCRst_RC5.Fields(I).OriginalTableName      '添加记录字段和属性
            Next
            tRst.Open    '打开记录集
    
            Do Until tCRst_RC5.EOF
                tRst.AddNew
    
                For i = 0 To tCRst_RC5.Fields.Count - 1
                    
                    tRst.Fields(i).VALUE = tCRst_RC5.Fields(i).VALUE
                    
                Next i
    
                tCRst_RC5.MoveNext
            Loop
            
            Set ConvertRC5Rst_TO_ADORst = tRst
            '        tRst.Close
        Else
        
            Set ConvertRC5Rst_TO_ADORst = Nothing
    
        End If
    
    End Function
    Last edited by Shaggy Hiker; Mar 31st, 2019 at 12:01 PM. Reason: Added CODE tags.

  24. #64

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: The 1001 questions about vbRichClient5 (2019-03-26)

    Hi yinxiaodan, welcome to ask questions in this thread. In most cases, it's very convenient to convert RC5 Sqlite Recordset to AdoDB.RecordSet using "Set adoRs = rc5Rs.GetADORsFromContent".

    However, in some special cases, you still need to manually write code to achieve conversion between different databases, such as converting some SQL Server DBs with a large amount of data into SqliteDBs. In this case, you may need a process bar, or you may need to perform some special conversion functions. So your code is still useful in some special cases.

  25. #65

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Qustion 018: Efficient stack operations (Push and Pop)?

    When I perform code parsing, I need to simulate stack operations (Push and Pop) frequently. I tried the following method:

    Code:
    Private m_CurToken As cToken
    
    Private m_ArrayList As cArrayList
    
    Private Sub Init()
        Set m_ArrayList = New_c.ArrayList(vbDataObject)
    End Sub
    
    Private Sub StackPush()
        m_ArrayList.Push m_CurToken
    End Sub
    
    Private Sub StackPop()
        Set m_CurToken = m_ArrayList.Pop()
    End Sub
    
    Public Sub Test()
        Dim i As Long, k As Long
        
        Set m_CurToken = New cToken
        
        m_CurToken.Name = "ABCDEFHIJKLMN"
        m_CurToken.Priority = 1
        m_CurToken.TokenType = 3
        
        New_c.Timing True
        
        For i = 1 To 3000000
            StackPush
            
            If m_ArrayList.Count > 10000 Then
                For k = 10000 To 1 Step -1
                    StackPop
                Next k
            End If
            
        Next
        
        MsgBox New_c.Timing
        
    End Sub
    But "Set m_CurToken = m_ArrayList.Pop" seems to be invalid.

  26. #66
    Frenzied Member
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    1,360

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    I tried your code and it seems to work for me (at least when I change the ArrayList variable type to vbObject instead of vbDataObject, which I had to do because I don't have a vbDataObject class type hanging around). What error are you getting?

  27. #67

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    Quote Originally Posted by jpbro View Post
    I tried your code and it seems to work for me (at least when I change the ArrayList variable type to vbObject instead of vbDataObject, which I had to do because I don't have a vbDataObject class type hanging around). What error are you getting?
    Yes, after changing vbDataObject to vbObject, the code is OK. I'll write a test program to compare the efficiency of RC5.ArrayList, RC5.Collection, VB.Collection, VB.Array in performing Push and Pop operations. Thank you very much, jpbro.

  28. #68

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    Hi jpbro, I posted the test results in the following links:
    http://www.vbforums.com/showthread.p...(Push-and-Pop)

    Oddly, in the VB6 IDE (in design mode) RC5.ArrayList and RC5.Collection have better performance than VB.Collection. But in EXE (in binary mode), the result is the opposite.
    Attached Files Attached Files

  29. #69
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    Quote Originally Posted by dreammanor View Post
    Oddly, in the VB6 IDE (in design mode) RC5.ArrayList and RC5.Collection have better performance than VB.Collection. But in EXE (in binary mode), the result is the opposite.
    There's several things wrong in your benchmark-code.
    (what concretly, I've described in the thread you linked to).

    Olaf

  30. #70

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    Quote Originally Posted by Schmidt View Post
    There's several things wrong in your benchmark-code.
    (what concretly, I've described in the thread you linked to).

    Olaf
    Yes, there are a few very low-level naive errors in my test program, I'll upload a new test program. Thank you for pointing out the errors.

    In additon, I'm having some problems with ArrayList when dealing with variant item:

    Code:
    Private Sub Command1_Click()
        Dim oArrayList As cArrayList
        
        Set oArrayList = New_c.ArrayList(vbVariant)
        
        oArrayList.Init vbVariant
        
        Dim arr1() As String
        ReDim arr1(10) As String
        oArrayList.Push arr1
        
        Dim oToken As cToken
        Set oToken = New cToken
        oToken.Name = "ABCDEFG"
        oArrayList.Push oToken
        
        Dim oItem As cItem
        Set oItem = New cItem
        oItem.Name = "Hello, world !"
        oArrayList.Push oItem
        
        Set oItem = oArrayList.Pop
        Set oToken = oArrayList.Pop
        arr1 = oArrayList.Pop
        
    End Sub
    When the program runs to "Set oItem = oArrayList.Pop", the system prompts "Object does not support this property or method" (error: 438)
    Last edited by dreammanor; May 11th, 2019 at 11:53 PM.

  31. #71
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    Quote Originally Posted by dreammanor View Post
    ... I'm having some problems with ArrayList when dealing with variant item:

    Code:
    Private Sub Command1_Click()
        Dim oArrayList As cArrayList
        Set oArrayList = New_c.ArrayList(vbVariant)
    
        Dim arr1() As String
        ReDim arr1(10) As String
        oArrayList.Push arr1
        
        Dim oToken As cToken
        Set oToken = New cToken
        oToken.Name = "ABCDEFG"
        oArrayList.Push oToken
        
        Dim oItem As cItem
        Set oItem = New cItem
        oItem.Name = "Hello, world !"
        oArrayList.Push oItem
        
        Set oItem = oArrayList.Pop
        Set oToken = oArrayList.Pop
        arr1 = oArrayList.Pop
    End Sub
    When the program runs to "Set oItem = oArrayList.Pop", the system prompts "Object does not support this property or method" (error: 438)
    Just uploaded a new version, where this is fixed now (together with a few other small things)...
    SQLite (vb_cairo_sqlite.dll) was upgraded from 3.24 to 3.28 at this occasion as well.

    Did not stumble over that in cArrayList so far, because I rarely use it in "Variant-Mode"
    (where each added Item will then take up at least 16Bytes).

    For Object-Items - I'm using cArrayList in vbObject-Mode (where each added Item-Ref takes up only the 4Bytes for the ObjPtr).
    That's one of the reasons, to choose cArrayList over a cCollection or a cSortedDictionary (where Items are always stored as Variant) -
    it can be forced to a certain type - and will then usually take up less memory (compared to Collection-usage in the same scenario).

    Olaf

  32. #72

    Thread Starter
    Frenzied Member
    Join Date
    Sep 2012
    Posts
    1,608

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    Quote Originally Posted by Schmidt View Post
    Just uploaded a new version, where this is fixed now (together with a few other small things)...
    SQLite (vb_cairo_sqlite.dll) was upgraded from 3.24 to 3.28 at this occasion as well.

    Did not stumble over that in cArrayList so far, because I rarely use it in "Variant-Mode"
    (where each added Item will then take up at least 16Bytes).

    For Object-Items - I'm using cArrayList in vbObject-Mode (where each added Item-Ref takes up only the 4Bytes for the ObjPtr).
    That's one of the reasons, to choose cArrayList over a cCollection or a cSortedDictionary (where Items are always stored as Variant) -
    it can be forced to a certain type - and will then usually take up less memory (compared to Collection-usage in the same scenario).

    Olaf
    After using the new version of RC5, now the ArrayList can pop variant-items normally. Thank you very much, Olaf.

    The reason I wrote some of the above weird code is because I'm translating some JavaScript code into VB6 code. JS is too flexible, it's cumbersome to translate it into VB6.

  33. #73
    New Member
    Join Date
    May 2018
    Posts
    11

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    hi,Schmidt and dreammanor and other:
    For multithreading, the ThreadHandler in RC5c that I use is great overall, but there are still the following problems. For example, thread Dll debugging is difficult, and sometimes it crashes for no reason to find out exactly where it is.And during the run, I found that memory was gradually increasing.

    In addition, how to actively uninstall loaded threads? (th = regfree. ThreadObjectCreate (cThreadKey, ThreadLibPath, cThreadClass)) is set directly to set th = nothing?

    TH. JobQueueCount ‘represents the task currently executed (including the number of functions or processes being executed?)
    TH. CancelExecution ‘Is to cancel the task being performed? If multiple tasks are cancelled altogether?

    TH. TimeoutSecondsToHardTerminate 'What does this do?
    thank you

  34. #74
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    Quote Originally Posted by yinxiaodan View Post
    For multithreading, the ThreadHandler in RC5c that I use is great overall, but there are still the following problems. For example, thread Dll debugging is difficult, and sometimes it crashes for no reason to find out exactly where it is.And during the run, I found that memory was gradually increasing.

    In addition, how to actively uninstall loaded threads? (th = regfree. ThreadObjectCreate (cThreadKey, ThreadLibPath, cThreadClass)) is set directly to set th = nothing?

    TH. JobQueueCount ‘represents the task currently executed (including the number of functions or processes being executed?)
    TH. CancelExecution ‘Is to cancel the task being performed? If multiple tasks are cancelled altogether?

    TH. TimeoutSecondsToHardTerminate 'What does this do?
    An RC5.cThreadHandler instance is only a "RemoteObject for your real ThreadClass-instance", so the ThreadHandler runs in your normal Main-Thread.

    The "Remoted-Thread-STA" (with your regfree created Thread-Class-instance in it), will terminate when you set the clientside ThreadHandler to Nothing.

    The TH.TimeoutSecondsToHardTerminate setting is the time in seconds, which the ThreadHandler waits
    (in its own Class-Terminate-Event) - before it will terminate the "remoted Thread-STA the hard way" (via the TerminateThread-API).

    So, your own thread-class-implementation has to play-along nicely (in case it sits in a longrunning-job which takes several seconds) -
    to allow for "early exiting" in such longer running loops, so that the outer cThreadHandler-instance can terminate this thread gracefully -
    not resorting to the "hard terminate" it will do otherwise (after a few adjustable seconds).

    That "graceful-early-exit-handling" (if not done properly) is the main-reason for potential crashes
    (because a hard terminated STA will introduce instabilities into the whole App - and can be done only a few times in my experience - so it needs to be avoided).
    The ThreadHandler can signalize such an early-exit-request via TH.CancelExecution (which will cancel the current - but also clear the JobQueue of still waiting Jobs)

    As for debugging - only "well-behaving and well-tested Classes" (e.g. in isolated Test-Projects which use the Class in question unthreaded),
    should be moved into their own "Threading-Dlls" (at a later point).

    As for TH.JobQueueCount...
    Multiple async Jobs can be triggered "in advance" (for the Thread-internal-ClassInstance to process them from its Queue).

    Here is a small example, which is specifying an internal RC5-Class as the "ThreadObject which runs on the STA" -
    and which demonstrates, what the JobQueueCount means (please paste directly into an empty Form):
    Code:
    Option Explicit
    
    Private WithEvents TH As cThreadHandler, CC As Long
    
    Private Sub Form_Load()
      'one can use RC5-internal Objects on their own thread,
      'by specifying "New_c" as the Dll-FileName and the Classname without the 'c'-Prefix
      '(instead of New_c.Collection we just pass the two parts around the '.' in their own String-Argument)
      Set TH = New_c.RegFree.ThreadObjectCreate("Col", "New_c", "Collection")
    End Sub
    
    Private Sub Form_Click()
      TH.CallAsync "Add", 1, "Key1"
      TH.CallAsync "Add", 2, "Key2"
      TH.CallAsync "Add", 3, "Key3"
     
      Debug.Print "3 async Add-Method-Calls were triggered, JobQueueCount=" & TH.JobQueueCount
    End Sub
    
    Private Sub TH_MethodFinished(MethodName As String, Result As Variant, ErrString As String, ErrSource As String, ByVal ErrNumber As Long)
      CC = CC + 1: Debug.Print MethodName, CC, TH.JobQueueCount, ErrString
      
      If TH.JobQueueCount = 0 Then
        Debug.Print "The Async Job-sequence is finished"
        Debug.Print "Col.Count:"; TH.CallSynchronous("Count")
        Debug.Print "Value behind Key3:"; TH.CallSynchronous("Item", "Key3")
        CC = 0
    '    TH.CallSynchronous "RemoveAll" 'comment this in, to avoid the Error-Reports whilst clicking the Form multiple times
      End If
    End Sub
    HTH

    Olaf
    Last edited by Schmidt; May 18th, 2019 at 08:48 AM.

  35. #75
    Frenzied Member
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    1,360

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    Olaf will can add more details/correct me on any errors, but here's my understanding of your questions:

    Quote Originally Posted by yinxiaodan View Post
    In addition, how to actively uninstall loaded threads? (th = regfree. ThreadObjectCreate (cThreadKey, ThreadLibPath, cThreadClass)) is set directly to set th = nothing?
    In my code I'm waiting for an empty job queue before setting the thread object to Nothing. Not sure if this is necessary though. Something like this:

    Code:
       Private Sub Class_Terminate()
          With mo_MyThread
              .WaitForEmptyJobQueue
              .CancelExecution
              .WaitForEmptyJobQueue
          End With
          Set mo_MyThread = Nothing
       End Sub
    Quote Originally Posted by yinxiaodan View Post
    TH. JobQueueCount ‘represents the task currently executed (including the number of functions or processes being executed?)
    This is the number of async jobs that are queued up for running on the thread. Everytime you call the CallAsync method, the job is either passed to the thread (if no jobs are running), or added to the end of the FIFO queue (if a job is already running).


    Quote Originally Posted by yinxiaodan View Post
    TH. CancelExecution ‘Is to cancel the task being performed? If multiple tasks are cancelled altogether?
    This will disconnect/reconnect the thread and remove any jobs from the queue so no new job processing will occur. I think if a job is currently running it will finish, but you won't get any events/results from it since the class gets disconnected from the thread pipe. Not sure about this though, Olaf will have to clarify.


    Quote Originally Posted by yinxiaodan View Post
    TH. TimeoutSecondsToHardTerminate 'What does this do?
    This is the number of seconds that must elapse before the thread handler considers the thread "lost" and will then force it to terminate...This is only relevant when the cThreadHandler class is terminating (e.g. when setting the last reference to it to Nothing). I don't think you will need this unless there's a bug in your threaded code that causes it to lock up (infinite loop for example).

    Hope that helps!

  36. #76
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    Quote Originally Posted by jpbro View Post
    In my code I'm waiting for an empty job queue before setting the thread object to Nothing. Not sure if this is necessary though. Something like this:

    Code:
       Private Sub Class_Terminate()
          With mo_MyThread
              .WaitForEmptyJobQueue
              .CancelExecution
              .WaitForEmptyJobQueue
          End With
          Set mo_MyThread = Nothing
       End Sub
    Yes, one can of course also wait "manually" (instead of relying on the stuff the ThreadHandler will do in its own Class_Terminate regarding the remote-thread).
    A thread can be terminated gracefully, when it currently "idles" (having a JobQueueCount of Zero, which is what the WairForEmptyJobKey-Function checks for).

    I'd make just a slight change in the above routine, since WaitForEmptyJobQueue will return immediately, when the JobQueueCount is zero, which CancelExecution will ensure
    (so the second call to .WaitForEmptyJobQueue is not really needed).

    Code:
       Private Sub Class_Terminate()
          'wait for max. 3secs, until the JobQueue is cleared the hard way via .CancelExecution
           'in case it returns within the 3secs with True - then the JobQueueCount reached zero - and the Thread is idling (needs no Cancelling)
          If Not mo_MyThread.WaitForEmptyJobQueue(3) Then mo_MyThread.CancelExecution
     
          Set mo_MyThread = Nothing
       End Sub
    Quote Originally Posted by jpbro View Post
    [CancelExecution]
    This will disconnect/reconnect the thread and remove any jobs from the queue so no new job processing will occur. I think if a job is currently running it will finish, but you won't get any events/results from it since the class gets disconnected from the thread pipe. Not sure about this though, Olaf will have to clarify.
    CancelExecution does what you describe above - and it is also correct,
    that a currently running job (the methodcall the ThreadClass-instance is currently processing) will have to "run to its end" -
    and then will not cause a MethodFinished-Event - because the Pipe-instance was renewed by the CancelExecution-call.
    Unless...:
    Such an outside cancelling is detectable from within any ThreadClass-instance-method (e.g. in case of a very longrunning loop) -
    by cyclically checking via the following mechanism (which one has to implement in the ThreadClass "by convention" as shown below):
    Code:
    'define an Event in the declaration-section of your ThreadClass
    Event CancelCheck(ByRef Cancelled As Boolean)
    
    'one can accompany that Event with a Private Function somewhere in the ThreadClass for more convenient usage
    '(which includes a mechanism, to not stress the underlying, hidden cThreadProxy-instance with too many Event-Requests per second)
    Private Function CancelRequestFromOutside() As Boolean
      Static LastT#, CurT#: CurT = New_c.HPTimer
      If CurT - LastT > 0.1 Then LastT = CurT: RaiseEvent CancelCheck(CancelRequestFromOutside) 'we only need to perform this any 0.1sec or so
    End Function
    
    'With the above two additions to the Class, one can now  perform a check for "gracefull, early exit" in longrunning Public methods:
    Public Sub SomeLongRunningMethod(P1, P2, ..., Pn)
       Do
          'some partial action within the long-running loop
          If CancelRequestFromOutside Then Exit Sub 'leave early, since we were required to do so from outside the thread
       Loop Until SomeNormalCondition
    End Sub
    HTH

    Olaf
    Last edited by Schmidt; May 18th, 2019 at 10:03 AM.

  37. #77
    New Member
    Join Date
    May 2018
    Posts
    11

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    Dear Schmidt and jpbro, thank you for your kind help and patient and meticulous answers. According to your method, I modified the code. After a day of testing, it really solved the problem of innocent memory increase and crash. Thank you again! This solves the big problem I've been plagued with. RC5, Great Creation.

  38. #78
    New Member
    Join Date
    May 2018
    Posts
    11

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    HI, Schmidt and jpbro,

    If Not TH. WaitForEmpty JobQueue (15) = True Then'over 15S automatically clears all

    TH. Cancel Execution

    Else

    End If

    If the thread executes for a long time, is the main program hung up and waited for 15S to execute again? If so, it is equivalent to blocking mode, which will affect the mouse click interface response. I used to use the following methods, there is no difference between the two methods, thank you.



    Dim tAddTickCount As Long, tTickCount As Long

    TAddTickCount = 15

    TTickCount = New_c.HPTimer



    Do

    New_c.SleepEx 10

    DoEvents

    If TH.WaitForEmpty JobQueue = True Then Exit Do

    If New_c.HPTimer - tTickCount > tAddTickCount Then

    TH. Cancel Execution

    Endif

    End If

    Loop Until TH.JobQueueCount < 1

  39. #79
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,376

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    Since we are at the threading-topic ...
    My little example in post #74 was showing, how to use an instance of a built-in RC5-Class on its own thread
    ( a cCollection, to show async method queueing )

    I've so far not used that feature for something serious (because of missing flexibility with just a single Object-Instance on a thread) -
    but thinking about it, a cActiveScript-instance on its own thread could offer that needed flexibility (avoiding the compilation of ones own thread-dll).

    So, below comes a first example which tries to use cActiveScript on its own thread -
    the passed and added ScriptCode currently written, to perform an async, threaded FileScan,
    to find "all image-files within a given Start-Directory recursively".

    I'd like some feedback from you, whether that works well also on your machines and systems...

    First a little "Project-Private" Helper-Class, which hides aways some of the Initializing- and -Cleanup-stuff with the ThreadHandler -
    so that the Form-Code remains relatively "lean and clean"...

    Into a Private Helper-Class, named cScriptThread:
    Code:
    Option Explicit
    
    Event ThreadStateChanged(ByVal NewState As String)
    Event MethodFinished(MethodName As String, Result As Variant, ErrString As String, ErrSource As String, ByVal ErrNumber As Long)
    
    Private WithEvents TH As cThreadHandler, WithEvents tmrState As cTimer
    Private ThreadState32K As String, CancelFlag As Variant
     
    Private Sub Class_Initialize()
      Set TH = New_c.RegFree.ThreadObjectCreate("T" & ObjPtr(Me) & App.hInstance, "New_c", "ActiveScript")
      
      ThreadState32K = String$(32768 + 1, vbNullChar)
      
      With New_c.ArrayList(vbString) 'ensure a few helper-routines on the threaded Script-instance
          .Add "Dim pState32K: pState32K=" & StrPtr(ThreadState32K)
          .Add "Dim pCancelFlag: pCancelFlag=" & VarPtr(CancelFlag)
          
          .Add "Sub SetNewState(S)" 'to be used from within the thread, e.g. for Progress-Notifications
          .Add "  S = Left(S, 32768)"
          .Add "  If pState32K Then New_c.MemCopy pState32K, StrPtr(S), LenB(S) + 2"
          .Add "End Sub"
          
          .Add "Function Cancelled()" 'to detect cancelling from outside (from our Main-Thread)
          .Add "  New_c.MemCopy VarPtr(Cancelled), pCancelFlag, 16"
          .Add "End Function"
          
          .Add "Sub Cleanup()" 'needed and called shortly before Thread-Termination
          .Add "  On Error Resume Next"
          .Add "    New_c.CleanupRichClientDll"
          .Add "  If Err Then Err.Clear"
          .Add "End Sub"
    
          AddCode .Join(vbCrLf) 'add a few default-Vars and -Routines which are needed for communication
      End With
      
      Set tmrState = New_c.Timer(100, True)
    End Sub
    
    Public Sub CancelExecution()
      CancelFlag = True
    End Sub
    
    Public Sub AddCode(Code As String, Optional ByVal ReplaceSingleQuotes As Boolean = True)
      If TH.JobQueueCount Then Err.Raise vbObjectError, , "The thread is not in Idle-Mode, try again later"
      If ReplaceSingleQuotes Then TH.CallSynchronous "AddCode", Replace(Code, "'", """") Else TH.CallSynchronous "AddCode", Code
    End Sub
    
    Public Function RunAsync(ProcedureName As String, ParamArray P())
      CancelFlag = Empty
      Select Case UBound(P)
        Case -1: TH.CallAsync "Run", ProcedureName
        Case 0:  TH.CallAsync "Run", ProcedureName, P(0)
        Case 1:  TH.CallAsync "Run", ProcedureName, P(0), P(1)
        Case 2:  TH.CallAsync "Run", ProcedureName, P(0), P(1), P(2)
        Case 3:  TH.CallAsync "Run", ProcedureName, P(0), P(1), P(2), P(3)
        Case 4:  TH.CallAsync "Run", ProcedureName, P(0), P(1), P(2), P(3), P(4)
        Case 5:  TH.CallAsync "Run", ProcedureName, P(0), P(1), P(2), P(3), P(4), P(5)
      End Select
    End Function
    
    Public Function RunSynchronous(ProcedureName As String, ParamArray P())
      If TH.JobQueueCount Then Err.Raise vbObjectError, , "The thread is not in Idle-Mode, try again later"
      CancelFlag = Empty
      Select Case UBound(P)
        Case -1: RunSynchronous = TH.CallSynchronous("Run", ProcedureName)
        Case 0:  RunSynchronous = TH.CallSynchronous("Run", ProcedureName, P(0))
        Case 1:  RunSynchronous = TH.CallSynchronous("Run", ProcedureName, P(0), P(1))
        Case 2:  RunSynchronous = TH.CallSynchronous("Run", ProcedureName, P(0), P(1), P(2))
        Case 3:  RunSynchronous = TH.CallSynchronous("Run", ProcedureName, P(0), P(1), P(2), P(3))
        Case 4:  RunSynchronous = TH.CallSynchronous("Run", ProcedureName, P(0), P(1), P(2), P(3), P(4))
        Case 5:  RunSynchronous = TH.CallSynchronous("Run", ProcedureName, P(0), P(1), P(2), P(3), P(4), P(5))
      End Select
    End Function
    
    Private Sub TH_MethodFinished(MethodName As String, Result As Variant, ErrString As String, ErrSource As String, ByVal ErrNumber As Long)
      RaiseEvent MethodFinished(MethodName, Result, ErrString, ErrSource, ErrNumber)
    End Sub
    
    Private Sub tmrState_Timer()
      Static LastS As String, CurS As String
      CurS = Left$(ThreadState32K, InStr(ThreadState32K, vbNullChar) - 1)
      If LastS <> CurS Then LastS = CurS: RaiseEvent ThreadStateChanged(CurS)
    End Sub
     
    Private Sub Class_Terminate()
      On Error Resume Next
        Set tmrState = Nothing
        CancelFlag = True
        If Not TH.WaitForEmptyJobQueue(10) Then TH.CancelExecution
        TH.CallSynchronous "Run", "Cleanup"
        Set TH = Nothing
      On Error GoTo 0
    End Sub
    And this into a normal Std-Exe-Project-Form for testing (please adjust the Scan-Path if needed in Form_Click, which is currently "c:\temp"):
    Code:
    Option Explicit
    
    Private WithEvents ST As cScriptThread
    
    Private Sub Form_Load()
      Caption = "Click Me to scan C:\Temp\... for Image-Files"
      
      Dim L As cArrayList
      Set L = New_c.ArrayList(vbString)
     
          L.Add "Function FindFilesRecursiveIn(DirPath, Filter)"
          L.Add "   Dim Col: Set Col = New_c.Collection(False)"
          L.Add "   DirScanRecursive DirPath, Col, Filter"
          L.Add "   SetNewState vbNullString"
          L.Add "   FindFilesRecursiveIn = Array(Col.Content, DirPath, Filter)"
          L.Add "End Function"
     
          L.Add "Private Sub DirScanRecursive(DirPath, ResultCol, Filter)"
          L.Add "  If Cancelled Then Exit Sub" '<- ensure an early exit in case of an outside cancel-request
          L.Add "  On Error Resume Next"
          L.Add "    Dim i, DL: Set DL = New_c.FSO.GetDirList(CStr(DirPath), , CStr(Filter))"
          L.Add "  If Err Then Err.Clear: Exit Sub"
          L.Add ""
          L.Add "  For i = 0 To DL.FilesCount - 1"
          L.Add "    ResultCol.Add DL.Path & DL.FileName(i)"
          L.Add "  Next"
          L.Add "  SetNewState 'Files found so far: ' & ResultCol.Count"
          L.Add "  For i = 0 To DL.SubDirsCount - 1"
          L.Add "    DirScanRecursive DL.Path & DL.SubDirName(i), ResultCol, Filter"
          L.Add "  Next"
          L.Add "End Sub"
     
      Set ST = New cScriptThread
          ST.AddCode L.Join(vbCrLf)
    End Sub
     
    Private Sub Form_Click() 'check for image-files recursively from a given start-directory
      ST.RunAsync "FindFilesRecursiveIn", "C:\temp", "*.svg; *.png; *.jpg"
    End Sub
    
    Private Sub ST_MethodFinished(MethodName As String, Result As Variant, ErrString As String, ErrSource As String, ByVal ErrNumber As Long)
      If ErrNumber Then Debug.Print ErrString: Exit Sub
      Dim Col As cCollection
      Set Col = New_c.Collection(, , , Result(0))
      Debug.Print "Async recursive DirScan finished on "; Result(1); " ("; Col.Count; Result(2); " Files )"
    End Sub
    
    Private Sub ST_ThreadStateChanged(ByVal NewState As String)
      Caption = IIf(Len(NewState), NewState, "Async DirScan finished")
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
      Set ST = Nothing 'terminate the ScriptThread
    End Sub
    HTH

    Olaf
    Last edited by Schmidt; May 20th, 2019 at 04:49 PM. Reason: updated Class_Terminate() in cScriptThread

  40. #80
    Frenzied Member
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    1,360

    Re: The 1001 questions about vbRichClient5 (2019-05-09)

    Olaf - thank you very much for the clarifications re: cThreadHandler, very informative.

    I just tried your threaded cActiveScript approach on Windows 10.1809 and it worked flawlessly when compiled, but I get the following error on Terminate in the IDE (maybe this is normal in the IDE?):

    Code:
    Run-time error '453':
    
    Error Calling: Run()
    ThreadError: Can't find DLL entry point AtlAxWinTerm in atl

Page 2 of 4 FirstFirst 1234 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
  •  



Featured


Click Here to Expand Forum to Full Width