Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Бьюсь над проблемой: как узнать, что скринсэйвер работает? [D6, Win95/98, NT4, WinXP]


Страницы:   1 2

Song ©   (2002-09-03 14:31:00) 

Отлавливаю WM_SYSCOOMAND c WParam=SC_SCREESAVE
по наступлению события включаю выполнениие нити (TThread), где постоянно опрашиваю:

SystemParametersInfo(SPI_GETSCREENSAVERRUNNING,0,@IsActive,0);
IF not IsActive then ...


При выключении хранителя экранаусловие не срабатывает!

Пробовал также через GetActiveWindow(). Почему-то на второй "итерации" TThread.Synchronize GetActiveWindow() возвращает ноль, хотя заставка запущена.

MSDN также советует через OpenDeskTop(), но.. это дремучая вещь, хотя и придётся сделать, если не получится.
Может у кого идеи есть?


Внук   (2002-09-04 10:15:00) [1]

>>Виктор Щербаков © (04.09.02 10:11)
SPI_SCREENSAVERRUNNING
Windows 95 only: Used internally; applications should not use this flag.


Виктор Щербаков   (2002-09-04 10:11:00) [2]


> Под Win95 - SPI_SCREENSAVERRUNING

Вот именно под Win95 она и не работает :(
См. Виктор Щербаков © (03.09.02 16:21)
Похоже, что работа функции с параметром SPI_SCREENSAVERRUNING не реализована в этой ОС.


Song   (2002-09-04 09:59:00) [3]

Под Win95 - SPI_SCREENSAVERRUNING. Под NT - OpenDeskTop()
Ну вообщем уже не надо, всё работает, спасибо Набережных С.

Но теперь новая проблема. TThread у меня запускается, как я уже говорил, по WM_SYSCOMMAND, SC_SCREENSAVE. И это всё теперь Ok работает, НО только когда прога активная, а когда скрыта и значок в трее или просто на заднем плане - хрен! Без хука как-нить можно обойтись?


Внук   (2002-09-04 09:55:00) [4]

Посмотрел я книгу, да, про параметр реестра я имел в виду именно ScreenSaveActive, но это не то (см. Виктор Щербаков © 03.09.02 16:34)
Пришлось идти другим путем (через SDK :)), вот этот код работает:

program ScreenTest;

uses Windows;

{$R *.RES}

var Flag:Bool;
ResFile:Text;
begin
Flag:=false;
Sleep(90000);
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING,0,@Flag,0);
AssignFile(ResFile,"ResFile.txt");
Rewrite(ResFile);
if Flag then WriteLn(ResFile,"ScreenSaver is active")
else WriteLn(ResFile,"ScreenSaver is passive");
CloseFile(ResFile);
end.
Проверено под WinXP, WinMe, будет работать под Win98, Win2000.
А вот под WinNT и Win95, скорее всего нужно что-то другое изобретать :)


Song   (2002-09-03 18:42:00) [5]

Всё, спасибо большое, Набережных С.
Сделал, завтра проверю на сети.
Надо было в WM_SYSCOMMAND сделать цикл до тех пор пока не поменяется GetForeGroundWindow(т.е. до тех пор пока не запуститься хранитель), а потом в потоке подождать пока дискриптор не поменяется снова, но теперь уже на ноль (дискрптор рабочего стола) что означает что хранитель экрана закрыт.
А... что до записи классов.. я сделал - TForm1 везде было :-))))


Набережных С.   (2002-09-03 18:03:00) [6]


> Song © (03.09.02 17:40)
> 2Набережных С.
> Нет, а задержку в 5 сек я для чего сделал?

А я почем знаю?:)))))
А если серьезно, так ты же ее в обработчике WM_SYSCOMMAND делаешь - ну и что с нее толку?


Набережных С.   (2002-09-03 17:54:00) [7]

Да ты попробуй:)


Song   (2002-09-03 17:40:00) [8]

2Набережных С.
Нет, а задержку в 5 сек я для чего сделал?


Song   (2002-09-03 17:38:00) [9]

