W przykładzie tego tematu używa elementów menu rysowania przez właściciela, w menu. Elementy menu Zaznacz atrybuty konkretnej czcionki, a aplikacja wyświetla każdy element menu Czcionka, która ma odpowiedni atrybut. Na przykład element menu kursywą jest wyświetlany kursywą. Znak nazwy menu na pasku menu otwiera menu.
Pasek menu i menu rozwijane są zdefiniowane wstępnie przez zasób rozszerzonych menu szablonu. Ponieważ szablon menu można określić elementy narysowane właściciela, menu zawiera początkowo cztery elementy menu Tekst z następujących ciągów: "Regularne," "pogrubienie," "Kursywa" i "Podkreślenie." Procedura okno zmiany te elementy narysowane właściciela, podczas przetwarzania wiadomości WM_CREATE . Po odebraniu wiadomości WM_CREATE procedurę okna wywołuje funkcję zdefiniowanych przez aplikację OnCreate, który wykonuje następujące czynności dla każdego elementu menu
Ponieważ wskaźnik do każdej budowli OKREŚLANĄ przez aplikację jest zapisywany jako element danych, to jest przekazywany do procedury okna w połączeniu z WM_MEASUREITEM i WM_DRAWITEM wiadomości dla odpowiedniego elementu menu. Wskaźnik jest zawarty w Państwa itemData konstrukcji MEASUREITEMSTRUCT i DRAWITEMSTRUCT.
WM_MEASUREITEM wiadomość jest wysyłana dla każdego elementu menu rysowane właściciel jest wyświetlana po raz pierwszy. Procesy aplikacji tej wiadomości przez wybranie czcionki dla elementu menu do kontekstu urządzenia, a następnie określenie miejsca wymagana do wyświetlania tekstu elementu menu w danej czcionki. Zarówno tekst pozycji Czcionka i menu są określane przez element menu OKREŚLANĄ struktury (struktury zdefiniowane przez aplikację). Wniosek określa rozmiar tekstu za pomocą GetTextExtentPoint32 funkcji.
Procedurę okna przetwarza wiadomość WM_DRAWITEM , wyświetlając tekst elementu menu w odpowiednią czcionkę. Zarówno tekst pozycji Czcionka i menu są określane przez element menu OKREŚLANĄ struktury. Aplikacja wybiera kolory tekstu i tła, odpowiednie do stanu elementu menu.
Procedurę okna przetwarza wiadomość WM_DESTROY do zniszczenia czcionki i wolnej pamięci. Stosowanie Usuwa czcionkę i zwalnia struktury OKREŚLANĄ przez aplikację, dla każdego elementu menu.
Poniżej przedstawiono odpowiednie fragmenty pliku nagłówka aplikacji.
/ / Identyfikatory elementu menu dla menu znak # define IDM_CHARACTER 10 # define 11 IDM_REGULAR # define 12 IDM_BOLD # define 13 IDM_ITALIC # define IDM_UNDERLINE 14 / / struktury skojarzone z menu elementów element typedef struct tagMYITEM {HFONT hfont;
int cchItemText;
char szItemText [1];
} OKREŚLANĄ;
# define CCH_MAXITEMTEXT 256
Poniżej przedstawiono istotne części procedury okna aplikacji i jej funkcje skojarzone.
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);
}