Voorbeeld van de eigenaar getekende Menu Items

Het voorbeeld in dit onderwerp wordt eigenaar getekende menu-items in een menu. De menu-items Selecteer specifieke lettertypekenmerken, en de toepassing wordt weergegeven, elk menu-item een lettertype gebruikt dat het bijbehorende kenmerk heeft. Bijvoorbeeld, wordt het cursief menu-item weergegeven in een cursief lettertype. De naam van het teken-menu op de menubalk met het menu.

De menubalk en drop-down menu worden in eerste instantie gedefinieerd door een uitgebreide menu-sjabloon resource. Omdat een menusjabloon eigenaar getekende objecten opgeven kunt, het menu in eerste instantie bevat vier tekst menu-items met de volgende tekenreeksen: "Reguliere", "vet," "Cursief", en "Underline". Van de toepassing venster procedure wijzigt deze aan eigenaar getekende objecten bij de verwerking van het WM_CREATE bericht. Wanneer het het WM_CREATE bericht ontvangt, roept de venster procedure de functie OnCreate toepassing gedefinieerde, die de volgende stappen uit voor elk menu-item voert

  1. Wijst een toepassing gedefinieerde MIJNITEM structuur.
  2. Hiermee wordt de tekst van het menu-item opgehaald en opgeslagen in de toepassing gedefinieerde MIJNITEM structuur.
  3. Het lettertype dat wordt gebruikt om het menu-item weer te geven in maakt en opslaat de greep de toepassing gedefinieerde MIJNITEM structuur.
  4. Het menu itemtype gewijzigd in MFT_OWNERDRAW en een pointer naar de toepassing gedefinieerde MIJNITEM structuur als item gegevens opgeslagen.

Omdat een aanwijzer naar elke toepassing gedefinieerde MIJNITEM structuur wordt opgeslagen als gegevens van het object, is het doorgegeven aan de procedure venster in combinatie met de WM_MEASUREITEM en WM_DRAWITEM -berichten voor het overeenkomstige menu-item. De aanwijzer is opgenomen in de itemData lid van zowel de MEASUREITEMSTRUCT als de DRAWITEMSTRUCT structuren.

Een WM_MEASUREITEM-bericht wordt verzonden voor elk eigenaar getekende menu-item de eerste keer die wordt weergegeven. De processen van toepassingen vereist dit bericht door het lettertype voor de menu-item te selecteren in een device-context en vervolgens bepalen de ruimte om de tekst menu item in dat lettertype weer te geven. De tekst van lettertype en menu item zijn beide opgegeven door het menu-item MIJNITEM structuur (de structuur die is gedefinieerd door de toepassing). De toepassing bepaalt de grootte van de tekst met behulp van de GetTextExtentPoint32 -functie.

Het venster procedure verwerkt het WM_DRAWITEM bericht door de tekst menu item weer te geven in het desbetreffende lettertype. De tekst van lettertype en menu item zijn beide opgegeven door het menu-item MIJNITEM structuur. De toepassing selecteert tekst en achtergrond kleuren naar het menu-item staat passende.

Het venster procedure verwerkt het WM_DESTROY bericht te vernietigen lettertypen en vrij geheugen. De toepassing wordt het lettertype verwijderd en bevrijdt de toepassing gedefinieerde MIJNITEM structuur voor elk menu-item.

Hier volgen de relevante gedeelten van de toepassing van de headerbestand.

 / / Menu-item-id's voor het menu van het teken # define IDM_CHARACTER 10 # define IDM_REGULAR 11 # define IDM_BOLD 12 # define IDM_ITALIC 13 # define IDM_UNDERLINE 14 / / structuur gekoppeld menu items typedef struct tagMYITEM {HFONT hfont; 
    int cchItemText; 
    char szItemText [1]; 
} MIJNITEM; 
 
# define CCH_MAXITEMTEXT 256 
 

Hier volgen de relevante delen van het venster van de aanvraagprocedure en de bijbehorende functies.

LRESULT CALLBACK MainWindowProc( 
        HWND hwnd, 
        UINT uMsg, 
        WPARAM wParam, 
        LPARAM lParam 
        ) 
{ 
    switch (uMsg) 
    { 
        case WM_CREATE: 
            if (!OnCreate(hwnd)) 
                return -1; 
            break; 
 
        case WM_DESTROY: 
            OnDestroy(hwnd); 
            PostQuitMessage(0); 
            break; 
 
        case WM_MEASUREITEM: 
            OnMeasureItem(hwnd, (LPMEASUREITEMSTRUCT) lParam); 
            return TRUE; 
 
        case WM_DRAWITEM: 
            OnDrawItem(hwnd, (LPDRAWITEMSTRUCT) lParam); 
            return TRUE; 
 
        // Additional message processing goes here. 
 
        default: 
            return DefWindowProc(hwnd, uMsg, wParam, lParam); 
    } 
    return 0; 
} 
 
 
BOOL WINAPI OnCreate(HWND hwnd) 
{ 
    HMENU hmenuBar = GetMenu(hwnd); 
    HMENU hmenuPopup; 
    MENUITEMINFO mii; 
    UINT uID; 
    MYITEM *pMyItem; 
 
    // Get the handle to the pop-up menu. 
 
    mii.fMask = MIIM_SUBMENU;     // information to get 
    GetMenuItemInfo(hmenuBar, IDM_CHARACTER, FALSE, &mii); 
    hmenuPopup = mii.hSubMenu; 
 
    // Modify each menu item. Assume that the IDs IDM_REGULAR 
    // through IDM_UNDERLINE are consecutive numbers. 
 
    for (uID = IDM_REGULAR; uID <= IDM_UNDERLINE; uID++) 
    { 
         // Allocate an item structure, leaving space for a 
         // string of up to CCH_MAXITEMTEXT characters. 
 
        pMyItem = (MYITEM *) LocalAlloc(LMEM_FIXED, 
                sizeof(MYITEM) + CCH_MAXITEMTEXT); 
 
        // Save the item text in the item structure. 
 
        mii.fMask = MIIM_TYPE; 
        mii.dwTypeData = pMyItem->szItemText; 
        mii.cch = CCH_MAXITEMTEXT; 
        GetMenuItemInfo(hmenuPopup, uID, FALSE, &mii); 
        pMyItem->cchItemText = mii.cch; 
 
        // Reallocate the structure to the minimum required size. 
 
        pMyItem = (MYITEM *) LocalReAlloc(pMyItem, 
                sizeof(MYITEM) + mii.cch, LMEM_MOVEABLE); 
 
        // Create the font used to draw the item. 
 
        pMyItem->hfont = CreateMenuItemFont(uID); 
 
        // Change the item to an owner-drawn item, and save 
        // the address of the item structure as item data. 
 
        mii.fMask = MIIM_TYPE | MIIM_DATA; 
        mii.fType = MFT_OWNERDRAW; 
        mii.dwItemData = (DWORD) pMyItem; 
        SetMenuItemInfo(hmenuPopup, uID, FALSE, &mii); 
    } 
    return TRUE; 
} 
 