А я вот думаю, а если у него вообще окошко-то? Все заставки что я проверял были с OpenGL т.е. там метаморфозы, объёмный текст и прочая дребедень... Может тогда есть какой-нибудь другой уникальный номер, PID например, по которому можно проверить.
Так или иначе сейчас проверять ничего не могу.. радиомышь сдохла :-((( Только завтра на работе.
Спасибо всем. Приходите завтра :-)


Набережных С.   (2002-09-03 17:37:00) [10]


> Song © (03.09.02 16:36)


> И вот реультат файла results:
> *********************
> 936
> 3840
> ********************
> Отчего бы?

Первый - хендл окна, активного перед запуском хранителя(вероятно, твоей проги).
Второй - хендл окна хранителя.
Добавь запись в файл класса окна.


Виктор Щербаков   (2002-09-03 16:46:00) [11]

Я делал очень просто:
procedure TForm1.Button1Click(Sender: TObject);
var IsActive: Integer;
begin
SendMessage(Handle, WM_SYSCOMMAND, SC_SCREENSAVE, 0);
Sleep(500);
Label1.Caption := IntToStr(GetForeGroundWindow);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Label1.Caption := IntToStr(GetForeGroundWindow);
end;
После примерно секунды работы заставки, я её выключал. Затем сравнивал хэндл с получаемым при нажатии на Button2. Они были разными. Так, конечно, делать нельзя (это о sleep(500)), но в качестве проверки - вполне.


Игорь Шевченко   (2002-09-03 16:43:00) [12]

Я бы рекомендовал заглянуть на

http://www.codeproject.com/samples/winmgr.asp

Может, что по теме найдется.

С уважением,


Alx2   (2002-09-03 16:41:00) [13]

Где-то вычитал, что класс окошка ScreenSavera зовется "WindowsScreenSaverClass". Может стоит попробовать FindWindow на это дело?




Screen savers contain specific exported functions, resource definitions, and variable declarations. The static-link library SCRNSAVE.LIB contains the main function and other startup code required for a screen saver. When a screen saver starts, the startup code in SCRNSAVE.LIB creates a full-screen window. The window class for this window is declared as follows.

WNDCLASS cls;

cls.hCursor = NULL;
cls.hIcon = LoadIcon(hInst, MAKEINTATOM(ID_APP));
cls.lpszMenuName = NULL;
cls.lpszClassName = "WindowsScreenSaverClass";
cls.hbrBackground = GetStockObject(BLACK_BRUSH);
cls.hInstance = hInst;
cls.style = CS_VREDRAW | CS_HREDRAW |
CS_SAVEBITS | CS_DBLCLKS;
cls.lpfnWndProc = (WNDPROC) ScreenSaverProc;
cls.cbWndExtra = 0;
cls.cbClsExtra = 0;


Song   (2002-09-03 16:36:00) [14]

С GetForeGroundWindow тоже ничего не вышло..
Вот интересно, я встроил "шпиона" в лице экземпляра TStringList и вот что у меня вышло:


unit ScreenSaverThread;

interface

uses
Classes, Windows, Kld, SysUtils;

type
TScreenSaveObject = class(TThread)
protected
procedure CheckForScreenSaverRunning;
procedure Execute; override;
end;

Procedure InitializeThread;

implementation

Var Thread:TScreenSaveObject; // Экземлпяр потока
ScreenSaverHandle:HWND;
Str:TStringList;

Procedure InitializeThread;
Begin
Sleep(5000);
Thread:=TScreenSaveObject.Create(False);
With Thread Do
Begin
FreeOnTerminate:=True;
Priority:=tpNormal;
End;
ScreenSaverHandle:=GetForeGroundWindow;
Str:=TStringList.Create;
Str.Add(IntToStr(ScreenSaverHandle));
End;

procedure TScreenSaveObject.CheckForScreenSaverRunning;
Begin
Str.Add(IntToStr(GetForeGroundWindow));
IF GetForeGroundWindow<>ScreenSaverHandle then // Терминируем поток, когда скринсэйвер закроется
Begin
...
// Скринсэйвер закрыт

Str.SaveToFile("c:\results");
Str.Free;
Thread.Terminate; // Закрываем поток
End;
End;

procedure TScreenSaveObject.Execute;
begin
While not Terminated Do Synchronize(CheckForScreenSaverRunning);
end;

end.


И вот реультат файла results:
*********************
936
3840
********************
Отчего бы?

С GetActiveWindow() примерно также, только последний ноль.

P.S. InitializeThread вызывается по WM_SYSCOMMAND


Виктор Щербаков   (2002-09-03 16:34:00) [15]

Внук © (03.09.02 16:27)
Не, этот параметр означает несколько иное. А именно, активен какой-нибудь скринсейвер или нет. При этом нельзя определить запущен ли он в данный момент.


Внук   (2002-09-03 16:27:00) [16]

Нашел я веточку
HKEY_CURRENT_USER\Control Panel\Desktop
Параметр ScreenSaveActive, да по-моему лажа это...


Song   (2002-09-03 16:23:00) [17]

MSDN советует использовать для скринсэйвера именно GetActiveWindow.. хотя ща попробую и foreground :-)


Виктор Щербаков   (2002-09-03 16:21:00) [18]

Наверно стоит попробовать GetForeGroundWindow?


Виктор Щербаков   (2002-09-03 16:17:00) [19]


> Отчего бы... ??

The GetActiveWindow function retrieves the window handle to the active window associated with the thread that calls the function.

Может по-этому?


Song   (2002-09-03 16:14:00) [20]

Вообще интересно.. почему не работает GetActiveWindow ?
В момент запуска GetActiveWindow возвращает дискриптор приложения-скринсэйвера, а потом на следующий вызов в нити возвращает ноль... Отчего бы... ??


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо