Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2002.09.16;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




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


8-50873
fore_3
2002-05-16 12:54
2002.09.16
Проблема с перемоткой DVD


3-50660
mas_alexey
2002-08-22 18:56
2002.09.16
BDE


14-50976
Жираф большой
2002-08-20 15:48
2002.09.16
Про яйца


14-50944
Malder
2002-08-20 22:18
2002.09.16
AudioGalaxy - был шедевром





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский