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

One instance (revisited yet again) 1

Status
Not open for further replies.

DSummZZZ

Programmer
Oct 24, 2000
4,250
US
My scenario:
I am developing a monitoring app (VFP 9 on Windows 7 64 bit) to run in the background on several hundred computers. All it does is periodically check internet connectivity by pinging some preconfigured IP addresses. If need be, it resets the VPN connection and re-establishes connectivity.
It needs to stay hidden from the screen and the taskbar unless manually accessed. So what I do is after it starts, it waits 10 seconds to do its check then uses a ThisForm.Hide() to hide itself. If someone needs to access the app, they can run the executable again to 'unhide' it. I have been using the usual API calls to prevent multiple instances of an app in order to just show it:

BringWindowToTop(lnHWND)
ShowWindow(lnHWND, SW_SHOWNORMAL)
SetForegroundWindow(lnHWND)

The problem is, when the app 'shows' again, I see a flicker of the original screen design, then just a plain white screen. I have added code to the Activate, Show, and GotFocus methods to try and redraw the form, but none of those seem to fire when the API calls are used.
Has anyone run into this?


-Dave Summers-
[cheers]
Even more Fox stuff at:
 
Perhaps you could make the form very, very small before you hide it?

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
Making it small isn't a good solution, a better solution is to move it outside the monitor, like yourform.left=-1000. However, it will still show up on the taskbar.
 
What I think both of you are missing is that whatever I do to hide the form, nothing works to restore it. I can make it disappear easy enough, but when it comes back in focus it's blank. No event (Activate, Show, or GotFocus) fires to redraw it. So if I move it clear off to the side, how would I get it back?


-Dave Summers-
[cheers]
Even more Fox stuff at:
 
Sorry I was concentrating on the 'White Screen' part.

I would suggest that you use a marker file and a second loop
in your app.

When your original app is hidden, place a marker file somewhere
consistent. Then use a loop on your scanner to check (quite often)
if that file is still there. If it isn't, show the app using VFP code
thisform.show or whatever.

Then in you app's second instance, make it delete the marker file before exiting

That should do it

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
I don't see what owuld prevent fom.left and top settings to work in conjunction with Show. If you use Thisfrom.Hide() to hide your form, it still won't show up again via API calls, you need to call Show(). Hide() and Show() are the pair of methods to use. Then you can use further API, especially SetForegroundWindow to ensure it comes to front. But the first thing to do to show it would be Show(), what else?

Bye, Olaf.

 
Olaf, Show() is what I can't get the form to use to show itself again after using SetForegroundWindow, so it won't redraw itself.

And yes Griff, after using SetForegroundWindow to gain focus on the app, it is white. I like your idea about the marker file though. That may work. A timer firing every half second or so, then not firing when the form is active. I'll see what I can come up with for that.


-Dave Summers-
[cheers]
Even more Fox stuff at:
 
Dave,

About 5 years ago, i created a System tray that auto launches when computer launched, and ran in the system tray area.

it was syncing data from the store to the corporate office.

and upon right-clicking on it, i activated a menu and a form etc..

Also, if the system tray was not running My app complained and ran it using shellexectue()


Ez Logic
Michigan
 
How is the form constructed? Is it a typical Form Designer form, or something else?

Tamar
 
EzLogic,
I am using the system tray method using the systray class library from the VFP 'Samples', and that part is working quite well - for the test computers that have a system tray.
As I mentioned, the app can't be minimized to the taskbar, because there isn't a taskbar. Therefore, there isn't a system tray. If the app is minimized, it still shows as a minimized app at the bottom of the screen rather than in the task bar.
Our company is using a shell app other than Explorer. So if the app is running and hidden using hide(), it needs to be brought to the forefront.

Tamar,
Yes, it's just a regular single form, running 'As Top-level Form', with screen=off in the config.fpw.
There are no pageframes etc, only some standard controls such as listbox, command buttons, text boxes and graphics controls, some of which I have subclassed in containers, but nothing all that special like ole controls.

Now going with Griff's suggestion on looking for a flag file using a timer, it is working quite well doing it this way. If the app sees the flag file, it executes a WindowState = 0 and a Show(), and all is well.
But like I mentioned, this app uses other timers to ping devices. So I hate to do it this way only because I don't want either to get behind on doing the jobs. But only time and testing will tell.
Still a star for Griff and that good suggestion!


