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

How to put my app be on top, and active...? 5

Status
Not open for further replies.

Mandy_crw

Programmer
Jul 23, 2020
578
0
16
PH
I have this codes in my app, with the intention of letting my app be at the foreground and active while cursor is blinking waiting for user input... the cursor is blinking but i still have to click the textbox so that i could input.... I also have alwaysontop set to .t. Please help me solve... Thanks and God bless

code...
go_Form.Visible = .T.
go_Form.Show(2)

code...
code...


Procedure Init()

thisform.pgfnames.activepage = 5

_screen.Visible = .f.
_screen.borderstyle = 2

DECLARE INTEGER SetForegroundWindow IN WIN32API INTEGER
SetForegroundWindow(thisform.HWnd)
CLEAR DLLS "SetForegroundWindow"

thisform.pgfnames.activepage = 5

WITH thisform.pgfnames.page5
.text1.setfocus()
ENDWITH

code ....
code...

endproc
 
Hi Mike… yes the form is on top, page 5 is active and text1 of page five is where the cursor blinks… i still need to click the form or the textbox for the form to be active… its been 2 days im figuring it out… thanks
 
Mandy,

I got a repro, I'm not so sure this is anyway near your code, though I think the problem is setting _screen.visible = .F.
If this is not done - as in this version making _screen.visible = .F. a comment - the go_Form is the active form.

Code:
Public go_Form

go_Form= Createobject("startform")
go_Form.Show(2)
Read Events


Define Class startform as form
   ShowWindow = 2
   Add Object pgfNames As PageFrame With PageCount=5

   Procedure Init()
      Thisform.pgfNames.page5.Addobject("text1","TextBox")
      Thisform.pgfNames.page5.text1.visible = .t.
      Thisform.pgfNames.ActivePage = 5
      
*      _Screen.Visible = .F.
      Thisform.pgfNames.ActivePage = 5

      With Thisform.pgfNames.page5
	 .text1.SetFocus()
      EndWith
   EndProc 
   
   Procedure Destroy()
      _Screen.BorderStyle  = 3
      _Screen.Visible = .t.
      Clear Events
   EndProc 
Enddefine

In an application, the last form generated (and shown) will be the active form with the active focused control. An application can't have two active forms. Just like there is one active control on a form, there is one active form of an application.

From that alone, hiding screen shouldn't make a difference, but it does. So acting on another form, even just to hide it, seems to remove focus from go_Form.

The best advice regarding _screen actually is not touching it while you develop in the IDE. Hide _screen in your exe by including a config.fpw with a line SCREEN=OFF. Then you don't ever need to act on it.

Mandy said:
i still need to click the form or the textbox for the form to be active
You (accidentally?) already describe the main point: The form itself is not active. So yes, you need to click on its title bar or into the control you want to use.

The problem I have with my own problem description is, that this focus problem even remains when I try to do the _screen.visible = .F. separately, before even creating and showing go_Form. But generally it's still true: The last form you create and show in an application will automatically be the active one and has the active control. If its not, there's something directly or indirectly focusing another form, making that active and having the active control.

Chriss
 
Yea Chriss, thats what im thinking… so there must be a something thats focusing another form… actually i have a small application launched first then the second form.. (both are exe) although the first was not set to alwaysontop=.t., does in any way affect my second form to be not in focused?

Thanks for your code Chriss, i’ll to i corporate it with my app…
 
Mandy, notice this code solves the problem for the price of keeping _screen.visible .t.,

to get what you want should nevertheless be possible with a config.fpw having SCREEN=OFF, which is the best way to turn off the screen for a VFP exe.

When you start two EXE, I won't guarantee anything, it might be the second EXE getting the focus, it might be whichever last shows up a form. If you want your EXE to become active after starting another EXE, then I guess the best way is to wait for the other process to get to the foreground and then finally activate/show your form. It's not the simplest task to know when the second exe has become the foreground process of Windows, especially when it can also change by user interactions.

