Mint arról az előző részben szó volt, a Windows-ban az ablakok üzenet segítségével kommunikálnak egymással és a felhasználóval is. De valójában milyen üzeneteket is küldözgetnek egymásnak az ablakok, és ezek hogyan befolyásolják működésüket, miként teszik lehetővé a felhasználóval történő kommunikációt?

Ablaküzenetek
Mint azt már tudjuk, minden egyes ablak egy egyedi, különálló üzenetsorral rendelkezik, amely a számára aszinkron módon postázott üzeneteket a feldolgozásig tárolja. E üzenetek feldolgozását az ún. ablakeljárás (window procedure) végzi. Az ablakeljárás valójában egy nagyon egyszerű, ám egyszersmind rendkívül komplex eljárás is, hiszen bár bemeneti paramétereként csak egy egyszerű, néhány bájtból álló - az üzenet tartalmazó - struktúrát fogad, ugyanakkor képes az összes, az adott ablak működése szempontjából fontos és/vagy jelentéssel bíró üzenet értelmezésére, és az azoknak megfelelő műveletek végrehajtására. Egy adott ablak viselkedését és megjelenését teljes egészében a vele társított ablakeljárás határozza meg.

Bár egy adott ablak által értelmezett üzenetek (kódok) száma a több százat is elérheti, valójában a programozóknak nem kell ezek mindegyikét külön-külön saját magának lekezelnie, az azoknak megfelelő műveleteket minden egyes ablakeljárásban külön-külön ismét megírnia. A legtöbb szabványosított üzenet minden ablak részéről azonos jellegű információk szolgáltatását vagy művelet elvégzését igényli, aminek köszönhetően azokat egyetlen közös, a Windows által már előre biztosított ún. alapértelmezett ablakeljárással (default window procedure) lehet kezeltetni, és elég mindössze az adott ablak működését, viselkedését és megjelenését egyedivé tevő, funkciójának megfelelő üzenetek feldolgozását az egyedi ablakeljárásban megírni. Természetesen a standard üzenetek kezelését sem kell feltétlenül az alapértelmezett ablakeljárásra bízni - amennyiben a programozó úgy kívánja, tetszőleges üzenetek kezelését átveheti attól, míg a fennmaradók kezelését továbbra is rábízhatja. Alapvetően érdemes az ablakeljárásokat úgy kialakítani, hogy azok csak az ismert és a működés szempontjából fontos, az alapértelmezett ablakeljárás által nem, vagy nem az igényeknek megfelelően kezelt üzenetek feldolgozását lássák el, míg minden további üzenetet feltétel nélkül adjanak tovább az alapértelmezett ablakeljárásnak. Természetesen elképzelhető, hogy ez utóbbi sem fogja tudni, hogyan kell egy adott üzenetet lekezelni (bár ez esetben a program nyilvánvalóan rosszul van megszerkesztve, hiszen a fogadó fél által nem ismert üzenetek küldésének nincs sok értelme), azonban ha nem ezt tesszük, akkor megfosztjuk ablakainkat attól a lehetőségtől, hogy az esetleges későbbi Windows verziókban kialakításra kerülő bővítéseket vagy esetleg módosított alapértelmezett mechanizmusokat automatikusan kezelni legyenek képesek. Hiszen az alapértelmezett ablakeljárás a Windows operációs rendszer részét képezi, és mint ilyen azzal automatikusan együtt fejlődik és gondoskodik a mindenkor lehetséges legsokrétűbb általános funkcionalitás megvalósításáról.

Minden a felhasználói által eszközölt bevitel (pl. egy billentyű lenyomása, vagy éppen felengedése, az egér mozgatása, stb.) és annak következtében, vagy akár attól függetlenül a rendszerben bekövetkező nem szigorúan lokalizálható változás (pl. egy ablak pozíciójának megváltozása, az idő átállítása, stb.) egy üzenetet generál, amely annak típusától függően egy adott ablaknak, vagy ablakok egész sorozatának kerül elküldésre feldolgozás végett.