-Dave Summers-
[cheers]
Even more Fox stuff at:
 
I'm wondering if it is worth testing which is more efficient, looking for a file, is it better to find it
or does it take longer to not find it... probably doesn't matter at all

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
It does matter.

File() can search 100,000 times for the presence of a file which exists in 16 secs, one that doesn't exist takes 25 seconds.

Adir() can do the same in 4 seconds either way.

So if you are looking for a file, use ADIR() it probably has to do with File() following the current PATH info.

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
Sys(2000) is much faster than Adir(). And while file() can cause problems since it doesn't always respect the given path, Sys(2000) does.
 
Sys(2000) yielded the exact same result as ADIR at 100,000 records and at 1,000,000 records.

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
>Olaf, Show() is what I can't get the form to use to show itself again after using SetForegroundWindow, so it won't redraw itself.
Well, have you tried the opposite order? I guess yes.

You say users can start you application again, so I asume you're using one of the semaphore solutions to detect your app already runs, activate it again and finish, or do you act on the hidden window from the new process? Then this is what you're doing wrong. You don't just revive your hidden form, you revive your sleeping but still running process. The new process is not the owner of the form. You could talk to the old process and trigger it via a file as Griff suggested, or use inter process communications.

The other solution might not be using Hide, but also use the API call to hide a window only, then the opposite API call should revive the form. Then lookout for events being triggered in the form just when shown again. The form itself and not an outside process should cause it to redraw. The brute force method is Thisform.Cls()

Bye, Olaf.
 
Olaf,
That again, is my issue. Thisform.Cls() doesn't work either. I tried it, but it never fires. My latest attempt was adding code to Thisform.Resize():
Code:
IF Thisform.WindowState = 1   &&... minimized
   Thisform.Hide()
ELSE 
   Thisform.Show()   
ENDIF 
RETURN
I thought that maybe when the API calls executed, it would bring the form forward, restore it, and the Resize() code would fire. No joy:
Code:
BringWindowToTop(lnHWND)
ShowWindow(lnHWND, SW_SHOWMINIMIZED)
ShowWindow(lnHWND, SW_SHOWNORMAL)
SetForegroundWindow(lnHWND)

I had considered using interprocess communications, and I still might. But I really need to get a reliably working version put in action as soon as I can (like always) so maybe I can tinker with that later on.

Griff,
Since I have the luxury of creating a flag file in specific location, I can also have the app check for that file in that specific place.
Right now the app runs, checks for the flag file and if it's there it deletes it. After 10 seconds, the app sets WindowState = 1 then executes Thisform.Hide(). If a second instance is run, that instance creates the flag file.
Now the first instance checks every second for the file and if it is there, sets its WindowState = 0, does a Show(), then
deletes the file.
The could be as much as a 1 second delay depending of course on which part of the 1000 milliseconds the timer is in, but so far it has been working quite well.



-Dave Summers-
[cheers]
Even more Fox stuff at:
 
That flag file is one way of (simple) interprocess communication, obviously. And it shows that thisform.Show works, when done from the original process, doesn't it?

faq184-839 does it with DDE, obvisouly you would react to the DDE call with something else than ZOOM WINDOW SCREEN NORM, but Show your form.
faq184-6206 only shuts down the new instance in case one already runs.
faq184-1767 has another three variants, but the variant with BringWindowTo Top adresses the _SCREEN here, which you hide anyway. I think this is what's not really working out good, as your window is not the main application window, even if your window is a top level form.

Anyway, you should never need to use API calls, you're working with them from a foreign process and don't have the privileges on your already running process ID from outside. Even if it's quite common to manipulate other foreign windows, but rather seldom hidden ones.

I would go for the DDE solution. Store a reference to your form to goApp.Mainform at the initial start of it. Then instead of ZOOM WINDOW SCREEN NORM you do goApp.Mainform.Show() in the DDEZOOM procedure. If you don't have goApp you can use _SCREEN, even though you have SCREEN=OFF, the _screen object always exists.

DDE is that simple in VFP and it still works.

Bye, Olaf.
 
Sounds pretty good to me.

Little overhead with the file check, but nothing that should spoil a users experience

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top