Az alkalmazások legtöbbje nem egy előre meghatározott séma szerint, teljesen automatikusan, hanem a felhasználóval interaktívan együtt dolgozva, azt választási lehetőségek elé állítva, utasításait követve manipulálja az adatokat, amelynek során információkat jelenít meg a képernyőn a felhasználó számára. Ez a folyamat nem igényel különös körültekintést egészen addig, amíg a megjelenítő eszközöket kizárólag egyetlen program használja. Egy olyan többfeladatos rendszerben - mint amilyen a Windows is - azonban egyszerre akár több tíz, vagy akár több száz alkalmazás is futhat párhuzamosan. Ha e programok mindegyike szabadon, tetszőleges helyre és időben rajzolhatna a képernyőre, úgy minden valószínűség szerint folyamatosan tönkretennék az egymás által generált grafikus kimeneteket, ezáltal használhatatlanná téve a képernyőt a kommunikáció ilyen formájára. Ha olyan megoldást alkalmaznánk, amelyben bármelyik program kisajátíthatja magának a képernyőt - ezáltal elkerülve a konfliktushelyzeteket - , úgy ezzel a szóban forgó megjelenítő eszközt az adott program kényének és kedvének szolgáltatnánk ki, adott esetben más programokat teljesen megfosztva a képernyőn keresztül történő kommunikáció lehetőségétől.

A probléma megoldását az ablakozás (windowing) alkalmazása jeleneti. Egy ablakozó rendszerben minden program csakis a képernyő egy, a felhasználó és/vagy a program által meghatározott részén - egy ún. ablakban (window) - jeleníthet meg információkat, amelyhez ugyanakkor más program viszont egyáltalán nem férhet hozzá. Az egyes programok által manipulálható megjelenítő felületek, azaz az ablakok kezelését egy, az alkalmazások "felett" álló, a grafikus kimenetek megjelenítésének összehangolását végző központi modul, az ún. ablakkezelő (window manager) végzi.

A legprimitívebb ablakozó rendszerekben az ablakkezelő a teljes képernyőt egymáshoz szorosan illeszkedő alakzatok (az egyszerűség kedvéért általában téglalapok) sokaságára osztja, amelyek mindegyikét egy-egy külön alkalmazás számára bocsátja rendelkezésre. E megoldás előnye egyszerűsége, hátránya azonban, hogy rendkívül erős megszorításokat támaszt az egyes ablakok alakjával és azok egymáshoz képest történő elrendezésével szemben.

Ezzel szemben a Windows platformok mindegyike egy igen fejlett ablakozó rendszerrel rendelkezik, melyben - többek között - az ablakok tetszőleges (zárt) alakzatokat vehetnek fel, és amely egy többszintű hierarchia bevezetésével az ablakok teljesen szabad méretezését és/vagy elhelyezését is lehetővé teszi.

Az ablakhierarchia

A Windows ablakozó rendszerében az ablakok alapvetően két, egymástól (elméletileg) független - de a gyakorlatban általában igen erős párhuzamot mutató - fastruktúrába szerveződnek, amelyek az ablakok egymással szemben fennálló viszonyait írják le.

