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 TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Setting the foreground app 2

Status
Not open for further replies.

Mandy_crw

Programmer
Jul 23, 2020
580
PH
thread184-1819600

Good afternoon everyone... I have these codes in my main program (Init)

WITH thisform
.windowstate = 1
ENDWITH

a = 10

DO FORM ATTMON WITH a


and these one in the form ATTMON init..

LPARAMETERS a

WITH thisform
.windowstate = 0
ENDWITH

DECLARE INTEGER SetForegroundWindow IN WIN32API INTEGER
DECLARE INTEGER GetForegroundWindow IN WIN32API
SetForegroundWindow(thisform.HWnd)
lnHWnd = GetForegroundWindow()
CLEAR DLLS SetForegroundWindow
CLEAR DLLS GetForegroundWindow

If Inlist(lnHWnd,thisform.HWnd,_screen.HWnd,_vfp.HWnd)
Messagebox("Setting the application to run in foreground... Please wait...",0+64+4096,"Attmon",2000)
ENDIF

thisform.text1.SetFocus()

The idea is that, i want my my main program to be minimised first then call FORM ATTMON...but the problem is the focus is not focusing in text1, and even the attmon form is not active... is just showing, i still need to click the form for the cursor to be shown in text1. Please help... thanks...
 
Your contradicting yourself, a main program means a prg, you have THISFORM in your code, which indicates you have set a form to be the main project item.

Just don't do that. Have a main.prg

If you want ATTMON to be the first form, then start it from there and only start your main form after that is finished.

Chriss
 
By the way, the thread you linked to was about two EXEs, within a single application you have the last form in foreground, always, it's just not at all a good idea to start a form from the init of another form.

As said, have a main.prg and start ATTMON from there, then start the main form of your application once whatever is handled by the ATTMON form is done. No need for tricks.

Chriss
 
Mandy, you say you want the main program to be minimised, but for it then to open a form, which would presumably not be minimised. The way to achieve that is not by setting WindowState, but rather by making the form (Attmon in this case) a top-level form. You do that by setting its ShowWindow property to 2.

Once you have done that, Attmon will exist independently of the main window. You will still be able to reference it in the usual way, including setting focus to specific controls. It should not be necessary to call SetForegroundWindow() to bring it to the front, but if you do, that should work as expected.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Chriss and Mike… Mike thats what i have done, i have set attmon showwindow property to 2, but it doesnt set the focus to Text1, i have to click it for attmon to be active… i dont what am I missing… thanks everyone…
 
Starting the attmon from the init of your mainform lets it go through the typical series of events: Load, Init, Activate, Gotfocus of the control with TabOrder 1. And then you come back to the Init of the main form, which then still goes through Activate and Gotfous of its first control in tab order.

Which means the mainform will be the one that's active and has focus in the end.

You can't get around this with any setting or explicit setfocus, what you need to change is what I already told you. Mikes advice doesn't work, so why don't you try what I advised, then? You add a main.prg into your project which you set as the main project item which starts first. Then you program into it that you first start the Attmon form, modal would work good, then start the mainform after attmon finished.

Chriss
 
We don't know your scenario, both I and Mike should have asked whether you suppress the main _Screen window in your project, which changes everything, too.

For example, then any form at its defaults of WindowState, WindowType, ShowWindow, and Desktop will be a child of _screen and not show if screen is not showing. You don't have that problem, you see ATTMON, but that's not telling whether you have _screen visible or not. So the question is: Do you either set _screen.Visible = .f. , call _screen.Hide(), or have a config.fpw with SCREEN=OFF?

If so, you have a more complicated scenario than a normal application using the screen as its desktop (kind of). It's easier to have the screen on, you can put in you application menu there in replacement of the sysmenu of VFP and then use it as the main application form which is just hosting all further forms. It's something that you just turn off when your application only has one form, because a desktop is overkill if you just need a single form, isn't it? It can still be okay as it can host the application menu, but the only form then is wrapped inside the screen and you have a titlebar of the main form under the screen titlebar and menu and that looks odd. So likely you have the screen off and the main form i a top level form. For such forms, setting them to modal does not work. That's making things harder.

But can you please tell, what's the screen situation? Advice will be different knowing that.

Chriss
 
Hi Mike... yes i have put text1.setfocus in the attmon... and yes Chriss... i have _screen.Visible = .F. in the init in my main program... Thanks...
 