HFONT CreateMenuItemFont(UINT uID) 
{ 
    LOGFONT lf; 
 
    ZeroMemory(&lf, sizeof(lf)); 
    lf.lfHeight = 20; 
    lstrcpy(lf.lfFaceName, "Times New Roman"); 
 
    switch (uID) 
    { 
        case IDM_BOLD: 
            lf.lfWeight = FW_HEAVY; 
            break; 
 
        case IDM_ITALIC: 
            lf.lfItalic = TRUE; 
            break; 
 
        case IDM_UNDERLINE: 
            lf.lfUnderline = TRUE; 
            break; 
    } 
    return CreateFontIndirect(&lf); 
} 
 
VOID WINAPI OnDestroy(HWND hwnd) 
{ 
    HMENU hmenuBar = GetMenu(hwnd); 
    HMENU hmenuPopup; 
    MENUITEMINFO mii; 
    UINT uID; 
    MYITEM *pMyItem; 
 
    // Get the handle to the menu. 
 
    mii.fMask = MIIM_SUBMENU;     // information to get  
    GetMenuItemInfo(hmenuBar, IDM_CHARACTER, FALSE, &mii); 
    hmenuPopup = mii.hSubMenu; 
 
    // Free resources associated with each menu item. 
 
    for (uID = IDM_REGULAR; uID <= IDM_UNDERLINE; uID++) 
    { 
        // Get the item data. 
 
        mii.fMask = MIIM_DATA; 
        GetMenuItemInfo(hmenuPopup, uID, FALSE, &mii); 
        pMyItem = (MYITEM *) mii.dwItemData; 
 
        // Destroy the font and free the item structure. 
 
        DeleteObject(pMyItem->hfont); 
        LocalFree(pMyItem); 
    } 
} 
 
VOID WINAPI OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis) 
{ 
    MYITEM *pMyItem = (MYITEM *) lpmis->itemData; 
    HDC hdc = GetDC(hwnd); 
    HFONT hfntOld = SelectObject(hdc, pMyItem->hfont); 
    SIZE size; 
 
    GetTextExtentPoint32(hdc, pMyItem->szItemText, 
            pMyItem->cchItemText, &size); 
 
    lpmis->itemWidth = size.cx; 
    lpmis->itemHeight = size.cy; 
 
    SelectObject(hdc, hfntOld); 
    ReleaseDC(hwnd, hdc); 
} 
 
VOID WINAPI OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis) 
{ 
    MYITEM *pMyItem = (MYITEM *) lpdis->itemData; 
    COLORREF clrPrevText, clrPrevBkgnd; 
    HFONT hfntPrev; 
    int x, y; 
 
    // Set the appropriate foreground and background colors. 
 
    if (lpdis->itemState & ODS_SELECTED) 
    { 
        clrPrevText = SetTextColor(lpdis->hDC, 
                GetSysColor(COLOR_HIGHLIGHTTEXT)); 
        clrPrevBkgnd = SetBkColor(lpdis->hDC, 
                GetSysColor(COLOR_HIGHLIGHT)); 
    } 
    else 
    { 
        clrPrevText = SetTextColor(lpdis->hDC, 
                GetSysColor(COLOR_MENUTEXT)); 
        clrPrevBkgnd = SetBkColor(lpdis->hDC, 
                GetSysColor(COLOR_MENU)); 
    } 
 
    // Determine where to draw and leave space for a check-mark. 
 
    x = lpdis->rcItem.left; 
    y = lpdis->rcItem.top; 
    x += GetSystemMetrics(SM_CXMENUCHECK); 
 
    // Select the font and draw the text. 
 
    hfntPrev = SelectObject(lpdis->hDC, pMyItem->hfont); 
    ExtTextOut(lpdis->hDC, x, y, ETO_OPAQUE, 
            &lpdis->rcItem, pMyItem->szItemText, 
            pMyItem->cchItemText, NULL); 
 
    // Restore the original font and colors. 
 
    SelectObject(lpdis->hDC, hfntPrev); 
    SetTextColor(lpdis->hDC, clrPrevText); 
    SetBkColor(lpdis->hDC, clrPrevBkgnd); 
} 
 

Index