něco o mně | fotogalerie | guestbook | download |

Programátorské hrátky

Globání RichEdit Fix

Tato aplikace byla primárně určena jako dočasné řešení problému chybného zobrazení v prvku richedit. I když jsem po relativně dlouhé době nalezl elegantnější řešení (použití konkrétní verze knihovny riched20.dll), jde svým způsobem o zajímavou, obecně použitelnou ukázku.

Celý kód je z úsporných důvodu napsán pomocí WinAPI funkcí, mimoto hlavní proces pracuje v nejnižší možné prioritě. Neviditelný hlavní formulář je přítomen pouze z důvodu práce s messages, dále je při startu vytvořen timer, který v požadovaném intervalu utváří seznam veškerých oken (EnumWindows). V těchto oknech jsou následně zjišťovány další komponenty, případně dále do hloubky (použitá rekurze EnumChildWindows), následně je nad každým nalezeným prvkem volána funkce SendREMessage. Ze získaných HWND lze již snadným způsobem odvodit jméno třídy, pakliže se jedná o námi hledané RichEdit*, pošleme odpovídající zprávu zajišťujících korekci.

Přeložená aplikace + zdrojový kód v Delphi.

SysColors

Jednoduchá pomocná utilita umožňující přenášet barevná schémata Windows. Při užití parametru save jsou nejprve zjištěny odpovídající barvy příslušných systémových konstant, ty jsou posléze uloženy do souboru SysColors.cfg. K opětovnému nahrání slouží parametr load. Program je dobrou pomůckou pro ověření výsledného vzhledu na OS s jiným barevným schématem (např. různé verze Windows). Jednoduchou úpravou kódu je možné vytvořit nová nestandardní témata (viz použití API funkcí GetSysColor,SetSystemColors).

Přeložená aplikace + zdrojový kód v Delphi.

Test znalostí Delphi

Celkem jednoduchý příklad, který jsem vypracoval v rámci jednoho vstupního pohovoru (ucházel jsem se o místo vývojáře). Poté následoval ještě druhý úkol, kdy jsem měl vytvořit stored proceduru pro MS SQL. Byla to vlastně vůbec první složitější SQL zkušenost, studoval jsem asi týden. Ale bavilo mě to a za podpory několika kamarádů jsem výsledek odevzdal. Z práce nakonec stejně nic nebylo, tedy mé znalosti byly dostačující, ale prostě jsme se tak nějak nedohodli. Dnes jsem tomu docela rád - přeci jen, pracovat ve firmě, kde nedokáže komunikovat ani její šéf, to už raději nic. :-)

Ale zpět k řešené úloze. Požadavkem bylo vytvořit objekt (v unitě uObject.pas), který by určitým způsobem poskytl základní, dovolím si to nazvat „databázové“ funkce. Tedy pole hodnot, do/ze kterého bude možné údaje přidávat, číst, odstraňovat, nahrazovat a také naprosto jednoduchým způsobem vyhledávat. Mým cílem bylo vytvořit co nejefektivnější a nejrychlejší algoritmus. Jak jsem následně zjistil, největším zdržováním byla funkce SetLength, respektive realokace (zvětšení/zmenšení) pole. Z tohoto důvodu jsem se rozhodl zapracovat jednoduchou vlastnost, která tento úkon několikanásobně urychluje. Jde o alokaci po blocích, jejichž velikost je možné ovlivnit (proměnná FSegLength). Pokud je tedy potřeba přidat nový prvek, zároveň se nám připraví místo i pro x následujících. A stejně tak opačně. Odstraníme-li dostatečný počet prvků, pole se automaticky zmenší o celý tento segment.

Popravdě to nebylo vůbec nic složitého, tedy nic, na čem bych mohl předvést své skutečné znalosti. Proto jsem ještě navíc zapracoval co nejpřesnější měření jednotlivých operací. Využil jsem k tomu PerformaceCounter – skvělá to věc nabízející poměrně vysokou přesnost. Použití je opravdu jednoduché a myslím, že i pro mnohé z vás může být dobrou inspirací. Jen doplním, proměnná Overhead zachycuje odchylku, která vzniká po dobu vlastního měření.

Přeložená aplikace + zdrojový kód v Delphi.

XP shutdown

