Dela via


Om fönsterklasser

Varje fönsterklass har en associerad fönsterprocedur som delas av alla fönster i samma klass. Fönsterproceduren bearbetar meddelanden för alla fönster i den klassen och styr därför deras beteende och utseende. Mer information finns i Fönsterprocedurer.

En process måste registrera en fönsterklass innan den kan skapa ett fönster i den klassen. När du registrerar en fönsterklass associeras en fönsterprocedur, klassformat och andra klassattribut med ett klassnamn. När en process anger ett klassnamn i funktionen CreateWindow eller CreateWindowEx skapar systemet ett fönster med fönsterproceduren, formatmallarna och andra attribut som är associerade med det klassnamnet.

I det här avsnittet beskrivs följande avsnitt.

Typer av fönsterklasser

Det finns tre typer av fönsterklasser:

Dessa typer skiljer sig åt i omfattning och i när och hur de registreras och förstörs.

Systemklasser

En systemklass är en fönsterklass som registrerats av systemet. Många systemklasser är tillgängliga för alla processer att använda, medan andra endast används internt av systemet. Eftersom systemet registrerar dessa klasser kan en process inte förstöra dem.

Systemet registrerar systemklasserna för en process första gången en av dess trådar anropar en användare eller en GDI-funktion (Windows Graphics Device Interface).

Varje program får en egen kopia av systemklasserna. Alla 16-bitars Windows-baserade program i samma VDM delar systemklasser, precis som de gör i 16-bitars Windows.

I följande tabell beskrivs de systemklasser som är tillgängliga för användning av alla processer.

Klass Beskrivning
Knapp Klassen för en knapp.
Kombinationsruta Klassen för en kombinationsruta.
Redigera Klassen för en redigeringskontroll.
Listruta Klassen för en listruta.
MDIClient Klassen för ett MDI-klientfönster.
Rullningslist Klassen för en rullningslist.
Statisk Klassen för en statisk kontroll.

 

I följande tabell beskrivs de systemklasser som endast är tillgängliga för användning av systemet. De visas här för fullständighet skull.

Klass Beskrivning
ComboLBox Klassen för listrutan som finns i en kombinationsruta.
DDEMLEvent Klassen för DDEML-händelser (Dynamic Data Exchange Management Library).
Meddelande Klassen för ett meddelandefönster.
#32768 Klassen för en meny.
#32769 Klassen för skrivbordsfönstret.
#32770 Klassen för en dialogruta.
#32771 Klassen för aktivitetsväxlingsfönstret.
#32772 Klassen för ikontitlar.

 

Globala programklasser

En global programklass är en fönsterklass som registrerats av en körbar fil eller DLL som är tillgänglig för alla andra moduler i processen. Din .dll kan till exempel anropa funktionen RegisterClassEx för att registrera en fönsterklass som definierar en anpassad kontroll som en global programklass så att en process som läser in .dll kan skapa instanser av den anpassade kontrollen.

Skapa en klass som kan användas i varje process genom att skapa fönsterklassen i en .dll och läsa in .dll i varje process. Om du vill läsa in .dll i varje process lägger du till dess namn i AppInit_DLLs-värdet i följande registernyckel:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows

När en process startar läser systemet in den angivna .dll i kontexten för den nyligen startade processen innan dess startpunktsfunktion anropas. .dll måste registrera klassen under initieringsproceduren och måste ange CS_GLOBALCLASS formatmall. Mer information finns i klassformat.

Om du vill ta bort en global programklass och frigöra lagringen som är associerad med den använder du funktionen UnregisterClass.

Lokala programklasser

En lokal programklass är alla fönsterklasser som en körbar fil eller .dll registrerar sig för exklusiv användning. Även om du kan registrera valfritt antal lokala klasser är det vanligt att bara registrera en. Den här fönsterklassen stöder fönsterproceduren i programmets huvudfönster.

Systemet förstör en lokal klass när modulen som registrerade den stängs. Ett program kan också använda funktionen UnregisterClass för att ta bort en lokal klass och frigöra lagringen som är associerad med den.

