Как определить версию Windows?
Определение что Screen Saver запустился.
Доп. возможности борьбы со Screen Saver-ом.
В практике написания программ иногда возникают моменты, когда необходимо определить, что на машине запустился Screen Saver (ScS), и выполнить какие-либо действия (скажем свернуть программу и т.д.).
Задача усложняется тем, что для различных версий Windows, механизм запуска и работы со ScS различны. Так, например в Win 3.5x, 4.x ScS запукается в отдельном рабочем столе, называемом «screen-saver» (кто бы мог подумать!), и не существует прямых способов узнать работает ли ScS или нет. (есть только кривой, описываемый ниже). Для Windows 95 мне так и не удалось отыскать способа для решения задачи по определению запущен ScS или нет. (буду рад, если кто поделится опытом).
Итак, исходя из вышесказанного, прежде чем браться за ScS, не худо бы для начала определить версию Windows, под которой работает программа.
Итак:
Определяем версиюWindows
(здесь и далее все приводится для 32-х разрядных приложений):
Для определения версии Windows существует несколько способов. Рассмотрим здесь применение горячо любимых в народе Win API.
Для определения версии Windows применяется функция:
GetVersionExA(*OSVERSIONINFO),BOOL,PASCAL,RAW
передаваемый параметр — буфер для приема информации по версии Windows. Сей буфер в кларионовском изображении выглядит следующим образом:
OSVERSIONINFO GROUP,TYPE dwOSVersionInfoSize DWORD !размер буфера dwMajorVersion DWORD !старший № в версии Windows dwMinorVersion DWORD !младший № в версии Windows dwBuildNumber DWORD !№ сборки dwPlatformId DWORD !идентификатор платформы Win32 szCSDVersion CHAR,DIM(128) !доп. инфо (напрмер о сервис-паках для NT) END
для более детального ознакомления с каждым из параметров можно глянуть в любой из Win API Help-ов. Приведем здесь значения, необходимые для определения версии Windows:
Win95
Win98
WinNT 5.51
WinNT 4.0
Win 2000
dwMajorVersion
4
4
3
4
5
dwMinorVersion
0
10
51
0
0
dwPlatformId
1
1
2
2
2
далее в программе:
CurrentVer GROUP(OSVERSIONINFO) !определяем группу END : CurrentVer.dwOSVersionInfoSize=SIZE(CurrentVer) !перед вызовом ф-ции определяем размерчик ERR#=GetVersionExA(CurrentVer) !вызываем функцию CASE CurrentVer.dwPlatformId !определяем тип OF 1 IF CurrentVer.dwMinorVersion=0 Ver"='Win95' ELSIF CurrentVer.dwMinorVersion=10 Ver"='Win98' END OF 2 IF CurrentVer.dwMajorVersion=3 Ver"='WinNT 3.51' ELSIF CurrentVer.dwMajorVersion=4 Ver"='WinNT 4.0' ELSIF CurrentVer.dwMajorVersion=5 Ver"='Windows 2000' END END
Вот так. Переходим теперь, собственно к
Определившись с типом Windows, можно приступать непосредственно к решению задачи по определению работы ScS. Для решения этой задачи нам потребуется определится с несколькими константами
MAXIMUM_ALLOWED EQUATE(02000000H) ERROR_ACCESS_DENIED EQUATE(5) ERROR_FILE_NOT_FOUND EQUATE(2)
Основная функция, используемая при этом будет:
SystemParametersInfo(unsigned uiAction, | unsigned uiParam, | pvoid pvParam, | unsigned fWinIni), bool, pascal, raw, name('SystemParametersInfoA')
Параметры:
uiAction
Определяет системный параметр который надо выставить или определить. Может принимать тучу значений, нас же в данный момент интересуют лишь 2:
SPI_SCREENSAVERRUNNING EQUATE(97) SPI_GETSCREENSAVERRUNNING EQUATE(114)
uiParam
Зависит от предпринимаемого действия, если не указано иначе, то 0.
pvParam
Зависит от предпринимаемого действия
fWinIni
Флаг обновления юзеровского профиля
Заводим некую переменную, в которой будет хранится результат активен ScS или нет:
IsActive BYTE
Далее в зависимости от версии Windows:
Для Win95:
ERR#=SystemParametersInfo(SPI_SCREENSAVERRUNNING,0,ADDRESS(IsActive),0)
судя по всему должно быть так, но не работает. Единственная возможность определения запущен ScS или нет видится в использовании того факта, что при старте ScS посылает WM_SYSCOMMAND сообщение к top-level окну с WPARAM равным SC_SCREENSAVE. Теоретически, если сделать subclass на окно и отловить это сообщение, то можно узнать о запуске ScS.
Для Win98, Win2000:
ERR#=SystemParametersInfo(SPI_GETSCREENSAVERRUNNING,0,ADDRESS(IsActive),0)
Если IsActive = true, то ScS работает.
Для WinNT (здесь начинается самое интересное):
DeskName='screen-saver' !имя desktop-а с ScS DHN#=OpenDesktop(DeskName,0,0,MAXIMUM_ALLOWED) !откр. desktop с полным доступом IF DHN# !есть такая партия CloseDesktop(DHN#) !закрываем desktop IsActive=true ELSE !ошибка IF GetLastError() = ERROR_ACCESS_DENIED !если не хватает прав но desktop есть, то IsActive=true !ScS активен END END
При удачном открытии desktop-а ф-ция OpenDesktop возвращает handle oткрытого desktop-а, при неудачном — NULL. При использовании этой ф-ции для определения Screen Saver-а возможны 3 варианта:
OpenDesktop удачно открыл desktop ‘screen-saver’. ScS запущен.
Попытка открыть desktop неудачна и GetLastError() вернул ошибку ERROR_ACCESS_DENIED — desktop ‘screen-saver’ существует, но не хватает прав на его открытие. ScS запущен
Попытка открыть desktop неудачна и GetLastError() вернул ошибку отличную от ERROR_ACCESS_DENIED (скорее всего ERROR_FILE_NOT_FOUND). ScS не запущен.
Вот, собственно и все по поводу определения активности Screen Saver-а.
Дополнительные возможности работы с Screen Saver-ом.
Как определить установлен ли ScS на машине:
SPI_GETSCREENSAVEACTIVE EQUATE(16) SPI_SETSCREENSAVEACTIVE EQUATE(17) : ERR#= SystemParametersInfo(SPI_GETSCREENSAVEACTIVE,0,ADDRESS(IsActive),0)
если переменная IsActive = true, то ScS установлен в панели «Настройки экрана».
Для запрещения ScS на компьютере, следует применить
SPIF_SENDWININICHANGE EQUATE(0002h) : ERR#= SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,false,0, SPIF_SENDWININICHANGE)
Для разрешения работы ScS на компьютере:
ERR#= SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,true,0, SPIF_SENDWININICHANGE)
Для остановки запущенного ScS для Win95-98 следует орудовать функцией Win API:
WM_CLOSE EQUATE(0010h) : PostMessage(GetActiveWindow(),WM_CLOSE,0,0)
для WinNT и Win 2000 опять идем другим путем:
сооружаем callback процедурку типа:
ShutUpScreenSaver ((HANDLE hWindow, LPARAM Param),BOOL,PASCAL CODE IF IsWindowVisible(hWindow) PostMessage(hWindow,WM_CLOSE,0,0) RETURN true END
определяем handle desktop-а, как было описано выше (можно использовать доступ не MAXIMUM_ALLOWED, а что-то вроде:
DESKTOP_READOBJECTS EQUATE(0001h) DESKTOP_WRITEOBJECTS EQUATE(0080h)
определивши handle desktop-а (скажем hDesk), пишем:
IF hDesk EnumDesktopWindows(hDesk, ShutUpScreenSaver,0) CloseDesktop(hDesk) END
Следует обратить внимание, что метод описанный для запрещения ScS на компьютере пригоден также для остановки запущенного ScS, но после этого для активизации ScS необходимо либо вручную запустить его через свойства экрана, либо см. (как разрешить работу ScS на компьютере).
PS. При написании данной статьи частично использовались материалы из IceTips Knowlege Base, в частности сообщение посланное Stephen Bottomley).
Новиков Антон (С) 2000