Velice jednoduchá aplikace zajišťující plánované vypnutí počítače. Přejete-li si během usínání poslouchat své oblínené MP3jky nebo nechat PC z jiného důvodu ještě nějakou tu chvilku pracovat (stahovat torrenty apod. :-)), je toto program právě pro Vás. Jednoduše naplánujete čas, zvolíte metodu: hibernace/shutdown a to je vše. Program se následně automaticky minimalizuje do tray oblasti, v případě potřeby lze dialog s nastavením opětovně vyvolat.

Přeložená aplikace + zdrojový kód v Delphi.

Domeček jedním tahem

Jistě každý znáte klasickou školní úlohu... Také mne tato myšlenka oslovila - kolik řešení vůbec existuje? Jedno, dvě, nebo snad více? Po několika hodinovém zamyšlení jsem pouhým pohledem nalezl 9 řešení, každé je ale proveditelné i "zrcadlově", celkem tedy 18. Pomohli také kolegové a kamarádi, někteří hledali, jiní pouze tipli výsledek. Začal jsem proto uvažovat nad možným programovým řešením, nejprve pouze teoreticky, v úvahách a zamyšleních s nemalou dávkou motivace vymyslet něco nového. Několik okamžiků jsem také věnoval pročtení matematické teorie grafů, na kterou jsem byl nasměrován, velký dík také patří K.Soukupovi za jeho studijní poznatek (platí, že každé správné řešení musí začínat a končit v bodě s lichým počtem vazeb - tedy C a D). Protože se mi nikde nepodařilo nalézt konečný výsledek, je to také jediný důkaz mého správného postupu.

Nyní již k samotnému algoritmu. Vzhledem k náročnějšímu výpočtu jsem se rozhodl celý proces přesunout do samostatného vlákna (threadu). Základem je dvojrozměrné pole, uchovávající stav jednotlivých spojů, každý takový spoj (relace) nabývá jednu ze tří hodnot pravda, nepravda nebo zakázáno. Nejprve je nutné provést vynulování všech vazeb a současné zakázání těch, které nejsou žádoucí - sem patří odstranění relací A-A,B-B... (žádný bod se nespojuje sám se sebou), dále je nutné zakázat vazby A-C a A-D. Vlastní logiku provádí rekurzivní funkce ComputeDomecek, která postupně generuje posloupnost všech dostupných kombinací (1953125). Každá devítimístná varianta je pak samostatně testována, je-li nalezena jedna nebo více relací ve stavu zakázáno, je jasné, že se domeček nepodařilo "dokreslit". V opačném případě si výsledek poznamenáme...

Myšlenka: Mým původním záměrem nebylo generování všech možností s následným porovnáním, ale okamžité měnění stavu vazby ihned při připojení dalšího bodu. Jinými slovy provádět porovnání bezprostředně, to by umožnilo vyřadit chybné kombinace již během první milné cesty (např. ABAB), podstatnou měrou by se také zkrátil čas výpočtu - to je ideální cesta k řešení.

Přeložená aplikace + zdrojový kód v Delphi.

AppsOnLAN

Kolega se na mě obrátil s dotazem, zda-li by se dalo nějakým způsobem zjistit, kde má nainstalované jaké verze Microsoft Office. Nechtělo se mu obcházet přes 80 stanic (také jsem lenoch ;)). Tak jsem přišel na docela zajímavou myšlenku, kterou jsem během několika minut proměnil v tuto utilitu.

Ta si nejprve vytvoří seznam všech okolních PC, která jsou na síti (nejen v doméně) k dispozici. Následuje pokus o připojení vzdáleného registru, z nějž jsou v případě úspěchu získávány informace o nainstalovaných programech (využití klíče ..\Uninstall v HKLM). Režim programu lze ovlivnit parametrem: * provede kompletní výstup bez jakéhokoli omezení, jiný parametr pak aktivuje jednoduchý filtr - zadané slovo musí být obsaženo, přičemž velikost písmen není zohledněna. Jen vyobrazení českých znaků v konzoli je trochu problém, záleží na nastavení prostředí (možná pomůže příkaz chcp, nemám vyzkoušeno).

Ukázka použití:
AppsOnLAN.exe * >sestava.txt | AppsOnLAN.exe oFFicE | AppsOnLAN.exe "Microsoft Office Professional"

Přeložená aplikace + zdrojový kód v Delphi.

Dělové koule