Så här letar systemet upp en fönsterklass

Systemet har en lista över strukturer för var och en av de tre typerna av fönsterklasser. När ett program anropar funktionen CreateWindow eller CreateWindowEx för att skapa ett fönster med en angiven klass, använder systemet följande procedur för att hitta klassen.

  1. Sök i listan över lokala programklasser efter en klass med det angivna namnet vars instanshandtag matchar modulens instanshandtag. (Flera moduler kan använda samma namn för att registrera lokala klasser i samma process.)
  2. Om namnet inte finns i listan över programlokala klasser söker du i listan över globala programklasser.
  3. Om namnet inte finns i listan över globala programklasser söker du i listan över systemklasser.

Alla fönster som skapats av programmet använder den här proceduren, inklusive fönster som skapats av systemet för programmets räkning, till exempel dialogrutor. Det går att åsidosätta systemklasser utan att påverka andra program. Ett program kan alltså registrera en lokal programklass med samma namn som en systemklass. Detta ersätter systemklassen i programmets kontext, men hindrar inte andra program från att använda systemklassen.

Registrera en fönsterklass

En fönsterklass definierar attributen för ett fönster, till exempel stil, ikon, markör, meny och fönsterprocedur. Det första steget i att registrera en fönsterklass är att fylla i en WNDCLASSEX- struktur med information om fönsterklassen. Mer information finns i element i en fönsterklass. Skicka sedan strukturen till funktionen RegisterClassEx. Mer information finns i Använda fönsterklasser.

Om du vill registrera en global programklass anger du formatet CS_GLOBALCLASS i stil medlem i WNDCLASSEX- struktur. När du registrerar en lokal programklass ska du inte ange CS_GLOBALCLASS formatmall.

Om du registrerar fönsterklassen med ansi-versionen av RegisterClassEx, RegisterClassExA, begär programmet att systemet skickar textparametrar för meddelanden till fönstren i den skapade klassen med hjälp av ANSI-teckenuppsättningen. om du registrerar klassen med unicode-versionen av RegisterClassEx, RegisterClassExW, begär programmet att systemet skickar textparametrar för meddelanden till fönstren i den skapade klassen med hjälp av Unicode-teckenuppsättningen. Funktionen IsWindowUnicode gör det möjligt för program att fråga efter varje fönster. Mer information om FUNKTIONERNA ANSI och Unicode finns i Konventioner för funktionsprototyper.

Den körbara filen eller DLL:en som registrerade klassen är klassens ägare. Systemet bestämmer klassägarskapet från hInstance medlem i WNDCLASSEX- struktur som skickas till funktionen RegisterClassEx när klassen är registrerad. För DLL:er måste hInstance- medlem vara referensen till den .dll instansen.

Klassen förstörs inte när den .dll som äger den tas bort. Om systemet anropar fönsterproceduren för ett fönster i den klassen orsakar det därför en åtkomstöverträdelse, eftersom .dll som innehåller fönsterproceduren inte längre finns i minnet. Processen måste förstöra alla fönster med hjälp av klassen innan .dll tas bort och anropa funktionen UnregisterClass.

Element i en fönsterklass

Elementen i en fönsterklass definierar standardbeteendet för fönster som tillhör klassen. Programmet som registrerar en fönsterklass tilldelar element till klassen genom att ange lämpliga medlemmar i en WNDCLASSEX- struktur och skicka strukturen till funktionen RegisterClassEx. Funktionerna GetClassInfoEx och GetClassLong hämtar information om en viss fönsterklass. Funktionen SetClassLong ändrar element i en lokal eller global klass som programmet redan har registrerat.

Även om en fullständig fönsterklass består av många element kräver systemet bara att ett program anger ett klassnamn, fönsterproceduradressen och en instansreferens. Använd de andra elementen för att definiera standardattribut för klassens fönster, till exempel markörens form och innehållet i menyn för fönstret. Du måste initiera eventuella oanvända medlemmar i WNDCLASSEX struktur till noll eller NULL-. Fönsterklasselementen visas som i följande tabell.

