Sto semplicemente cercando di aggiungere piccole campioni di colore al mio menu contestuale Ecco una versione Photoshopped di quello che sto cercando di realizzare (visualizzato tramite il TrackPopupMenu API.):Come misurare e visualizzare correttamente la voce del menu di scelta rapida del proprietario con un segno di spunta?
Per quanto mi capire il menu predefinito non lo supporta. Btw, il campione di cui sopra (senza campioni di colore) è stata generata in questo modo:
MENUITEMINFO mii = {0};
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE | MIIM_STRING;
mii.fType = MFT_STRING;
mii.wID = ID_1_MARKER_01 + m;
mii.dwTypeData = L"Marker";
mii.cch = TSIZEOF(L"Marker");
mii.fState = m == 1 ? MFS_CHECKED : MFS_ENABLED;
if(m == 2)
mii.fState |= MFS_GRAYED;
VERIFY(::InsertMenuItem(hMenu, ID_1_BEFORE, FALSE, &mii));
Così ho scoperto che ho bisogno di usare MFT_OWNERDRAW
stile per disegnare le voci di menu me stesso, ma è qui che cominciano i problemi.
ho cambiato il mio codice per visualizzare il menu come tale:
MENUITEMINFO mii = {0};
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE;
mii.fType = MFT_OWNERDRAW;
mii.wID = ID_1_MARKER_01 + m;
mii.dwItemData = MARKER_ID_01 + m;
mii.fState = m == 1 ? MFS_CHECKED : MFS_ENABLED;
if(m == 2)
mii.fState |= MFS_GRAYED;
VERIFY(::InsertMenuItem(hMenu, ID_1_BEFORE, FALSE, &mii));
poi ho bisogno di ignorare WM_MEASUREITEM
e WM_DRAWITEM
messaggi. Ma quando lo faccio con il codice che ti faccio vedere qui di seguito, ecco cosa ottengo:
Quindi, per favore abbiate pazienza con me. Ho molte domande su questo argomento:
1) Durante l'elaborazione WM_MEASUREITEM
come faccio a conoscere le dimensioni del testo, se non forniscono né DC
né HWND
per il menu? In altre parole, se faccio questo, la dimensione del menu è sbagliato:
#define TSIZEOF(f) ((sizeof(f) - sizeof(TCHAR))/sizeof(TCHAR))
//hwnd = HWND supplied in WM_MEASUREITEM notification
HDC hDC = ::GetDC(hwnd);
HGDIOBJ hOldFont = ::SelectObject(hDC, ::SendMessage(hwnd, WM_GETFONT, 0, 0));
SIZE szTxt = {0};
::GetTextExtentPoint32(hDC,
L"Marker",
TSIZEOF(L"Marker"),
&szTxt);
//lpmis = MEASUREITEMSTRUCT*
lpmis->itemWidth = szTxt.cx;
lpmis->itemHeight = szTxt.cy;
::SelectObject(hDC, hOldFont);
::ReleaseDC(hwnd, hDC);
2) Poi durante l'elaborazione WM_DRAWITEM
come faccio a sapere l'offset per iniziare a disegnare il testo a sinistra? Se faccio questo, i miei menu non sono compensati abbastanza a destra (come si può vedere dalla schermata qui sopra):
int nCheckW = ::GetSystemMetrics(SM_CXMENUCHECK);
//lpdis = DRAWITEMSTRUCT*
::ExtTextOut(lpdis->hDC,
lpdis->rcItem.left + nCheckW,
lpdis->rcItem.top,
ETO_OPAQUE,
&lpdis->rcItem,
L"Marker",
TSIZEOF(L"Marker"),
NULL);
3) E infine come faccio a disegnare quella casella di controllo di default sul lato sinistro della la voce del menu?
Quando si utilizza elementi OwnerDraw di Windows disegna intero menu in stile classico senza l'utilizzo di temi. Perché non vuoi usare le icone dei colori invece delle voci di menu ownerdraw? Risolverà tutti i tuoi problemi. –
@DenisAnisimov: Non sono quelle icone colorate a sinistra? Se è così, ho bisogno di spazio per quei segni di spunta da mostrare sulla sinistra. – c00000fd
1) Per la misurazione, l'unico modo sicuro era ottenere 'LOGFONT' da' SystemParametersInfo (SPI_GETNONCLIENTMETRICS) 'che viene restituito in' lfMenuFont' e creare un font da esso usando 'CreateFontIndirect' e quindi usarlo per' SelectObject() ' e solo allora chiama 'GetTextExtentPoint32' per ottenere la dimensione del testo. So che sembra un sacco di passaggi, ma sembra darmi un vero risultato. – c00000fd