Okay, you work without the screen.
And you have a main. program

1. What are the values for these properties in you mainform and the attmon form?
[pre]Desktop
ShowWindow
ShowInTaskBar
WindowState
WindowType[/pre]

2. Why start attmon from the mainform, if you have a main program and can easily use the straight forward way of first starting attmon from the main programm and then the mainform after attmon closed?

As said the mainform init is the wrong place to start attmon. There you're in the middle of a sequence of events that lead to the mainform becoming active with its first focussed control. You start attmon from there and for a short period of time attmon is active and its text1 textbox has focus, but then you get back to the mainform init and its activate event followed by its first taborder control are overriding that state just split seconds later. That's your problem.

Just do the straight forward thing and start mainform after attmon was closed, then you also don't need the mainform to be minimized, it'll just start after the user is through with the attmon form.

Anyway, if you provide the information about your two forms I could better understand what you need and provide a simple code example, from which you can see how to get things in the right order.

Chriss
 
Chris,

I can seee why Mandy might want to call the form that way - but ONLY if there is data in the "opening" form which is needed in the next form. Of course, as you say, there are better ways of doing it.

Steve
 

attmon
showwindow = 2
ShowInTaskBar = .t.
windowstate = 0
windowtype = 0

mainform
showwindow = 2
ShowInTaskBar = default
windowstate = 0
windowtype = 0

Hi Chriss... i hope these help you help me... I want to start attmon first because in my main pogram it already has alot of routine that im thinking it would be best just to add a new form to isolate debugging and for me it is easier... plus what i want my computer to do first is in the attmon... i dont know if I have said it well Chriss... forgive me... Thanks steve
 
I also thought about that in more general.

If you have any general initialisation in the main form, then adding a second form into the application requires reorganizing that, there are multiple options to go for.

Either make a base class you use for all forms with private datasession that has the intialization necessary for any form. Put whatever intilisations are general into the main.prg instead of the main form, etc. etc.

But the general chain of events happening when a form is started is even well known as LISA G. Load, Init, Show, Activate, GotFocus (of the control with Taborder 1). So starting the second form from the first form at that moment is pretty much the cause of trouble, the chain of events is:

[pre]mainform:Load
mainform:Init
attmon:Load
attmon:Init
attmon:Activate
attmon:Show
attmon:Gotfocus (here Text1.GotFocus as forced by code doing Text1.Setfocus)
mainform:Show
mainform:Activate
mainform:GotFocus of the control with taborder 1[/pre]

And I hope if it wasn't clear enough before it now becomes clear the mainform then is the "winner" and will finally be the focussed active form. Everything up to the last event only takes split secnds, so while attmon is active attmon.Text1 has focus (you can put code into the GotFocus event to test that), it's not the end of the event chain that's still due to happen.

It can all differ slightly depending on the property settings of the forms and that's why I (we) need to know that from Mandy and I'm waiting for that now before I do what I usually tend to do and what annys anyone else including me in the end for endless but useless efforts about every case including corner cases that don't even play a role.

So Mandy, your turn again. Unless you figured it out yourself by now. The general advice to do it differently is on the table already anyway.

Chriss
 
I see Mandy, our posts crossed, we posted at almost the same time. Let me see. You forgot to tell what the Desktoip setting is, but well, most important is you have both forms as top level form.

I'll be back with a sample project in short.

Chriss
 
This (download in the attachment) will show attmon, then mainform, started by main.prg in succession with the help of two READ EVENTS.

Notice for this to work attmon finishes with a Clear Events in its Destroy event, which is repeated in the mainform, too.

There's one detail which may not be important to you, but just notice that the taskbar will not show an entry for the EXE until you exit the attmon form and the mainform starts. It's not good design to have a taskbar item for every top level form, even if they don't run in parallel. The attmon (I don't know what it does but that doesn't matter for the case of how to get the activation behavior and order) will just be centered with AutoCenter=.T. and after you exit that mainform comes up and gets its entry in the taskbar.

The solution can be seen in the main.prg, each form is started with a Read Events afterwards waiting for the destroy of the form to do a Clear Events, so the forms run sequentially, first attmon, then mainform. An assumption I make here is that you only need attmon for starters, for example as login, for attaching to a monitor/beamer, something like that, and the mainform then is the actual main application for the lifetime of the application session which you end by closing it.

The Murphy fan in me expects you to abide to his law and want to run the two forms in parallel. Well, that just takes a slight change in the order of code. But before I post that, just try out this.
By the way, it's also easy to debug and test, just start main.prg as a finally built exe would do anyway. Put a breakpoint anywhere you want. Within the IDE I set the current directory so the Do forms work, you might adjust this to your project when you need another default directory, but then also put in full paths of the forms to start, as there can only be one default/current directory, of course, and if you switch that to data, for example, then Do Form attmon and Do Form mainform won't find the SCXes there. The current directory regarding forms or also reports and images and other files becomes unimportant in an EXE later, but is essential for being able to test within the IDE.

So I made that with the CD for the aspect you said is important to you, too: Being able to test this and debug it withn the IDE without first building an EXE from the project. In general this just always depends on files being found that are not yet conglomerated into one EXE. If you need more ideas about that, just start a new thread.

What you definitely won't ever get under your conttrol is the chain of event when starting attmon from mainform just because you think it's easier to just run mainform and get attmon started from there, always. You see in the description of the chain of events in my previous post you can put the do form anywhere within that chain of events and still the attmon will never be the form that finally is active. You can't change the order of the chain of events happening when you DO a form. It also doesn't differ from LISA G when you design form classes instead of SCX forms. And it's actually more complex because of the data environment also happening on the way. But it's not just init, init is neither the first event and by far not the last event happening when a form is started. That's what you clearly think and think starting attmon from there is enough to make it the active last started form. It's not.

Therefore the major lesson is to avoid nesting form starts into each other. You see and experienced it yourself. On one side it doesn't cause compile errors or a non working exe, but you didn't get the order of events under your control. It's why you don't, this event chain is set in stone, it's always happening that way. Therefore the simplest straight forward solution is to not nest starts of forms.

Chriss
 
 https://files.engineering.com/getfile.aspx?folder=f9b1281d-029d-4333-94e5-bebb74940e6f&file=twoforms.zip
I fought with myself to tell about another straight forward solution and lost that battle:

Formsets.

There, I said it. We rarely recommend them because they have design flaws which you very likely come across at some point even though they make the aspect to start a set of forms easy, because that's what they are by name and definition - sets of forms.

Especially since I get from your idea that you always want attmon to start together with mainform. Well, then attmon can be made a second form of a formset that includes mainform as the main form, but, well, since attmon should have focus first, actually attmon becomes the main form of the formset, the form with taborder 1, as you want that to be the active form. It doesn't dictate the role of the form for the user, though.

A formset will also be stored in a single file pair (scx/sct) and just like you can start a form from the IDE with the [!] toolbar icon or the run button of the project manager, you can thereby start a set of forms and just like controls activation order by tabbing is determined with taborder the form taborder determines which form of a formset is activated in which order.

I just thought I'd mention it, as it surely points out another straight forward solution besides a PRG starting two forms in sequence (as in my sample project attached earlier) or in parallel than nesting form starts the way you tried. But in some way a prg, may it also be a mainplusattmon.prg test program instead of modifying main.prg, is giving you the ability to add as many do forms as you like and other code in between, also that you can sequantialize the run of the forms, so a prg is a way of doing without formsets. And to me it is still the most straight forward solution in doing anything you like not only with forms. You have all you need in a prg as it can run any code doing much more than just running a single form or report or any project item can do. From that perspective the IDE would not lose much of the comfort of the Run button, if that would only run prgs, if you ask me.

We don't recommend formsets often, as being able to run forms individually or in certain orchestrations with code is making formsets unnecessary, really. Code can also contain descriptions, explanations, set prerequisites and have the right parameterization of starting something, so they are the ideal starting point, that's essentially also why you use a main.prg for the whole EXE itself. Within the IDE you just might not want to start from the application starting point but test a specific form or report, fine. Do a maintest.prg for that or as many componenttest.prgs as you like and run that for fast testing and debugging, a prg is always a good starting point.

Chriss
 
Oh i see... I knew that i still have alot to study Chriss as you explained it well... for me its overwhelming but im really thrilled that i am learning alot from all of you here.... I will study and read to understand it well... and probably could appl it to my projects... Thank you for the example that you have given Chriss as you always do... God bless you... Thank you again...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top