Element Avsikt
klassnamn Skiljer klassen från andra registrerade klasser.
fönsterproceduradress Pekare till funktionen som bearbetar alla meddelanden som skickas till windows i klassen och definierar fönstrets beteende.
instanshandtag Identifierar programmet eller .dll som registrerade klassen.
Definierar musmarkören som systemet visar för ett fönster i klassen.
klassikoner Definierar den stora ikonen och den lilla ikonen.
bakgrundspenslar för klass Definierar färgen och mönstret som fyller klientområdet när fönstret öppnas eller målas.
klassmeny Anger standardmenyn för fönster som inte uttryckligen definierar en meny.
klassformat Definierar hur du uppdaterar fönstret när du har flyttat eller ändra storlek på det, hur du bearbetar dubbelklicka på musen, hur du allokerar utrymme för enhetskontexten och andra aspekter av fönstret.
extra klassminne Anger mängden extra minne i byte som systemet ska reservera för klassen. Alla fönster i klassen delar det extra minnet och kan använda det för alla programdefinierade syften. Systemet initierar det här minnet till noll.
extra Anger mängden extra minne i byte som systemet ska reservera för varje fönster som tillhör klassen. Det extra minnet kan användas för alla programdefinierade syften. Systemet initierar det här minnet till noll.

 

Klassnamn

Varje fönsterklass behöver ett klassnamn för att skilja en klass från en annan. Tilldela ett klassnamn genom att ange lpszClassName medlem i WNDCLASSEX- struktur till adressen för en null-avslutad sträng som anger namnet. Eftersom fönsterklasser är processspecifika måste namn på fönsterklasser endast vara unika inom samma process. Eftersom klassnamn upptar utrymme i systemets privata atomtabell bör du också hålla klassnamnsträngarna så korta som möjligt.

Funktionen GetClassName hämtar namnet på den klass som ett visst fönster tillhör.

Adress för fönsterprocedur

Varje klass behöver en fönsterproceduradress för att definiera startpunkten för den fönsterprocedur som används för att bearbeta alla meddelanden för windows i klassen. Systemet skickar meddelanden till proceduren när det kräver att fönstret utför uppgifter, till exempel att måla sitt klientområde eller svara på indata från användaren. En process tilldelar en fönsterprocedur till en klass genom att kopiera adressen till lpfnWndProc medlem i WNDCLASSEX- struktur. Mer information finns i Fönsterprocedurer.

Instanshandtag

Varje fönsterklass kräver ett instanshandtag för att identifiera programmet eller .dll som registrerade klassen. Systemet kräver instanshandtag för att hålla reda på alla moduler. Systemet tilldelar ett handtag till varje kopia av en körbar körbar fil eller .dll.

Systemet skickar en instansreferens till startpunktsfunktionen för varje körbar fil (se WinMain) och .dll (se DllMain). Den körbara filen eller .dll tilldelar den här instansreferensen till klassen genom att kopiera den till hInstance medlem i WNDCLASSEX- struktur.

Klassmarkör

-klassmarkören definierar markörens form när den är i klientområdet i ett fönster i klassen. Systemet ställer automatiskt in markören till den angivna formen när markören går in i fönstrets klientområde och ser till att den behåller formen medan den finns kvar i klientområdet. Om du vill tilldela en markörform till en fönsterklass läser du in en fördefinierad markörform med hjälp av funktionen LoadCursor och tilldelar sedan det returnerade markörhandtaget till hCursor medlem i WNDCLASSEX- struktur. Alternativt kan du ange en anpassad markörresurs och använda funktionen LoadCursor för att läsa in den från programmets resurser.

Systemet kräver ingen klassmarkör. Om ett program anger hCursor medlem i WNDCLASSEX- struktur till NULL-definieras ingen klassmarkör. Systemet förutsätter att fönstret anger markörens form varje gång markören flyttas in i fönstret. Ett fönster kan ange markörens form genom att anropa funktionen SetCursor när fönstret tar emot WM_MOUSEMOVE meddelande. Mer information om markörer finns i cursors.

