multiple applications

In our system we have a mainmenu app and many modular executables coming from it. The entire system is very large and changes regularly so it is easiest to develop it in this way.

The modular apps are run from the mainmenu by clicking on a dbgrid. If the user clicks twice (by accident) the first click runs the app and the second gives focus back to the mainmenu app.

When the modular app loads it loads in front because its form is set to fsstayontop (the app must run on top) but does not have focus.

When a modular app exits it sends a message to the main menu telling it to activate itself.

How can I make the mainmenu not receive any more mouse clicks or keyboard inputs or anything that would make it active again after they have chosen to run a program from it?

Best case scenario would be to have a flag set when a program is run so that the mainmenu app won't become active but I have not been successful in implementing this or overriding the appropriate messages.

Even on assigning a message handler to an application and setting handled to true for every message it overrides every message EXCEPT when the app is not active and you click on it, it does become active???

This has been the thorn in my side for about 2 years now and remains the only system issue. Please help :)

The way we do it, is we create the new process with CreateProcess, and then set the main app.enabled to false, and then call WaitForSingleObjectEx, checking for the spawned process to terminate, before setting the main app.Enabled back to true and continuing from where we left off...

The ExecuteExclusiveProcess function starts an exe.
It disables your main form.
It waits for the exe to finish (using a different thread)
While that's going on, it is still handling messages (like Paint) with calls to Application.HandleMessage.
When the exe finishes, it enables your main form, and brings it to the front.

Cheers,
Phil.

>>>>>>>>>>>>>
unit execute;

interface

{ Create a process and wait until it completes before continuing with
current process }
function ExecuteExclusiveProcess(CmdLine : String) : boolean;

Thanks so much to the people who responded, your help has been much appreciated.

I think I will use that execute unit over what I am currently using, Thankyou Philip.

The only problem I have now is although the mainmenu app runs the application and although the mainactive becomes inactive while the other program is running, you can still lose focus from the modular application by clicking on the mainmenu application.

Hmm, you could add a handler for Application.OnActivate. If you have a child exe running, then activate that child instead? You'd have to get it's window handle, and use SetForegroundWindow.
That's a bit nasty and things might flicker a bit.

Or prehaps you could capture WM_WindowPosChanging and see if the Z order is changing. If the Z order will cause your main app to cover the other one, then set Msg.Result to 1 (or whatever) and don't call inherited. That will stop the window manager from processing the message.
That's a bit nasty too, but it's the best I can think of right now, sorry.

Cheers,
Phil.

0

SmegboyAuthor Commented: 1999-12-15

I have tried the application.onactivate one before but for some reason I think having something to do with still having the mouse down on the mainmenu app, it never actually loses/gains focus, the child app just loads without it so onactivate for mainmenu is never called?

I have tried using WM_ACTIVATE and if its value is WA_INACTIVE then setforegroundwindow.. this doesn't completely work I think because the message is sent when the mouse button is pressed down while outside the app, when the mousebutton is on its way up again it doesn't deactivate it but leaves the edit controls without focus.
Any ideas?

Next port of call was to try and intercept WM_KILLFOCUS but have had no luck with this.

Any more thoughts?

Cheers.

0

SmegboyAuthor Commented: 1999-12-15

I have also tried intercepting WM_ACTIVATE and WM_ACTIVATE APP using
similar methods to the following,

A kiwi yeah, I'm in Christchurch. Have you been here? Where are you from?

Cheers,
Phil.

0

SmegboyAuthor Commented: 1999-12-15

A modal window cannot lose focus to its parent window, I know that you can make a window from another application your parent window, is there some way you can make the mainform of another app (the child app) modal?

This is not a nasty hack. It is the way that Borland says you should put dialogs in a dll.

It is robust. The freeing of the dll is in a finally block so it is called no matter what. But don't take my word for it. You'd have to try it out and see if it fits in with your system.

Cheers,
Phil.

0

SmegboyAuthor Commented: 1999-12-16

Philip, I have been playing around with the whole dll process, seems quite good. Only problem I have so far is when I drop one of my visual components onto a project and compile it as a dll it throws access violation errors.

Obviously something I am doing wrong within the code for that component.

Are there limitations to dlls? There are probably things like this that always pop up when converting from an app to dll, are there common probs?

>>
Are there any problems with calling a dll from within another dll
<<
No, this is reasonably common.

As far as the AV, the major difference is that the DLL is using the Application object of the parent exe. It doesn't have it's own Application object.
That means that Application.MainForm is your form with the main menu bar.

If you can track the AV down to a few lines of code, then paste them here if you like and I'll see if I can help.

By the way, do you know how to debug the dll? Open the dll project, click Run Parameters and type the exe into the Host Application box. Now you can "run" the dll and stop at breakpoints in the dll code.

Cheers,
Phil.

0

SmegboyAuthor Commented: 1999-12-16

Phil, thanks for your help,

I have narrowed the problem down to a call in one of my visual components (I think based on a timage class). The call is

The image calls a dll procedure and passes its handle to it so that the dll can be drawn, the important thing to note hear is that the call is not even being made, its the createoleobject call that is throwing the error.

Cheers.

0

SmegboyAuthor Commented: 1999-12-16

I just found out that if I take the call out of the constructor and move it to a button, it throws an error

CoInitialize needs to be called once for each thread. You DLL is now in the same thread as the parent exe. So I guess you should add ComObj (or is it ComServ) to the DPR of the parent exe?

Is the 'mjc.nwobject' class something that was in one of your sub-exes? If so then another possibility is that the 'mjc.nwobject' class is now exposed from a dll instead. If so, then the CLSID in the registry probably only knows about a LocalServer32, not an Inproc one. Registering the dll would sort that out though.
Your dll will need to export DllRegisterServer and stuff. Create a new Automation Library and copy the relevant exports from the dpr.

Cheers,
Phil.

0

SmegboyAuthor Commented: 1999-12-16

I added comobj to the uses clause in the mainapps unit and it did work ! Well Done.

The mjc.nwobject is used by everything !! this includes every module and the mainmenu itself. Should I simply create an object in the mainmenu and reference that object from all dlls?