Niinkin yksinkertainen käyttöliittymäelementti kuin painonappi vaatii erityiskäsittelyä. Yleisimpien nappityyppien, kuten radiopainike, valintaruutu ja painonappi luokkana on pelkkä Button, joten tyypintunnistus luokan perusteella ei onnistu. Yksi ratkaisu on Win32 APIn funktio GetWindowLongPtr, joka palauttaa long-tyyppisenä haluttua ikkunakohtaista tietoa. Ikkunan kahvan lisäksi funktiolle on annettava jokin ikkunakohtaisista vakioista tai indeksi ikkunan lisämuistiin (engl. extra memory). Ikkunan tyyppi selviää vakiolla GWL_STYLE.
GetWindowLongPtr on suhteellisen uusi funktio, ja sen käyttö Visual Studio 6-ympäristössä vaatii otsikko- ja kirjastotiedostojen päivittämistä Microsoftin verkkosivuilla osoitteessa http://www.microsoft.com/msdownload/platformsdk/sdkupdate/ . Lisäksi on määriteltävä Windows-versioksi vähintään Windows 98 (esimerkissä 2000):
#define _WIN32_WINNT 0x0500 #define WINVER 0x0500Nappityyppejä on useita erilaisia. Tuttujen tyylien, kuten painonappi (BS_PUSHBUTTON), valintaruutu (BS_CHECKBOX) ja radiopainike (BS_RADIOBUTTON) ohella eksoottisemmasta päästä löytyy nappiryhmä (BS_GROUPBOX), kolmitila valintaruutu (BS_3STATE) ja ulkonäöltään räätälöidyt napit (BS_OWNERDRAW ja vanhentunut BS_USERBUTTON). Tavallisten nappien lisäksi ns. valittavista (engl. checkable) napeista on erikseen auto-versiot, joiden valitsemisen ja valinnan poistamisen Windows hoitaa täysin automaattisesti toisin kuin napeilla yleensä.
Sen selvittäminen onko ikkuna, kuten nappi, todella jotain tiettyä tyyliä ei ole aivan triviaalia. Ikkunan tyyliliput on pakattu long-tyyppiin mutta winuser.h-otsikkotiedoston perusteella ne eivät ole tavanomaisia, yhden bitin määrääviä, bittitason (engl. bitwise) tailla yhdistettäviä lippuja. Tyylit ovat toisensa poissulkevia (nappi ei voi olla radiopainike ja painonappi samanaikaisesti), mikä näkyy myös bittitasolla nappivakioiden määrityksissä. Helpoin, joskaan ei arkkitehtuuririippumaton, tapa selvittää painonapin tyyli on hankkiutua bittitason tailla eroon muista kuin neljästä alimmasta bitistä ja vertailla toimenpiteen tulosta suoraan winuser.h:ssa määriteltyihin tyyleihin:
DWORD s = GetWindowLongPtr(hWindow, GWL_STYLE) & 0xFL; // All but the 4 LSB.
// ...
if(s == BS_PUSHBUTTON || s == BS_DEFPUSHBUTTON)
{
isCheckable = FALSE;
lstrcat(textOut, "push button ");
} // if
// ...
else if(s == BS_CHECKBOX || s == BS_AUTOCHECKBOX)
lstrcat(textOut, "check box ");
// ...
Jos napilla on tila (valittu, osittain valittu, ei valittu) se ei selviä GetWindowLongPtr-funktiolla. Napin tilaa voi kuitenkin tiedustella lähettämällä sille BM_GETCHECK viestin. Nappi ei välitä kummastakaan parametrista vaan ilmaisee tilansa lähetysfunktion paluuarvona. Seuraavassa esimerkki viestistä:
switch(SendMessage(hWindow, BM_GETCHECK, 0, 0))
{
case BST_CHECKED:
lstrcat(textOut, "selected");
break;
case BST_INDETERMINATE:
lstrcat(textOut, "partially Selected");
break;
case BST_UNCHECKED:
lstrcat(textOut, "unselected");
break;
} // switch
Koska näppäimistöfokus ei tavallisesti siirry kontrollilta toiselle nappia käytettäessä, pelkkä CBT-koukun HCBT_SETFOCUS viestin käsittely ei esimerkkiohjelmassa takaa reagointia nappien tilojen muutoksiin. Napin tilan muuttuessa se lähettää kuitenkin isäikkunalleen (ikkuna, dialogi) yleisen WM_COMMAND-tyypin viestin. Käyttöliittymäolioiden tapauksessa WM_COMMAND viestin lParam on MSDN:n perusteella (Microsoft, 1999, WM_COMMAND) kahva lähettäjään (esim. painonappi) ja kaksi ylintä tavua (engl. high-word) puolestaan komennon tunniste. Painonappia painettaessa tunniste on BN_CLICKED, joten napin tilan uudelleentarkistus hoituu näin:
if(cwp->message == WM_COMMAND && HIWORD(cwp->wParam) == BN_CLICKED)
{ // On button click.
lstrcat(textOut, "State ");
handleControls((HWND) cwp->lParam);
lstrcat(textOut, "\r\n");
notifyObserver();
} // if
HIGHWORD on luvusta 16 ylintä bittiä antava makro (jonka vastakohta on LOWORD).