Solved

Detect when screensaver activates

Posted on 1998-07-21
15
290 Views
Last Modified: 2010-04-04
Seems to be my day asking questions - but with the help of E-E my programming has come on leaps and bounds and the encouragement of my school IT Manager means that I'm busily writing quite-handy ( :) ) little apps during these long summer holidays (tough life, eh?)

I had the idea of an app that detected when the screensaver activated, waited a few minutes and then if the screensaver hadn't turned off, logged-off the user to stop people forgetting to log-off and consequently having trouble logging on the next day.

I had a look at SystemParametersInfo, with GETSCREENSAVERACTIVE (which is great for disabling c-a-d) but this only seems to find out whether screen-saving is enabled in display control panel....

TIA,

Ed
0
Comment
Question by:edmoore
  • 5
  • 5
  • 4
  • +1
15 Comments
 

Author Comment

by:edmoore
Comment Utility
Just to make it clear - I'm asking how to implement the idea I suggested.  Maybe I was a bit vague - maybe it's just me?
0
 
LVL 4

Expert Comment

by:erajoj
Comment Utility
Hi Ed,
a simple solution is to make your own screensaver and then invoke whatever screensaver you want to see on screen from within it.
A screensaver is just an EXE-file with another extension (SCR) and can be executed in the ordinary way (createprocess...).
The idea is that your (nonvisual) screensaver would get the handle of the visual screensaver and run a loop to detect if the process attached to the handle is stopped.
If not it would log off in the ordinary way (ExitWindowsEx...) after the desired time.
Not the most beautiful solution, but easy enough to implement in 15-20 mins or so...
If you need further assistance; mail me...

Regards,
/// John
0
 
LVL 6

Expert Comment

by:Holger101497
Comment Utility
erajoj: It takes a lot more to write a "good" screen saver than just renaming it!
For one thing, it must make sure it covers the task bar, it should provide a "config-dialog" when "Configure" is clicked and last but definitely not least, it should display a litttle preview in the desktop-properties window (in the little monitor). I spent more than 2 of hours writing one (a very simplistic one) two weeks ago and I have a good URL abut it... maybe I'll post it if I can find it...

But apart from that:
edmoore, I'm pretty optimistic I can help you find a solution, but I don't have the time right now to write a working program...

Here's something from the Delphi FAQ:
How do I turn the Windows Screen Saver on in code?

 Answer:

 The following function tests to see if the WIndows Screen Saver is
 available, and if so, turns it on:

 function TurnScreenSaverOn : bool;
 var
   b : bool;
 begin
   result := false;
   if SystemParametersInfo(SPI_GETSCREENSAVEACTIVE,
                           0,
                           @b,
                           0) <> true then exit;
   if not b then exit;
   PostMessage(GetDesktopWindow, WM_SYSCOMMAND, SC_SCREENSAVE, 0);
   result := true;
 end;

but I guess you already knew that, right?

The truly interesting part is from Delphi\Source\RTL\Win\WINDOWS.PAS:
const
  { Parameter for SystemParametersInfo() }
  {$EXTERNALSYM SPI_GETBEEP}
  SPI_GETBEEP = 1;
.
  {$EXTERNALSYM SPI_GETSCREENSAVEACTIVE}
  SPI_GETSCREENSAVEACTIVE = $10;
. (now this is the good part :-)
  {$EXTERNALSYM SPI_SCREENSAVERRUNNING}
  SPI_SCREENSAVERRUNNING = 97;
.

That should do it, shouldn't it?? I would imagine that
 SystemParametersInfo(SPI_GETSCREENSAVERRUNNING,
                           0,
                           @b,
                           0) <> true then exit;
returns what you're looking for in b :-))))

Good luck and let me know if that's all you need so I can post an "official answer" :-))
0
 

Author Comment

by:edmoore
Comment Utility
OK, Holger, thanks - that's great.  Post it as an answer and collect your points!

Ed
0
 
LVL 3

Expert Comment

by:vladika
Comment Utility
function IsScreenSaverRunning: LongBool;
var Dummy: Integer;
begin
  SystemParametersInfo(SPI_SCREENSAVERRUNNING, 1, @Result, 0);
  SystemParametersInfo(SPI_SCREENSAVERRUNNING, Integer(Result), @Dummy, 0);
end;

Reject if you want.

0
 
LVL 3

Expert Comment

by:vladika
Comment Utility
Edmore, Holger !

SORRY!!! Reject my answer!!!

0
 

Author Comment

by:edmoore
Comment Utility
"Rejection" sounds like such a strong term - sorry vladika - your answer was very helpful as well, but I had already promised the points to Holger.  Shame E-E doesn't let you give two "corrects"! (now there's an idea....)

Ed
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 6

Accepted Solution

by:
Holger101497 earned 50 total points
Comment Utility
ok, here it is - the "official answer" - solution see below/above.

Two "corrects" might be a good idea if they are different answers, but basically, vladika's answer is the same as mine (guess he didn't see it until after he posted his answer).
vladika: What does your second line do?
0
 
LVL 3

Expert Comment

by:vladika
Comment Utility
After first line I set SPI_SCREENSAVERRUNNING = 1

My second line restore previous SPI_SCREENSAVERRUNNING value
I must do it, isn't it? :)

0
 
LVL 6

Expert Comment

by:Holger101497
Comment Utility
Why do you have to restore something you don't change?
Ed doesn't want to start the screen saver, he just want to DETECT IF it is running. The state of the screen saver should not be changed and therefore, nothing has to be restored either...
0
 
LVL 3

Expert Comment

by:vladika
Comment Utility
You are mistaken.

> Why do you have to restore something you don't change?
I change by
  SystemParametersInfo(SPI_SCREENSAVERRUNNING, 1, @Result, 0);
I set SPI_SCREENSAVERRUNNING = 1
and previous SPI_SCREENSAVERRUNNING value went into Result.
Previous value maybe 0, maybe 1.
So, I must restore this value.

And I restore it by
  SystemParametersInfo(SPI_SCREENSAVERRUNNING, Integer(Result), @Dummy, 0);

If you did not restore previous state, you will have some by-effect.
For example disabling CTRL-ALT-DEL, maybe more...

0
 
LVL 6

Expert Comment

by:Holger101497
Comment Utility
ok, *might* be true, but I'll have to check the API when I'm back home. The code I posted is from the official Delphi FAQ:
  if SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, @b, 0) <> true then exit;
  if not b then exit;
  PostMessage(GetDesktopWindow, WM_SYSCOMMAND, SC_SCREENSAVE, 0);

Following your point, this code would first disable the screen saver before trying to turn it on - strange, huh?

Now I don't say you're wrong before checking... but it would be a serious problem... I guess ed wants to check for the status of the screen saver in a timer and he'd probably be very unhappy if the screen saver is turned off/off and back on/off every 30 seconds :-)))
Also, why would we have the PostMessage(GetDesktopWindow, WM_SYSCOMMAND, SC_SCREENSAVE, 0); command??

Let's hear ed's opinion - I guess he's tried the code already and it sounded like it worked.
If you're right, he'd notice right away because the screen saver wouldn't work any more (being turned off as soon as the function is called)

P.S.: Just a formality: SPI_SCREENSAVERRUNNING is a constant and it's value is 97
0
 
LVL 3

Expert Comment

by:vladika
Comment Utility
> Following your point, this code would first disable the screen saver before trying to turn it on - strange, huh?
No, It is not my point.

SPI_GETSCREENSAVEACTIVE only query whether screen saving is enabled or not.
SPI_SETSCREENSAVEACTIVE only set the state of the screen saver. (not running it)

BUT!!!
SPI_SCREENSAVERRUNNING query and set params at the same time!!!

Also I think you will not find SPI_SCREENSAVERRUNNING description in API.
I found in API only that SPI_SCREENSAVERRUNNING is internal parameter and all.

0
 

Author Comment

by:edmoore
Comment Utility
OK, I got it to work but Delphi 2 didn't like SPI_SCREENSAVERRUNNING (wasn't listed in the windows.pas Holger came up with either - maybe that's D3?) but when I stuck 97 in instead it worked fine...

Incidentally, what do think is the best way to first, keep checking if the screensaver is on, and then wait say 10 minutes.  I was going to use a timer, but are they particularly resource-intensive?

Ed
0
 
LVL 6

Expert Comment

by:Holger101497
Comment Utility
As far as I know, a timer is the best way to wait for a longer time and Borland probably implemented them very efficiently by using the windows-functions that are available - they use a "windows timer event" - whatever that is.

The only way of waiting without a timer looks like this:

procedure Delay(ms : longint);
 var TheTime : LongInt;
 begin
   TheTime := GetTickCount + ms;
   while GetTickCount < TheTime do
     Application.ProcessMessages;
 end;

but I really can't imagine that that's more efficient, since the loop keeps going and going and going... I think if you set your timer interval to 20000 ms or so, that should be quite ok. Check the ressource-meter and I'm pretty sure your process will have less than 1% CPU-time (if you use NT, you can check CPU time for individual programs)
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now