Attól, hogy egy ablakeljárás ismeri egy üzenet jelentését, nem feltétlenül kell fel is dolgoznia azt - a feldolgozást függővé teheti az adott vezérlőelem mindenkori állapotától, vagy akár attól független jellemzőktől is. Az ennek megfelelő feltételrendszer kialakítása teljes egészében a programozóra van bízva, és így a mindenkori igényeknek és rendeltetésnek megfelelően szabadon alakítható. Ilyen alapvető mechanizmusokat az alapértelmezett ablakeljárás is tartalmaz, amely pl. az adott ablak letiltott állapotában számos olyan - elsősorban a felhasználó bevitellel összefüggő - eseményt nem dolgoz fel, amelyeket azonban az ablak engedélyezett állapotában kezelne.

Természetesen a direkt, csakis egy konkrét ablaknak szóló üzenet feldolgozásának elmulasztásának nincs sok értelme. A Windows rendszerben azonban számos olyan üzenet is keletkezik amely nem csak egyetlen ablaknak kerül elküldésre, hanem adott esetben ablakok egész sorozatának egészen addig, amíg az adott üzenetet valamelyik ablak sikeresen le nem kezeli. Ilyen mechanizmusok esetén az üzenet le-nem-kezelése valójában azt jelenti, hogy annak kezelését az adott ablak egy sorrendben utána következő ablak számára adja tovább, amely természetesen szintén élhet ezzel a lehetőséggel, és önmaga is továbbadhatja ugyanezt a lehetőséget. Természetesen ilyen mechanizmusok a forrásoldalon csakis explicit az üzeneteket a feldolgozásától függően ciklikusan újabb és újabb ablakoknak ismételten elküldő vezérlési szerkezettel valósíthatóak meg, bár pl. maga az ablakkezelő is tartalmaz olyan eljárást aminek hívásával egyetlen lépésben minden ablak számára elküldhető egy adott üzenet. Ilyen, feltételes feldolgozású, "továbbgyűrűző" jellegű üzenetek a felhasználói beviteli eseményekről (pl. billentyű lenyomása, felengedése, stb.) értesítő, valamint néhány, az ablakhierarchiával összefüggésben lévő üzenet, de természetesen hasonló mechanizmus kialakítására az alkalmazásprogramozónak is bármikor lehetősége nyílik.

Ezeken az üzeneteken kívül a Windows rendszerben számos olyan értesítés jellegű üzenet is keletkezik, amely csak igen kevés feladat és így ablak számára bír jelentőséggel. Ezek feldolgozásának "elmulasztása" szintén megengedett, hiszen ezek nem követelnek meg egy előre meghatározott válaszlépést, hanem csak informatív jelleggel kerülnek létrehozásra és szétküldésre.

Az ablakeljárásokhoz nem csak az üzenetsor feldolgozása során, hanem annak megkerülésével, gyakorlatilag közvetlenül is kerülhetnek üzenetek. Az ilyen módon történő üzenetek küldése során a küldő szál egészen addig blokkolásra kerül, amíg az ablakeljárás be nem fejezi az üzenet feldolgozását, azaz vissza nem tér a Windows által eszközölt hívásból. Ez utóbbi esetben szinkron üzenet-feldolgozásról beszélünk.

Egy adott szál által létrehozott ablakok ablakeljárásai közül egyszerre mindig csakis egyetlen egy fut, és az is csak egyetlen példányban. Amennyiben az ablakeljárás önmaga is szinkron üzenetküldést kezdeményez, abban az esetben végrehajtása felfüggesztésre kerül a küldött üzenet a másik ablakeljárás által történő feldolgozásáig. Amennyiben a célablak a küldővel azonos szálban került létrehozásra úgy ez gyakorlatilag csak egy "normál" funkcióhívást jelent ami azonnal kivitelezésre is kerül. Ha azonban egy másik szál birtokolja, úgy a küldő szál blokkolásra kerül az üzenet feldolgozásának végéig. A célablak szálában a feldolgozás nem feltétlenül kezdődik meg azonnal, mert eltérő forrás- és célszál esetén a Windows az üzenet feldolgozását a célszálban csakis akkor végzi majd el, amikor a célszál az ablakhoz, vagy esetleg a szálhoz kapcsolódó - ez utóbbi esetben ugye előbbit is magában foglaló) - üzenetsor ürítését kezdeményezné. Ez a mechanizmus gondoskodik arról, hogy egy adott ablaknak szóló üzenetek feldolgozása mindig csakis az ablakot birtokló szál kontextusában kerüljön végrehajtásra, azaz, az üzenet forrásától és küldési módjától (szinkron/aszinkron) függetlenül az ablakeljárás mindig azonos körülmények között kerüljön meghívásra.