You can only have one active application in windows, too. SetForegroundWindow makes that, but while VFP apps are activated by it, I think they are not (always) getting focus, depending on what else runs.

When you compile multiple EXEs that are all part of your application, that's not the usual way, you get such app activation issues, so another way to modularize things is to not compile into EXE but into apps. Have one EXE that you use to DO some.app and all apps will be in the same EXE process and it's still one application staying the active application. Within all apps you'd do this way, it'll still be the last window/form shown, that's the active one.

If there are multiple forms, in the end there's no two active forms at the same time in separate or the same process, but at least you'll not change the active application with all your APPs working in one process. The apps do share anything global like settings, path, etc. and a goApp is for all apps.

You might actually need - for whatever reason - separate EXE processes, but you're not making your own life easier with it.

Chriss
 
Thank you so much Chriss for the very clear and comprehensive explanation… i am still debugging and trying some ways considering all your suggestions… i appreciate all your help Chriss.., thank you very much…

With the config.fpw, is this pure notepad? Will i just type SCREEN=OFF save it and put in the folder where my exe is also located?
 
With the config.fpw, is this pure notepad? Will i just type SCREEN=OFF save it and put in the folder where my exe is also located?

Yes, it's a plain ordinary text file. You can use Notepad.EXE to create it (if doesn't already exist) or edit it. Place [tt]SCREEN = OFF[/tt] on a line by itself. Then place the file in the same folder as your EXE.

