ODMenu.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:26k
- // ODMenu.cpp
- //
- #include "odmenu.h"
- using namespace std;
- ODMenu::ODMenu()
- {
- m_seqNumber = 0;
- //Set default colors
- //Transparent color is color of "transparent" background in bitmaps
- m_clrTranparent = RGB(192, 192, 192);
- m_clrItemText = GetSysColor(COLOR_MENUTEXT);
- m_clrItemBackground = GetSysColor(COLOR_MENU);
- if(GetColorIntensity(m_clrItemBackground) < 0.82)
- m_clrItemBackground = LightenColor(m_clrItemBackground, 0.27);
- else
- m_clrItemBackground = DarkenColor(m_clrItemBackground, 0.10);
- m_clrHighlightItemText = GetSysColor(COLOR_HIGHLIGHTTEXT);
- m_clrHighlightItemBackground = GetSysColor(COLOR_HIGHLIGHT);
- m_clrHighlightItemBackground = LightenColor(m_clrHighlightItemBackground, 0.5);
- m_clrHighlightItemOutline = GetSysColor(COLOR_HIGHLIGHT);
- m_clrSeparator = GetSysColor(COLOR_3DSHADOW);
- m_clrIconBar = GetSysColor(COLOR_MENU);
- m_clrIconShadow = GetSysColor(COLOR_3DSHADOW);
- m_clrCheckMark = GetSysColor(COLOR_MENUTEXT);
- m_clrCheckMarkBackground = AverageColor(m_clrIconBar, m_clrHighlightItemBackground, 0.8);
- m_clrCheckMarkBackgroundHighlight = AverageColor(m_clrIconBar, m_clrHighlightItemBackground, 0.25);
- m_clrCheckMarkBackgroundHighlight = DarkenColor(m_clrHighlightItemBackground, 0.1);
- //Get the system font for menus
- NONCLIENTMETRICS ncms;
- ncms.cbSize = sizeof(NONCLIENTMETRICS);
- if(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncms, 0))
- m_hFont = CreateFontIndirect(&ncms.lfMenuFont);
- //Set menu metrics
- m_iconBarMargin = 3;
- m_textLeftMargin = 6;
- m_textRightMargin = 3;
- m_iconWidth = GetSystemMetrics(SM_CXSMICON);
- m_iconHeight = GetSystemMetrics(SM_CYSMICON);
- m_verticalSpacing = 6;
- //Create GDI objects
- m_hItemBackground = CreateSolidBrush(m_clrItemBackground);
- m_hIconBarBrush = CreateSolidBrush(m_clrIconBar);
- m_hIconShadowBrush = CreateSolidBrush(m_clrIconShadow);
- m_hHighlightItemBackgroundBrush = CreateSolidBrush(m_clrHighlightItemBackground);
- m_hCheckMarkBackgroundBrush = CreateSolidBrush(m_clrCheckMarkBackground);
- m_hCheckMarkBackgroundHighlightBrush = CreateSolidBrush(m_clrCheckMarkBackgroundHighlight);
- m_hSelectionOutlinePen = CreatePen(PS_SOLID, 1, m_clrHighlightItemOutline);
- m_hSeparatorPen = CreatePen(PS_SOLID, 1, m_clrSeparator);
- m_hCheckMarkPen = CreatePen(PS_SOLID, 1, m_clrCheckMark);
- }
- ODMenu::~ODMenu()
- {
- if(m_hFont)
- DeleteObject(m_hFont);
- if(m_hIconBarBrush)
- DeleteObject(m_hIconBarBrush);
- if(m_hIconShadowBrush)
- DeleteObject(m_hIconShadowBrush);
- if(m_hCheckMarkBackgroundBrush)
- DeleteObject(m_hCheckMarkBackgroundBrush);
- if(m_hCheckMarkBackgroundHighlightBrush)
- DeleteObject(m_hCheckMarkBackgroundHighlightBrush);
- if(m_hSelectionOutlinePen)
- DeleteObject(m_hSelectionOutlinePen);
- if(m_hSeparatorPen)
- DeleteObject(m_hSeparatorPen);
- if(m_hCheckMarkPen)
- DeleteObject(m_hCheckMarkPen);
- if(m_hItemBackground)
- DeleteObject(m_hItemBackground);
- if(m_hHighlightItemBackgroundBrush)
- DeleteObject(m_hHighlightItemBackgroundBrush);
- }
- bool ODMenu::Init(HWND hOwnerWnd, HMENU hMenu)
- {
- m_hRootMenu = hMenu;
- //Traverse through all menu items to allocate a map of ODMENUITEM which
- //will be subsequently used to measure and draw menu items.
- if(m_seqNumber == 0)
- EnumMenuItems(hMenu);
- return true;
- }
- void ODMenu::EnumMenuItems(HMENU hMenu)
- {
- int i, numItems;
- MENUITEMINFO miInfo;
- numItems = GetMenuItemCount(hMenu);
- if(numItems > 0)
- {
- miInfo.cbSize = sizeof(MENUITEMINFO);
- miInfo.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
- miInfo.dwTypeData = m_szItemText;
- miInfo.cch = sizeof(m_szItemText);
- for(i=0; i<numItems; i++)
- {
- if(GetMenuItemInfo(hMenu, i, TRUE, &miInfo))
- AddItem(hMenu, i, &miInfo);
- if(miInfo.hSubMenu)
- {
- //Resursive call
- EnumMenuItems(miInfo.hSubMenu);
- }
- miInfo.cch = sizeof(m_szItemText);
- miInfo.dwTypeData = m_szItemText;
- }
- }
- }
- void ODMenu::DeleteSubMenu(HMENU hMenu)
- {
- //Recursively remove map items according to menu structure
- int i;
- MENUITEMINFO miInfo;
- i = 0;
- miInfo.cbSize = sizeof(MENUITEMINFO);
- miInfo.fMask = MIIM_SUBMENU | MIIM_DATA;
- while(GetMenuItemInfo(hMenu, i, TRUE, &miInfo))
- {
- //Make recursive call
- if(miInfo.hSubMenu)
- DeleteSubMenu(miInfo.hSubMenu);
- //Remove this item from map
- m_menuItems.erase(miInfo.dwItemData);
- i++;
- }
- }
- void ODMenu::SetMenuItemOwnerDrawn(HMENU hMenu, UINT item, UINT type)
- {
- //Set menu item type to owner-drawn and set itemdata to sequence number.
- MENUITEMINFO miInfo;
-
- miInfo.cbSize = sizeof(MENUITEMINFO);
- miInfo.fMask = MIIM_TYPE | MIIM_DATA;
- miInfo.fType = type | MFT_OWNERDRAW;
- miInfo.dwItemData = m_seqNumber++;
-
- SetMenuItemInfo(hMenu, item, TRUE, &miInfo);
- }
- void ODMenu::GenerateDisplayText(ODMENUITEM& item)
- {
- TCHAR* pChr;
- int i;
- item.displayText = "";
- item.rawDisplayText = "";
- item.shortcutText = "";
- //Does shortcut text exist?
- if(pChr = strchr((LPTSTR)item.rawText.c_str(), 't'))
- item.shortcutText = pChr + 1;
- i = 0;
- pChr = (LPTSTR)item.rawText.c_str();
- while(*(pChr + i) != 't' && *(pChr + i) != ' ')
- {
- if(*(pChr + i) == '&')
- {
- item.rawDisplayText.append(pChr + i, 1);
- i++;
- continue;
- }
- item.rawDisplayText.append(pChr + i, 1);
- item.displayText.append(pChr + i, 1);
- i++;
- }
- }
- void ODMenu::DrawItemText(DRAWITEMSTRUCT* lpdis, ODMENUITEM& item)
- {
- int x, y;
- SIZE size;
- RECT rectText;
- RECT rectItem;
- memcpy(&rectItem, &lpdis->rcItem, sizeof(RECT));
- //Get size of text to draw
- GetTextExtentPoint32(lpdis->hDC, item.displayText.c_str(), item.displayText.length(), &size);
- // Determine where to draw.
- ComputeMenuTextPos(lpdis, item, x, y, size);
- rectText.left = x;
- rectText.right = lpdis->rcItem.right - m_textRightMargin;
- rectText.top = y;
- rectText.bottom = lpdis->rcItem.bottom;
- //Adjust rectangle that will contain the menu item
- if(!item.topMost)
- {
- rectItem.left += (m_iconWidth + 2*m_iconBarMargin);
- }
- //Draw the item rectangle with appropriate background color
- ExtTextOut(lpdis->hDC, x, y, ETO_OPAQUE, &rectItem, "", 0, NULL);
- //Draw the text
- DrawText(lpdis->hDC, item.rawDisplayText.c_str(), item.rawDisplayText.length(),
- &rectText, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
- DrawText(lpdis->hDC, item.shortcutText.c_str(), item.shortcutText.length(),
- &rectText, DT_RIGHT | DT_SINGLELINE | DT_VCENTER);
- }
- void ODMenu::DrawIconBar(DRAWITEMSTRUCT* lpdis, ODMENUITEM& item)
- {
- RECT rectBar;
- memcpy(&rectBar, &lpdis->rcItem, sizeof(RECT));
- //Draw icon bar if not top level
- if(!item.topMost)
- {
- rectBar.right = rectBar.left + m_iconWidth + 2*m_iconBarMargin + 1;
- if(lpdis->itemState & ODS_SELECTED &&
- !(lpdis->itemState & ODS_DISABLED || lpdis->itemState & ODS_GRAYED))
- {
- FillRect(lpdis->hDC, &rectBar, m_hHighlightItemBackgroundBrush);
- }
- else
- {
- FillRect(lpdis->hDC, &rectBar, m_hIconBarBrush);
- }
- }
- int x, y;
- //Draw icon for menu item if handle is valid
- if(item.hBitmap)
- {
- x = m_iconBarMargin;
- y = rectBar.top + ((rectBar.bottom - rectBar.top - 16) / 2);
- if(lpdis->itemState & ODS_DISABLED || lpdis->itemState & ODS_GRAYED)
- {
- //Draw disabled icon in normal position
- DrawTransparentBitmap(lpdis->hDC, item.hBitmap, x, y, m_clrTranparent, eDisabled);
- }
- else if(lpdis->itemState & ODS_SELECTED)
- {
- //Draw icon "raised"
- //Draw shadow right one pixel and down one pixel from normal position
- DrawTransparentBitmap(lpdis->hDC, item.hBitmap, x+1, y+1, m_clrTranparent, eShadow);
- //Draw normal left one pixel and up one pixel from normal position
- DrawTransparentBitmap(lpdis->hDC, item.hBitmap, x-1, y-1, m_clrTranparent);
- }
- else
- {
- //Draw faded icon in normal position
- DrawTransparentBitmap(lpdis->hDC, item.hBitmap, x, y, m_clrTranparent, eFaded);
- }
- }
- else if(lpdis->itemState & ODS_CHECKED)
- {
- HBRUSH hPrevBrush;
- HPEN hPrevPen;
- RECT rect;
- //Draw filled, outlined rectangle around checkmark first
- if(lpdis->itemState & ODS_SELECTED)
- hPrevBrush = (HBRUSH)SelectObject(lpdis->hDC, m_hCheckMarkBackgroundHighlightBrush);
- else
- hPrevBrush = (HBRUSH)SelectObject(lpdis->hDC, m_hCheckMarkBackgroundBrush);
- hPrevPen = (HPEN)SelectObject(lpdis->hDC, m_hSelectionOutlinePen);
- rect.left = m_iconBarMargin;
- rect.right = m_iconBarMargin + m_iconWidth;
- rect.top = rectBar.top + (rectBar.bottom - rectBar.top - m_iconHeight) / 2;
- rect.bottom = rect.top + m_iconHeight;
- Rectangle(lpdis->hDC, rect.left, rect.top, rect.right, rect.bottom);
- SelectObject(lpdis->hDC, hPrevBrush);
- SelectObject(lpdis->hDC, hPrevPen);
- //Draw check mark
- x = (m_iconWidth + 2*m_iconBarMargin - 6) / 2;
- y = rectBar.top + ((rectBar.bottom - rectBar.top - 7) / 2) + 1;
- DrawCheckMark(lpdis->hDC, x, y, true);
- }
- }
- void ODMenu::ComputeMenuTextPos(DRAWITEMSTRUCT* lpdis, ODMENUITEM& item, int& x, int& y, SIZE& size)
- {
- x = lpdis->rcItem.left;
- y = lpdis->rcItem.top;
- // y += ((lpdis->rcItem.bottom - lpdis->rcItem.top - size.cy) / 2);
- if(!item.topMost)
- {
- //Correct position for drop down menus. Leave space for a bitmap
- x += (m_iconWidth + 2*m_iconBarMargin + m_textLeftMargin);
- }
- else
- {
- //Center horizontally for top level menu items
- x += ((lpdis->rcItem.right - lpdis->rcItem.left - size.cx) / 2);
- }
- }
- void ODMenu::DrawTransparentBitmap(HDC hDC, HBITMAP hBitmap, short xStart,
- short yStart, COLORREF cTransparentColor,
- bitmapType eType)
- {
- BITMAP bm;
- COLORREF cColor;
- HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
- HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
- HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
- POINT ptSize;
- HBRUSH hOldBrush;
- BOOL bRC;
- hdcTemp = CreateCompatibleDC(hDC);
- SelectObject(hdcTemp, hBitmap); // Select the bitmap
- GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
- ptSize.x = bm.bmWidth; // Get width of bitmap
- ptSize.y = bm.bmHeight; // Get height of bitmap
- DPtoLP(hdcTemp, &ptSize, 1); // Convert from device
- // to logical points
- // Create some DCs to hold temporary data.
- hdcBack = CreateCompatibleDC(hDC);
- hdcObject = CreateCompatibleDC(hDC);
- hdcMem = CreateCompatibleDC(hDC);
- hdcSave = CreateCompatibleDC(hDC);
- // Create a bitmap for each DC. DCs are required for a number of
- // GDI functions.
- // Monochrome DC
- bmAndBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
- // Monochrome DC
- bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
- bmAndMem = CreateCompatibleBitmap(hDC, ptSize.x, ptSize.y);
- bmSave = CreateCompatibleBitmap(hDC, ptSize.x, ptSize.y);
- // Each DC must select a bitmap object to store pixel data.
- bmBackOld = (HBITMAP)SelectObject(hdcBack, bmAndBack);
- bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject);
- bmMemOld = (HBITMAP)SelectObject(hdcMem, bmAndMem);
- bmSaveOld = (HBITMAP)SelectObject(hdcSave, bmSave);
- // Set proper mapping mode.
- SetMapMode(hdcTemp, GetMapMode(hDC));
- // Save the bitmap sent here, because it will be overwritten.
- bRC = BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
- // Create an "AND mask" that contains the mask of the colors to draw
- // (the nontransparent portions of the image).
- // Set the background color of the source DC to the color.
- // contained in the parts of the bitmap that should be transparent
- cColor = SetBkColor(hdcTemp, cTransparentColor);
- // Create the object mask for the bitmap by performing a BitBlt
- // from the source bitmap to a monochrome bitmap.
- bRC = BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
- // Set the background color of the source DC back to the original color.
- SetBkColor(hdcTemp, cColor);
- // Create the inverse of the object mask.
- bRC = BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, NOTSRCCOPY);
- // Copy the background of the main DC to the destination.
- bRC = BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hDC, xStart, yStart, SRCCOPY);
- // Mask out the places where the bitmap will be placed.
- // hdcMem then contains the background color of hDC only in the places
- // where the transparent pixels reside.
- bRC = BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
- if(eType == eNormal)
- {
- // Mask out the transparent colored pixels on the bitmap.
- // hdcTemp then contains only the non-transparent pixels.
- BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
- // XOR the bitmap with the background on the destination DC.
- // hdcMem then contains the required result.
- BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
- }
- else if(eType == eShadow)
- {
- //Select shadow brush into hdcTemp
- hOldBrush = (HBRUSH)SelectObject(hdcTemp, m_hIconShadowBrush);
- //Copy shadow brush pixels for all non-transparent pixels to hdcTemp
- bRC = BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, MERGECOPY);
- // XOR the bitmap with the background on the destination DC.
- // hdcMem then contains the required result.
- bRC = BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
- //Restore the brush in hdcTemp
- SelectObject(hdcTemp, hOldBrush);
- }
- else if(eType == eFaded)
- {
- COLORREF col;
- int x, y;
- //Lighten the color of each pixel in hdcTemp
- for(x=0; x<ptSize.x; x++)
- {
- for(y=0; y<ptSize.y; y++)
- {
- col = GetPixel(hdcTemp, x, y);
- col = LightenColor(col, 0.3);
- SetPixel(hdcTemp, x, y, col);
- }
- }
- // Mask out the transparent colored pixels on the bitmap.
- // hdcTemp then contains only the non-transparent pixels.
- BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
- // XOR the bitmap with the background on the destination DC.
- // hdcMem then contains the required result.
- BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
- }
- else if(eType == eDisabled)
- {
- COLORREF discol, col;
- BYTE r, g, b;
- int x, y;
- int avgcol;
- double factor;
- //Lighten the color of COLOR_BTNSHADOW by a weighted average of the color at each pixel in hdcTemp.
- //Set the pixel to the lightened color.
- discol = GetSysColor(COLOR_BTNSHADOW);
- for(x=0; x<ptSize.x; x++)
- {
- for(y=0; y<ptSize.y; y++)
- {
- col = GetPixel(hdcTemp, x, y);
- r = GetRValue(col);
- g = GetGValue(col);
- b = GetBValue(col);
- avgcol = (r + g + b) / 3;
- factor = avgcol / 255.0;
- SetPixel(hdcTemp, x, y, LightenColor(discol, factor));
- }
- }
- // Mask out the transparent colored pixels on the bitmap.
- // hdcTemp then contains only the non-transparent pixels.
- BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
- // XOR the bitmap with the background on the destination DC.
- // hdcMem then contains the required result.
- BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
- }
- // Copy the destination to the screen.
- bRC = BitBlt(hDC, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY);
- // Place the original bitmap back into the bitmap sent here.
- bRC = BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);
- // Delete the memory bitmaps.
- DeleteObject(SelectObject(hdcBack, bmBackOld));
- DeleteObject(SelectObject(hdcObject, bmObjectOld));
- DeleteObject(SelectObject(hdcMem, bmMemOld));
- DeleteObject(SelectObject(hdcSave, bmSaveOld));
- // Delete the memory DCs.
- DeleteDC(hdcMem);
- DeleteDC(hdcBack);
- DeleteDC(hdcObject);
- DeleteDC(hdcSave);
- DeleteDC(hdcTemp);
- }
- void ODMenu::DrawCheckMark(HDC hDC, short x, short y, bool bNarrow)
- {
- HPEN hOldPen;
- int dp = 0;
- if(bNarrow)
- dp = 1;
- //Select check mark pen
- hOldPen = (HPEN)SelectObject(hDC, m_hCheckMarkPen);
- //Draw the check mark
- MoveToEx(hDC, x, y + 2, NULL);
- LineTo(hDC, x, y + 5 - dp);
-
- MoveToEx(hDC, x + 1, y + 3, NULL);
- LineTo(hDC, x + 1, y + 6 - dp);
-
- MoveToEx(hDC, x + 2, y + 4, NULL);
- LineTo(hDC, x + 2, y + 7 - dp);
-
- MoveToEx(hDC, x + 3, y + 3, NULL);
- LineTo(hDC, x + 3, y + 6 - dp);
-
- MoveToEx(hDC, x + 4, y + 2, NULL);
- LineTo(hDC, x + 4, y + 5 - dp);
-
- MoveToEx(hDC, x + 5, y + 1, NULL);
- LineTo(hDC, x + 5, y + 4 - dp);
-
- MoveToEx(hDC, x + 6, y, NULL);
- LineTo(hDC, x + 6, y + 3 - dp);
- //Restore original DC pen
- SelectObject(hDC, hOldPen);
- }
- COLORREF ODMenu::LightenColor(COLORREF col, double factor)
- {
- if(factor > 0.0 && factor <= 1.0)
- {
- BYTE red, green, blue, lightred, lightgreen, lightblue;
- red = GetRValue(col);
- green = GetGValue(col);
- blue = GetBValue(col);
- lightred = (BYTE)((factor*(255 - red)) + red);
- lightgreen = (BYTE)((factor*(255 - green)) + green);
- lightblue = (BYTE)((factor*(255 - blue)) + blue);
- col = RGB(lightred, lightgreen, lightblue);
- }
- return col;
- }
- COLORREF ODMenu::DarkenColor(COLORREF col, double factor)
- {
- if(factor > 0.0 && factor <= 1.0)
- {
- BYTE red, green, blue, lightred, lightgreen, lightblue;
- red = GetRValue(col);
- green = GetGValue(col);
- blue = GetBValue(col);
- lightred = (BYTE)(red - (factor*red));
- lightgreen = (BYTE)(green - (factor*green));
- lightblue = (BYTE)(blue - (factor*blue));
- col = RGB(lightred, lightgreen, lightblue);
- }
- return col;
- }
- COLORREF ODMenu::AverageColor(COLORREF col1, COLORREF col2, double weight)
- {
- BYTE avgRed, avgGreen, avgBlue;
- if (weight <= 0.0)
- return col1;
- else if (weight > 1.0)
- return col2;
- avgRed = (BYTE) (GetRValue(col1) * weight + GetRValue(col2) * (1.0 - weight));
- avgGreen = (BYTE) (GetGValue(col1) * weight + GetGValue(col2) * (1.0 - weight));
- avgBlue = (BYTE) (GetBValue(col1) * weight + GetBValue(col2) * (1.0 - weight));
- return RGB(avgRed, avgGreen, avgBlue);
- }
- double ODMenu::GetColorIntensity(COLORREF col)
- {
- BYTE red, green, blue;
- red = GetRValue(col);
- green = GetGValue(col);
- blue = GetBValue(col);
- //denominator of 765 is (255*3)
- return (double)red/765.0 + (double)green/765.0 + (double)blue/765.0;
- }
- void ODMenu::MeasureItem(HWND hWnd, LPARAM lParam)
- {
- MEASUREITEMSTRUCT* lpmis = (MEASUREITEMSTRUCT*)lParam;
- ODMENUITEMS::iterator it;
- ODMENUITEM item;
- HDC hDC;
- HFONT hfntOld;
- RECT rect;
- it = m_menuItems.find(lpmis->itemData);
- if(it == m_menuItems.end())
- return;
- hDC = GetDC(hWnd);
- hfntOld = (HFONT)SelectObject(hDC, m_hFont);
- item = it->second;
- if(item.displayText.length() > 0)
- {
- DrawText(hDC, item.rawText.c_str(), item.rawText.length(), &rect,
- DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
- lpmis->itemWidth = rect.right - rect.left;
- if(!item.topMost)
- {
- //Correct size for drop down menus
- lpmis->itemWidth += (m_iconWidth + 2*m_iconBarMargin + m_textLeftMargin + m_textRightMargin);
- lpmis->itemHeight += m_verticalSpacing;
- }
- }
- else if(item.dwType & MFT_SEPARATOR)
- {
- //Correct size for drop down menus
- if(!item.topMost)
- {
- lpmis->itemWidth += (m_iconWidth + 2*m_iconBarMargin + m_textLeftMargin + m_textRightMargin);
- lpmis->itemHeight = 3;
- }
- }
- SelectObject(hDC, hfntOld);
- ReleaseDC(hWnd, hDC);
- }
- void ODMenu::DrawItem(HWND hWnd, LPARAM lParam)
- {
- DRAWITEMSTRUCT* lpdis = (DRAWITEMSTRUCT*)lParam;
- ODMENUITEMS::iterator it;
- ODMENUITEM item;
- COLORREF clrPrevText, clrPrevBkgnd;
- HFONT hPrevFnt;
- HPEN hPrevPen;
- HBRUSH hPrevBrush;
- it = m_menuItems.find(lpdis->itemData);
- if(it == m_menuItems.end())
- return;
- item = it->second;
- //Draw based on type of item
- if(item.displayText.length() > 0)
- {
- // Set the appropriate foreground and background colors.
- if(item.topMost)
- {
- if(lpdis->itemState & ODS_SELECTED)
- {
- clrPrevText = SetTextColor(lpdis->hDC, m_clrHighlightItemText);
- clrPrevBkgnd = SetBkColor(lpdis->hDC, m_clrHighlightItemBackground);
- }
- else
- {
- clrPrevText = SetTextColor(lpdis->hDC, m_clrItemText);
- clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor(COLOR_MENU));
- }
- }
- else
- {
- if(lpdis->itemState & ODS_GRAYED || lpdis->itemState & ODS_DISABLED)
- {
- clrPrevText = SetTextColor(lpdis->hDC, GetSysColor(COLOR_3DSHADOW));
- clrPrevBkgnd = SetBkColor(lpdis->hDC, m_clrItemBackground);
- }
- else if(lpdis->itemState & ODS_SELECTED)
- {
- clrPrevText = SetTextColor(lpdis->hDC, m_clrHighlightItemText);
- clrPrevBkgnd = SetBkColor(lpdis->hDC, m_clrHighlightItemBackground);
- }
- else
- {
- clrPrevText = SetTextColor(lpdis->hDC, m_clrItemText);
- clrPrevBkgnd = SetBkColor(lpdis->hDC, m_clrItemBackground);
- }
- }
- // Select the font.
- hPrevFnt = (HFONT)SelectObject(lpdis->hDC, m_hFont);
- //Draw the text
- DrawItemText(lpdis, item);
- //Restore original font
- SelectObject(lpdis->hDC, hPrevFnt);
- SetTextColor(lpdis->hDC, clrPrevText);
- SetBkColor(lpdis->hDC, clrPrevBkgnd);
- }
- else if(item.dwType & MFT_SEPARATOR)
- {
- //Fill menu space with menu background, first.
- RECT rect;
- memcpy(&rect, &lpdis->rcItem, sizeof(RECT));
- rect.left += (m_iconWidth + 2*m_iconBarMargin);
- FillRect(lpdis->hDC, &rect, m_hItemBackground);
- //Draw the separator line
- hPrevPen = (HPEN)SelectObject(lpdis->hDC, m_hSeparatorPen);
- MoveToEx(lpdis->hDC, lpdis->rcItem.left + m_iconWidth + 2*m_iconBarMargin + m_textLeftMargin,
- lpdis->rcItem.top+1, NULL);
- LineTo(lpdis->hDC, lpdis->rcItem.right, lpdis->rcItem.top+1);
- //Restore GDI objects in DC
- SelectObject(lpdis->hDC, hPrevPen);
- }
- //Draw the left icon bar
- DrawIconBar(lpdis, item);
- //Draw selection outline if drawing a selected item
- if(lpdis->itemState & ODS_SELECTED && !(lpdis->itemState & ODS_GRAYED || lpdis->itemState & ODS_DISABLED))
- {
- hPrevBrush = (HBRUSH)SelectObject(lpdis->hDC, (HBRUSH)GetStockObject(NULL_BRUSH));
- hPrevPen = (HPEN)SelectObject(lpdis->hDC, m_hSelectionOutlinePen);
- Rectangle(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
- lpdis->rcItem.right, lpdis->rcItem.bottom);
- //Restore GDI objects in DC
- SelectObject(lpdis->hDC, hPrevBrush);
- SelectObject(lpdis->hDC, hPrevPen);
- }
- }
- void ODMenu::OnDestroy()
- {
- }
- bool ODMenu::GetItem(UINT id, ODMENUITEM** ppItem)
- {
- bool bRC = true;
- if(!ppItem)
- return false;
- ODMENUITEMS::iterator it = m_menuItems.find(id);
- if(it != m_menuItems.end())
- *ppItem = &it->second;
- return bRC;
- }
- void ODMenu::SetItemImage(HINSTANCE hInst, UINT wID, UINT idBitmap)
- {
- // Get iterator to ODMENUITEM
- ODMENUITEMS::iterator it;
- HBITMAP hBitmap;
- // Load the bitmap resource
- hBitmap = (HBITMAP) LoadImage(hInst,
- MAKEINTRESOURCE(idBitmap),
- IMAGE_BITMAP, 0, 0, LR_SHARED);
- if (hBitmap)
- {
- // Find menu item having specified wID.
- it = m_menuItems.begin();
- while(it != m_menuItems.end())
- {
- if(it->second.wID == wID)
- {
- it->second.hBitmap = hBitmap;
- break;
- }
- it++;
- }
- }
- else
- {
- DWORD dwErr = GetLastError();
- dwErr = 0;
- }
- }
- void ODMenu::AddItem(HMENU hMenu, int index, MENUITEMINFO* pItemInfo)
- {
- MENUITEMINFO miInfo;
- ODMENUITEM odInfo;
- //Obtain menu item info if not supplied
- if(!pItemInfo)
- {
- miInfo.cbSize = sizeof(MENUITEMINFO);
- miInfo.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
- miInfo.dwTypeData = m_szItemText;
- miInfo.cch = sizeof(m_szItemText);
- if(GetMenuItemInfo(hMenu, index, TRUE, &miInfo))
- pItemInfo = &miInfo;
- }
- //Add menu info to map of menu items
- if(pItemInfo)
- {
- if(pItemInfo->hSubMenu != NULL && hMenu == m_hRootMenu)
- odInfo.topMost = true;
- else
- odInfo.topMost = false;
- if(pItemInfo->fType == MFT_STRING)
- {
- odInfo.rawText = pItemInfo->dwTypeData;
- GenerateDisplayText(odInfo);
- }
- else
- {
- odInfo.rawText = "";
- odInfo.displayText = "";
- }
- odInfo.dwType = pItemInfo->fType;
- odInfo.wID = pItemInfo->wID;
- odInfo.hBitmap = NULL;
- m_menuItems[m_seqNumber] = odInfo;
- SetMenuItemOwnerDrawn(hMenu, index, pItemInfo->fType);
- }
- }
- void ODMenu::DeleteItem(HMENU hMenu, int index)
- {
- //Item data for item is map index
- MENUITEMINFO miInfo;
- miInfo.cbSize = sizeof(MENUITEMINFO);
- miInfo.fMask = MIIM_SUBMENU | MIIM_DATA;
- if(GetMenuItemInfo(hMenu, index, TRUE, &miInfo))
- {
- if(miInfo.hSubMenu)
- DeleteSubMenu(miInfo.hSubMenu);
- //Remove this item from map
- m_menuItems.erase(miInfo.dwItemData);
- }
- }