Ablakosztályok
Egy alkalmazás általában nem mind-mind egymástól élesen eltérő, teljesen egyedi ablakok sokaságából, hanem általában ugyanolyan, de legalábbis nagyon hasonló, legtöbbször csak kiterjedésükben és méretükben (vagy sokszor még abban sem) eltérő ablakok struktúrált halmazából áll. Az azonos megjelenésű és viselkedésű ablakok mögött azonban nyilvánvalóan identikus ablakeljárások szükségesek. Ilyen körülmények között bosszantó lenne, ha minden egyes ablakhoz külön-külön ismét meg kellene adni a hozzá kapcsolódó ablakeljárás címét, a fenntartott adatterület hosszát, az ablakban megjelenő mutató, és az ablak ikonjának azonosítóját, stb., amikor ezen jellemzők minden egyes az adott típushoz tartozó ablakpéldány esetén gyakorlatilag identikusak lennének. Ráadásul ez a mechanizmus nem tenné lehetővé, hogy a különállóan elhelyezkedő, egymás kódjához közvetlen hozzáféréssel nem bíró modulok az egymás által implementált "ablaksémákat", építőelemeket kölcsönösen felhasználják. E problémák leküzdésére vezeti be a Windows az ablakosztály fogalmát.

Az ablakosztályok (window class) alkalmazásának lényege, hogy a fent említett, egy adott ablaktípushoz kapcsolódó, annak általános megjelenésével és viselkedésével kapcsolatos jellemzők egy egyedi névvel, az ún. (ablak)osztálynévvel (class name) kerülnek társításra, amelyek keresztül közvetve hivatkozhatóvá válnak. Ezt társítási eljárást az ablakosztály regisztrálásának hívják.

Az ablakosztályoknak köszönhetően egy adott ablakpéldány létrehozásakor a fent felsorolt jellemzők halmazának megadása helyett elegendő mindössze egyetlen jellemzőt, az egyedi osztálynevet megadni, amely közvetve az összes az ablakra jellemző paramétert meghatározza. Egyszersmind lehetővé válik olyan megoldások alkalmazása, amelyben egy adott típusú ablak jellemzőit és belső működését egy elkülönülő modul határozza meg és tartalmazza, miközben a mellérendelt funkcionalitást tetszőleges számú, közvetlen hozzáféréssel nem bíró másik modul is igénybe veheti, hiszen az egyedi osztálynév ismeretében tetszőleges számú ablakpéldányt hozhat létre az adott típusból annak belső működésének, vagy akár csak eredeti (implementációs/regisztrációs) helyének legcsekélyebb ismerete nélkül is. A funkcionalitás és az implementáció ilyen gondos szétválasztása egyben utóbbi előbbitől független változtatásának lehetőségét is magában rejti (aminek természetesen csak a visszamenőleges kompatibilitás szem előtt tartása mellett van igazán értelme). Pl. ez utóbbi működésének szép példája a Windows felületre az eredetitől eltérő "bőr" (skin) húzását lehetővé tevő WindowBlinds nevű program, ami működésének alapja a standard ablakosztályok mögötti implementációs kód cseréje, és így azon keresztül az azokból (osztály)név alapján létrehozott ablakpéldányok megjelenésének és/vagy viselkedésének megváltoztatása (ezt az eljárást szokás egyébként "window subclassing"-nak hívni).

Vezérlőelemek
Az ablakok elsődleges célja az információ megjelenítése ill. interaktív bevitelének lehetővé tétele a felhasználó számára. A különböző jellegű megjelenítendő/beviendő információk eltérő vizuális formák és beviteli mechanizmusok kialakítását teszik szükségessé. Az egy adott jellegű információ bevitelét és/vagy megjelenítését lehetővé tevő, egy diszkrét egységet alkotó kommunikációs entitást szokás vezérlőelemnek hívni. A vezérlőelem, mint fogalom nincs szoros összefüggésben az ablakokkal és az azok által alkotott hierarchiával. Ennek megfelelően egy vezérlőelem akár több ablakból is állhat, valamint egy ablak akár több vizuálisan elkülönülő vezérlőelemet is magában foglalhat. Bár a legtöbb vezérlőelem vizuálisan jól el- és behatárolható, ez utóbbi sem szükséges jellemzője. A hangsúly a vezérlőelemek esetében az egy adott típusú információ megjelenítésén/bevitelén van. A vezérlőelemek megjelenése és viselkedése teljes egészében e szempontoknak van alárendelve.

