Dela via


Anpassade kontroller

Det här avsnittet innehåller information om programdefinierade eller anpassade kontroller.

Följande ämnen diskuteras.

Skapa Owner-Drawn-kontroller

Knappar, menyer, statiska textkontroller, listrutor och kombinationsrutor kan skapas med en ägarritad stilflagga. När en kontroll har den ägarritade stilen hanterar systemet användarens interaktion med kontrollen som vanligt, utför sådana uppgifter som att identifiera när en användare har valt en knapp och meddela knappens ägare av händelsen. Men eftersom kontrollen är ägarskapad ansvarar kontrollens överordnade fönster för kontrollens visuella utseende. Det överordnade fönstret tar emot ett meddelande när kontrollen måste ritas.

För knappar och statiska textkontroller påverkar den ägarritade stilen hur systemet ritar hela kontrollen. För listrutor och kombinationsrutor ritar det överordnade fönstret poster i kontrollen, och kontrollen ritar sin egen kontur. Ett program kan till exempel anpassa en listruta så att den visar en liten bitmapp bredvid varje objekt i listan.

Följande exempelkod visar hur du skapar en ägarritad statisk textkontroll. Anta att Unicode har definierats.

// g_myStatic is a global HWND variable.
g_myStatic = CreateWindowEx(0, L"STATIC", L"Some static text", 
            WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, 
            25, 125, 150, 20, hDlg, 0, 0, 0);

I följande exempel, från fönsterproceduren för dialogrutan som innehåller kontrollen som skapades i föregående exempel, hanteras det WM_DRAWITEM meddelandet genom att texten visas i en anpassad färg med standardteckensnittet. Observera att du inte behöver anropa BeginPaint och EndPaint när du hanterar WM_DRAWITEM.

case WM_DRAWITEM:
{
    LPDRAWITEMSTRUCT pDIS = (LPDRAWITEMSTRUCT)lParam;
    if (pDIS->hwndItem == g_myStatic)
    {
        SetTextColor(pDIS->hDC, RGB(100, 0, 100));
        WCHAR staticText[99];
        int len = SendMessage(myStatic, WM_GETTEXT, 
            ARRAYSIZE(staticText), (LPARAM)staticText);
        TextOut(pDIS->hDC, pDIS->rcItem.left, pDIS->rcItem.top, staticText, len);
    }
    return TRUE;
}

Mer information om ägarritade kontroller finns i Skapa en ägarritad listruta och ägarritade kombinationsrutor.

Underklassera fönsterklassen för en befintlig kontroll

Att underklassa en befintlig kontroll är ett annat sätt att skapa en anpassad kontroll. Underklassproceduren kan ändra kontrollens valda beteende genom att bearbeta de meddelanden som påverkar de valda beteendena. Alla andra meddelanden skickas till den ursprungliga fönsterproceduren för kontrollen. Ett program kan till exempel visa en liten bitmap bredvid texten i en endast läsbar, enradig redigeringskontroll genom att subklassa kontrollen och bearbeta meddelandet WM_PAINT. Mer information finns i Om fönsterprocedurer och subklasskontroller.

Implementera en Application-Defined-fönsterklass

Om du vill skapa en kontroll som inte uttryckligen baseras på en befintlig kontroll måste programmet skapa och registrera en fönsterklass. Processen för att registrera en programdefinierad fönsterklass för en anpassad kontroll är densamma som att registrera en klass för ett vanligt fönster. Om du vill skapa en anpassad kontroll anger du namnet på fönsterklassen i funktionen CreateWindowEx eller i en dialogrutemall. Varje klass måste ha ett unikt namn, en motsvarande fönsterprocedur och annan information.

Som minst ritar fönsterproceduren kontrollen. Om ett program använder kontrollen för att låta användaren skriva information bearbetar fönsterproceduren även indatameddelanden från tangentbordet och musen och skickar meddelanden till det överordnade fönstret. Om kontrollen dessutom stöder kontrollmeddelanden bearbetar fönsterproceduren meddelanden som skickas till den av det överordnade fönstret eller andra fönster. Kontroller bearbetar till exempel ofta det WM_GETDLGCODE meddelande som skickas av dialogrutor för att dirigera en dialogruta för att bearbeta tangentbordsindata på ett visst sätt.

Fönsterproceduren för en programdefinierad kontroll bör bearbeta alla fördefinierade kontrollmeddelanden i följande tabell om meddelandet påverkar kontrollens funktion.

