Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.09.16;
Скачать: CL | DM;

Вниз

Бьюсь над проблемой: как узнать, что скринсэйвер работает?   Найти похожие ветки 

 
Song ©   (2002-09-03 14:31) [0]

Отлавливаю 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-03 14:37) [1]

Если я не брежу, на время работы ScreenSaver в реестре выставляется флажок... Надо будет поглядеть дома книгу


 
Song ©   (2002-09-03 14:43) [2]

О.. класс, а могёшь мне на почту скинуть? Надо...


 
Внук ©   (2002-09-03 14:45) [3]

Завтра, постараюсь не забыть, если не соврал, конечно :)


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

Вот здесь вроде что-то есть:
http://cw.net.gaming.ru/Russian/ARTS/Screen_Saver.html


 
Song ©   (2002-09-03 15:54) [5]

Не работает SPI_GETSCREENSAVERRUNNING в Windows98SE, хоть убей...


 
Виктор Щербаков ©   (2002-09-03 16:06) [6]

Song © (03.09.02 15:54)
Ага. Она вообще без изменений оставляет значение по адресу @IsActive. Наверно Билл и его ребята оставили это на сладкое, а потом и вовсе забыли :)


 
Song ©   (2002-09-03 16:14) [7]

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


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


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

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

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


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

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


 
Song ©   (2002-09-03 16:23) [10]

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


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

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


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

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


 
Song ©   (2002-09-03 16:36) [13]

С 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


 
Alx2 ©   (2002-09-03 16:41) [14]

Где-то вычитал, что класс окошка 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;


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

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

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

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

С уважением,


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

Я делал очень просто:
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 17:37) [17]


> Song © (03.09.02 16:36)


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

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


 
Song ©   (2002-09-03 17:38) [18]

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


 
Song ©   (2002-09-03 17:40) [19]

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


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

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


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


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

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


 
Song ©   (2002-09-03 18:42) [22]

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


 
Внук ©   (2002-09-04 09:55) [23]

Посмотрел я книгу, да, про параметр реестра я имел в виду именно 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-04 09:59) [24]

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

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


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


> Под Win95 - SPI_SCREENSAVERRUNING

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


 
Внук ©   (2002-09-04 10:15) [26]

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



Страницы: 1 вся ветка

Текущий архив: 2002.09.16;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.011 c
1-50798
maxim2
2002-09-03 08:14
2002.09.16
Как текст из RichEdit сохранить в файл?


7-50987
Zlo@der
2002-06-27 15:53
2002.09.16
Как узнать серийный номер винта.


1-50686
Лана Розанова
2002-09-04 16:03
2002.09.16
Фильтры


1-50817
ErmSergey
2002-08-31 14:24
2002.09.16
Утечка ресурсов


1-50725
Незнайка
2002-09-05 14:27
2002.09.16
Таблицы в RichEdit