A grafikus felületek történelme során a különböző jellegű információk bevitelére a legkülönbözőbb megoldásokat találták ki, amelyek azonban mára már néhány általános jellegű, mindenki által ismert vezérlőelem formájában kristályosodtak ki. Természetesen ezek a megoldások nem feltétlenül a legalkalmasabbak az elképzelhető összes típusú információ megjelenítésére és bevitelére (ez nem is lehetséges, hiszen naponta újabb és újabb alkalmazási területeit fedezzük fel az informatikának, amik újabb és újabb típusú információk prezentálását teszik szükségessé), de mindenképpen általánosságban jónak mondható: szemléletes, könnyen követhető és főként egyszerű megoldást nyújtanak az információk prezentálására a humán felhasználó felé. Legtöbbjük megjelenése és elnevezése a valós világból vett vizuális, vagy funkcionális analógián alapul (pl. "rádiógombok"-"radiobuttons").

A leggyakrabban használatos beviteli és megjelenítési feladatokra (pl. "sima", formázás nélküli szöveg beírása, választás több lehetőség közül, akcióindítása, statikus szöveg stb.) a Windows az operációs rendszer szintjén összesen hét vezérlőelemet bocsát az alkalmazásprogramozók rendelkezésére, amelyeket implementáló ablakosztályok minden egyes processz indításakor automatikusan regisztrálásra kerülnek, és amelyek így minden körülmények között elérhetőek. A standard rendszer-vezérlőelemek leírását az alábbi táblázat, tipikus megjelenési formájukat pedig az alábbi kép tartalmazza:
 

Osztály neve Jelentés
BUTTON Alapvetően kis kiterjedésű, téglalap alakú vezérlőelem, amely egy gombot mintáz. A gombok különállóan, vagy akár csoportokba foglalva is használhatók - utóbbi esetben állapotuk egymástól függővé tehető. A gombokra kattintás a gomb állapotának megváltozását vonja maga után.
COMBOBOX Egy beviteli mező (EDIT) és egy listadoboz (LISTBOX) kombinálásából létrejövő vezérlő. Alapvetően szöveges információ bevitelére alkalmas, amelyet azonban egy előre meghatározott listából kiválasztása útján is megadhatunk.
EDIT Téglalap alakú vezérlőelem, amely formázatlan szöveges információ a billentyűzetről történő bevitelét teszi lehetővé. A szövegen belül egy ún. szövegkurzot (caret) mutatja a következő beírásra kerülő karakter pozícióját. A már beírt szöveg vagy egyes részei szabadon törölhetőek, módosíthatók és másolhatók.
LISTBOX Téglalap alakú, előre definiált karakterfüzérek listájából történő választást lehetővé tevő vezérlőelem. 
RICHEDIT Funkciójában az EDIT-hez hasonló, de attól eltérően formázott szöveg bevitelét és szerkesztését lehetővé tevő vezérlőelem.
SCROLLBAR Téglalap alakú, információ egy adott halmazon belüli elhelyezkedésének megállapítására, ill. az információ pozíció alapján történő kijelölésére alkalmas vezérlőelem, amely általában más, saját effektív felületüknél több információt is tárolni képes vezérlőelemek integráns részét képezi.
STATIC Önmagában nem-interkatív, szöveges információ megjelenítését ill. geometria alakzatok formájában vizuális elhatárolást lehetővé tevő téglalap alakú vezérlőelem. Másik vezérlőelemmel összekapcsolva általában azok funkciójával, rendeltetésével kapcsolatban nyújt leírást.

A fenti felsorolásból kimaradtak a RICHEDIT_CLASS és az MDICLIENT osztályok - előbbi a RICHEDIT elem egy fejlettebb változatát, míg utóbbi egy speciális ablaktípust takar, amelyekre azonban majd a későbbiekben térünk ki részletesen.

Az automatikusan regisztrálásra kerülő, minden processzben már induláskor jelen levő vezérlőket jónéhány szintén standardnak nevezhető, minden Windows rendszerben elérhető vezérlőkből álló ún. Common Controls csomag egészít ki, amelynek elemeit azonban a dinamikus csatolású COMCTL32.DLL betöltése és/vagy importálása után lehet csak használni.
(folytatjuk)