You might also find it useful to put [tt]RESOURCE = OFF[/tt] in the file - again, on a line by itself. This will prevent your program from creating spurious resource files. (But this is not essential, so don't worry too much about it.)

(It doesn't matter what order the lines appear within the file.)

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
You have already been guided by the Mikes. If you search config.fpw you'll find "How to: Create a Configuration File" which does not only tell you that but also concepts and what can be in it. It also doesn't hurt to read help topics ranked higher in the search result of "config.fpw".

What you wanted to do will also work, Any VFP exe will by default look for a config file called config.fpw in its own directory. Mike Yearwoods hint is important as you already told you have multiple EXE and likely have them all in the same folder. Then maybe you don't want to hide the screen for all of them. But indeed, if your second process also only has a top level form or has no windows at all and is just for doing background processing in a parallel process, then it would be fine if the same config.fpw with SCREEN=OFF also affects it. It could even do away the problem of losing the application focus, as then the second EXE process shows no window. _SCREEN will always exist, and _VFP also always exist in any VFP process, so there are always both these windows in any VFP application and I think one of them will become the foreground window of Windows, even if they both are hidden. I think any process you start will therefore at some point become the active application and take away the focus of your first EXE process. So whenever you start an EXE you start something that truly runs in parallel and if you finally want to stay the active process you have to start and focus your own main window late enough that it doesn't become inactive.

I prefer to put the config.fpw in some folder not in the path of the PJX and EXEs, as
1. I can "switch" them on or off by embedding them or not.
2. I don't have a config.fpw file in the EXE folder that could be edited to become wrong, i.e. as the developer of the EXE I'd like to keep control about what a config.fpw can do to it.

Of course, an educated user could use config.fpw to change minor things with it. But nothing you couldn't offer to users by other means of configurations like an INI file. The danger of an open extra config.fpw file in the final application installation folder is that you can add a config.fpw line starting with COMMAND= and then any command the runtime executes and that can be used to break things, circumvent security and what not. So it's nothing you give into the hands of users lightheartedly. If installing into the usual system folder for programs, editing this file is not possible for non-admin users, but any person with his own PC or laptop will likely work as an administrative account, so there's no real protection about a text file in your application folder and it's best to include it.

When you're at that, you can break the added security of an included config file by adding a line ALLOWEXTERNAL ON, I'd only do it for own purposes in the prerelease phase. The good news is it's off by default. The bad news, without an internal config.fpw externals are allowed and there is a -C command line switch that also allows users to specify another config file than config.fpw. That alone quite forces you to take control and embed a config file into your EXEs, even if you don't intend to make any use of it at all, to prevent influence from an external config.

Chriss
 
Let me report on checking some things about the foreground process of Windows. This all beomes obsolete, when you manage to do whatever you want to do with multiple EXEs in your main EXE alone.
But lets assume an application with one or more additional processes/EXEs started by a main exe make sense for any reason.

The SetForegroundWindow API call you used describes this aspect:
SetForegroundProcess said:
The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:

[ul]
[li]The process is the foreground process.[/li]
[li]The process was started by the foreground process.[/li]
[li]The process received the last input event.[/li]
[li]There is no foreground process.[/li]
[li]The process is being debugged.[/li]
[li]The foreground process is not a Modern Application or the Start Screen.[/li]
[li]The foreground is not locked (see LockSetForegroundWindow).[/li]
[li]The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).[/li]
[li]No menus are active.[/li]
[/ul]

The first point makes it seem useless, but: One one side the other bullet points mean situations in which SetForegroundProcess can also act without the process being the foreground process. On the other side this also tells it does more than making the process the foreground process. Well, it makes the one window of the foreground process the active window.

So how can it fail in your mainform init? It can be too early. If you start another EXE that doesn't immediately make that new EXE the foreground process and starting another exe means starting another parallel running process. So your own SetForegroundWindow can come before the new EXE is the foreground process with a foreground window or not. You don't control how parallelism works and is times. An exe can take long initialization steps before it finally shows a window that takes the foreground status.

So far it becomes obvious you better start another EXE as soon as possible in your exe, to also get to the point this other exe is the forground process and you can then take back the foregorund state to your own exe. That should always be possible as you started the other exe and therefore "own" it.

The question now becomes: Can we determine which process is the foreground process of Windows, and can we remove it from thar "throne" and put our own process in the foreground? If not, can we at least know when our won process lost the foreground state and then regain it?

I asked the second question last, as the first question is specific about the EXE we know we started, so it could be more successful than knowing when our own EXE loses the focus. There are APIS about that: GetForegroundWindow and GetWindowThreadProcessId. I think this should be enough to find our what happens if one VFP EXE starts another and still wants to keep or at least get back the foreground process. I'll try it with processes with or without hidden _screen and with or without any other own form and will get back with the results.

One special aspect of it would be detecting and preventing double start of your own exe, though that's already covered in the FAQ section and it's not the topic here, when we explicily talk of a seperate second EXE.

Chriss
 
Mandy, I'm not sure this will help, but I create each project (.exe) in a folder dedicated only to one project. I can have Config.fpw files for any or all of my projects and they will NOT conflict.

For example I created an exe which rings a "bell" at a time I set. I set a time then minimize the window and it will still be "live". I then work on another project or run an exe and it will be in front. I can always click the icon on task bar to bring the alarm window to foreground or click another window for same.

I realize this is my personal preference but I believe putting projects in separate folders makes life much simpler.

Steve
 
I realize this is my personal preference but I believe putting projects in separate folders makes life much simpler.

That makes sense. I also have separate folder for each of my projects. But I also have a set of folders for the components that I share between applications. These include my generic class library and my generic procedure file.

All of these folders live within a parent Fox folder (which is separate from my VFP9 folder, which contains VFP itself and all its bits and pieces.)

This arrangement has worked well for me for many years. But, as you say, it is a personal preference.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mandy,

I'm near a conclusion. One thing I found out early already is, that the _VFP.hwnd is what GetForegroundWindow() will report as the OS foreground process foreground window, before anything else like your own main form becomes a foreground window. So even a windowless background process you compile as an EXE with hidden screen will take the active process and foreground window status away from your first starting EXE.

Which means it's true, you can do SetForegroundWindow too early.

I added waiting for the background process window to appear using GetWindowTitle. But even then and even adding an extra wait time, SetForegroundWindow has no effect in the first EXE trying to get back the active state. So it seems to me none of the conditions necessary for SetForegroundWindow to work are satisfied once the bakground.exe has become the last started process with the last started form and therefore the foreground process. One detail is maybe important for it: I added an editobox to the background process main form, so this window actually has an input control that can become an active input.

But I'd not give up at that point to be able to start a background process EXE and still stay being the active form should be possible. There is one obvious solution, of course: Turn it around. Let the user start what becomes the background process. When this EXE starts your main foreground process EXE, that EXE and its main window become active and focused without any efforts of using API routines at all.

So it's just a matter of accepting that the foreground process shouldn't be started first - and the problem is solved.

I also second Steve, that it's a mere click into your main app. If that annoys you, I think just turning it around , as said, would get rid of the focus problem. The only price you pay, maybe, is that now the EXE name the user starts and will associate with your application is actually not what he'd need to look for in the Task Manager. He'll find it there, but it actually is just the background process.

I think there are still possible simple ways out of this "dilemma": Name the exe the user starts Applaunch.exe and your main application process App.exe and the user will know he just started the launcher and App.exe is the main process. The Applauncher.exe can stay an active process and do background tasks or whatever you intend this background process to do after it did RUN /N App.EXE.

The only thing that would make it worthwhile is if a main process.exe should be able to start many background processes, with none of them taking the foreground process/form state away from it. Perhaps looking into would give a solution to that. It's the main concern of this project to enable parallel processing. Not as elegant as using multiple threads, which would actually be another possibility, albeit even more complicated. Since even single CPUs nowadays have several cores that allow running multiple processes truly parallel it is a nice thing to have the possibilies of it at your finger tips.

I think the way to get to multiple background processes is to use CreateProcess and gain fuller control about what actually happens in these child processes so they don't take away the foreground status from the main process that starts them.

Chriss
 
Just had another idea: You can do olepublic classes, so you can have something like YourApp.background and "call" it by doing oBackground = CreateObject("Yourapp.background").
This can be compiled to an "in process" (DLL) or "out-of-process" (EXE) com server and when you do them, you have a usually formless class that you also have a referenceto, so you can do more than just start one, you can define methods you want to be able to call. In itself this doesn't establish a way to do things in parallel, i.e. once you have an object oBackground and call a method to send a batch of mails, for example, oBackground.sendmails(), this will only return after it finished the method.

But what you can do inside the method is start a timer that does something and immediately return. This way you can make use of OLE automation of your own COM automation server classes to have parallel processing.
I'm totally aware you already had problems understanding timers before, so this doesn't seem helpful, but I'm sure we can get to what you need in the end.

You can also read something completely different between the lines of all this: I propose quite complicated ideas and whatever you need to do usually was done by others already in simpler ways. So sometimes it would really help to know your actual real world problem only, without any half working code ideas of how to solve them, starting from scratch and showing you how such things are done with well established solutions could make things much easier than trying to get the final step in your solution path, that may just be the wrong path to take overall.

Chriss
 
Good day everyone! i am still figuring it out till today... still doesn't work... i just wonder, it used to work before... since i keep on improving the app, i did not notice where and what might have i changed to not work as it worked before.... thanks for extending help always... God bless....
 
Mandy, didn't you say:

Mandy said:
i have a small application launched first then the second form.. (both are exe)

If you have two exe, the one you start last will have the foreground process and foreground window state of the OS. Why do you split this into an EXE for each form. I think you got a wrong idea that keeping files small with just one function, one class definition, etc. also extends to having an exe for each form. That's not recommendable. While you now can't even accidentally get scope problems you can't share a reference or anything without much ado about interprocess communication, besides these problems with foreground.

Keep everything that can be called one application into one project and EXE. Minimize the scope of variables and values, use private datasessions in forms, such thigs help that forms don't interfere with each other and then also don't need to be separated into seprate EXEs and processes.



Chriss
 
Mike Yearwood, I agree.

It makes debugging harder to have a timer in your application, though there is the debugger option to display timer events you can untick in Tools->Options->Debug tab.

But even with that, the timer always risks to run in the wrong moment, you need to be cautious in the timer code to not do something that affects the responsiveness. In thread184-1817692 Mandy showed she did something in a timer that could do that, if there are not frequently new records in a certain table that is processed in the timer. That may have been reason for other mishaps, too.

I'm also still at doing something that enables an EXE to start a background process without losing its own foreground process state. I remembered one of the features of the enhancements of the Bindevent() function from VFP8 to VFP9 was being able to detect the deactivation of _screen. Because despite _screen being a VFP form with all VFP form methods and events, you can't program _Screen.deactivate as it already runs and there is no _Screen class you could edit.

That doesn't help much in itself, but I have an idea.

Chriss
 
Hi Chriss and Myearwood, is there a way that the first exe to be minimised automatically when its run? so that te second exe would be in the foreground? I dnot know.. just a thought...
 
Mandy,

yes, surely, I already said above, changing the meaning of both executables is the easiest way, the first EXE starting can easily be the background process, as whatever it starts automatically becomes the foreground process. And the first exe can easily stay in memory, it just does have to not end after starting the foreground process EXE.

Then I talked about how that could lead to misunderstanding which EXE runs as main process, but I also already stated how naming the EXEs could prevent that misunderstanding. AppLauncher.EXE being the first exe starting App.EXE and staying in memory as background process is a solution for both the order of execution and understanding the meaning of the EXEcutables. At least after you tell them what a launcher is.

There's still bad news, one more risk I also already mentioned not so long ago in a completely different thread, that's not that far fetched: If users pin an application to their task bar to have a fast way of restarting, then they'd pin the visually shown EXE, so they'd pin App.EXE and not AppLauncher.EXE and so next time they start from the pinned application they'd not start the background process. And I don't think there's an easy solution to prevent pinning the running application to the task bar or automatically changing the pinned EXE to be the AppLauncher.exe instead of the actually pinned App.EXE.

If users can be instructed not to do so, it's a solution. You just generally have a bad experience telling people what they should not do. So to me that's not a sufficient solution. But it works if users comply with it.



I continue to think about a more general solution for background processes as it's a reusable feature you could want to have in any application. For more than one background process, for starting them at any time in your application when it already runs and starting as many as you like or need. I get back to that later, I said I have an idea, that turned out not to work as I liked. There's a mode for windows that's "Show, but not activate". It's ShowWindow mode 4 and can be used with RUN /N4 or ShellExecute(), but it won't work when starting a VFP EXE. It also doesn't help to have a VFP EXE without a form, the moment a VFP exe starts it becomes the foreground process by the system form _VFP, which becomes the foreground window and you can't prevent that as it happens even before one line of your code runs. You can see it from GetForegroundWindow returning _VFP.HWnd. It must be built into the initialization phase of the VFP runtime. And SetForegroundWindow doesn't work in your main application once it lost its foreground state.

There are still several paths I can follow. In regard to pinning it could be solved by using the App.EXE as it's own launcher. But there also must be a more normal solution as an EXE that is currently the foreground process of Windows should be able to take advantage of that privileged state to keep it for itself. Googling you find this is asked quite often and proposed solutions don't work for a VFP EXE, they ask for a windowless EXE and a VFP EXE always has both _VFP and _SCREEN, even if hidden. _VFP, as said, becomes the ForegroundWindow, as it's a state not only visible windows can have. The Z-order top-most meaning of foreground is done by BringWindowToTop or SetWindowPos, which I already also had in mind because of the current video related thread. But they don't change the foreground process state.

So from my perspective it's still unsolved, while it would work to simply start background, then start foreground from it. With the concerns about application pinning.

Chriss
 
Btw, I'm totally aware that a solution for both order of execution and pinning is that AppLauncher.EXE and App.exe are the same EXE. It's still a wish I have to a solution to be doable in a way that I can start background processes as many as I want and when I need them, not just a single one right at the start. And the background process would then just have a load of things in it which are unnecessary for the background.

I also already proposed creating a COM server as a solution. You cannot only start them as you like, you also have an object reference to them. So that might be a solution. It's just not really simple, even though it's simple to create a COM server EXE. It'd still be a problem that a VFP EXE has _VFP in it.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top