Meddelande Rekommendation
WM_GETDLGCODE Bearbeta om kontrollen använder tangenterna RETUR, ESC, TAB eller pil. Funktionen IsDialogMessage skickar det här meddelandet till kontroller i en dialogruta för att avgöra om nycklarna ska bearbetas eller skickas till kontrollen.
WM_GETFONT Bearbeta WM_SETFONT-meddelandet om det också behöver bearbetas.
WM_GETTEXT Bearbeta om kontrolltexten inte är samma som rubriken som anges av funktionen CreateWindowEx.
WM_GETTEXTLENGTH Bearbeta om kontrolltexten inte är samma som rubriken som anges av funktionen CreateWindowEx.
WM_KILLFOCUS Bearbeta om kontrollen visar en caret, en fokusrektangel eller ett annat objekt för att indikera att den har indatafokus.
WM_SETFOCUS Bearbeta om kontrollen visar en caret, en fokusrektangel eller ett annat objekt för att indikera att den har indatafokus.
WM_SETTEXT Bearbeta om kontrolltexten inte är samma som rubriken som anges av funktionen CreateWindowEx.
WM_SETFONT Bearbeta om kontrollen visar text. Systemet skickar det här meddelandet när du skapar en dialogruta som har DS_SETFONT formatmall.

 

Programdefinierade kontrollmeddelanden är specifika för den angivna kontrollen och måste uttryckligen skickas till kontrollen med hjälp av en SendMessage- eller SendDlgItemMessage- funktion. Det numeriska värdet för varje meddelande måste vara unikt och får inte stå i konflikt med värdena för andra fönstermeddelanden. För att säkerställa att programdefinierade meddelandevärden inte är i konflikt bör ett program skapa varje värde genom att lägga till ett unikt tal i WM_USER-värdet.

Skicka meddelanden från en kontroll

Anpassade kontroller kan krävas för att skicka meddelanden om händelser till det överordnade fönstret så att värdprogrammet kan svara på dessa händelser. En anpassad listvy kan till exempel skicka ett meddelande när användaren väljer ett objekt och ett annat meddelande när ett objekt dubbelklickas.

Meddelanden skickas som WM_COMMAND eller WM_NOTIFY meddelanden. WM_NOTIFY meddelanden innehåller mer information än WM_COMMAND meddelanden.

Kontrollidentifieraren är ett unikt nummer som programmet använder för att identifiera den kontroll som skickar meddelandet. Programmet anger identifieraren för en kontroll när kontrollen skapas. Programmet anger identifieraren antingen i parametern hMenu för funktionen CreateWindowEx eller i id medlem i DLGITEMTEMPLATEEX struktur.

Eftersom kontrollen i sig inte anger kontrollidentifieraren måste kontrollen hämta identifieraren innan den kan skicka meddelanden. En kontroll måste använda funktionen GetDlgCtrlID för att hämta sin egen kontrollidentifierare. Även om kontrollidentifieraren anges som menyreferens när kontrollen skapas kan inte funktionen GetMenu användas för att hämta identifieraren. En kontroll kan också hämta identifieraren från medlemmen hMenu i CREATESTRUCT--strukturen när WM_CREATE-meddelandet bearbetas.

Följande exempel, där hwndControl är kontrollfönstrets handtag och CN_VALUECHANGED är en anpassad meddelandedefinition, visar de två sätten att skicka ett kontrollspecifikt meddelande.

 // Send as WM_COMMAND.
SendMessage(GetParent(hwndControl), 
    WM_COMMAND,
    MAKEWPARAM(GetDlgCtrlID(hwndControl), CN_VALUECHANGED),
    (LPARAM)hwndControl);

// Send as WM_NOTIFY.           
NMHDR nmh;
nmh.code = CN_VALUECHANGED;
nmh.idFrom = GetDlgCtrlID(hwndControl);
nmh.hwndFrom = hwndControl;
SendMessage(GetParent(hwndControl), 
    WM_NOTIFY, 
    (WPARAM)hwndControl, 
    (LPARAM)&nmh);

Observera att NMHDR- struktur kan ingå i en större kontrolldefinierad struktur som innehåller ytterligare information. I exemplet kan de gamla och nya värdena för kontrollen finnas i den här strukturen. (Sådana utökade strukturer används med många standardmeddelanden, till exempel se LVN_INSERTITEM, som använder NMLISTVIEW- struktur.)

Tillgänglighet

Alla vanliga kontroller har stöd för Microsoft Active Accessibility (MSAA), som möjliggör programmatisk åtkomst av programbaserade program som skärmläsare. MSAA gör det också möjligt för UI Automation, en nyare teknik, att interagera med kontroller.

Anpassade kontroller bör implementera antingen gränssnittet IAccessible (för att stödja MSAA) eller gränssnitten för UI Automation eller båda. Annars kan produkter med tillgänglig teknik endast hämta mycket begränsad information om kontrollfönstret, inte ha åtkomst till kontrollens egenskaper och kommer inte att kunna utlösa händelser i kontrollen.

Mer information om hur du gör din kontroll tillgänglig finns i Windows Automation API.

konceptuell

allmän kontrollreferens

Anpassa en kontrolls visuella utseende med hjälp av anpassad ritning

Kontrollmeddelanden

Använda visuella format med Owner-Drawn kontroller