home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / windows / c / mobjm260 / smenu.cp_ / smenu.cp
Encoding:
Text File  |  1994-09-06  |  9.9 KB  |  346 lines

  1. //    Microworks ObjectMate  2.6
  2. //
  3. //    Ownerdraw Menu Functions
  4. //
  5. //    Copyright 1992-94 Microworks Sydney, Australia.
  6. //
  7. //  SMENU.CPP
  8.  
  9. /* This file contains the functions necessary to draw ownerdraw menus. The main
  10.  * functions are 'DrawMenuItem' and 'MeasureMenuItem' and should be called from
  11.  * EvDrawItem and EvMeasureItem respecitively. You can specify the menu text font,
  12.  * highlight color and highlight text color as arguments in a call to DrawMenuItem.
  13.  * The default values are zero and specify a fine system font and the standard
  14.  * Windows' highlight and highlight-text colors. The font handle passed as an
  15.  * argument to DrawMenuItem should also be passed to MeasureMenuItem so that each
  16.  * item is measured and drawn using the same font.
  17.  *
  18.  * The other functions 'StripStrLen', 'GetMenuItemPos', 'ProcessSystemChar' and
  19.  * 'Set3DSystemMenu' are accessory functions. GetMenuItemPos returns the zero based
  20.  * position of a menu item. It's used to determine if the next or previous menu
  21.  * item is a separator and if it is, draw its the adjacent 3D part along with the 
  22.  * current item. Set3DSystemMenu sets up an ownerdraw system menu and ProcessSystemChar
  23.  * processes its mnemonics. You should call Set3DSystemMenu from somewhere like
  24.  * SetupWindow. It takes a window handle and application name as arguments.
  25.  * ProcessSystemChar must be called from EvMenuChar if the active menu is the system
  26.  * menu. StripStrLen calculates the length of the menu text minus any 'single' or
  27.  * 'first of a pair' ampersands.
  28.  *
  29.  * Since the system menu rarely gets modified the Set3DSystemMenu and
  30.  * ProcessSystemChar functions are provided for convenience.
  31.  *
  32.  * You can enhance your ownerdraw menu's by adding a bitmap or icon glyph to each
  33.  * item. If you do, you will need to pass a pointer to a structure that specifies
  34.  * the menu item text and bitmap or icon handle as its members. This pointer is
  35.  * passed as the itemData member of the DRAWITEMSTRUCT and MEASUREITEMSTRUCT
  36.  * structures. You will need to retrieve the text string and bitmap or icon handle
  37.  * in MeasureMenuItem to calculate the itemWidth and itemHeight, and in DrawMenuItem
  38.  * to draw each item.
  39.  */
  40. #include <windows.h>
  41. #include <sfx\sfx200.h>
  42. #include <sfx\smenu.h>
  43. #include <string.h>
  44.  
  45. const COLORREF BLACK = 0;
  46. const COLORREF LTGRAY = RGB(192, 192, 192);
  47.  
  48. //    StripStrLen - returns the length of string "str" minus any "underline" or
  49. //    "first of a pair" ampersands.
  50.  
  51. int StripStrLen(char* str)
  52. {
  53.     int i = strlen(str);
  54.     char* ptr = strchr(str, '&');
  55.     while (ptr)
  56.     {
  57.         i--;
  58.         ptr = strchr(&ptr[2], '&');
  59.     }
  60.     return i;
  61. }
  62.  
  63. //    DrawMenuItem - draws the ownerdraw menu items. hFont, color and textColor can be zero.
  64.  
  65. void
  66. DrawMenuItem(DRAWITEMSTRUCT far& dis, HFONT hFont, COLORREF color, COLORREF textColor)
  67. {
  68.     BOOL   isNext, isPrev;
  69.     HBRUSH grayBrush, whiteBrush;
  70.     HBRUSH brush, oldBrush;
  71.     HFONT  oldFont;
  72.     HPEN   oldPen, pen;
  73.     int    a, b, c;
  74.     UINT   count, pos;
  75.     char   menuText[144];
  76.  
  77.     if (dis.CtlType == ODT_MENU)
  78.     {
  79.         isNext = FALSE;
  80.         isPrev = FALSE;
  81.         if (GetSystemMetrics(SM_CYSIZE) == 26)
  82.             a = b = 5;
  83.         else
  84.         {
  85.             if (GetSystemMetrics(SM_CXSCREEN) == 640)
  86.                 a = 3;
  87.             else
  88.                 a = 4;
  89.             b = 3;
  90.         }
  91.         whiteBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
  92.         grayBrush = (HBRUSH)GetStockObject(GRAY_BRUSH);
  93.  
  94.         if (dis.itemState & ODS_SELECTED)
  95.         {
  96.             if (!color)
  97.                 color = GetSysColor(COLOR_HIGHLIGHT);
  98.             if (!textColor)
  99.                 textColor = GetSysColor(COLOR_HIGHLIGHTTEXT);
  100.         }
  101.         else
  102.         {
  103.             color = LTGRAY;
  104.             textColor = BLACK;
  105.         }
  106.  
  107.         brush = CreateSolidBrush(color);
  108.         SetBkColor(dis.hDC, color);
  109.         SetBkMode(dis.hDC, TRANSPARENT);
  110.         if (dis.itemState & ODS_GRAYED)
  111.         {
  112.             if (dis.itemState & ODS_SELECTED)
  113.             {
  114.                 if (color == LTGRAY)
  115.                     SetTextColor(dis.hDC, RGB(221, 221, 221));
  116.                 else
  117.                     SetTextColor(dis.hDC, LTGRAY);
  118.             }
  119.             else
  120.                 SetTextColor(dis.hDC, GetSysColor(COLOR_GRAYTEXT));
  121.         }
  122.         else
  123.             SetTextColor(dis.hDC, textColor);
  124.  
  125.         count = GetMenuItemCount((HMENU)dis.hwndItem) - 1;
  126.         pos = GetMenuItemPos((HMENU)dis.hwndItem, dis.itemID);
  127.         if (pos <= count && !GetMenuItemID((HMENU)dis.hwndItem, pos + 1))
  128.         {
  129.             dis.rcItem.bottom += a;
  130.             isNext = TRUE;
  131.         }
  132.         if (pos && !GetMenuItemID((HMENU)dis.hwndItem, pos - 1))
  133.         {
  134.             dis.rcItem.top -= b;
  135.             isPrev = TRUE;
  136.         }
  137.  
  138.         oldBrush = (HBRUSH)SelectObject(dis.hDC, whiteBrush);
  139.         PatBlt(dis.hDC, dis.rcItem.left, dis.rcItem.top, 2, dis.rcItem.bottom -
  140.                dis.rcItem.top, PATCOPY);
  141.         SelectObject(dis.hDC, grayBrush);
  142.         PatBlt(dis.hDC, dis.rcItem.right-2, dis.rcItem.top, 2, dis.rcItem.bottom -
  143.                dis.rcItem.top, PATCOPY);
  144.         if (!pos || isPrev)
  145.         {
  146.             SelectObject(dis.hDC, whiteBrush);
  147.             PatBlt(dis.hDC, dis.rcItem.left+2, dis.rcItem.top, dis.rcItem.right -
  148.                    dis.rcItem.left-2, 1, PATCOPY);
  149.             PatBlt(dis.hDC, dis.rcItem.left+2, dis.rcItem.top+1, dis.rcItem.right -
  150.                    dis.rcItem.left-3, 1, PATCOPY);
  151.             dis.rcItem.top += 2;
  152.         }
  153.         if (pos == count || isNext)
  154.         {
  155.             SelectObject(dis.hDC, grayBrush);
  156.             PatBlt(dis.hDC, dis.rcItem.left+1, dis.rcItem.bottom-1, dis.rcItem.right -
  157.                    dis.rcItem.left-2, 1, PATCOPY);
  158.             PatBlt(dis.hDC, dis.rcItem.left+2, dis.rcItem.bottom-2, dis.rcItem.right -
  159.                    dis.rcItem.left-4, 1, PATCOPY);
  160.             dis.rcItem.bottom -= 2;
  161.         }
  162.         InflateRect(&dis.rcItem, -2, 0);
  163.         if (dis.itemState & ODS_SELECTED)
  164.         {
  165.             if (isNext)
  166.             {
  167.                 dis.rcItem.bottom -= a;
  168.                 if (dis.itemState & ODS_SELECTED)
  169.                 {
  170.                     SelectObject(dis.hDC, GetStockObject(LTGRAY_BRUSH));
  171.                     PatBlt(dis.hDC, dis.rcItem.left, dis.rcItem.bottom, dis.rcItem.right -
  172.                            dis.rcItem.left, a, PATCOPY);
  173.                 }
  174.             }
  175.             if (isPrev)
  176.             {
  177.                 dis.rcItem.top += b;
  178.                 if (dis.itemState & ODS_SELECTED)
  179.                 {
  180.                     SelectObject(dis.hDC, GetStockObject(LTGRAY_BRUSH));
  181.                     PatBlt(dis.hDC, dis.rcItem.left, dis.rcItem.top -3, dis.rcItem.right -
  182.                            dis.rcItem.left, b, PATCOPY);
  183.                 }
  184.             }
  185.  
  186.         }
  187.         FillRect(dis.hDC, &dis.rcItem, brush);
  188.         SelectObject(dis.hDC, oldBrush);
  189.  
  190.         if (dis.itemState & ODS_CHECKED)
  191.         {
  192.             pen = CreatePen(PS_SOLID, 1, textColor);
  193.             oldPen = (HPEN)SelectObject(dis.hDC, pen);
  194.             c = dis.rcItem.top + ((dis.rcItem.bottom - dis.rcItem.top - 10)/2);
  195.             MoveTo(dis.hDC, dis.rcItem.left + 3, c + 5);
  196.             LineTo(dis.hDC, dis.rcItem.left + 3, c + 10);
  197.             MoveTo(dis.hDC, dis.rcItem.left + 4, c + 4);
  198.             LineTo(dis.hDC, dis.rcItem.left + 4, c + 10);
  199.             MoveTo(dis.hDC, dis.rcItem.left + 5, c + 7);
  200.             LineTo(dis.hDC, dis.rcItem.left + 12, c + 0);
  201.             MoveTo(dis.hDC, dis.rcItem.left + 5, c + 8);
  202.             LineTo(dis.hDC, dis.rcItem.left + 13, c + 0);
  203.             SelectObject(dis.hDC, oldPen);
  204.             DeleteObject(pen);
  205.         }
  206.  
  207.         strcpy(menuText, (const char*)dis.itemData);
  208.         if (hFont)
  209.             oldFont = (HFONT)SelectObject(dis.hDC, hFont);
  210.         else
  211.             oldFont = (HFONT)SelectObject(dis.hDC, (HFONT)GetSFXObject(SYSTEM_FINE_FONT));
  212.         dis.rcItem.left = 7 + 12;
  213.         if (!dis.itemState & ODS_SELECTED)
  214.         {
  215.             if (isNext)
  216.                 dis.rcItem.bottom -= a;
  217.             else
  218.             if (isPrev)
  219.                 dis.rcItem.top += b;
  220.         }
  221.         DrawText(dis.hDC, menuText, -1, &dis.rcItem, DT_SINGLELINE + DT_VCENTER + DT_EXPANDTABS);
  222.         if ((dis.itemState & ODS_SELECTED) && color != LTGRAY)
  223.         {
  224.             OffsetRect(&dis.rcItem, 1, 0);
  225.             DrawText(dis.hDC, menuText, -1, &dis.rcItem, DT_SINGLELINE + DT_VCENTER +
  226.                      DT_EXPANDTABS);
  227.         }
  228.         SelectObject(dis.hDC, oldFont);
  229.         DeleteObject(brush);
  230.     }
  231. }
  232.  
  233. //    GetMenuItemPos - returns the zero based position of a menu item
  234.  
  235. int
  236. GetMenuItemPos(HMENU hMenu, int itemId)
  237. {
  238.     int pos = GetMenuItemCount(hMenu) - 1;
  239.     if (IsMenu((HMENU)itemId))
  240.     {
  241.         int item = (int)GetSubMenu(hMenu, pos);
  242.         while (pos && item != itemId)
  243.         {
  244.             pos--;
  245.             item = (int)GetSubMenu(hMenu, pos);
  246.         }
  247.     }
  248.     else
  249.     {
  250.         int item = GetMenuItemID(hMenu, pos);
  251.         while (pos && item != itemId)
  252.         {
  253.             pos--;
  254.             item = GetMenuItemID(hMenu, pos);
  255.         }
  256.     }
  257.     return pos;
  258. }
  259.  
  260. //    MeasureMenuItem - sets the width and height of ownerdraw menu items. hFont can be zero.
  261.  
  262. void
  263. MeasureMenuItem(HWND hWnd, MEASUREITEMSTRUCT far& mis, HFONT hFont)
  264. {
  265.     HDC   dc;
  266.     HFONT menuFont, oldFont;
  267.     SIZE  size;
  268.     char  menuText[144];
  269.  
  270.     if (mis.CtlType == ODT_MENU)
  271.     {
  272.         dc = GetDC(hWnd);
  273.         if (hFont)
  274.             menuFont = hFont;
  275.         else
  276.             menuFont = (HFONT)GetSFXObject(SYSTEM_FINE_FONT);
  277.         oldFont = (HFONT)SelectObject(dc, menuFont);
  278.         strcpy(menuText, (const char*)mis.itemData);
  279.         GetTextExtentPoint(dc, menuText, StripStrLen((char*)menuText), &size);
  280.         mis.itemWidth = size.cx + 20;
  281.         mis.itemHeight = size.cy + ((size.cy / 5) * 2);
  282.         SelectObject(dc, oldFont);
  283.         ReleaseDC(hWnd, dc);
  284.     }
  285. }
  286.  
  287. //    ProcessSystemChar - call from EvMenuChar to process the system menu's mnemonics
  288.  
  289. DWORD
  290. ProcessSystemChar(UINT nChar)
  291. {
  292.     switch (nChar)
  293.     {
  294.         case 82:
  295.         case 114:
  296.             return MAKELONG(0, 2);
  297.  
  298.         case 77:
  299.         case 109:
  300.             return MAKELONG(1, 2);
  301.  
  302.         case 83:
  303.         case 115:
  304.             return MAKELONG(2, 2);
  305.  
  306.         case 78:
  307.         case 110:
  308.             return MAKELONG(3, 2);
  309.  
  310.         case 88:
  311.         case 120:
  312.             return MAKELONG(4, 2);
  313.  
  314.         case 67:
  315.         case 99:
  316.             return MAKELONG(6, 2);
  317.  
  318.         default:
  319.             return 0L;
  320.     }
  321. }
  322.  
  323. //    Set3DSystemMenu - sets up a basic 3D system menu, minus the "Switch To" item.
  324.  
  325. void
  326. Set3DSystemMenu(HWND hWnd, const char* name)
  327. {
  328.     static char textStr[50];
  329.  
  330.     HMENU  sysMenu = GetSystemMenu(hWnd, FALSE);
  331.     RemoveMenu(sysMenu, 7, MF_BYPOSITION);
  332.     RemoveMenu(sysMenu, 7, MF_BYPOSITION);
  333.     ModifyMenu(sysMenu, 0, MF_BYPOSITION | MF_OWNERDRAW, SC_RESTORE, "&Restore");
  334.     ModifyMenu(sysMenu, 1, MF_BYPOSITION | MF_OWNERDRAW, SC_MOVE, "&Move");
  335.     ModifyMenu(sysMenu, 2, MF_BYPOSITION | MF_OWNERDRAW, SC_SIZE, "&Size");
  336.     ModifyMenu(sysMenu, 3, MF_BYPOSITION | MF_OWNERDRAW, SC_MINIMIZE, "Mi&nimize");
  337.     ModifyMenu(sysMenu, 4, MF_BYPOSITION | MF_OWNERDRAW, SC_MAXIMIZE, "Ma&ximize");
  338.     wsprintf(textStr, "&Close  %s      Alt+F4", name);
  339.     ModifyMenu(sysMenu, 6, MF_BYPOSITION | MF_OWNERDRAW, SC_CLOSE, textStr);
  340. }
  341.  
  342.  
  343.  
  344.  
  345.  
  346.