Klassikoner

En klassikon är en bild som systemet använder för att representera ett fönster i en viss klass. Ett program kan ha två klassikoner – en stor och en liten. Systemet visar ett fönsters stora klassikonen i aktivitetsväxlingsfönstret som visas när användaren trycker på ALT+TAB och i de stora ikonvyerna i aktivitetsfältet och utforskaren. Den lilla klassikonen visas i ett fönsters namnlist och i de små ikonvyerna i aktivitetsfältet och utforskaren.

Om du vill tilldela en stor och liten ikon till en fönsterklass anger du referenserna för ikonerna i hIcon och hIconSm medlemmar i WNDCLASSEX- struktur. Ikondimensionerna måste överensstämma med nödvändiga dimensioner för stora och små klassikoner. För en stor klassikon kan du fastställa nödvändiga dimensioner genom att ange värdena SM_CXICON och SM_CYICON i ett anrop till funktionen GetSystemMetrics. För en liten klassikon anger du värdena SM_CXSMICON och SM_CYSMICON. Mer information finns i Ikoner.

Om ett program anger hIcon och hIconSm medlemmar i WNDCLASSEX struktur för att NULL-använder systemet standardprogramikonen som stora och små klassikoner för fönsterklassen. Om du anger en stor klassikon men inte en liten, skapar systemet en liten klassikon baserat på den stora. Men om du anger en liten klassikon men inte en stor, använder systemet standardprogramikonen som den stora klassikonen och den angivna ikonen som den lilla klassikonen.

Du kan åsidosätta den stora eller lilla klassikonen för ett visst fönster med hjälp av meddelandet WM_SETICON. Du kan hämta den aktuella stora eller lilla klassikonen med hjälp av WM_GETICON meddelande.

Bakgrundspenslar för klass

En bakgrundsborste för klassen förbereder klientområdet i ett fönster för efterföljande ritning av programmet. Systemet använder penseln för att fylla klientområdet med en fast färg eller ett mönster, vilket tar bort alla tidigare bilder från den platsen oavsett om de tillhör fönstret eller inte. Systemet meddelar ett fönster att dess bakgrund ska målas genom att skicka WM_ERASEBKGND meddelandet till fönstret. Mer information finns i Penslar.

Om du vill tilldela en bakgrundsborste till en klass skapar du en pensel med hjälp av lämpliga GDI-funktioner och tilldelar det returnerade penselhandtaget till hbrBackground medlem i WNDCLASSEX- struktur.

I stället för att skapa en pensel kan ett program ange hbrBackground medlem till ett av standardsystemfärgvärdena. En lista över standardsystemfärgvärdena finns i SetSysColors.

Om du vill använda en standardsystemfärg måste programmet öka bakgrundsfärgvärdet med en. Till exempel är COLOR_BACKGROUND + 1 systemets bakgrundsfärg. Du kan också använda funktionen GetSysColorBrush för att hämta ett handtag till en pensel som motsvarar en standardsystemfärg och sedan ange referensen i hbrBackground medlem i WNDCLASSEX- struktur.

Systemet kräver inte att en fönsterklass har en bakgrundsborste för klassen. Om den här parametern är inställd på NULL-måste fönstret måla sin egen bakgrund när det tar emot WM_ERASEBKGND meddelande.

Klassmeny

En klassmeny definierar standardmenyn som ska användas av fönstren i klassen om ingen explicit meny ges när fönstren skapas. En meny är en lista över kommandon från vilka en användare kan välja åtgärder som programmet ska utföra.

Du kan tilldela en meny till en klass genom att ange lpszMenuName medlem i WNDCLASSEX struktur till adressen till en null-avslutad sträng som anger resursnamnet på menyn. Menyn antas vara en resurs i det angivna programmet. Systemet läser automatiskt in menyn när den behövs. Om menyresursen identifieras av ett heltal och inte med ett namn, kan programmet ange lpszMenuName medlem till det heltalet genom att använda MAKEINTRESOURCE- makro innan värdet tilldelas.

Systemet kräver ingen klassmeny. Om ett program anger lpszMenuName medlem i WNDCLASSEX- struktur till NULL-, har windows i klassen inga menyrader. Även om ingen klassmeny anges kan ett program fortfarande definiera en menyrad för ett fönster när det skapar fönstret.

Om en meny ges för en klass och ett underordnat fönster i den klassen skapas ignoreras menyn. Mer information finns i menyer.

Klassformat

Klassformaten definierar ytterligare element i fönsterklassen. Två eller flera format kan kombineras med hjälp av operatorn BITVIS ELLER (|). Om du vill tilldela en formatmall till en fönsterklass tilldelar du formatet till formatmallen medlem i WNDCLASSEX- struktur. En lista över klassformat finns i Fönsterklassformat.

Klasser och enhetskontexter

En enhetskontext är en särskild uppsättning värden som program använder för att rita i klientområdet i sina fönster. Systemet kräver en enhetskontext för varje fönster på skärmen, men ger viss flexibilitet i hur systemet lagrar och behandlar den enhetskontexten.

Om inget format för enhetskontext uttryckligen anges förutsätter systemet att varje fönster använder en enhetskontext som hämtats från en pool med kontexter som underhålls av systemet. I sådana fall måste varje fönster hämta och initiera enhetskontexten innan du målar och frigör den efter målning.

För att undvika att hämta en enhetskontext varje gång det behöver målas i ett fönster kan ett program ange CS_OWNDC formatmall för fönsterklassen. Det här klassformatet instruerar systemet att skapa en privat enhetskontext, dvs. att allokera en unik enhetskontext för varje fönster i klassen. Programmet behöver bara hämta kontexten en gång och sedan använda den för all efterföljande målning.

Extra klassminne

Systemet har en WNDCLASSEX- struktur internt för varje fönsterklass i systemet. När ett program registrerar en fönsterklass kan det dirigera systemet att allokera och lägga till ett antal ytterligare byte minne i slutet av WNDCLASSEX- struktur. Det här minnet kallas extra klassminne och delas av alla fönster som tillhör klassen. Använd det extra klassminnet för att lagra all information som rör klassen.

Eftersom extra minne allokeras från systemets lokala heap bör ett program använda extra klassminne sparsamt. Funktionen RegisterClassEx misslyckas om mängden extra klassminne som begärs är större än 40 byte. Om ett program kräver mer än 40 byte bör det allokera sitt eget minne och lagra en pekare till minnet i det extra klassminnet.

Funktionerna SetClassWord och SetClassLong kopierar ett värde till det extra klassminnet. Om du vill hämta ett värde från det extra klassminnet använder du funktionerna GetClassWord och GetClassLong. cbClsExtra medlem i WNDCLASSEX- struktur anger mängden extra klassminne som ska allokeras. Ett program som inte använder extra klassminne måste initiera cbClsExtra medlem till noll.

Extra fönsterminne

Systemet har en intern datastruktur för varje fönster. När du registrerar en fönsterklass kan ett program ange ett antal ytterligare byte minne, som kallas extra fönsterminne. När du skapar ett fönster i klassen allokerar och lägger systemet till den angivna mängden extra fönsterminne i slutet av fönstrets struktur. Ett program kan använda det här minnet för att lagra fönsterspecifika data.

Eftersom extra minne allokeras från systemets lokala heap bör ett program använda extra fönsterminne sparsamt. Funktionen RegisterClassEx misslyckas om mängden extra fönsterminne som begärs är större än 40 byte. Om ett program kräver mer än 40 byte bör det allokera sitt eget minne och lagra en pekare till minnet i det extra fönsterminnet.

Funktionen SetWindowLong kopierar ett värde till det extra minnet. Funktionen GetWindowLong hämtar ett värde från det extra minnet. cbWndExtra medlem i WNDCLASSEX- struktur anger mängden extra fönsterminne som ska allokeras. Ett program som inte använder minnet måste initiera cbWndExtra till noll.