No announcement yet.

Shelling to modeless children

  • Filter
  • Time
  • Show
Clear All
new posts

  • Shelling to modeless children

    Lance (and/or other interested members).

    Searched the forums in vain for discussions on this notion.
    The problem is this:

    1. Large application, with all modules running as tiny EXE's shelled from the master (parent) module.
    2. Each shelled EXE must stay within the master window, i.e. as a child process.
    3. Shelled EXE's must be able to co-exist with siblings.
    4. Shelled EXE's must be modeless, since we want to hop between siblings, when simultaneous access required.
    5. I use only Shell and DDT (and not CreateProcess etc. via Win32 API).

    I have successfully solved all the data transfer issues, but cannot get a modeless dialog to function as a child process, when it's not part of the main module.
    The problem is not related to Shell, since the Exe's run fine on their own, until %WS_CHILD style is used, then they terminate immediately.

    All modules use the proper approach (i.e. message pumping via DIALOG DOEVENTS and callbacks) as documented in previous forums on modeless dialogs.
    Simple test: I modified your "find" dialog in Address sample as a stand-alone modeless dailog. It runs fine from the desktop, but the instant one adds %WS_CHILD, it behaves like a teenager and vanishes.

    Your opinion would be greatly appreciated.

  • #2
    Dev --

    Shelled Exe are running in another processes.
    Because message loops doesn't work through processes/threads, you have expected results.

    That's why it's necessary to use MODAL. Note, even you will set a main window as a parent for a window in another Exe, it will not ordinary parent-child relations, because both windows are top-level.
    Probably, you need to change your approach and to have one big program
    (meanwhile you can debug parts separately and then to assemble, using Include).

    E-MAIL: [email protected]


    • #3

      Thanks for taking the trouble to respond.

      The ideas behind multiple tiny EXE's (as opposed to one huge program), are the following:
      1. "Thin" client, with ALL software stored on server.
      2. Hundreds (thousands?) of sub-modules (tiny exe's) comprising a fully integrated accounting/operations enterprise-wide application.
      3. Dynamic menus, i.e. table driven in software (hence DDT)
      4. Dynamic additions/modifications to modules: e.g. fix bug in one tiny EXE at a time, and update one EXE module on server only, via remote software such as pcanywhere..
      5. Add new modules by modifying menu file and transferring new EXE to server.
      6. Minimum network traffic, each work station runs only the master and a sub-EXE at a time (statistically, work-stations spend 80% to 90% of their time running one accounts module only.
      7. Internet applications, for dial-up access, with VERY quick download of server software modules.

      The modules must be restrained within the master container, for transfer of common information (password control etc) and the ability to interact via messaging (all solved already, using "SendMessage hDlgR, %WM_COPYDATA" protocols.

      So the issue revolves around child behaviour via DDT and SHELL only, as I can already achieve the above scenario quite comfortably using WinMain and defining a MDICLIENT window, with the sub-exe's behaving correctly using the WS_EX_MDICHILD extended window style, and a MODELESS window.

      It appears that I am unable to activate the equivalent %WS_EX_MDICHILD behaviour using DDT dialog boxes.

      If this is possible (and theoretically it should be, since one can achieve the same thing in C++ and SDK, using only the win32 API), then it opens up possibilities of developing multi-user enterprise-wide applications using this "thin" client approach.

      The benefits re software maintenance are enormous, since we don't have to update all the hundreds of workstations with the same software, each time we make a minor change.




      • #4
        How about using dll's instead of exe's?




        • #5

          Yes, that's a good idea. I already use DLL's for functions and subs common to all modules. The only problem with DLL's is that external function declarations must(?) be hard-coded into the EXE module that calls the DLL.

          What I'm doing here is to create new modules on the fly, and the master menu stays constant, since no menu's or DLL names need to be hard-coded. The system just keeps growing dynamically, with new modules being added even by different programmers. Such modules would 'hook' into the system by:
          (a) Changing the ASCII table (the menu structure), which "points" to the new module name and
          (b) Creating the new child EXE, which must respond to standard messages sent out by the master menu module.

          This design allows unlimited future additions to the system, without recompilation of any previous modules, including the master menu.

          Would the same approach work with DLL's? I'll give it a try and see if one can achieve the same result, i.e. DLL's created on the fly, and referenced via an ASCII menu table. Could one declare external DLL functions as variables? Don't know until we try it!

          Thanks for the suggestion.




          • #6
            Yes, it can easily be made to work with DLLs as James suggests... However, since you want to make the whole thing "dynamic", you'll need to use run-time linking instead of load-time linking.

            Load-time linking is done with "hardcoded" declarations of functions/subs in DLLs that cause them to be automatically loaded (by Windows) when the app is initially loaded (but before the app actually starts running).

            Run-time linking is completely dynamic. You declare [generic in your case] functions without any LIB reference (just like a normal 'internal' functions/subs), and load the required DLL with LoadLibrary(). You then use GetProcAddress() to get a pointer to the desired function/sub, and then call the function/sub with CALL DWORD...USING. Finally, use FreeLibrary() to release the DLL from memory.

            Search the BBS for "getprocaddress" and you should find plenty of examples.

            PowerBASIC Support
            mailto:[email protected][email protected]</A>
            mailto:[email protected]


            • #7
              Lance was faster
              I wanted to recommend the same LoadLibrary / GetProcAddr

              E-MAIL: [email protected]

              [This message has been edited by Semen Matusovski (edited December 18, 2000).]


              • #8
                Originally posted by Dev Oberholzer:
                Yes, that's a good idea. I already use DLL's for functions and subs common to all modules.
                The only problem with DLL's is that external function declarations must(?) be hard-coded
                into the EXE module that calls the DLL.
                Define a few standard functions common to all DLL-s, just like commandline-arguments
                I use 3 exported functions.
                Function DLL_INIT(parameters)Export As Long
                Function DLL_EXECUTE(parameters)Export as Long
                Function DLL_ABORT()As long

                Use LoadLibrary/FreeLibrary to load it when it is needed.

                mailto:[email protected][email protected]</A>

                mailto:[email protected][email protected]</A>


                • #9
                  Lance, James, Semen and Fred

                  Many thanks for pointing me in the right direction. I will give your suggestions a try and when a workable prototype emerges, will post an example or two on the code forum.

                  Much obliged for your help!!!



                  • #10
                    Some further observations:

                    Both approaches, i.e. shelled exe's and dynamically Loaded DLL's work OK, and behave in a similar fashion.

                    1. The DLL approach works very efficiently, as per Fred's suggestions of 3 exported DLL functions. The benefit of using a DLL is minimum memory consumption, but only for MDI access to a single module (for example, handling multiple customer orders simultaneously from the same workstation, using only one instance of the application).
                    2. Exe's as separate processes function equally efficiently. They are slightly easier to use: no need for function declarations, release memory themselves when terminating (no FreeLibrary statement). Drawback: additional overhead in MDI usage, where Windows will create a new process space for each MDI shell (my interpretation anyway, I may be wrong!) Since this would happen infrequently in the application, it's not a crisis, the EXEs are tiny (20k max).

                    The "trick" with both approaches is to declare a separate MDI container in the master window, and then have all sub-modules create their dialog boxes as MDI child functions or processes within the MDI box. Advantage: all sub-modules stay within the window, you can hop between sub-modules and when you kill the main app, all the "slaves" die with it.

                    Only two mysteries remain: title bars in sub-modules are never highlighted, despite receiving focus, and menu bars disappear in the MDI children.

                    Some example code to follow, once I solve the (minor) mysteries.




                    • #11
                      You may also want to rethink your mdi approach. If I'm not mistaken
                      MS now recommends not using it. Another way to get similar results is the
                      approach Jules took when designing his Dialog Editor. He has a Hidden (or not)
                      Main Window that is the parent of all others. Here is the link.


                      [This message has been edited by jcfuller (edited December 20, 2000).]


                      • #12

                        Quite correct! MDI appears unstable when the MDI child windows are created by 'other' processes or dll's, i.e. not part of app's message pump.

                        More research into Win32 API also revealed that:
                        (a) Child windows are not allowed menus
                        (b) Only uppermost windows are highlighted, and not the children.

                        So the MDI approach is a pipe dream (damn!).

                        Nevertheless, the previous discussions are still valid (i.e. modeless windows), provided one accepts the fact that the spawned exe's and/or dll's have a bit of independence. More inter-process messaging will make them toe the line, I guess.

                        Thanks for the input. I'll have a look at the link you suggested.




                        • #13
                          Of course, you could dynamically alter the menu (or a portion of it)
                          appearing in the main window depending on which of the sub-windows
                          was active.


                          [email protected]
                          :) IRC :)