Az egyik struktúra az ablakok vizuális megjelenését határozza meg. Minden ablak potenciálisan más, ún. gyerekablakokat (child windows) foglalhat magába, amelyek aztán hasonlóképpen szintén újabb gyerekablakokkal rendelkezhetnek. A más ablakokat magában foglaló ablakot az illető gyerekablakok szülőablakának (parent window) szokás nevezni. Az ablakok közt fennálló szülő-gyerek viszony a vizuális megjelenítést befolyásolja, mégpedig olyan módon, hogy a gyerekablak mindig a szülőablakon belül helyezkedik el, azon kívülre nem is képes rajzolni, valamint, hogy koordinátarendszere is relatív a szülőablakéhoz képest. Az azonos szülőablakhoz tartózó gyerekablakokat testvérablakoknak (siblings) szokás hívni. Azt, hogy az testvérablakok rajzolhatnak -e egymás felületére vagy sem, a szülő ablak létrehozásakor lehet meghatározni. A szülő-gyerek fastruktúra csúcsában a teljes képernyőfelületet reprezentáló ablak, az ún. asztal (desktop) helyezkedik el, melynek közvetlen gyerekei az ún. csúcsszintű (top level) ablakok. (Ez az "asztal" nem keverendő össze a Windows alapértelmezett héja, az Explorer által létrehozott, szintén "asztal" névvel illetett felülettel! Előbbi az említetten kívül semmilyen más funkcióval nem bír, míg utóbbi maga is egy csúcsszintű ablak, ami csakis a rá ruházott operatív funkcionalitás és speciális "viselkedésminták" miatt különbözik a "mezei" alkalmazásablakoktól). A csúcsszintű ablakok az egyetlen ablakok, amelyek nem gyerekablakok is egyben (pontosabban a struktúrában az asztal gyerekei, de mivel az asztal gyakorlatilag nem igazi ablak, hanem csak egy logikai fogalom, így helytálló az eredeti kijelentés).

A testvérablakok egy, a szülőablakhoz kapcsolódó listában kerülnek tárolásra, amelyben azonban nem teljesen "egyenrangúak" egymással. A testvérablakok egymáshoz képest a listában elfoglalt helye ugyanis a vizuális megjelenítést, valamint a felhasználói bevitel kezelését is befolyásolja. A listában előrébb elhelyezkedő ablakok ugyanis átfedés esetén elfedik (pozíciójuktól függően részben vagy teljesen kitakarják) a listában hátrébb elhelyezkedő testvérablakaikat (ezt hívják "mélységi", azaz Z sorrendnek), valamint ezzel összefüggésben bizonyos beviteli események kezelésének lehetőségét szintén a gyereklistában elfoglalt sorrendnek megfelelően kapják meg. A Windows lehetőséget ad bizonyos speciális ún. legfelső (topmost) ablakok létrehozására is. A legfelső ablakok a szülőablak gyereklistájában mindig megelőzik "mezei" testvéreiket, azonban közöttük pontosan ugyanazok a szabályok (pl. kitakarás) érvényesülnek, mint előbbi társaik között. (A legfelső ablakok általában kis helyet foglalnak el - hogy keveset takarjanak ki -, és tipikusan olyan információk megjelenítésére használják őket, amelyeknek mindig szem előtt kell lenniük, függetlenül az éppen aktív testvérablaktól.)

A másik fastruktúra az ablakok életciklusát befolyásoló, ún. tulajdonosi (ownership) viszonyokat írja le. Hasonlóan az előzőhöz, e struktúra is tetszőleges mélységet vehet fel, azaz egy ablak tulajdonosa lehet olyan ablakoknak is, amelyek maguk is tulajdonosai további ablakoknak. A tulajdonosi viszony az ablakok megsemmisítésekor kap jelentőséget: egy adott ablak megszűnésekor ugyanis az összes általa birtokolt ablak is automatikusan megsemmisítésre kerül (ami viszont egyben azt is jelenti, hogy nem csak a közvetlenül, de a közvetve birtokolt ablakok is megsemmisítésre kerülnek).