Středověcí dělostřelci stavěli tehdejší kamenné koule do pyramid. A to buď se čtvercovitou nebo trojúhelníkovou základnou. Např.: základnu pyramidy tvořil čtverec 5x5 koulí, na ní postavili 4x4 koule, atd., na vrchol umístili jednu kouli. Tato čtvercová pyramida tedy obsahovala 25+16+9+4+1=55 koulí. Avšak mohli stavět koule do pyramid s trojúhelníkovou základnou. Základnu tak tvoří např. 10 koulí, další vrstvu 6, na ní jsou 3 koule a na vrcholu jedna koule. Celkem je v této trojúhelníkové pyramidě takto sestaveno 10+6+3+1=20 koulí. Otázka zní: Existuje počet koulí, ze kterých se dá postavit čtvercová i trojúhelníková pyramida? Triviální řešení jedna koule neuvažujeme.

Úloha je postavená na porovnávání objemů, na jedné straně výpočet se čtvercovou a na straně druhé pak s trojúhelníkovou podstavou. Každá strana rovnice je ztvárněna samostatnou funkcí, jejímž vstupem je aktuální počet koulí (inkrementálně se zvětšující) a výstupem pravda či nepravda, podle toho, lze-li z takového počtu sestavit příslušný útvar beze zbytku.

Jak jsem se dozvěděl, tato úloha nemá řešení, neexistuje jednotné množství koulí, ze kterých by bylo možné postavit obě varianty. Praktický důkaz mi ale zůstal utajen, takže bych si nebyl úplně tak jistý. :) Čistě teoreticky se ale také přikláním k tomu, že řešení prostě není. Můj příklad je jen takový malý pokus těžkopádného systematického (pomalého) vyhledávání, přinejmenším je to ale zajímavý námět k nějaké další distributed-computing aplikaci.

Přeložená aplikace + zdrojový kód v Delphi nebo C++ (WinAPI).

Recognizer

... popis se připravuje

...

...

Přeložená aplikace + zdrojový kód v Delphi.

Baťáček s rekurzí

Potřebujete provést libovolnou operaci se soubory určitého typu, které se nacházejí třeba i v několikáté úrovni podadresářů? Nemám namysli přejmenování, které v dnešní době zvládne kdejaký program, ale využití odpovídajícího jména jako parametru pro jiný program. Baťáček dokáže projít dostupné podadresáře (začíná na úrovni, kde je spuštěn), najít soubory vyhovující zadané masce a ty pak předat další aplikaci obstarávající zbytek akce. Osobně používám například pro hromadnou legalizaci Eagle projektů (soubory schémat i desek). Nebudu popisovat jednotlivé příkazy, raději doporučuji osobně prozkoumat. Chtěl jsem spíše ukázat použitelnost a především jednoduchost tohoto řešení.

Ukázkový cmd/bat soubor.

MoreCPU example

Tato aplikace je malou ukázkou využití výpočetního výkonu na víceprocesorovém stroji. Toto téma mne lákalo již delší dobu, nicméně jsem neměl k dispozici potřebný hardware, na kterém bych s něčím takový mohl začít experimentovat. Alespoň částečným uspokojením se mi stalo mé nové pracovní PC s Intel P4 (HyperThreading), na kterém jsem si prográmek poprvé ozkoušel.

Základem je získání několika prvotních údajů - počet všech dostupných procesorů (dwNumberOfProcessors) a bitové masky (dwActiveProcessorMask), která udává, na jaké "pozici" se nachází. Informace o architektuře je pouze doplňující. Potřebný náročný výpočet jsem nevymýšlel, rozhodl jsem se použít výše popsanou úlohu dělových koulí, bez rozsáhlejších úprav, tak jak byla vytvořena.

Pro zjednodušení si k výpisu procesorů přidávám vždy příslušný MaskBit, který se případnou změnou škrtátka aktivuje nebo deaktivuje v globální masce. Právě manipulaci s jednotlivými bity obstarává trojice jednoduchých funkcí SetBit,GetBit a RstBit, samotné přiřazení aktivních procesorů vláknu pak zařídí WinAPI funkce SetThreadAffinityMask.

Tento příklad si nekladl za cíl nic konkrétního, je to jen taková obecná demonstrace, případný námět pro vaše vlastní aplikace. Rozkládání výkonu je samo o sobě jistě velice zajímavou (ač trochu specifickou) kapitolou.

Přeložená aplikace + zdrojový kód v Delphi.