Tipy a triky v Delphi, díl 5.

22. srpna 2001
ee SDÍLET NA FACEBOOKU TWEETNOUT
Tématem dnešního dílu bude restart a ukončení Windows, spouštění a ukončení cizích aplikací a závěrem jedna malá drobnost pro pobavení.
Restart a ukončení Windows

Nejprve si ukážeme, jak celkem snadno restartovat systém. Tato funkce se nám může hodit při různých příležitostech, např. pokud vaše aplikace provede určité změny v konfiguraci Windows, obvykle se projeví až po restartu systému (záleží samozřejmě na "závažnosti" provedených změn). Nejčastěji se s požadavkem na restart setkáte pravděpodobně při instalaci nového software a nutno poznamenat, že neustálé restarty nemají uživatelé příliš rádi. Proto je třeba s touto funkcí nakládat s rozumem, a co je nejdůležitější, vždy byste měli před restartem uživatele upozornit a dát mu možnost restartu zabránit.

Pod Windows 9x je situace poměrně jednoduchá. Stačí nám k tomu jeden řádek kódu:

procedure Restart;

begin

ExitWindowsEx(EWX_REBOOT, 0);

end;

Tento způsob je ten šetrnější, kdy je (zjednodušeně řečeno) ostatním aplikacím poslán dotaz, zda je možné systém ukončit, a ty nám to buď povolí nebo ne (viz další kapitola článku). Pokud chcete ukončit systém "násilím", stačí drobně upravit parametry na:

ExitWindowsEx(EWX_FORCE or EWX_REBOOT, 0);

V tomto případě by mělo dojít k restartu systému bez ohledu na to, zda nám to ostatní aplikace dovolí či ne. Osobně bych se přikláněl spíše k první variantě, protože dáte ostatním aplikacím možnost se na ukončení systému "připravit".

Tato funkce má však i další možnosti parametrů kromě EWX_REBOOT. Jsou to:

  • EWX_SHUTDOWN
  • EWX_LOGOFF
  • EWX_POWEROFF
Názvy jsou myslím dostatečně jasné a netřeba dalšího vysvětlování. Snad jen drobnou poznámku: ačkoliv popis parametrů a použití této funkce pochází přímo od Borlandu, občas se mi stane, že v určitých případech nefungují, jak mají (jedná se hlavně o poslední dvě varianty). Pokud snad někdo ze čtenářů ví proč, neváhejte se prosím pochlubit.

U Windows 2000 je situace poněkud složitější. Pojďme si rovnou ukázat zdrojový kód:

procedure Restart2000;

var

hToken, hProcess: THandle;

tp, prev_tp: TTokenPrivileges;

Len, Flags: DWORD;

begin

if Win32Platform = VER_PLATFORM_WIN32_NT then

begin

hProcess := OpenProcess(PROCESS_ALL_ACCESS, True, GetCurrentProcessID);

try

if not OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,hToken) then Exit;

finally

CloseHandle(hProcess);

end;

try

if not LookupPrivilegeValue(``, `SeShutdownPrivilege`,tp.Privileges[0].Luid) then Exit;

tp.PrivilegeCount := 1;

tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;

if not AdjustTokenPrivileges(hToken, False, tp, SizeOf(prev_tp),prev_tp, Len) then Exit;

finally

CloseHandle(hToken);

end;

end;

ExitWindowsEx(EWX_REBOOT, 0);

end;

Vysvětlování, jak to celé funguje, by asi zabralo více času. Zjednodušeně řečeno je nutné projít všechny běžící procesy, zjistit, zda je možné je ukončit (protože pod Windows NT či 2000 jak jistě víte není z důvodů bezpečnosti dovoleno, jen tak se "hrabat" do systému, ke všemu potřebujete ta správná oprávnění), a nakonec se systém restartuje již stejným způsobem jako u výše uvedeného příkladu pro Windows 9x. Opět můžete použít již zmiňované parametry, které vám umožní systém nejen restartovat, ale i kompletně vypnout apod. Příklad byl testován v Delphi 5 a nejsem si jist, zda bude v této podobě pracovat ve všech verzích Delphi. Proto budu rád, když se ozvete, jak příklad pracuje i ve verzích starších či novějších.

Detekce ukončení systému

S předchozí kapitolou souvisí i následující tip. Ukážeme si, jak zjistit, že se cizí aplikace (např. instalátor) nebo prostě samotný systém snaží ukončit Windows. Pokud naše aplikace zrovna provádí nějakou velmi důležitou činnost, můžeme vypnutí systému i zabránit a nebo včas zajistit případné uložení všech důležitých dat. Je to vlastně velice snadné. Když se Windows ukončují, odešlou všem běžícím aplikacím zprávu WM_QUERYENDSESSION, kterou "zachytíme" událostí OnCloseQuery hlavního formuláře aplikace. Parametr CanClose nastavíme na True, pokud chceme systému dovolit ukončení, a nebo False pro opačný efekt. Jednoduchý zdrojový kód může vypadat kupříkladu takto:

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);

begin

if MessageDlg(`Opravdu ukočit ?`, mtConfirmation, mbYesNoCancel, 0) = mrYes

then CanClose := true

else CanClose := false;

end;

Při pokusu o ukončení se zobrazí dialogové okno s potvrzením. To je samozřejmě pouze ukázkové řešení pro názornost a v reálných aplikacích použijeme určitě jiné řešení. Zkušenější z vás jistě vědí, že takto napsaný kód ovšem zobrazí onen dialog při každém ukončení aplikace, tedy ne jen pouze při pokusu o ukončení z "vnějšku", ale i při uzavření aplikace běžným způsobem. Proto by bylo vhodné doplnit proceduru o test, který nám určí, "kdo" aplikaci ukončuje. To nechám čtenářům za domácí úkol.

