Beispiel von Ownerdrawn-Menüelemente

Das Codebeispiel in diesem Thema Ownerdrawn-Menüelemente in einem Menü. Die Menüpunkte wählen Sie bestimmte Schriftartattribute, und die Anwendung zeigt jedes Menüelement verwenden eine Schriftart, die das entsprechende Attribut hat. Z. B. ist das kursiv Menüelement in einer kursiven Schriftart angezeigt. Die Bezeichnung des Zeichens im Menü in der Menüleiste öffnet das Menü.

Die Menüleiste und die Drop-Down-Menü werden zunächst durch eine erweiterte Menü-Dialogfeldvorlagen-Ressource definiert. Da eine Menüvorlage ownerdrawn-Elemente angeben kann, enthält das Menü zunächst vier Text-Menüelemente mit folgenden Zeichenfolgen: "Normal", "Fett" "Kursiv" und "Underline". Fensterprozedur der Anwendung ändert diese ownerdrawn-Elemente, wenn es die WM_CREATE -Nachricht verarbeitet. Wenn sie die WM_CREATE-Nachricht empfängt, ruft die Fensterprozedur die Anwendung definierten OnCreate Funktion, die die folgenden Schritte für jedes Menüelement ausführt

  1. Weist eine anwendungsdefinierte MYITEM-Struktur.
  2. Ruft den Text des Menüelements ab und speichert sie in der Anwendung definierten MYITEM Struktur.
  3. Erstellt die Schriftart verwendet, um das Menüelement anzuzeigen und speichert das Handle in der Anwendung definierten MYITEM Struktur.
  4. Ändert den Menü-Elementtyp in MFT_OWNERDRAW und speichert einen Zeiger auf die anwendungsdefinierte MYITEM Struktur als Elementdaten.

Da ein Zeiger auf jede Anwendung definierte MYITEM Struktur als Elementdaten gespeichert ist, wird es an die Fensterprozedur, die in Verbindung mit den WM_MEASUREITEM und WM_DRAWITEM -Meldungen für das entsprechende Menüelement übergeben. Der Zeiger ist in der ItemData -Mitglied der MEASUREITEMSTRUCT und DRAWITEMSTRUCT Strukturen enthalten.

Eine WM_MEASUREITEM Nachricht ist für jedes Ownerdrawn-Menüelement zum ersten Mal gesendet, ist es angezeigt. Die Anwendungsprozesse benötigt diese Nachricht durch Auswählen der Schriftart für das Menüelement einen Gerätekontext und bestimmen dann den Raum den Menü Elementtext in dieser Schriftart angezeigt. Die Schriftart und Menü Elementtext werden beide durch das Menüelement MYITEM Struktur (die von der Anwendung definierte) angegeben. Die Anwendung bestimmt die Größe des Textes mithilfe der GetTextExtentPoint32 Funktion.

Die Fensterprozedur verarbeitet die WM_DRAWITEM Nachricht durch den Text im Menü Element in der entsprechenden Schriftart anzeigen. Die Schriftart und Menü Elementtext werden beide durch das Menüelement MYITEM Struktur angegeben. Die Anwendung wählt Text- und Hintergrundfarben entsprechend des Menüelements Zustand.

Die Fensterprozedur verarbeitet die Nachricht WM_DESTROY , Schriftarten und freien Speicher zu zerstören. Die Anwendung löscht die Schriftart und befreit von die Anwendung definierten MYITEM Struktur für jedes Menüelement.

Im folgenden werden die relevanten Teile der Header-Datei der Anwendung.

 / / Menü-Element-IDs für im Menü Zeichenbedienfelds # define # define # define # define # define IDM_ITALIC-13 IDM_BOLD-12 IDM_REGULAR-11 IDM_CHARACTER-10 IDM_UNDERLINE 14 / / Struktur zugeordnete Menü Elemente Typedef Struct TagMYITEM {HFONT Hfont; 
    Int CchItemText; 
    Char SzItemText [1]; 
} MYITEM; 
 
# define CCH_MAXITEMTEXT 256 

 

Im folgenden werden die relevanten Teile der Anwendung Fensterprozedur und der dazugehörigen Funktionen.

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