Fontos megjegyezni, hogy a Windows terminológiában az ablak nem csak a hagyományos értelemben vett fejléccel, kerettel ellátott, önálló vizuális elemet jelenti, hanem bármilyen egyéb látható, vagy éppen (permanensen) láthatatlan entitást, amik a megfelelő API függvényekkel kerülnek létrehozásra. Ennek megfelelően egy hagyományos értelemben vett (alkalmazás)ablak valójában általában ablakok tucatjából, sőt, nem kevésszer százaiból áll, amelyek egy része önálló vizuális elemként felismerhető (nyomógomb, beviteli mező, stb.), míg mások esetleg nem alkotnak külön vizuális egységet, vagy teljesen rejtve maradnak. Ugyanakkor azt is hangsúlyozni kell, hogy a fent megismert jellegzetességeken kívül semmilyen más párhuzam nem vonható a képernyőn megjelenő vizuálisan elkülönülő elemek, valamint az ablakok között, tehát pl. több különállónak tűnő elem mögött is lehet, hogy csak egyetlen ablak húzódik meg (pl. tipikusan az eszköztárak több vizuálisan elkülönülő gombot tartalmaznak, mégis valójában egyetlen ablakot "rejtőzik" mögöttük), valamint olyan megoldás is elképzelhető, amelyben a vizuálisan egyetlen egységnek tűnő felületet valójában több elemi ablak együttműködéséből jön létre (pl. a standard legördülő lista elem - a combobox, - valójában két külön ablak, egy beviteli mező és egy lista egy szülőablakba foglalásából jön létre).

Üzenetek

A Windows eredendően egy üzenetalapú rendszer, amelyben az egyes ablakok rövid adatcsomagokon, azaz üzeneteken keresztül kommunikálnak egymással. Az üzenetek az egymástól többé-kevésbé független entitások közti kommunikáció egy rendkívül primitív, ugyanakkor egyszersmind rendkívül rugalmas és általános formáját biztosítják.

A Win32 rendszerekben minden egyes üzenet egy, a konkrét kiváltott/kiváltandó eseményt/funkciót azonosító 32 bites egyedi azonosítóból, valamint az opcionálisan hozzá kapcsolható 2x32 bit adatból áll. (Természetesen a paraméterek/adatok átadásához használt mezők is felhasználhatók a funkció további azonosítására, de ez már alapvetően implementációs jellegű probléma.) Az összességében 3x32 bitnyi információ tárolásának képessége alapvetően elég kevésnek tekinthető, azonban a legalapvetőbb funkcionalitás megvalósítására alkalmas. Komplex üzenetsorozatok és egyéb trükkök alkalmazásával azonban ez a korlát is áthidalható. Pl. konkrét adatok küldése helyett adott esetben sokkal célszerűbb egy előre meghatározott felépítésű, jóval nagyobb mennyiségű információt tároló struktúrára mutató pointer (!) átadása, amelyet aztán az üzenetet feldolgozó entitás dereferrálva hozzájuthat az eredeti adattartalomhoz. (Bár e megoldásnak is vannak hátrányai, hiszen pl. gondoskodni kell a referrált pufferterület fenntartásáról az üzenetek feldolgozásának végeztéig, illetve csakis egyetlen processzen belül alkalmazható, hiszen - mint arról korábban már többször szó volt - a win32-ben minden processz diszjunkt címtartománnyal rendelkezik, aminek következtében mutatók processzek közti átadása értelmetlen.)

Az üzenetalapú kommunikáció lényege, hogy bizonyos műveleteknek/eseményeknek egy adott számkódot feleltetünk meg, amellyel aztán majd jeleni tudjuk, hogy az adott esemény bekövetkeztét, vagy éppen kérni tudjuk egy adott művelet végrehajtását. A lényeg, hogy mind az üzenetet feladó, mind az azt fogadó entitás pontosan tisztában legyen az adott kód jelentésével, és esetleges paramétereinek értelmezési módjával. Az üzenetek továbbításában résztvevő elemeknek azonban nem kell tudniuk semmit sem a kódok jelentéseiről, ők pusztán számokként dolgozhatnak velük. Ez rendkívüli rugalmasságot biztosít mind az üzenetek kezelése során a háttérben végbemenő folyamatokat illetően, ugyanakkor nem korlátozza az entitások egymás közti interakcióinak sokrétűségét sem. Újabb és újabb üzenetkódok bevezetésével a végpontokon található entitások plusz funkcionalitással ruházhatók fel, sőt, akár a már meglévő funkcionalitás is módosítható válik a közbenső csatornák legcsekélyebb módosítása nélkül is.

