Помощь в написании студенческих работ
Антистрессовый сервис

Создание хранителя екрана

РефератПомощь в написанииУзнать стоимостьмоей работы

Если все-таки важко уникнути використання Delphi-форм, можна вступити як у із запровадженням пароля: форму зміни параметрів хранителя зберегти в вигляді DLL і динамічно її завантажувати за необхідності. Т.а. буде маленькі груди й шустрий файл самого хранителя екрану і доважка DLL для конфигурирования і іншого (там об'єм і швидкість не критичны). Технически, хранитель екрана є нормальним EXE… Читать ещё >

Создание хранителя екрана (реферат, курсовая, диплом, контрольная)

Создание хранителя екрана

Главное про що варто згадати це, що ваша хранитель екрана працюватиме на фоновому режимі, і вона повинна заважати роботи інших запущених програм. Тому сам хранитель має бути як можна меншого обсягу. Для зменшення обсягу файла в описаної нижче програмі немає візуальні компоненти Delphi, включення хоча самого їх призведе до підвищення розміру файла понад 200кб, а так, описана нижче програма, має розмір всього 20кб!!!

Технически, хранитель екрана є нормальним EXE файлом (з розширенням .SCR), який управляється через командні параметри рядки. Наприклад, якщо користувач хоче змінити параметри вашого хранителя, Windows виконує його з параметром «-з «в командної рядку. Тому розпочати створення вашого хранителя екрана варто з створення приблизно такою функции:

Procedure RunScreenSaver;

Var P. S: String;

Begin.

S := ParamStr (1);

If (Length (S) > 1) Then Begin.

Delete (S, 1,1);

{ delete first char — usally «/ «or «- «}.

S[1] := UpCase (S[1]);

End;

LoadSettings; { load settings from registry }.

If (P.S = «З ») Then RunSettings.

Else If (P.S = «P ») Then RunPreview.

Else If (P.S = «A ») Then RunSetPassword.

Else RunFullScreen;

End;

Поскольку ми мусимо створювати невеличке вікно попереднього перегляду і полноэкранное вікно, ліпше об'єднати, використовуючи єдиний клас вікна. Дотримуючись правилам доброго тону, нам також потрібно використовувати численні нитки. Річ у тім, що, по-перше, хранитель ні переставати працювати, навіть якщо щось «важке «сталося, і, по-друге, ми мусимо використовувати таймер.

Процедура для запуску хранителя на повному екрані - приблизно такова:

Procedure RunFullScreen;

Var.

R: TRect;

Msg: TMsg;

Dummy: Integer;

Foreground: hWnd;

Begin.

IsPreview := False; MoveCounter := 3;

Foreground := GetForegroundWindow;

While (ShowCursor (False) > 0) do ;

GetWindowRect (GetDesktopWindow, R);

CreateScreenSaverWindow (R.Right-R.Left, R. Bottom-R.Top, 0);

CreateThread (nil, 0,@PreviewThreadProc, nil, 0, Dummy);

SystemParametersInfo (spi_ScreenSaverRunning, 1,@Dummy, 0);

While GetMessage (Msg, 0,0,0) do Begin //відповідаємо на сообщения.

TranslateMessage (Msg); //що не повісити windows.

DispatchMessage (Msg);

End;

SystemParametersInfo (spi_ScreenSaverRunning, 0,@Dummy, 0);

ShowCursor (True);

SetForegroundWindow (Foreground);

End;

Во-первых, ми проинициализировали деякі глобальні перемінні (описані далі), потім ховаємо курсор миші і створюємо вікно хранителя екрана. Майте у вигляді, це важливо повідомляти Windows, що це — хранителя екрана через SystemParametersInfo (це виводить з експлуатації Ctrl-Alt-Del щоб не міг повернутися до Windows не запровадивши пароль). Створення вікна хранителя:

Function CreateScreenSaverWindow (Width, Height: Integer;ParentWindow: hWnd): hWnd;

Var WC: TWndClass;

Begin.

With WC do Begin.

Style := cs_ParentDC;

lpfnWndProc := @PreviewWndProc;

cbClsExtra := 0; cbWndExtra := 0;

hIcon := 0; hCursor := 0;

hbrBackground := 0; lpszMenuName := nil;

lpszClassName:= «MyDelphiScreenSaverClass » ;

hInstance := System. hInstance;

end;

RegisterClass (WC);

If (ParentWindow 0) Then.

Result := CreateWindow («MyDelphiScreenSaverClass », «MySaver », ws_Child Or ws_Visible or ws_Disabled, 0,0,Width, Height, ParentWindow, 0, hInstance, nil).

Else Begin.

Result := CreateWindow («MyDelphiScreenSaverClass », «MySaver », ws_Visible or ws_Popup, 0,0,Width, Height, 0,0,hInstance, nil);

SetWindowPos (Result, hwnd_TopMost, 0,0,0,0,swp_NoMove or swp_NoSize or swp_NoRedraw);

End;

PreviewWindow := Result;

End;

Теперь вікна створено використовуючи виклики АПІ. Я видалив перевірку помилки, але зазвичай усе проходить добре, особливо у цьому типі приложения.

Теперь Можете поворожити, як ми матимемо handle батьківського вікна попереднього перегляду? Насправді, це ще просто: Windows просто передає handle в командної рядку, коли це потрібно. Таким образом:

Procedure RunPreview;

Var.

R: TRect;

PreviewWindow: hWnd;

Msg: TMsg;

Dummy: Integer;

Begin.

IsPreview := True;

PreviewWindow := StrToInt (ParamStr (2));

GetWindowRect (PreviewWindow, R);

CreateScreenSaverWindow (R.Right-R.Left, R. Bottom-R.Top, PreviewWindow);

CreateThread (nil, 0,@PreviewThreadProc, nil, 0, Dummy);

While GetMessage (Msg, 0,0,0) do Begin.

TranslateMessage (Msg);

DispatchMessage (Msg);

End;

End;

Как Ви бачите, window handle є другим параметром (після «-p »).

Чтобы «виконувати «хранителя екрана — потрібна нам нитку. Це створюється з вищевказаним CreateThread. Процедура нитки виглядає так:

Function PreviewThreadProc (Data:Integer): Integer; StdCall;

Var R: TRect;

Begin.

Result := 0; Randomize;

GetWindowRect (PreviewWindow, R);

MaxX := R. Right-R.Left;

MaxY := R. Bottom-R.Top;

ShowWindow (PreviewWindow, sw_Show);

UpdateWindow (PreviewWindow);

Repeat.

InvalidateRect (PreviewWindow, nil, False);

Sleep (30);

Until QuitSaver;

PostMessage (PreviewWindow, wm_Destroy, 0,0);

End;

Нить просто змушує оновлюватися зображення на нашому вікні, спить на деяке час, і оновлює зображення знову. А Windows слатиме повідомлення WM_PAINT нашу вікно (над нитку !). А, щоб оперувати цим повідомленням, потрібна нам процедура:

Function PreviewWndProc (Window:hWnd; Msg, WParam, LParam: Integer): Integer;StdCall;

Begin.

Result := 0;

Case Msg of.

wm_NCCreate: Result := 1;

wm_Destroy: PostQuitMessage (0);

{ paint something }.

wm_Paint: DrawSingleBox;

wm_KeyDown: QuitSaver := AskPassword;

wm_LButtonDown, wm_MButtonDown,.

wm_RButtonDown, wm_MouseMove :

Begin.

If (Not IsPreview) Then Begin.

Dec (MoveCounter);

If (MoveCounter <= 0) Then.

QuitSaver :=AskPassword;

End;

End;

Else Result := DefWindowProc.

(Window, Msg, WParam, LParam);

End;

End;

Если миша переміщається чи натиснута кнопки, ми вимагаємо в користувача пароль:

Function AskPassword: Boolean;

Var.

Key: hKey;

D1,D2: Integer; { two dummies }.

Value: Integer;

Lib: THandle;

F: TVSSPFunc;

Begin.

Result := True;

If (RegOpenKeyEx (hKey_Current_User, «Control PanelDesktop », 0, Key_Read, Key) = Error_Success) Then.

Begin.

D2 := SizeOf (Value);

If (RegQueryValueEx (Key, «ScreenSaveUsePassword », nil,@D1, @Value,@D2) = Error_Success) Then.

Begin.

If (Value 0) Then Begin.

Lib := LoadLibrary («PASSWORD.CPL »);

If (Lib > 32) Then Begin.

@F := GetProcAddress (Lib, «VerifyScreenSavePwd »);

ShowCursor (True);

If (@F nil) Then Result := F (PreviewWindow);

ShowCursor (False);

{ reset again if password was wrong }.

MoveCounter := 3;

FreeLibrary (Lib);

End;

End;

End;

RegCloseKey (Key);

End;

End;

Это також демонструє використання registry лише на рівні АПІ. Також майте у вигляді як ми динамічно завантажуємо функції пароля, використовуючи LoadLibrary. Запам’ятайте тип функции?

TVSSFunc ВИЗНАЧЕНО как:

Type.

TVSSPFunc = Function (Parent: hWnd): Bool; StdCall;

Теперь майже всі готове, крім діалогу конфігурації. Це запросто:

Procedure RunSettings;

Var Result: Integer;

Begin.

Result := DialogBox (hInstance, «SaverSettingsDlg », 0,@SettingsDlgProc);

If (Result = idOK) Then SaveSettings;

End;

Трудная частинаце створити діалоговий сценарій (запам'ятайте: ми використовуємо тут Delphi форми!). Я зробив, використовуючи 16-битовую Resource Workshop (залишився ще від Turbo Pascal для Windows). Я зберіг файл як сценарій (текст), і скомпільований це з BRCC32:

SaverSettingsDlg DIALOG 70, 130, 166, 75.

STYLE WS_POPUP | WS_DLGFRAME | WS_SYSMENU.

CAPTION «Settings for Boxes «.

FONT 8, «MS Sans Serif «.

BEGIN.

DEFPUSHBUTTON «OK », 5, 115, 6, 46, 16.

PUSHBUTTON «Cancel », 6, 115, 28, 46, 16.

CTEXT «Box &Color: », 3, 2, 30, 39, 9.

COMBOBOX 4, 4, 40, 104, 50, CBS_DROPDOWNLIST |.

CBS_HASSTRINGS.

CTEXT «Box &Type: », 1, 4, 3, 36, 9.

COMBOBOX 2, 5, 12, 103, 50,.

CBS_DROPDOWNLIST | CBS_HASSTRINGS.

LTEXT «Boxes Screen Saver for.

Win32 Copyright© 1996 Jani Jurvinen. «.

7, 4, 57, 103, 16,.

WS_CHILD | WS_VISIBLE | WS_GROUP.

END.

Почти також легко зробити діалогове меню:

Function SettingsDlgProc (Window:hWnd;Msg, WParam, LParam: Integer): Integer; StdCall;

Var P. S: String;

Begin.

Result := 0;

Case Msg of.

wm_InitDialog: Begin.

{ initialize the dialog box }.

Result := 0;

End;

wm_Command: Begin.

If (LoWord (WParam) = 5) Then.

EndDialog (Window, idOK).

Else.

If (LoWord (WParam) = 6) Then.

EndDialog (Window, idCancel);

End;

wm_Close: DestroyWindow (Window);

wm_Destroy: PostQuitMessage (0);

Else Result := 0;

End;

End;

После того, як користувач вибрав деякі настановні параметри, ми мусимо зберегти их.

Procedure SaveSettings;

Var.

Key: hKey;

Dummy: Integer;

Begin.

If (RegCreateKeyEx (hKey_Current_User,.

" SoftwareSilverStreamSSBoxes " ,.

0,nil, Reg_Option_Non_Volatile,.

Key_All_Access, nil, Key,.

@Dummy) = Error_Success) Then Begin.

RegSetValueEx (Key, «RoundedRectangles », 0, Reg_Binary,@RoundedRectangles,.

SizeOf (Boolean));

RegSetValueEx (Key, «SolidColors », 0, Reg_Binary, @SolidColors, SizeOf (Boolean));

RegCloseKey (Key);

End;

End;

Загружаем параметри так:

Procedure LoadSettings;

Var.

Key: hKey;

D1,D2: Integer; { two dummies }.

Value: Boolean;

Begin.

If (RegOpenKeyEx (hKey_Current_User, «SoftwareSilverStreamSSBoxes », 0, Key_Read, Key) = Error_Success) Then Begin.

D2 := SizeOf (Value);

If (RegQueryValueEx (Key, «RoundedRectangles », nil,@D1,@Value, @D2) = Error_Success) Then.

Begin.

RoundedRectangles := Value;

End;

If (RegQueryValueEx (Key, «SolidColors », nil,@D1,@Value,@D2) = Error_Success) Then.

Begin.

SolidColors := Value;

End;

RegCloseKey (Key);

End;

End;

Легко? Нам також потрібно дозволити користувачеві, встановити пароль. Я чесно не знаю чому це залишено розробникові додатків! Проте він менее:

Procedure RunSetPassword;

Var.

Lib: THandle;

F: TPCPAFunc;

Begin.

Lib := LoadLibrary («MPR.DLL »);

If (Lib > 32) Then Begin.

@F := GetProcAddress (Lib, «PwdChangePasswordA »);

If (@F nil) Then F («SCRSAVE », StrToInt (ParamStr (2)), 0,0);

FreeLibrary (Lib);

End;

End;

Мы динамічно завантажуємо (недокументированную) бібліотеку MPR. DLL, має функцію, аби з’ясувати пароль хранителя екрана, отже ми мусимо турбуватися про этом.

TPCPAFund ВИЗНАЧЕНО как:

Type.

TPCPAFunc = Function (A: PChar; Parent: hWnd; B, C: Integer): Integer; StdCall;

(Не запитуйте мене, що за параметри B і З ! :-).

Теперь єдина річ, яку потрібно розглянути, — сама дивна частина: створення графіки. Не великий ГУРУ графіки, отже Ви побачите затеняющие багатокутники, які працюють у часі. Я зробив деякі ящики.

Procedure DrawSingleBox;

Var.

PaintDC: hDC;

Info: TPaintStruct;

OldBrush: hBrush;

X, Y: Integer;

Color: LongInt;

Begin.

PaintDC := BeginPaint (PreviewWindow, Info);

X := Random (MaxX); Y := Random (MaxY);

If SolidColors Then.

Color := GetNearestColor (PaintDC,.

RGB (Random (255), Random (255).

Random (255))).

Else Color := RGB (Random (255),.

Random (255), Random (255));

OldBrush := SelectObject (PaintDC,.

CreateSolidBrush (Color));

If RoundedRectangles Then.

RoundRect (PaintDC, X, Y, X+Random (MaxX-X),.

Y+Random (MaxY-Y), 20,20).

Else Rectangle (PaintDC, X, Y, X+Random (MaxX-X),.

Y+Random (MaxY-Y));

DeleteObject (SelectObject (PaintDC, OldBrush));

EndPaint (PreviewWindow, Info);

End;

И останнє - глобальні переменные:

Var.

IsPreview: Boolean;

MoveCounter: Integer;

QuitSaver: Boolean;

PreviewWindow: hWnd;

MaxX, MaxY: Integer;

RoundedRectangles: Boolean;

SolidColors: Boolean;

Затем вихідна програма проекту (.dpr). Гарна, а?!

program MySaverIsGreat;

uses.

windows, messages, Utility;

{ defines all routines }.

{$R SETTINGS. RES}.

begin.

RunScreenSaver;

end.

Ох, майже забув! Якщо, Ви використовуєте SysUtils у вашій проекті (наприклад фуекцию StrToInt) ви отримаєте EXE-файл більш ніж обіцяний в 20k. :) Якщо ви хочете все-таки иметь20k, треба якось уникнути SysUtils, наприклад самому написати власну StrToInt процедуру.

Если все-таки важко уникнути використання Delphi-форм, можна вступити як у із запровадженням пароля: форму зміни параметрів хранителя зберегти в вигляді DLL і динамічно її завантажувати за необхідності. Т.а. буде маленькі груди й шустрий файл самого хранителя екрану і доважка DLL для конфигурирования і іншого (там об'єм і швидкість не критичны).

Список литературы

Для підготовки даної праці були використані матеріали із сайту internet.

Показать весь текст
Заполнить форму текущей работой