Delen via


Besturingselementen voor subklassen

Als een besturingselement bijna alles doet wat u wilt, maar u nog een paar functies nodig hebt, kunt u functies wijzigen of toevoegen aan het oorspronkelijke besturingselement door dit te subklassen. Een subklasse kan alle functies van een bestaande klasse en eventuele aanvullende functies hebben die u wilt geven.

Dit document beschrijft hoe subklassen worden gemaakt en bevat de volgende onderwerpen.

Besturingselementen voor subklassen vóór ComCtl32.dll versie 6

U kunt een besturingselement in een subklasse plaatsen en gebruikersgegevens opslaan in een besturingselement. U doet dit wanneer u versies van ComCtl32.dll vóór versie 6 gebruikt. Er zijn enkele nadelen bij het maken van subklassen met eerdere versies van ComCtl32.dll.

Als u een nieuw besturingselement wilt maken, kunt u het beste beginnen met een van de algemene Besturingselementen van Windows en deze uitbreiden naar een bepaalde behoefte. Als u een besturingselement wilt uitbreiden, maakt u een besturingselement en vervangt u de bestaande vensterprocedure door een nieuwe procedure. De nieuwe procedure onderschept de berichten van het besturingselement en handelt erop of geeft ze door aan de oorspronkelijke procedure voor standaardverwerking. Gebruik de functie SetWindowLong of SetWindowLongPtr om de WNDPROC van de controle te vervangen. In het volgende codevoorbeeld ziet u hoe u een WNDPROC vervangt.

OldWndProc = (WNDPROC)SetWindowLongPtr (hButton,
GWLP_WNDPROC, (LONG_PTR)NewWndProc);

Gebruikersgegevens opslaan

Mogelijk wilt u gebruikersgegevens opslaan met een afzonderlijk venster. Deze gegevens kunnen door de nieuwe vensterprocedure worden gebruikt om te bepalen hoe het besturingselement getekend moet worden of waarheen bepaalde berichten moeten worden verzonden. U kunt bijvoorbeeld gegevens gebruiken om een C++-klasse aanwijzer op te slaan naar de klasse die het besturingselement vertegenwoordigt. In het volgende codevoorbeeld ziet u hoe u SetProp- gebruikt om gegevens op te slaan met een venster.

SetProp (hwnd, TEXT("MyData"), (HANDLE)pMyData);

Nadelen van de oude subklassebenadering

De volgende lijst wijst op enkele nadelen van het gebruik van de eerder beschreven benadering voor het subklasseren van een besturingselement.

  • De vensterprocedure kan slechts eenmaal worden vervangen.
  • Het is moeilijk om een subklasse te verwijderen nadat deze is gemaakt.
  • Het koppelen van privégegevens aan een venster is inefficiënt.
  • Als u de volgende procedure in een subklasseketen wilt aanroepen, kunt u de oude vensterprocedure niet casten en aanroepen. U moet deze aanroepen met behulp van de functie CallWindowProc.

Besturingselementen subclasseren met ComCtl32.dll versie 6

Notitie

ComCtl32.dll versie 6 is alleen in Unicode. De algemene controls die worden ondersteund door ComCtl32.dll versie 6 mogen niet in een subklasse (of superklasse) worden geplaatst met ANSI-vensterprocedures.

 

ComCtl32.dll versie 6 bevat vier functies die het maken van subklassen gemakkelijker maken en de eerder besproken nadelen elimineren. De nieuwe functies bevatten het beheer van meerdere referentiegegevens, waardoor de ontwikkelaar zich kan richten op programmeerfuncties en niet op het beheren van subklassen. De subklassefuncties zijn:

SetWindowSubclass

Deze functie wordt gebruikt om in eerste instantie een venster te subklassen. Elke subklasse wordt uniek geïdentificeerd door het adres van de pfnSubclass en de bijbehorende uIdSubclass. Beide zijn parameters van de functie SetWindowSubclass. Verschillende subklassen kunnen dezelfde subklasseprocedure delen en de id kan elke aanroep identificeren. Als u referentiegegevens wilt wijzigen, kunt u opeenvolgende aanroepen doen naar SetWindowSubclass. Het belangrijkste voordeel is dat elke subklasse-instantie eigen referentiegegevens heeft.

De declaratie van een subklasseprocedure verschilt enigszins van een reguliere vensterprocedure omdat deze twee extra gegevens bevat: de subklasse-id en de referentiegegevens. In de laatste twee parameters van de volgende functiedeclaratie wordt dit weergegeven.

LRESULT CALLBACK MyWndProc (HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass,
DWORD_PTR dwRefData);

Telkens wanneer een bericht wordt ontvangen door de nieuwe vensterprocedure, worden een subklasse-id en referentiegegevens opgenomen.

Notitie

Alle tekenreeksen die aan de procedure worden doorgegeven, zijn Unicode-tekenreeksen, zelfs als Unicode niet is opgegeven als een preprocessordefinitie.

 

In het volgende voorbeeld ziet u een skelet-implementatie van een vensterprocedure voor een subklassebeheer.

LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam,
                               LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch (uMsg)
    {
    case WM_PAINT:
        .
        .
        .
        return TRUE;
    // Other cases...
    } 
    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

De vensterprocedure kan worden gekoppeld aan het besturingselement in de WM_INITDIALOG handler van de dialoogvensterprocedure, zoals wordt weergegeven in het volgende voorbeeld.

case WM_INITDIALOG:
{
    HWND button = GetDlgItem(hDlg, IDC_OWNERDRAWBUTTON);
    SetWindowSubclass(button, OwnerDrawButtonProc, 0, 0);
    return TRUE;
}

GetWindowSubclass

Met deze functie wordt informatie opgehaald over een subklasse. U kunt bijvoorbeeld GetWindowSubclass gebruiken om toegang te krijgen tot de referentiegegevens.

VerwijderWindowSubklasse

Met deze functie worden subklassen verwijderd. RemoveWindowSubclass in combinatie met SetWindowSubclass kunt u subklassen dynamisch toevoegen en verwijderen.

DefSubclassProc

Met de functie DefSubclassProc wordt de volgende handler in de subklasseketen aangeroepen. De functie haalt ook de juiste id- en referentiegegevens op en geeft de informatie door aan de volgende vensterprocedure.