Az üzenetkódok nagy részét a Windows fenntartja saját céljaira, míg egy kisebb hányadát az alkalmazás szabadon használhatja fel. Az előre definiált üzenetkódok jelentéseit és a kapcsolódó szemantikát a megfelelő programozási dokumentációk részletesen leírják.

Alapvetően elmondható, hogy az üzenetalapú kommunikációt a jelenlegi, igen intenzív formájában a Windows leginkább csak a korábbi változatokkal történő kompatibilitás fenntartása (a már létező kód egyszerű újrafelhasználhatósága, portolása) végett alkalmazza, bár pontosan ez okból kifolyólag ez még nagyon sokáig így is fog maradni. Az újonnan bevezetésre kerülő vezérlőelemek (pl. a RichEdit, propertysheet-ek, stb.) azonban már a minden ablak által minimálisan támogatandó funkcionalitáson kívül alapvetően nem üzeneteken, hanem egyéb, alternatív interfészeken (elsősorban COM) teszik elérhetővé szolgáltatásaikat.

Többfeladatos rendszerekben az üzenetek keletkezése és feldolgozása egymástól független módon zajlik, ahol elképzelhető, hogy csak jelentős időbeli eltéréssel kerülhet csak rájuk sor (ezt elsősorban a gép feldolgozási sebessége szempontjából "jelentős" értelemben kell érteni), hiszen egyszerre több forrás is megpróbálhat ugyanannak az elemnek üzeneteket küldeni, amely azonban csak egymás után, sorban tudja azokat feldolgozni. Ugyanakkor a rendszerben keletkező üzenetek jelentős része értesítés jellegű, ami azt jelenti, hogy a küldő entitás számára érdektelen, hogy az üzenet a célentitás által mikor kerül majd feldolgozásra, és direkt hátrányos lenne, ha neki meg kellene várnia, amíg "sorra kerül". A probléma megoldását egy köztes pufferterület kialakításával lehet megoldani, amely a feldolgozásra váró értesítés jellegű üzeneteket a feldolgozásig a célentitás számára tárolja, ezáltal lehetővé téve a küldők számára a futás zavartalan folytatását a cél pillanatnyi terhelésétől függetlenül. Ezt a pufferterületet szokás üzenetsornak hívni.

Az üzenetsor működése alapvetően nagyon egyszerű: a sor egyik oldalán az üzenetforrások folyamatosan pakol(hat)ják be az értesítéseket a csőbe, ami azokat egészen addig tárolja, míg a másik oldalon a célentitás készen nem áll azok feldolgozására (pl. éppen befejezte az előző üzenet feldolgozását), amikor is aztán a soron következő üzenet kiemelése után nekilát feldolgozásának. A sor bemeneti oldalán felmerülő szinkronizációs problémák elhárításáról az operációs rendszer gondoskodik.

Más, hasonló operációs rendszerektől eltérően a Windows-ban az ablakok és az üzenetsor(ok) szoros egységet alkotnak egymással. Egy ablak létrehozásakor automatikusan létrehozásra kerül egy üzenetsor is, de külön önálló üzenetsor létrehozására nincs lehetőség. (Megj: Windows 2000 rendszerben már lehet úgymond önálló üzenetsort is létrehozni, de valójában ezt is az ablakok létrehozására használt API függvénnyel kell megtenni, csak egy speciális paramétert kell a híváshoz használni.)

Az ablakokon kívül minden szál is rendelkezik egy önálló üzenetsorral, amely azonban egyben magában foglalja az összes, az adott szál által létrehozott ablak üzenetsorát is, de egyben lehetőséget biztosít explicit a szálnak címzett üzenetek pufferelésére is. A szálhoz kapcsolódó üzenetsor olvasásakor a szálnak illetve a szál által létrehozott ablakoknak küldött üzenetek egyaránt feldolgozásra kerülnek.

(folytatjuk)