Spuštění a ukončení cizí aplikace

Další užitečnou věcí, kterou se teď naučíme, je spouštění cizích aplikací. To se nám může hodit například tehdy, když potřebujeme "spustit" nějaký typ dokumentu v externí aplikaci, protože s ním náš program neumí pracovat, a podobně.

Budeme potřebovat knihovnu ShellAPI, proto ji nezapomeňte přidat mezi ostatní do Uses. Vytvoříme si jednoduchou proceduru s několika málo parametry, která nám spustí libovolný soubor.

.

.

.

uses ShellApi;

.

.

.

procedure Spust(soubor,param,defaultdir:string);

begin

ShellExecute(0,nil,soubor,param,defaultdir, SW_SHOWNORMAL);

end;

Parametry jsou myslím jasné – aplikace včetně cesty, případné parametry (můžete nechat prázdné) a "pracovní" adresář (obvykle taktéž můžete ponechat prázdné). Kvůli zjednodušení není prováděna žádná kontrola úspěšnosti pokusu spustit aplikaci (tj. jestli vůbec aplikace existuje).

Pokud již aplikace splnila náš požadavek nebo ji už z jiného důvodu dále nepotřebujeme, můžeme ji jednoduše ukončit. Jeden z jednoduchých způsobů si teď ukážeme. Jediné, co potřebujeme vědět, je titulek okna aplikace, kterou chceme ukončit. Poté jí "pošleme zprávu" o našem požadavku na ukončení. Jednoduchá procedura může vypadat například takto:

procedure Ukonci(titulek:string);

begin

PostMessage(FindWindow(Nil, titulek), WM_QUIT, 0, 0);

end;

Klávesy NumLock, CapsLock a Scroll Lock

Na závěr si trošku pohrajeme s výše uvedenými klávesami. Ukážeme si, jak je programově "stisknout", tj. aktivovat či deaktivovat jejich funkci, což je – jak jistě víte – doprovázeno rozsvícením či zhasnutím příslušných diod, takže pokud si dáte záležet, můžete vytvořit docela zajímavý efekt. Následující příklad aktivuje nebo deaktivuje (podle jejich aktuálního stavu) uvedené klávesy.

procedure TForm1.Button1Click(Sender: TObject);

var KeyState : TKeyboardState;

begin

GetKeyboardState(KeyState);

if (KeyState[VK_NUMLOCK] = 0) then KeyState[VK_NUMLOCK] := 1

else KeyState[VK_NUMLOCK] := 0;

if (KeyState[VK_CAPITAL] = 0) then KeyState[VK_CAPITAL] := 1

else KeyState[VK_CAPITAL] := 0;

if (KeyState[VK_SCROLL] = 0) then KeyState[VK_SCROLL] := 1

else KeyState[VK_SCROLL] := 0;

SetKeyboardState(KeyState);

end;

Pokud máte dostatečnou fantazii, jistě dokážete blikání jednotlivých diod synchronizovat v zajímavé světelné efekty.

Témata článku: Software, Windows, Programování, Blikání, Elsa, Restart, Nota, Exit, Zajímavý efekt, Trik, Zjednodušený příklad, Díl, Ukázkový příklad

17 komentářů

Nejnovější komentáře

  • Petr Vones 26. 8. 2001 12:38:56

    Svět není jen http://www.builder.cz

  • Radek Chalupa 26. 8. 2001 12:16:40

    Zdravím,

    souhlasím s Vámi v tom, že na Internetu lze nalézt mnoho...

  • Petr Vones 26. 8. 2001 12:16:33

    Procedura Spust je dobrym prikladem kde lze najít hned několik chyb. Za...

Určitě si přečtěte

Země se jenom o vlásek vyhnula věčnému zmrznutí

Země se jenom o vlásek vyhnula věčnému zmrznutí

** Země po většinu doby své existence zmrzlá rozhodně nebyla ** Podle nového výzkumu tomu však unikla jen o vlásek ** Kdyby totiž byla jenom o 15 procent dále od Slunce, tak by prý kompletně celá zamrzla

Včera | Stanislav Mihulka | 9

CCleaner obsahuje softwarovou havěť! Tvůrcům se do kódu dostali hackeři

CCleaner obsahuje softwarovou havěť! Tvůrcům se do kódu dostali hackeři

** Masově oblíbený program pro softwarovou očistu Windows ovládli hackeři ** Narušení se podařilo zavčas odhalit, unikla jen data o počítačích uživatelů ** Je paradoxní, že CCleaner byl slabě zabezpečen, když jej letos koupil Avast

18.  9.  2017 | David Polesný | 45

Noční strana Venuše vydala další tajemství

Noční strana Venuše vydala další tajemství

18.  9.  2017 | Jiří Černý

Jak tankují bombardéry: Z létající benzinky šest kilometrů nad Českem

Jak tankují bombardéry: Z létající benzinky šest kilometrů nad Českem

** Bombardéry tankují z létající benzinky Boeing KC-135 Stratotanker ** Tu americké letectvo pro doplňování paliva jiných letounů ve vzduchu využívá už více jak půlstoletí ** Tankování probíhá přes speciální výsuvné čerpací rameno na zádi

17.  9.  2017 | Natoaktual.cz


Aktuální číslo časopisu Computer

Vyplatí se ještě těžit kryptoměny?

Velký test studentských notebooků

Test pěti levných soundbarů

Nejlepší chytré hodinky