Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

ODMenu.cpp

Go to the documentation of this file.
00001 // ODMenu.cpp
00002 //
00003 
00004 #include "odmenu.h"
00005 
00006 using namespace std;
00007 
00008 ODMenu::ODMenu()
00009 {
00010     m_seqNumber = 0;
00011 
00012     //Set default colors
00013 
00014     //Transparent color is color of "transparent" background in bitmaps
00015     m_clrTranparent = RGB(192, 192, 192);
00016 
00017     m_clrItemText = GetSysColor(COLOR_MENUTEXT);
00018     m_clrItemBackground = GetSysColor(COLOR_MENU);
00019     if(GetColorIntensity(m_clrItemBackground) < 0.82)
00020         m_clrItemBackground = LightenColor(m_clrItemBackground, 0.27);
00021     else
00022         m_clrItemBackground = DarkenColor(m_clrItemBackground, 0.10);
00023     m_clrHighlightItemText = GetSysColor(COLOR_HIGHLIGHTTEXT);
00024     m_clrHighlightItemBackground = GetSysColor(COLOR_HIGHLIGHT);
00025     m_clrHighlightItemBackground = LightenColor(m_clrHighlightItemBackground, 0.5);
00026     m_clrHighlightItemOutline = GetSysColor(COLOR_HIGHLIGHT);
00027     m_clrSeparator = GetSysColor(COLOR_3DSHADOW);
00028     m_clrIconBar = GetSysColor(COLOR_MENU);
00029     m_clrIconShadow = GetSysColor(COLOR_3DSHADOW);
00030     m_clrCheckMark = GetSysColor(COLOR_MENUTEXT);
00031     m_clrCheckMarkBackground = AverageColor(m_clrIconBar, m_clrHighlightItemBackground, 0.8);
00032     m_clrCheckMarkBackgroundHighlight = AverageColor(m_clrIconBar, m_clrHighlightItemBackground, 0.25);
00033     m_clrCheckMarkBackgroundHighlight = DarkenColor(m_clrHighlightItemBackground, 0.1);
00034 
00035     //Get the system font for menus
00036     NONCLIENTMETRICS ncms;
00037     ncms.cbSize = sizeof(NONCLIENTMETRICS);
00038     if(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncms, 0))
00039         m_hFont = CreateFontIndirect(&ncms.lfMenuFont);
00040 
00041     //Set menu metrics
00042     m_iconBarMargin = 3;
00043     m_textLeftMargin = 6;
00044     m_textRightMargin = 3;
00045     m_iconWidth = GetSystemMetrics(SM_CXSMICON);
00046     m_iconHeight = GetSystemMetrics(SM_CYSMICON);
00047     m_verticalSpacing = 6;
00048 
00049     //Create GDI objects
00050     m_hItemBackground = CreateSolidBrush(m_clrItemBackground);
00051     m_hIconBarBrush = CreateSolidBrush(m_clrIconBar);
00052     m_hIconShadowBrush = CreateSolidBrush(m_clrIconShadow);
00053     m_hHighlightItemBackgroundBrush = CreateSolidBrush(m_clrHighlightItemBackground);
00054     m_hCheckMarkBackgroundBrush = CreateSolidBrush(m_clrCheckMarkBackground);
00055     m_hCheckMarkBackgroundHighlightBrush = CreateSolidBrush(m_clrCheckMarkBackgroundHighlight);
00056     m_hSelectionOutlinePen = CreatePen(PS_SOLID, 1, m_clrHighlightItemOutline);
00057     m_hSeparatorPen = CreatePen(PS_SOLID, 1, m_clrSeparator);
00058     m_hCheckMarkPen = CreatePen(PS_SOLID, 1, m_clrCheckMark);
00059 }
00060 
00061 ODMenu::~ODMenu()
00062 {
00063     if(m_hFont)
00064         DeleteObject(m_hFont);
00065     if(m_hIconBarBrush)
00066         DeleteObject(m_hIconBarBrush);
00067     if(m_hIconShadowBrush)
00068         DeleteObject(m_hIconShadowBrush);
00069     if(m_hCheckMarkBackgroundBrush)
00070         DeleteObject(m_hCheckMarkBackgroundBrush);
00071     if(m_hCheckMarkBackgroundHighlightBrush)
00072         DeleteObject(m_hCheckMarkBackgroundHighlightBrush);
00073     if(m_hSelectionOutlinePen)
00074         DeleteObject(m_hSelectionOutlinePen);
00075     if(m_hSeparatorPen)
00076         DeleteObject(m_hSeparatorPen);
00077     if(m_hCheckMarkPen)
00078         DeleteObject(m_hCheckMarkPen);
00079     if(m_hItemBackground)
00080         DeleteObject(m_hItemBackground);
00081     if(m_hHighlightItemBackgroundBrush)
00082         DeleteObject(m_hHighlightItemBackgroundBrush);
00083 }
00084 
00085 bool ODMenu::Init(HWND hOwnerWnd, HMENU hMenu)
00086 {
00087     m_hRootMenu = hMenu;
00088 
00089     //Traverse through all menu items to allocate a map of ODMENUITEM which
00090     //will be subsequently used to measure and draw menu items.
00091 
00092     if(m_seqNumber == 0)
00093         EnumMenuItems(hMenu);
00094 
00095     return true;
00096 }
00097 
00098 void ODMenu::EnumMenuItems(HMENU hMenu)
00099 {
00100     int i, numItems;
00101     MENUITEMINFO miInfo;
00102 
00103     numItems = GetMenuItemCount(hMenu);
00104     if(numItems > 0)
00105     {
00106         miInfo.cbSize = sizeof(MENUITEMINFO);
00107         miInfo.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
00108         miInfo.dwTypeData = m_szItemText;
00109         miInfo.cch = sizeof(m_szItemText);
00110 
00111         for(i=0; i<numItems; i++)
00112         {
00113             if(GetMenuItemInfo(hMenu, i, TRUE, &miInfo))
00114                 AddItem(hMenu, i, &miInfo);
00115 
00116             if(miInfo.hSubMenu)
00117             {
00118                 //Resursive call
00119                 EnumMenuItems(miInfo.hSubMenu);
00120             }
00121 
00122             miInfo.cch = sizeof(m_szItemText);
00123             miInfo.dwTypeData = m_szItemText;
00124         }
00125     }
00126 }
00127 
00128 void ODMenu::DeleteSubMenu(HMENU hMenu)
00129 {
00130     //Recursively remove map items according to menu structure
00131     int i;
00132     MENUITEMINFO miInfo;
00133 
00134     i = 0;
00135     miInfo.cbSize = sizeof(MENUITEMINFO);
00136     miInfo.fMask = MIIM_SUBMENU | MIIM_DATA;
00137     while(GetMenuItemInfo(hMenu, i, TRUE, &miInfo))
00138     {
00139         //Make recursive call
00140         if(miInfo.hSubMenu)
00141             DeleteSubMenu(miInfo.hSubMenu);
00142 
00143         //Remove this item from map
00144         m_menuItems.erase(miInfo.dwItemData);
00145 
00146         i++;
00147     }
00148 }
00149 
00150 void ODMenu::SetMenuItemOwnerDrawn(HMENU hMenu, UINT item, UINT type)
00151 {
00152     //Set menu item type to owner-drawn and set itemdata to sequence number.
00153     MENUITEMINFO miInfo;
00154   
00155     miInfo.cbSize = sizeof(MENUITEMINFO);
00156     miInfo.fMask = MIIM_TYPE | MIIM_DATA;
00157     miInfo.fType = type | MFT_OWNERDRAW;
00158     miInfo.dwItemData = m_seqNumber++;
00159     
00160     SetMenuItemInfo(hMenu, item, TRUE, &miInfo);
00161 }
00162 
00163 void ODMenu::GenerateDisplayText(ODMENUITEM& item)
00164 {
00165     TCHAR* pChr;
00166     int i;
00167 
00168     item.displayText = "";
00169     item.rawDisplayText = "";
00170     item.shortcutText = "";
00171 
00172     //Does shortcut text exist?
00173     if(pChr = strchr((LPTSTR)item.rawText.c_str(), '\t'))
00174         item.shortcutText = pChr + 1;
00175 
00176     i = 0;
00177     pChr = (LPTSTR)item.rawText.c_str();
00178     while(*(pChr + i) != '\t' && *(pChr + i) != '\0')
00179     {
00180         if(*(pChr + i) == '&')
00181         {
00182             item.rawDisplayText.append(pChr + i, 1);
00183             i++;
00184 
00185             continue;
00186         }
00187 
00188         item.rawDisplayText.append(pChr + i, 1);
00189         item.displayText.append(pChr + i, 1);
00190         i++;
00191     }
00192 }
00193 
00194 void ODMenu::DrawItemText(DRAWITEMSTRUCT* lpdis, ODMENUITEM& item)
00195 {
00196     int x, y;
00197     SIZE size;
00198     RECT rectText;
00199     RECT rectItem;
00200 
00201     memcpy(&rectItem, &lpdis->rcItem, sizeof(RECT));
00202 
00203     //Get size of text to draw
00204     GetTextExtentPoint32(lpdis->hDC, item.displayText.c_str(), item.displayText.length(), &size);
00205 
00206     // Determine where to draw.
00207     ComputeMenuTextPos(lpdis, item, x, y, size);
00208 
00209     rectText.left = x;
00210     rectText.right = lpdis->rcItem.right - m_textRightMargin;
00211     rectText.top = y;
00212     rectText.bottom = lpdis->rcItem.bottom;
00213 
00214     //Adjust rectangle that will contain the menu item
00215     if(!item.topMost)
00216     {
00217         rectItem.left += (m_iconWidth + 2*m_iconBarMargin);
00218     }
00219 
00220     //Draw the item rectangle with appropriate background color
00221     ExtTextOut(lpdis->hDC, x, y, ETO_OPAQUE, &rectItem, "", 0, NULL);
00222 
00223     //Draw the text
00224     DrawText(lpdis->hDC, item.rawDisplayText.c_str(), item.rawDisplayText.length(),
00225         &rectText, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
00226     DrawText(lpdis->hDC, item.shortcutText.c_str(), item.shortcutText.length(),
00227         &rectText, DT_RIGHT | DT_SINGLELINE | DT_VCENTER);
00228 }
00229 
00230 void ODMenu::DrawIconBar(DRAWITEMSTRUCT* lpdis, ODMENUITEM& item)
00231 {
00232     RECT rectBar;
00233     memcpy(&rectBar, &lpdis->rcItem, sizeof(RECT));
00234 
00235     //Draw icon bar if not top level
00236     if(!item.topMost)
00237     {
00238         rectBar.right = rectBar.left + m_iconWidth + 2*m_iconBarMargin + 1;
00239         if(lpdis->itemState & ODS_SELECTED &&
00240                 !(lpdis->itemState & ODS_DISABLED || lpdis->itemState & ODS_GRAYED))
00241         {
00242             FillRect(lpdis->hDC, &rectBar, m_hHighlightItemBackgroundBrush);
00243         }
00244         else
00245         {
00246             FillRect(lpdis->hDC, &rectBar, m_hIconBarBrush);
00247         }
00248 
00249     }
00250 
00251     int x, y;
00252 
00253     //Draw icon for menu item if handle is valid
00254     if(item.hBitmap)
00255     {
00256         x = m_iconBarMargin;
00257         y = rectBar.top + ((rectBar.bottom - rectBar.top - 16) / 2);
00258 
00259         if(lpdis->itemState & ODS_DISABLED || lpdis->itemState & ODS_GRAYED)
00260         {
00261             //Draw disabled icon in normal position
00262             DrawTransparentBitmap(lpdis->hDC, item.hBitmap, x, y, m_clrTranparent, eDisabled);
00263         }
00264         else if(lpdis->itemState & ODS_SELECTED)
00265         {
00266             //Draw icon "raised"
00267             //Draw shadow right one pixel and down one pixel from normal position
00268             DrawTransparentBitmap(lpdis->hDC, item.hBitmap, x+1, y+1, m_clrTranparent, eShadow);
00269 
00270             //Draw normal left one pixel and up one pixel from normal position
00271             DrawTransparentBitmap(lpdis->hDC, item.hBitmap, x-1, y-1, m_clrTranparent);
00272         }
00273         else
00274         {
00275             //Draw faded icon in normal position
00276             DrawTransparentBitmap(lpdis->hDC, item.hBitmap, x, y, m_clrTranparent, eFaded);
00277         }
00278     }
00279     else if(lpdis->itemState & ODS_CHECKED)
00280     {
00281         HBRUSH hPrevBrush;
00282         HPEN hPrevPen;
00283         RECT rect;
00284 
00285         //Draw filled, outlined rectangle around checkmark first
00286         if(lpdis->itemState & ODS_SELECTED)
00287             hPrevBrush = (HBRUSH)SelectObject(lpdis->hDC, m_hCheckMarkBackgroundHighlightBrush);
00288         else
00289             hPrevBrush = (HBRUSH)SelectObject(lpdis->hDC, m_hCheckMarkBackgroundBrush);
00290         hPrevPen = (HPEN)SelectObject(lpdis->hDC, m_hSelectionOutlinePen);
00291         rect.left = m_iconBarMargin;
00292         rect.right = m_iconBarMargin + m_iconWidth;
00293         rect.top = rectBar.top + (rectBar.bottom - rectBar.top - m_iconHeight) / 2;
00294         rect.bottom = rect.top + m_iconHeight;
00295         Rectangle(lpdis->hDC, rect.left, rect.top, rect.right, rect.bottom);
00296         SelectObject(lpdis->hDC, hPrevBrush);
00297         SelectObject(lpdis->hDC, hPrevPen);
00298 
00299         //Draw check mark
00300         x = (m_iconWidth + 2*m_iconBarMargin - 6) / 2;
00301         y = rectBar.top + ((rectBar.bottom - rectBar.top - 7) / 2) + 1;
00302         DrawCheckMark(lpdis->hDC, x, y, true);
00303     }
00304 }
00305 
00306 void ODMenu::ComputeMenuTextPos(DRAWITEMSTRUCT* lpdis, ODMENUITEM& item, int& x, int& y, SIZE& size)
00307 {
00308     x = lpdis->rcItem.left;
00309     y = lpdis->rcItem.top;
00310 //    y += ((lpdis->rcItem.bottom - lpdis->rcItem.top - size.cy) / 2);
00311 
00312     if(!item.topMost)
00313     {
00314         //Correct position for drop down menus. Leave space for a bitmap
00315         x += (m_iconWidth + 2*m_iconBarMargin + m_textLeftMargin);
00316     }
00317     else
00318     {
00319         //Center horizontally for top level menu items
00320         x += ((lpdis->rcItem.right - lpdis->rcItem.left - size.cx) / 2);
00321     }
00322 }
00323 
00324 void ODMenu::DrawTransparentBitmap(HDC hDC, HBITMAP hBitmap, short xStart,
00325                                    short yStart, COLORREF cTransparentColor,
00326                                    bitmapType eType)
00327 {
00328     BITMAP     bm;
00329     COLORREF   cColor;
00330     HBITMAP    bmAndBack, bmAndObject, bmAndMem, bmSave;
00331     HBITMAP    bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
00332     HDC        hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
00333     POINT      ptSize;
00334     HBRUSH     hOldBrush;
00335 
00336     BOOL bRC;
00337 
00338     hdcTemp = CreateCompatibleDC(hDC);
00339     SelectObject(hdcTemp, hBitmap);   // Select the bitmap
00340 
00341     GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
00342     ptSize.x = bm.bmWidth;            // Get width of bitmap
00343     ptSize.y = bm.bmHeight;           // Get height of bitmap
00344     DPtoLP(hdcTemp, &ptSize, 1);      // Convert from device
00345                                       // to logical points
00346 
00347     // Create some DCs to hold temporary data.
00348     hdcBack   = CreateCompatibleDC(hDC);
00349     hdcObject = CreateCompatibleDC(hDC);
00350     hdcMem    = CreateCompatibleDC(hDC);
00351     hdcSave   = CreateCompatibleDC(hDC);
00352 
00353     // Create a bitmap for each DC. DCs are required for a number of
00354     // GDI functions.
00355 
00356     // Monochrome DC
00357     bmAndBack   = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
00358 
00359     // Monochrome DC
00360     bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
00361 
00362     bmAndMem    = CreateCompatibleBitmap(hDC, ptSize.x, ptSize.y);
00363     bmSave      = CreateCompatibleBitmap(hDC, ptSize.x, ptSize.y);
00364 
00365     // Each DC must select a bitmap object to store pixel data.
00366     bmBackOld   = (HBITMAP)SelectObject(hdcBack, bmAndBack);
00367     bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject);
00368     bmMemOld    = (HBITMAP)SelectObject(hdcMem, bmAndMem);
00369     bmSaveOld   = (HBITMAP)SelectObject(hdcSave, bmSave);
00370 
00371     // Set proper mapping mode.
00372     SetMapMode(hdcTemp, GetMapMode(hDC));
00373 
00374     // Save the bitmap sent here, because it will be overwritten.
00375     bRC = BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
00376 
00377     // Create an "AND mask" that contains the mask of the colors to draw
00378     // (the nontransparent portions of the image).
00379 
00380     // Set the background color of the source DC to the color.
00381     // contained in the parts of the bitmap that should be transparent
00382     cColor = SetBkColor(hdcTemp, cTransparentColor);
00383 
00384     // Create the object mask for the bitmap by performing a BitBlt
00385     // from the source bitmap to a monochrome bitmap.
00386     bRC = BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
00387 
00388     // Set the background color of the source DC back to the original color.
00389     SetBkColor(hdcTemp, cColor);
00390 
00391     // Create the inverse of the object mask.
00392     bRC = BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, NOTSRCCOPY);
00393 
00394     // Copy the background of the main DC to the destination.
00395     bRC = BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hDC, xStart, yStart, SRCCOPY);
00396 
00397     // Mask out the places where the bitmap will be placed.
00398     // hdcMem then contains the background color of hDC only in the places
00399     // where the transparent pixels reside.
00400     bRC = BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
00401 
00402     if(eType == eNormal)
00403     {
00404         // Mask out the transparent colored pixels on the bitmap.
00405         // hdcTemp then contains only the non-transparent pixels.
00406         BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
00407 
00408         // XOR the bitmap with the background on the destination DC.
00409         // hdcMem then contains the required result.
00410         BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
00411     }
00412     else if(eType == eShadow)
00413     {
00414         //Select shadow brush into hdcTemp
00415         hOldBrush = (HBRUSH)SelectObject(hdcTemp, m_hIconShadowBrush);
00416 
00417         //Copy shadow brush pixels for all non-transparent pixels to hdcTemp
00418         bRC = BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, MERGECOPY);
00419 
00420         // XOR the bitmap with the background on the destination DC.
00421         // hdcMem then contains the required result.
00422         bRC = BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
00423 
00424         //Restore the brush in hdcTemp
00425         SelectObject(hdcTemp, hOldBrush);
00426     }
00427     else if(eType == eFaded)
00428     {
00429         COLORREF col;
00430         int x, y;
00431 
00432         //Lighten the color of each pixel in hdcTemp
00433         for(x=0; x<ptSize.x; x++)
00434         {
00435             for(y=0; y<ptSize.y; y++)
00436             {
00437                 col = GetPixel(hdcTemp, x, y);
00438                 col = LightenColor(col, 0.3);
00439                 SetPixel(hdcTemp, x, y, col);
00440             }
00441         }
00442 
00443         // Mask out the transparent colored pixels on the bitmap.
00444         // hdcTemp then contains only the non-transparent pixels.
00445         BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
00446 
00447         // XOR the bitmap with the background on the destination DC.
00448         // hdcMem then contains the required result.
00449         BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
00450     }
00451     else if(eType == eDisabled)
00452     {
00453         COLORREF discol, col;
00454         BYTE r, g, b;
00455         int x, y;
00456         int avgcol;
00457         double factor;
00458 
00459         //Lighten the color of COLOR_BTNSHADOW by a weighted average of the color at each pixel in hdcTemp.
00460         //Set the pixel to the lightened color.
00461         discol = GetSysColor(COLOR_BTNSHADOW);
00462         for(x=0; x<ptSize.x; x++)
00463         {
00464             for(y=0; y<ptSize.y; y++)
00465             {
00466                 col = GetPixel(hdcTemp, x, y);
00467                 r = GetRValue(col);
00468                                 g = GetGValue(col);
00469                                 b = GetBValue(col);
00470                 avgcol = (r + g + b) / 3;
00471                                 factor = avgcol / 255.0;
00472                 SetPixel(hdcTemp, x, y, LightenColor(discol, factor));
00473             }
00474         }
00475 
00476         // Mask out the transparent colored pixels on the bitmap.
00477         // hdcTemp then contains only the non-transparent pixels.
00478         BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
00479 
00480         // XOR the bitmap with the background on the destination DC.
00481         // hdcMem then contains the required result.
00482         BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
00483     }
00484 
00485     // Copy the destination to the screen.
00486     bRC = BitBlt(hDC, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY);
00487 
00488     // Place the original bitmap back into the bitmap sent here.
00489     bRC = BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);
00490 
00491     // Delete the memory bitmaps.
00492     DeleteObject(SelectObject(hdcBack, bmBackOld));
00493     DeleteObject(SelectObject(hdcObject, bmObjectOld));
00494     DeleteObject(SelectObject(hdcMem, bmMemOld));
00495     DeleteObject(SelectObject(hdcSave, bmSaveOld));
00496 
00497     // Delete the memory DCs.
00498     DeleteDC(hdcMem);
00499     DeleteDC(hdcBack);
00500     DeleteDC(hdcObject);
00501     DeleteDC(hdcSave);
00502     DeleteDC(hdcTemp);
00503 }
00504 
00505 void ODMenu::DrawCheckMark(HDC hDC, short x, short y, bool bNarrow)
00506 {
00507     HPEN hOldPen;
00508     int dp = 0;
00509 
00510     if(bNarrow)
00511         dp = 1;
00512 
00513     //Select check mark pen
00514     hOldPen = (HPEN)SelectObject(hDC, m_hCheckMarkPen);
00515 
00516     //Draw the check mark
00517     MoveToEx(hDC, x, y + 2, NULL);
00518         LineTo(hDC, x, y + 5 - dp);
00519         
00520         MoveToEx(hDC, x + 1, y + 3, NULL);
00521         LineTo(hDC, x + 1, y + 6 - dp);
00522         
00523         MoveToEx(hDC, x + 2, y + 4, NULL);
00524         LineTo(hDC, x + 2, y + 7 - dp);
00525         
00526         MoveToEx(hDC, x + 3, y + 3, NULL);
00527         LineTo(hDC, x + 3, y + 6 - dp);
00528         
00529         MoveToEx(hDC, x + 4, y + 2, NULL);
00530         LineTo(hDC, x + 4, y + 5 - dp);
00531         
00532         MoveToEx(hDC, x + 5, y + 1, NULL);
00533         LineTo(hDC, x + 5, y + 4 - dp);
00534         
00535         MoveToEx(hDC, x + 6, y, NULL);
00536         LineTo(hDC, x + 6, y + 3 - dp);
00537 
00538     //Restore original DC pen
00539     SelectObject(hDC, hOldPen);
00540 }
00541 
00542 COLORREF ODMenu::LightenColor(COLORREF col, double factor)
00543 {
00544         if(factor > 0.0 && factor <= 1.0)
00545     {
00546                 BYTE red, green, blue, lightred, lightgreen, lightblue;
00547                 red = GetRValue(col);
00548                 green = GetGValue(col);
00549                 blue = GetBValue(col);
00550                 lightred = (BYTE)((factor*(255 - red)) + red);
00551                 lightgreen = (BYTE)((factor*(255 - green)) + green);
00552                 lightblue = (BYTE)((factor*(255 - blue)) + blue);
00553                 col = RGB(lightred, lightgreen, lightblue);
00554         }
00555 
00556         return col;
00557 }
00558 
00559 COLORREF ODMenu::DarkenColor(COLORREF col, double factor)
00560 {
00561         if(factor > 0.0 && factor <= 1.0)
00562     {
00563                 BYTE red, green, blue, lightred, lightgreen, lightblue;
00564                 red = GetRValue(col);
00565                 green = GetGValue(col);
00566                 blue = GetBValue(col);
00567                 lightred = (BYTE)(red - (factor*red));
00568                 lightgreen = (BYTE)(green - (factor*green));
00569                 lightblue = (BYTE)(blue - (factor*blue));
00570                 col = RGB(lightred, lightgreen, lightblue);
00571         }
00572         return col;
00573 }
00574 
00575 COLORREF ODMenu::AverageColor(COLORREF col1, COLORREF col2, double weight)
00576 {
00577     BYTE avgRed, avgGreen, avgBlue;
00578 
00579     if (weight <= 0.0)
00580         return col1;
00581         else if (weight > 1.0)
00582                 return col2;
00583 
00584     avgRed   = (BYTE) (GetRValue(col1) * weight + GetRValue(col2) * (1.0 - weight));
00585     avgGreen = (BYTE) (GetGValue(col1) * weight + GetGValue(col2) * (1.0 - weight));
00586     avgBlue  = (BYTE) (GetBValue(col1) * weight + GetBValue(col2) * (1.0 - weight));
00587 
00588     return RGB(avgRed, avgGreen, avgBlue);
00589 }
00590 
00591 double ODMenu::GetColorIntensity(COLORREF col)
00592 {
00593     BYTE red, green, blue;
00594 
00595     red = GetRValue(col);
00596     green = GetGValue(col);
00597         blue = GetBValue(col);
00598 
00599     //denominator of 765 is (255*3)
00600     return (double)red/765.0 + (double)green/765.0 + (double)blue/765.0;
00601 }
00602 
00603 void ODMenu::MeasureItem(HWND hWnd, LPARAM lParam)
00604 {
00605     MEASUREITEMSTRUCT* lpmis = (MEASUREITEMSTRUCT*)lParam;
00606     ODMENUITEMS::iterator it;
00607     ODMENUITEM item;
00608     HDC hDC;
00609     HFONT hfntOld;
00610     RECT rect;
00611 
00612     it = m_menuItems.find(lpmis->itemData);
00613     if(it == m_menuItems.end())
00614         return;
00615 
00616     hDC = GetDC(hWnd);
00617     hfntOld = (HFONT)SelectObject(hDC, m_hFont);
00618 
00619     item = it->second;
00620     if(item.displayText.length() > 0)
00621     {
00622         DrawText(hDC, item.rawText.c_str(), item.rawText.length(), &rect,
00623             DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
00624         lpmis->itemWidth = rect.right - rect.left;
00625 
00626         if(!item.topMost)
00627         {
00628             //Correct size for drop down menus
00629             lpmis->itemWidth += (m_iconWidth + 2*m_iconBarMargin + m_textLeftMargin + m_textRightMargin);
00630             lpmis->itemHeight += m_verticalSpacing;
00631         }
00632      }
00633     else if(item.dwType & MFT_SEPARATOR)
00634     {
00635         //Correct size for drop down menus
00636         if(!item.topMost)
00637         {
00638             lpmis->itemWidth += (m_iconWidth + 2*m_iconBarMargin + m_textLeftMargin + m_textRightMargin);
00639             lpmis->itemHeight = 3;
00640         }
00641     }
00642 
00643     SelectObject(hDC, hfntOld);
00644     ReleaseDC(hWnd, hDC);
00645 }
00646 
00647 void ODMenu::DrawItem(HWND hWnd, LPARAM lParam)
00648 {
00649     DRAWITEMSTRUCT* lpdis = (DRAWITEMSTRUCT*)lParam;
00650     ODMENUITEMS::iterator it;
00651     ODMENUITEM item;
00652     COLORREF clrPrevText, clrPrevBkgnd;
00653     HFONT hPrevFnt;
00654     HPEN hPrevPen;
00655     HBRUSH hPrevBrush;
00656 
00657     it = m_menuItems.find(lpdis->itemData);
00658     if(it == m_menuItems.end())
00659         return;
00660 
00661     item = it->second;
00662 
00663     //Draw based on type of item
00664     if(item.displayText.length() > 0)
00665     {
00666         // Set the appropriate foreground and background colors. 
00667         if(item.topMost)
00668         {
00669             if(lpdis->itemState & ODS_SELECTED)
00670             { 
00671                 clrPrevText = SetTextColor(lpdis->hDC, m_clrHighlightItemText);
00672                 clrPrevBkgnd = SetBkColor(lpdis->hDC, m_clrHighlightItemBackground);
00673             }
00674             else
00675             { 
00676                 clrPrevText = SetTextColor(lpdis->hDC, m_clrItemText);
00677                 clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor(COLOR_MENU));
00678             }
00679         }
00680         else
00681         {
00682             if(lpdis->itemState & ODS_GRAYED || lpdis->itemState & ODS_DISABLED)
00683             {
00684                 clrPrevText = SetTextColor(lpdis->hDC, GetSysColor(COLOR_3DSHADOW));
00685                 clrPrevBkgnd = SetBkColor(lpdis->hDC, m_clrItemBackground);
00686             }
00687             else if(lpdis->itemState & ODS_SELECTED)
00688             {
00689                 clrPrevText = SetTextColor(lpdis->hDC, m_clrHighlightItemText);
00690                 clrPrevBkgnd = SetBkColor(lpdis->hDC, m_clrHighlightItemBackground);
00691             }
00692             else
00693             { 
00694                 clrPrevText = SetTextColor(lpdis->hDC, m_clrItemText);
00695                 clrPrevBkgnd = SetBkColor(lpdis->hDC, m_clrItemBackground);
00696             }
00697         }
00698 
00699         // Select the font.
00700         hPrevFnt = (HFONT)SelectObject(lpdis->hDC, m_hFont);
00701 
00702         //Draw the text
00703         DrawItemText(lpdis, item);
00704 
00705         //Restore original font
00706         SelectObject(lpdis->hDC, hPrevFnt);
00707 
00708         SetTextColor(lpdis->hDC, clrPrevText);
00709         SetBkColor(lpdis->hDC, clrPrevBkgnd);
00710     }
00711     else if(item.dwType & MFT_SEPARATOR)
00712     {
00713                 //Fill menu space with menu background, first.
00714         RECT rect;
00715         memcpy(&rect, &lpdis->rcItem, sizeof(RECT));
00716         rect.left += (m_iconWidth + 2*m_iconBarMargin);
00717         FillRect(lpdis->hDC, &rect, m_hItemBackground);
00718 
00719         //Draw the separator line
00720         hPrevPen = (HPEN)SelectObject(lpdis->hDC, m_hSeparatorPen);
00721         MoveToEx(lpdis->hDC, lpdis->rcItem.left + m_iconWidth + 2*m_iconBarMargin + m_textLeftMargin,
00722             lpdis->rcItem.top+1, NULL);
00723         LineTo(lpdis->hDC, lpdis->rcItem.right, lpdis->rcItem.top+1);
00724 
00725         //Restore GDI objects in DC
00726         SelectObject(lpdis->hDC, hPrevPen);
00727     }
00728 
00729     //Draw the left icon bar
00730     DrawIconBar(lpdis, item);
00731 
00732     //Draw selection outline if drawing a selected item
00733     if(lpdis->itemState & ODS_SELECTED && !(lpdis->itemState & ODS_GRAYED || lpdis->itemState & ODS_DISABLED))
00734     {
00735         hPrevBrush = (HBRUSH)SelectObject(lpdis->hDC, (HBRUSH)GetStockObject(NULL_BRUSH));
00736         hPrevPen = (HPEN)SelectObject(lpdis->hDC, m_hSelectionOutlinePen);
00737         Rectangle(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
00738             lpdis->rcItem.right, lpdis->rcItem.bottom);
00739 
00740         //Restore GDI objects in DC
00741         SelectObject(lpdis->hDC, hPrevBrush);
00742         SelectObject(lpdis->hDC, hPrevPen);
00743     }
00744 }
00745 
00746 void ODMenu::OnDestroy()
00747 {
00748 }
00749 
00750 bool ODMenu::GetItem(UINT id, ODMENUITEM** ppItem)
00751 {
00752     bool bRC = true;
00753 
00754     if(!ppItem)
00755         return false;
00756 
00757     ODMENUITEMS::iterator it = m_menuItems.find(id);
00758     if(it != m_menuItems.end())
00759         *ppItem = &it->second;
00760 
00761     return bRC;
00762 }
00763 
00764 void ODMenu::SetItemImage(HINSTANCE hInst, UINT wID, UINT idBitmap)
00765 {
00766     // Get iterator to ODMENUITEM
00767     ODMENUITEMS::iterator it;
00768     HBITMAP hBitmap;
00769 
00770     // Load the bitmap resource
00771     hBitmap = (HBITMAP) LoadImage(hInst,
00772                                   MAKEINTRESOURCE(idBitmap),
00773                                   IMAGE_BITMAP, 0, 0, LR_SHARED);
00774     if (hBitmap)
00775     {
00776         // Find menu item having specified wID.
00777         it = m_menuItems.begin();
00778         while(it != m_menuItems.end())
00779         {
00780             if(it->second.wID == wID)
00781             {
00782                 it->second.hBitmap = hBitmap;
00783                 break;
00784             }
00785 
00786             it++;
00787         }
00788     }
00789     else
00790     {
00791         DWORD dwErr = GetLastError();
00792         dwErr = 0;
00793     }
00794 }
00795 
00796 void ODMenu::AddItem(HMENU hMenu, int index, MENUITEMINFO* pItemInfo)
00797 {
00798     MENUITEMINFO miInfo;
00799     ODMENUITEM odInfo;
00800 
00801     //Obtain menu item info if not supplied
00802     if(!pItemInfo)
00803     {
00804         miInfo.cbSize = sizeof(MENUITEMINFO);
00805         miInfo.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
00806         miInfo.dwTypeData = m_szItemText;
00807         miInfo.cch = sizeof(m_szItemText);
00808 
00809         if(GetMenuItemInfo(hMenu, index, TRUE, &miInfo))
00810             pItemInfo = &miInfo;
00811     }
00812 
00813     //Add menu info to map of menu items
00814     if(pItemInfo)
00815     {
00816         if(pItemInfo->hSubMenu != NULL && hMenu == m_hRootMenu)
00817             odInfo.topMost = true;
00818         else
00819             odInfo.topMost = false;
00820         if(pItemInfo->fType == MFT_STRING)
00821         {
00822             odInfo.rawText = pItemInfo->dwTypeData;
00823             GenerateDisplayText(odInfo);
00824         }
00825         else
00826         {
00827             odInfo.rawText = "";
00828             odInfo.displayText = "";
00829         }
00830         odInfo.dwType = pItemInfo->fType;
00831         odInfo.wID = pItemInfo->wID;
00832         odInfo.hBitmap = NULL;
00833         m_menuItems[m_seqNumber] = odInfo;
00834         SetMenuItemOwnerDrawn(hMenu, index, pItemInfo->fType);
00835     }
00836 }
00837 
00838 void ODMenu::DeleteItem(HMENU hMenu, int index)
00839 {
00840     //Item data for item is map index
00841     MENUITEMINFO miInfo;
00842 
00843     miInfo.cbSize = sizeof(MENUITEMINFO);
00844     miInfo.fMask = MIIM_SUBMENU | MIIM_DATA;
00845     if(GetMenuItemInfo(hMenu, index, TRUE, &miInfo))
00846     {
00847         if(miInfo.hSubMenu)
00848             DeleteSubMenu(miInfo.hSubMenu);
00849 
00850         //Remove this item from map
00851         m_menuItems.erase(miInfo.dwItemData);
00852     }
00853 }

Generated on Sat Jan 14 22:30:31 2006 for Celestia by  doxygen 1.4.1