Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Why could Forms not show? 2

Status
Not open for further replies.

Olaf Doschke

Programmer
Oct 13, 2004
14,847
DE
I have an EXE, that works fine on it's own (for 4 years, extended about 3 times a year, current main work).

I thought I add the feature to enable automating it, like Word or Excel can be automated. I was writing this small ole class for a start:

Code:
Define Class OleApp As Custom OlePublic
   _Screen.Visible = .t.
   DO main.prg IN (_vfp.ServerName)
EndDefine

One important thing to add to main.prg is to NOT execute READ EVENTS in case it's started from the OLE class, as that would not let creation of the OLEAPP class return to the callee. I therefore made READ EVENTS execution depend on _VFP.Startmode<2.

And that makes it work: oYourAPP = CREATEOBJECT("YourApp.OleApp")

So far I can see the _screen of the application started as OLE Server, and it starts normal, gives me a login form and starts menu and toolbar. But if I pick some menu item, nothing happens. I can actually use some menu items, like the login, to relogin as another user. But other forms don't work.

I fear it's a very specific problem you can't solve without further info, but what could cause that?
What, if you do that for one of your applications? Does it work out for you?

Bye, Olaf.


 
Change the menu item destinations to something simple like WAIT WINDOW "Menu Option x" and see if it's even selecting the other menu items as well.

After you find that's working, modify the target code of those activities (such as if the menu code says "DO FOO" then modify foo.prg to say "WAIT WINDOW foo.prg" at the top).

When that works, create a macro which goes through each line of code and changes something like this:

Code:
use c:\foo.dbf alias myfoo
goto top

to instead do this:
Code:
wait window "use c:\foo.dbf alias myfoo"
use c:\foo.dbf alias myfoo
wait window "goto top"
goto top

And see where it's stopping. You'll find out what the cause is. I'm going to guess it has to do with not issuing READ EVENTS from within the code you're executing because I'd bet there are scores if not hundreds of messages above WM_USER being sent within VFP for its internal processing. These are likely being intercepted by the other message handler that you're relying upon for its own WM_USER messages. I think it will ONLY work properly if you have READ EVENTS from within your own app, so it processes all window messages.

Best regards,
Rick C. Hodgin
 
READ EVENTS - That could be a point, but with it, I never return from CREATEOBJECT("YourApp.OleApp").
Actually some forms work, but just some less important ones, an info form, the help and login, nothing of the core of the application.

I think it has to do with some base form init or load code I forgot about. I'll go the route you suggest and start with the menu item code. Anyway, it has to wait until monday.

Have a nice weekend, Rick!

Bye, Olaf.
 
Try manually executing DOEVENTS rather than an explicit READ EVENTS after trying each menu item. That would process messages up until there aren't any more, and then return.

Code:
* menu code:
DO FORM frmWhatever
DOEVENTS

See if it is made visible that way.

Best regards,
Rick C. Hodgin
 
What's in those menu items? Any conditional logic? Anything in SKIP FOR?

Just as a general comment I don't think automation was intended to provide U/I. That's why most automation servers -- including VFP! -- start non-visible. It's actually a problem when an invisible automation server presents unexpected modal U/I.

 
Thanks for the ideas, Dan.

There are SKIP FOR, yes. But the menu looks normal, the disabled items are ok. What most menu items execute is a user defined function "doform(formname,param1,param2...)" which is from the framework and starts a form in it's specific way via some meta data. Looks a bit like this function isn't available and only menu items not using it work, but I will see that monday. Since the menu code is generated from meta data it was not a straight forward looking into menu code. That would be irritating, since some forms work, so classes must be found and not finding that single doform procedure then would be odd.

About Non-visible COM automation Servers: Well, I plan to start invisible later, anyway. But in the first place in this application there is a login, even before the app goes into READ EVENTS, so I couldn't start invisible for now. I will add a Login method to the ole server to enable programmatic login, later. I don't see the problem is about that, you can show office apps, too. This is about EXE automation, not DLL COM servers having a restricted vfp9t.dll runtime. I know there is SYS(2335), but if this would be set even the login wouldn't work.

Maybe Rick has a point there about windows messages from the menu items being intercepted in a wrong way. Since I automate a VFP app from VFP, this might cause some sort of confusion about the two _VFPs and _SCREENs involved. But visibility also works with MS office apps, so it is a bit of an esoteric explanation. Still my first thought was, the form, that should start "can't decide" where to show in which _screen. I could try to automate YourApp.OleApp from a Word macro or any other COM enabled language and see, if that helps.

I also wonder, if there isn't a call to main.prg even when just instanciating "YourApp.OleApp". I first just tried _screen.visible=.t. and it only showed an empty _screen, so I think that's not the case, but I can't tell for sure if there isn't simply some branch off in main.prg as I'm using a framework here, which isn't by me, and not publicly available, too. On monday I can also contact the vendor of that framework again.

Bye, Olaf.
 
It turns out the reason was buried quite deep. The whole application got stuck each time a certain type of class was instanciated, which in case of _vfp.startmode=2 restarted the whole framework, resetted database connections etc.

I got there by WAIT WINDOW "debugging", tracing deeper and deeper, intil I got to the 8th level of branching off somewhere the execution didn't return so WAIT WINDOWs never showed and put more WAIT WINDOWS in there. Unfortunately not a very effective way to see what happens, since it requered several cycles of try&error.

Now, as I changed that init to not check for _vfp.startmode and instead see, if goAPP already is instanciated, there is no general problem anymore, with starting a VFP application that way I first said.

It is perhaps preferrable to keep that OLE Instance of your application invisible. So what you can do essentially to make your application olepublic is:

Code:
Define Class OleApp As Custom OlePublic
   Procedure Init()
      DO main.prg IN (_vfp.ServerName)
   Endproc 

   Procedure Show()
      _Screen.Visible = .T.
   Endproc

   Procedure Hide()
      _Screen.Visible = .F.
   Endproc
EndDefine
And if your app has SCREEN=OFF and instead creates a top level form, that form would then need to be shown or hidden instead of _SCREEN, of course.

There are two further things to look out for, besides _vfp.startmode, as you can't READ EVENTS in main.prg:
1. Main.prg isn't on the call stack all the time this way and class definitions or functions defined in it are not available, therefore move such functions, procedures and class definitions elsewhere.
2. CLEAR EVENTS doesn't quit this oleapp instance. You will have to QUIT

Otherwise: It works. For me, it works now. Ricks advice helped me most, but every thought was welcome.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top