test: mncomput.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# mncomput.c File Reference

`#include "precomp.h"`

Go to the source code of this file.

## Functions

DWORD | MNRecalcTabStrings (HDC, PMENU, UINT, UINT, DWORD, DWORD)
BOOL | xxxMNGetBitmapSize (LPITEM pItem, PWND pwndNotify)
BOOL | xxxMNItemSize (PMENU pMenu, PWND pwndNotify, HDC hdc, PITEM pItem, BOOL fPopup, LPPOINT lppt)
int | xxxMNCompute (PMENU pMenu, PWND pwndNotify, DWORD yMenuTop, DWORD xMenuLeft, DWORD cxMax, LPDWORD lpdwMenuHeight)
void | MBC_RightJustifyMenu (PMENU pMenu)
int | xxxMenuBarCompute (PMENU pMenu, PWND pwndNotify, DWORD yMenuTop, DWORD xMenuLeft, int cxMax)
void | xxxMNRecomputeBarIfNeeded (PWND pwndNotify, PMENU pMenu)
PWND | GetMenuPwnd (PWND pwnd, PMENU pmenu)
BOOL | xxxGetMenuItemRect (PWND pwnd, PMENU pMenu, UINT uIndex, LPRECT lprcScreen)
UINT | MNItemHitTest (PMENU pMenu, PWND pwnd, POINT pt)
int | xxxMenuItemFromPoint (PWND pwnd, PMENU pMenu, POINT ptScreen)
PMENU | MakeMenuRtoL (PMENU pMenu, BOOL bRtoL)

## Function Documentation

PWND GetMenuPwnd | ( | PWND | pwnd,
|  | PMENU | pmenu
| ) |

Definition at line 893 of file mncomput.c.

References FNID_MENU, GETFNID, MFISPOPUP, MNGetPopupFromMenu(), NULL, tagPOPUPMENU::spmenu, tagPOPUPMENU::spwndPopupMenu, and TestMF.

Referenced by xxxGetMenuItemRect(), and xxxMenuItemFromPoint().

    00894 {
    00895     if (TestMF(pmenu, MFISPOPUP)) {
    00896         if ((pwnd == NULL) || (GETFNID(pwnd) != FNID_MENU)) {
    00897             PPOPUPMENU ppopup = MNGetPopupFromMenu(pmenu, NULL);
    00898             if (ppopup != NULL) {
    00899                 UserAssert(ppopup->spmenu == pmenu);
    00900                 pwnd = ppopup->spwndPopupMenu;
    00901             }
    00902         }
    00903     }
    00904     return pwnd;
    00905 }

PMENU MakeMenuRtoL | ( | PMENU | pMenu,
|  | BOOL | bRtoL
| ) |

Definition at line 995 of file mncomput.c.

References tagMENU::cItems, ClearMF, ClearMFT, MFRTL, tagMENU::rgItems, SetMF, SetMFT, and tagITEM::spSubMenu.

Referenced by xxxInsertMenuItem(), and xxxSetMenuItemInfo().

    00996 {
    00997     PITEM  pItem;
    00998     int    cItem;
    00999
    01000     if (bRtoL)
    01001         SetMF(pMenu,MFRTL);
    01002     else
    01003         ClearMF(pMenu,MFRTL);
    01004
    01005     for (cItem = 0; cItem < (int)pMenu->cItems; cItem++) {
    01006         pItem = pMenu->rgItems + cItem;
    01007         if (bRtoL) {
    01008             SetMFT(pItem, MFT_RIGHTJUSTIFY);
    01009             SetMFT(pItem, MFT_RIGHTORDER);
    01010         } else {
    01011             ClearMFT(pItem, MFT_RIGHTJUSTIFY);
    01012             ClearMFT(pItem, MFT_RIGHTORDER);
    01013         }
    01014         if (pItem->spSubMenu)
    01015             MakeMenuRtoL(pItem->spSubMenu, bRtoL);
    01016     }
    01017     return pMenu;
    01018 }

void MBC_RightJustifyMenu | ( | PMENU | pMenu | ) |

Definition at line 571 of file mncomput.c.

References BOOL, tagMENU::cItems, tagITEM::cxItem, tagMENU::cxMenu, tagITEM::cyItem, DWORD, tagITEM::hbmp, IsMDIItem(), MFMWFP_NOITEM, MFRTL, tagMENU::rgItems, tagMENU::spwndNotify, TestMF, TestMFT, TestWF, WFWIN40COMPAT, tagITEM::xItem, and tagITEM::yItem.

Referenced by xxxMenuBarCompute().

    00573 {
    00574     PITEM pItem;
    00575     int cItem;
    00576     int iFirstRJItem = MFMWFP_NOITEM;
    00577     DWORD xMenuPos;
    00578     DWORD  yPos;
    00579     DWORD  xPosStart;
    00580     DWORD  xPosEnd;
    00581     int    cItemEnd;
    00582     int    cItemStart;
    00583     BOOL   bIsWin95;
    00584
    00585     //
    00586     // need to compensate for MDI menus.  need to do all here as Win31/Hebrew did
    00587     // this.  also screwed up computation, anything non-text was not moved.
    00588     //
    00589     if (pMenu->cItems == 0)
    00590         return;
    00591
    00592     pItem = (PITEM)&pMenu->rgItems[0];
    00593     cItemStart = 0;
    00594
    00595     if (TestMF(pMenu,MFRTL)) {
    00596         bIsWin95 = TestWF(pMenu->spwndNotify, WFWIN40COMPAT);
    00597
    00598         while( cItemStart < (int)pMenu->cItems ) {
    00599             if (bIsWin95) {  //(not time critical)
    00600                 //
    00601                 // deal with fake MDI dude.
    00602                 //
    00603                 if (!cItemStart && IsMDIItem(pItem))
    00604                     goto StillFindStart;
    00605                 else
    00606                     break;
    00607             }
    00608
    00609             if( TestMFT(pItem, MFT_BITMAP) ) {
    00610                 if ( pItem->hbmp > (HBITMAP)HBMMENU_MAX )
    00611                     break;
    00612                 else
    00613                     goto StillFindStart;
    00614             }
    00615
    00616             if (!TestMFT(pItem, MFT_OWNERDRAW) )
    00617                 break;
    00618
    00619 StillFindStart:
    00620             cItemStart++;
    00621             pItem = pMenu->rgItems + cItemStart;
    00622         }
    00623         //
    00624         // anything before cItems should be left where it is! Now need to find
    00625         // the last item to fool with.
    00626         //
    00627         cItemEnd = pMenu->cItems - 1;
    00628         pItem   = pMenu->rgItems + cItemEnd;
    00629
    00630         while( cItemEnd > cItemStart ) {
    00631             if (bIsWin95) {
    00632                 //
    00633                 // fake mdi dudes
    00634                 //
    00635                 if (IsMDIItem(pItem))
    00636                     goto StillFindEnd;
    00637                 else
    00638                     break;
    00639             }
    00640             if ( !TestMFT(pItem, MFT_BITMAP) && !TestMFT(pItem, MFT_OWNERDRAW) )
    00641                 break;
    00642 StillFindEnd:
    00643             cItemEnd --;
    00644             pItem = pMenu->rgItems + cItemEnd;
    00645         }
    00646
    00647         yPos      = pMenu->rgItems[0].yItem;
    00648         xMenuPos  = pMenu->cxMenu ;
    00649         xPosStart = xMenuPos;              // for 2nd row onward
    00650         xPosEnd   = pMenu->rgItems[cItemStart].xItem ;
    00651
    00652         for (cItem = pMenu->cItems-1; cItem > cItemEnd; cItem--) {
    00653             //
    00654             // force any MDI dudes back to the top line again.
    00655             //
    00656             pItem        = pMenu->rgItems + cItem;
    00657             xMenuPos      =
    00658             pItem->xItem = xMenuPos - pItem->cxItem;
    00659             pItem->yItem = yPos;
    00660         }
    00661
    00662         for( cItem = cItemStart; cItem <= cItemEnd; cItem++ ) {
    00663             pItem = pMenu->rgItems + cItem;
    00664             if (xMenuPos - pItem->cxItem > xPosEnd) {
    00665                 xMenuPos -= pItem->cxItem;
    00666             } else {
    00667                 xMenuPos = xPosStart - pItem->cxItem;
    00668                 yPos     += pItem->cyItem;
    00669                 xPosEnd  = 0;
    00670             }
    00671             pItem->xItem = xMenuPos;
    00672             pItem->yItem = yPos;
    00673         }
    00674     } else {
    00675         // B#4055
    00676         // Use signed arithmetic so comparison cItem >= iFirstRJItem won't
    00677         // cause underflow.
    00678         for (cItem = 0; cItem < (int)pMenu->cItems; cItem++) {
    00679             // Find the first item which is right justified.
    00680             if (TestMFT((pMenu->rgItems + cItem), MFT_RIGHTJUSTIFY)) {
    00681                 iFirstRJItem = cItem;
    00682                 xMenuPos = pMenu->cxMenu + pMenu->rgItems[0].xItem;
    00683                 for (cItem = (int)pMenu->cItems - 1; cItem >= iFirstRJItem; cItem--) {
    00684                     pItem = pMenu->rgItems + cItem;
    00685                     xMenuPos -= pItem->cxItem;
    00686                     if (pItem->xItem < xMenuPos)
    00687                         pItem->xItem = xMenuPos;
    00688                 }
    00689                 return;
    00690             }
    00691         }
    00692     }
    00693 }

UINT MNItemHitTest | ( | PMENU | pMenu,
|  | PWND | pwnd,
|  | POINT | pt
| ) |

Definition at line 2983 of file ntuser/kernel/menu.c.

    02984 {
    02985     PITEM  pItem;
    02986     UINT    iItem;
    02987     RECT    rect;
    02988
    02989     PTHREADINFO ptiCurrent = PtiCurrent();
    02990
    02991     if (pMenu->cItems == 0)
    02992         return MFMWFP_NOITEM;
    02993
    02994
    02995     /*
    02996      * This point is screen-relative.  Menu bar coordinates relative
    02997      * to the window.  But popup menu coordinates are relative to the client.
    02998      */
    02999     if (TestMF(pMenu, MFISPOPUP)) {
    03000
    03001         /*
    03002          * Bail if it's outside rcWindow
    03003          */
    03004         CopyInflateRect(&rect, &(pwnd->rcWindow),
    03005                 -SYSMET(CXFIXEDFRAME), -SYSMET(CYFIXEDFRAME));
    03006
    03007         if (!PtInRect(&rect, pt)) {
    03008             return MFMWFP_NOITEM;
    03009         }
    03010
    03011         /* ScreenToClient */
    03012 #ifdef USE_MIRRORING
    03013         if (TestWF(pwnd, WEFLAYOUTRTL)) {
    03014             pt.x = pwnd->rcClient.right - pt.x;
    03015         } else
    03016 #endif
    03017         {
    03018             pt.x -= pwnd->rcClient.left;
    03019         }
    03020         pt.y -= pwnd->rcClient.top;
    03021
    03022         /*
    03023          * If on the non client area, then it's on the scroll arrows
    03024          */
    03025         if (pt.y < 0) {
    03026             return MFMWFP_UPARROW;
    03027         } else if (pt.y > (int)pMenu->cyMenu) {
    03028             return MFMWFP_DOWNARROW;
    03029         }
    03030
    03031     } else {
    03032         /* ScreenToWindow */
    03033 #ifdef USE_MIRRORING
    03034         if (TestWF(pwnd, WEFLAYOUTRTL) &&
    03035             (
    03036              (ptiCurrent->pq->codeCapture == SCREEN_CAPTURE) || (ptiCurrent->pq->codeCapture == NO_CAP_SYS)
    03037             )
    03038            ) {
    03039             pt.x = pwnd->rcWindow.right - pt.x;
    03040         } else
    03041 #endif
    03042         {
    03043             pt.x -= pwnd->rcWindow.left;
    03044         }
    03045         pt.y -= pwnd->rcWindow.top;
    03046     }
    03047
    03048     /*
    03049      * Step through all the items in the menu.
    03050      * If scrollable menu
    03051      */
    03052     if (pMenu->dwArrowsOn != MSA_OFF) {
    03053         UserAssert(TestMF(pMenu, MFISPOPUP));
    03054         pItem = MNGetToppItem(pMenu);
    03055         rect.left = rect.top = 0;
    03056         rect.right = pItem->cxItem;
    03057         rect.bottom = pItem->cyItem;
    03058         for (iItem = pMenu->iTop; (iItem < (int)pMenu->cItems) && (rect.top < (int)pMenu->cyMenu); iItem++) {
    03059
    03060             if (PtInRect(&rect, pt)) {
    03061                 return iItem;
    03062             }
    03063
    03064             pItem++;
    03065             rect.top = rect.bottom;
    03066             rect.bottom += pItem->cyItem;
    03067         }
    03068     } else {
    03069         /*
    03070          * No scroll bars.
    03071          */
    03072         for (iItem = 0, pItem = pMenu->rgItems; iItem < pMenu->cItems; iItem++, pItem++) {
    03073             /* Is the mouse inside this item's rectangle? */
    03074             rect.left       = pItem->xItem;
    03075             rect.top        = pItem->yItem;
    03076             rect.right      = pItem->xItem + pItem->cxItem;
    03077             rect.bottom     = pItem->yItem + pItem->cyItem;
    03078
    03079             if (PtInRect(&rect, pt)) {
    03080                 return(iItem);
    03081             }
    03082         }
    03083     }
    03084
    03085
    03086     return(MFMWFP_NOITEM);
    03087 }

DWORD MNRecalcTabStrings | ( | HDC | ,
|  | PMENU | ,
|  | UINT | ,
|  | UINT | ,
|  | DWORD | ,
|  | DWORD |
| ) |

Definition at line 796 of file mncomput.c.

References CALL_LPK, CheckLock, tagMENU::cItems, DWORD, FindCharPosition(), gcxMenuFontChar, gpsi, NULL, OBI_MENUCHECK, PtiCurrentShared, tagMENU::rgItems, TestMFT, TextPointer, UINT, and xxxClientGetTextExtentPointW().

Referenced by xxxMNCompute().

    00803 {
    00804     UINT i;
    00805     UINT    cOwnerDraw;
    00806     int adx;
    00807     int     maxWidth = 0;
    00808     int     cx;
    00809     PITEM pItem;
    00810     CheckLock(pMenu);
    00811
    00812     xTab += hCount;
    00813
    00814     if ((iBeg >= pMenu->cItems) || (iBeg > iEnd))
    00815         goto SeeYa;
    00816
    00817     cOwnerDraw = 0;
    00818
    00819     for (i = iBeg, pItem = pMenu->rgItems + iBeg; i < iEnd; pItem++, i++) {
    00820         adx = 0;
    00821
    00822         /*
    00823          * Subtract hCount to make dxTab relative to start of column for
    00824          * multi-column menus.
    00825          */
    00826
    00827         pItem->dxTab = xTab - hCount;
    00828
    00829         // Skip non-string or empty string items
    00830         if ((pItem->lpstr != NULL) && !TestMFT(pItem, MFT_OWNERDRAW)) {
    00831             LPWSTR   lpString = TextPointer(pItem->lpstr);
    00832             int     tp;
    00833             SIZE size;
    00834
    00835             // Are there any tabs?
    00836             tp = FindCharPosition(lpString, TEXT('\t'));
    00837             if (tp < (int) pItem->cch) {
    00838                 PTHREADINFO ptiCurrent = PtiCurrentShared();
    00839
    00840                 if (CALL_LPK(ptiCurrent)) {
    00841                     xxxClientGetTextExtentPointW(hdc, lpString + tp + 1,
    00842                           pItem->cch - tp - 1, &size);
    00843                 } else {
    00844                     GreGetTextExtentW(hdc, lpString + tp + 1,
    00845                           pItem->cch - tp - 1, &size, GGTE_WIN3_EXTENT);
    00846                 }
    00847                 adx = gcxMenuFontChar + size.cx;
    00848             }
    00849         } else if (TestMFT(pItem, MFT_OWNERDRAW))
    00850             cOwnerDraw++;
    00851
    00852         adx += xTab;
    00853
    00854         if (adx > maxWidth)
    00855             maxWidth = adx;
    00856
    00857     }
    00858
    00859     /*
    00860      * Add on space for hierarchical arrow.  So basically, popup menu items
    00861      * can have 4 columns:
    00862      *      (1) Checkmark
    00863      *      (2) Text
    00864      *      (3) Tabbed text for accel
    00865      *      (4) Hierarchical arrow
    00866      *
    00867      * But, we only do this if at least one item isn't ownerdraw
    00868      *  and if there's at least one submenu in the popup.
    00869      */
    00870     if (cOwnerDraw != (iEnd - iBeg)) {
    00871         maxWidth += gcxMenuFontChar + gpsi->oembmi[OBI_MENUCHECK].cx;
    00872     }
    00873
    00874     cx = maxWidth - hCount;
    00875
    00876     for (i = iBeg, pItem = pMenu->rgItems + iBeg; i < iEnd; pItem++, i++)
    00877         pItem->cxItem = cx;
    00878
    00879 SeeYa:
    00880     return(maxWidth);
    00881 }

BOOL xxxGetMenuItemRect | ( | PWND | pwnd,
|  | PMENU | pMenu,
|  | UINT | uIndex,
|  | LPRECT | lprcScreen
| ) |

Definition at line 911 of file mncomput.c.

References BOOL, CheckLock, tagMENU::cItems, tagITEM::cxItem, tagITEM::cyItem, FALSE, GetMenuPwnd(), MFISPOPUP, NULL, OffsetRect(), tagWND::rcClient, tagWND::rcWindow, tagMENU::rgItems, SetRectEmpty, TestMF, TestWF, TRUE, WFWIN50COMPAT, tagITEM::xItem, xxxMNRecomputeBarIfNeeded(), and tagITEM::yItem.

Referenced by NtUserGetMenuItemRect().

    00912 {
    00913     PITEM  pItem;
    00914     int     dx, dy;
    00915
    00916     CheckLock(pwnd);
    00917     CheckLock(pMenu);
    00918
    00919     SetRectEmpty(lprcScreen);
    00920
    00921     if (uIndex >= pMenu->cItems)
    00922         return(FALSE);
    00923
    00924     /*
    00925      * Raid #315084: Compatiblity with NT4/Win95/98
    00926      *
    00927      * WordPerfect does a long complex way to calc the menu rect
    00928      * by calling this API. It calls GetMenuItemRect() with the app's
    00929      * window.
    00930      */
    00931     if (pwnd == NULL || TestWF(pwnd, WFWIN50COMPAT)) {
    00932         pwnd = GetMenuPwnd(pwnd, pMenu);
    00933     }
    00934
    00935     /*
    00936      * If no pwnd, no go.
    00937      * IMPORTANT: for MFISPOPUP we might get a different pwnd but we don't lock
    00938      *   it because we won't call back
    00939      */
    00940     if (pwnd == NULL) {
    00941         return FALSE;
    00942     }
    00943
    00944     if (TestMF(pMenu, MFISPOPUP)) {
    00945         dx = pwnd->rcClient.left;
    00946         dy = pwnd->rcClient.top;
    00947     } else {
    00948         xxxMNRecomputeBarIfNeeded(pwnd, pMenu);
    00949
    00950         dx = pwnd->rcWindow.left;
    00951         dy = pwnd->rcWindow.top;
    00952     }
    00953
    00954     if (uIndex >= pMenu->cItems)
    00955         return(FALSE);
    00956
    00957     pItem = pMenu->rgItems + uIndex;
    00958
    00959     lprcScreen->right   = pItem->cxItem;
    00960     lprcScreen->bottom  = pItem->cyItem;
    00961
    00962     OffsetRect(lprcScreen, dx + pItem->xItem, dy + pItem->yItem);
    00963     return(TRUE);
    00964 }

int xxxMenuBarCompute | ( | PMENU | pMenu,
|  | PWND | pwndNotify,
|  | DWORD | yMenuTop,
|  | DWORD | xMenuLeft,
|  | int | cxMax
| ) |

Definition at line 706 of file mncomput.c.

References CheckLock, DWORD, MBC_RightJustifyMenu(), MFISPOPUP, SYSMET, TestMF, and xxxMNCompute().

Referenced by xxxCalcClientRect(), xxxDrawMenuBarTemp(), xxxMenuBarDraw(), and xxxMNRecomputeBarIfNeeded().

    00712 {
    00713     int size;
    00714     /* menuHeight is set by MNCompute when dealing with a top level menu and
    00715      * not all items in the menu bar have the same height.  Thus, by setting
    00716      * menuHeight, MNCompute is called a second time to set every item to the
    00717      * same height.  The actual value stored in menuHeight is the maximum
    00718      * height of all the menu bar items
    00719      */
    00720     DWORD menuHeight = 0;
    00721
    00722     CheckLock(pwndNotify);
    00723     CheckLock(pMenu);
    00724
    00725     size = xxxMNCompute(pMenu, pwndNotify, yMenuTop, xMenuLeft, cxMax, &menuHeight);
    00726
    00727     if (!TestMF(pMenu, MFISPOPUP)) {
    00728         if (menuHeight != 0) {
    00729
    00730             /*
    00731              * Add a border for the multi-row case.
    00732              */
    00733             size = xxxMNCompute(pMenu, pwndNotify, yMenuTop, xMenuLeft,
    00734                     cxMax, &menuHeight);
    00735         }
    00736
    00737         /*
    00738          * Right justification of HELP items is only needed on top level
    00739          * menus.
    00740          */
    00741         MBC_RightJustifyMenu(pMenu);
    00742     }
    00743
    00744     /*
    00745      * There's an extra border underneath the menu bar, if it's not empty!
    00746      */
    00747     return(size ? size + SYSMET(CYBORDER) : size);
    00748 }

int xxxMenuItemFromPoint | ( | PWND | pwnd,
|  | PMENU | pMenu,
|  | POINT | ptScreen
| ) |

Definition at line 972 of file mncomput.c.

References CheckLock, GetMenuPwnd(), MFISPOPUP, MFMWFP_NOITEM, MNItemHitTest(), NULL, TestMF, and xxxMNRecomputeBarIfNeeded().

Referenced by NtUserMenuItemFromPoint().

    00973 {
    00974     CheckLock(pwnd);
    00975     CheckLock(pMenu);
    00976
    00977     /*
    00978      * If no pwnd, no go.
    00979      * IMPORTANT: for MFISPOPUP we might get a different pwnd but we don't lock
    00980      *   it because we won't call back
    00981      */
    00982     pwnd = GetMenuPwnd(pwnd, pMenu);
    00983     if (pwnd == NULL) {
    00984         return MFMWFP_NOITEM;
    00985     }
    00986
    00987     if (!TestMF(pMenu, MFISPOPUP)) {
    00988         xxxMNRecomputeBarIfNeeded(pwnd, pMenu);
    00989     }
    00990
    00991     return(MNItemHitTest(pMenu, pwnd, ptScreen));
    00992 }

int xxxMNCompute | ( | PMENU | pMenu,
|  | PWND | pwndNotify,
|  | DWORD | yMenuTop,
|  | DWORD | xMenuLeft,
|  | DWORD | cxMax,
|  | LPDWORD | lpdwMenuHeight
| ) |

Definition at line 233 of file mncomput.c.

References _GetDCEx(), _ReleaseDC(), BOOL, CH_HELPPREFIX, CheckLock, tagMENU::cItems, tagITEM::cxItem, tagMENU::cxMenu, tagMENU::cxTextAlign, tagITEM::cyItem, tagMENU::cyMenu, tagTHREADINFO::dwExpWinVer, DWORD, FALSE, tagMENU::fFlags, gcxMenuFontChar, ghMenuFont, gpsi, tagITEM::hbmp, INT, L, Lock, tagITEM::lpstr, max, MFISPOPUP, MFMULTIROW, MNLEFTMARGIN, MNRecalcTabStrings(), MNXSPACE, NULL, OBI_MENUCHECK, PtiCurrent, tagMENU::rgItems, tagMENU::spwndNotify, SYSMET, TestMF, TestMFT, TestWF, TextPointer, TRUE, UINT, VER40, WFWIN40COMPAT, tagITEM::xItem, xxxMNItemSize(), and tagITEM::yItem.

Referenced by xxxMenuBarCompute(), and xxxMenuWindowProc().

    00240 {
    00241     UINT         cItem;
    00242     DWORD        cxItem;
    00243     DWORD        cyItem;
    00244     DWORD        cyItemKeep;
    00245     DWORD        yPopupTop;
    00246     INT          cMaxWidth;
    00247     DWORD        cMaxHeight;
    00248     UINT         cItemBegCol;
    00249     DWORD        temp;
    00250     int          ret;
    00251     PITEM        pCurItem;
    00252     POINT        ptMNItemSize;
    00253     BOOL         fOwnerDrawItems;
    00254     BOOL         fMenuBreak;
    00255     LPWSTR       lpsz;
    00256     BOOL         fPopupMenu;
    00257     DWORD        menuHeight = 0;
    00258     HDC          hdc;
    00259     HFONT        hOldFont;
    00260     PTHREADINFO  ptiCurrent = PtiCurrent();
    00261     BOOL         fStringAndBitmapItems;
    00262
    00263     CheckLock(pMenu);
    00264     CheckLock(pwndNotify);
    00265
    00266     /*
    00267      * Whoever computes the menu, becomes the owner.
    00268      */
    00269     if (pwndNotify != pMenu->spwndNotify) {
    00270         Lock(&pMenu->spwndNotify, pwndNotify);
    00271     }
    00272
    00273
    00274     if (lpdwMenuHeight != NULL)
    00275         menuHeight = *lpdwMenuHeight;
    00276
    00277     /*
    00278      * Empty menus have a height of zero.
    00279      */
    00280     ret = 0;
    00281     if (pMenu->cItems == 0)
    00282         return ret;
    00283
    00284     hdc = _GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE);
    00285     hOldFont = GreSelectFont(hdc, ghMenuFont);
    00286
    00287     /*
    00288      * Try to make a non-multirow menu first.
    00289      */
    00290     pMenu->fFlags &= (~MFMULTIROW);
    00291
    00292     fPopupMenu = TestMF(pMenu, MFISPOPUP);
    00293
    00294     if (fPopupMenu) {
    00295
    00296         /*
    00297          * Reset the menu bar height to 0 if this is a popup since we are
    00298          * being called from menu.c MN_SIZEWINDOW.
    00299          */
    00300         menuHeight = 0;
    00301     } else if (pwndNotify != NULL) {
    00302         pMenu->cxMenu = cxMax;
    00303     }
    00304
    00305     /*
    00306      * Initialize the computing variables.
    00307      */
    00308     cMaxWidth = cyItemKeep = 0L;
    00309     cItemBegCol = 0;
    00310
    00311     cyItem = yPopupTop = yMenuTop;
    00312     cxItem = xMenuLeft;
    00313
    00314     pCurItem = (PITEM)&pMenu->rgItems[0];
    00315     /*
    00316      * cxTextAlign is used to align the text in all items; this is useful
    00317      *  in popup menus that mix text only items with bitmap-text items. It's
    00318      *  set to the max bitmap width plus some spacing.
    00319      * Do this for new menus wich use string AND bitmaps on the same item
    00320      */
    00321     fStringAndBitmapItems = FALSE;
    00322     pMenu->cxTextAlign = 0;
    00323
    00324     /*
    00325      * Process each item in the menu.
    00326      */
    00327     fOwnerDrawItems = FALSE;
    00328     for (cItem = 0; cItem < pMenu->cItems; cItem++) {
    00329
    00330         /*
    00331          * If it's not a separator, find the dimensions of the object.
    00332          */
    00333         if (TestMFT(pCurItem, MFT_SEPARATOR) &&
    00334                 ( !TestMFT(pCurItem, MFT_OWNERDRAW) ||
    00335                   (LOWORD(ptiCurrent->dwExpWinVer) < VER40)) ) {
    00336             /*
    00337             * If version is less than 4.0  don't test the MFT_OWNERDRAW
    00338             * flag. Bug 21922; App MaxEda has both separator and Ownerdraw
    00339             * flags on. In 3.51 we didn't test the OwnerDraw flag
    00340             */
    00341
    00342             //
    00343             // This is a separator.  It's drawn as wide as the menu area,
    00344             // leaving some space above and below.  Since the menu area is
    00345             // the max of the items' widths, we set our width to 0 so as not
    00346             // to affect the result.
    00347             //
    00348             pCurItem->cxItem = 0;
    00349             pCurItem->cyItem = SYSMET(CYMENUSIZE) / 2;
    00350
    00351
    00352         } else {
    00353             /*
    00354              * Are we using NT5 strings and bitmaps?
    00355              */
    00356             fStringAndBitmapItems |= ((pCurItem->hbmp != NULL) && (pCurItem->lpstr != NULL));
    00357             /*
    00358              * Get the item's X and Y dimensions.
    00359              */
    00360             if (xxxMNItemSize(pMenu, pwndNotify, hdc, pCurItem, fPopupMenu, &ptMNItemSize))
    00361                 fOwnerDrawItems = TRUE;
    00362
    00363             pCurItem->cxItem = ptMNItemSize.x;
    00364             pCurItem->cyItem = ptMNItemSize.y;
    00365             if (!fPopupMenu && ((pCurItem->hbmp == NULL) || (pCurItem->lpstr != NULL))) {
    00366                 pCurItem->cxItem += gcxMenuFontChar * 2;
    00367             }
    00368         }
    00369
    00370         if (menuHeight != 0)
    00371             pCurItem->cyItem = menuHeight;
    00372
    00373         /*
    00374          * If this is the first item, initialize cMaxHeight.
    00375          */
    00376         if (cItem == 0)
    00377             cMaxHeight = pCurItem->cyItem;
    00378
    00379         /*
    00380          * Is this a Pull-Down menu?
    00381          */
    00382         if (fPopupMenu) {
    00383
    00384             /*
    00385              * If this item has a break or is the last item...
    00386              */
    00387             if ((fMenuBreak = TestMFT(pCurItem, MFT_BREAK)) ||
    00388                 pMenu->cItems == cItem + (UINT)1) {
    00389
    00390                 /*
    00391                  * Keep cMaxWidth around if this is not the last item.
    00392                  */
    00393                 temp = cMaxWidth;
    00394                 if (pMenu->cItems == cItem + (UINT)1) {
    00395                     if ((int)(pCurItem->cxItem) > cMaxWidth)
    00396                         temp = pCurItem->cxItem;
    00397                 }
    00398
    00399                 /*
    00400                  * Get new width of string from RecalcTabStrings.
    00401                  */
    00402                 temp = MNRecalcTabStrings(hdc, pMenu, cItemBegCol,
    00403                         (UINT)(cItem + (fMenuBreak ? 0 : 1)), temp, cxItem);
    00404
    00405                 /*
    00406                  * If this item has a break, account for it.
    00407                  */
    00408                 if (fMenuBreak) {
    00409                     //
    00410                     // Add on space for the etch and a border on either side.
    00411                     // NOTE:  For old apps that do weird stuff with owner
    00412                     // draw, keep 'em happy by adding on the same amount
    00413                     // of space we did in 3.1.
    00414                     //
    00415                     if (fOwnerDrawItems && !TestWF(pwndNotify, WFWIN40COMPAT))
    00416                         cxItem = temp + SYSMET(CXBORDER);
    00417                     else
    00418                         cxItem = temp + 2 * SYSMET(CXEDGE);
    00419
    00420                     /*
    00421                      * Reset the cMaxWidth to the current item.
    00422                      */
    00423                     cMaxWidth = pCurItem->cxItem;
    00424
    00425                     /*
    00426                      * Start at the top.
    00427                      */
    00428                     cyItem = yPopupTop;
    00429
    00430                     /*
    00431                      * Save the item where this column begins.
    00432                      */
    00433                     cItemBegCol = cItem;
    00434
    00435                     /*
    00436                      * If this item is also the last item, recalc for this
    00437                      * column.
    00438                      */
    00439                     if (pMenu->cItems == (UINT)(cItem + 1)) {
    00440                         temp = MNRecalcTabStrings(hdc, pMenu, cItem,
    00441                                 (UINT)(cItem + 1), cMaxWidth, cxItem);
    00442                     }
    00443                 }
    00444
    00445                 /*
    00446                  * If this is the last entry, supply the width.
    00447                  */
    00448                 if (pMenu->cItems == cItem + (UINT)1)
    00449                     pMenu->cxMenu = temp;
    00450             }
    00451
    00452             pCurItem->xItem = cxItem;
    00453             pCurItem->yItem = cyItem;
    00454
    00455             cyItem += pCurItem->cyItem;
    00456
    00457             if (cyItemKeep < cyItem)
    00458                 cyItemKeep = cyItem;
    00459
    00460         } else {
    00461
    00462             /*
    00463              * This a Top Level menu, not a Pull-Down.
    00464              */
    00465
    00466             /*
    00467              * Adjust right aligned items before testing for multirow
    00468              */
    00469             if (pCurItem->lpstr != NULL) {
    00470                 lpsz = TextPointer(pCurItem->lpstr);
    00471                 if ((lpsz != NULL) && (*lpsz == CH_HELPPREFIX)) {
    00472                     pCurItem->cxItem -= gcxMenuFontChar;
    00473                 }
    00474             }
    00475
    00476
    00477             /*
    00478              * If this is a new line or a menu break.
    00479              */
    00480             if ((TestMFT(pCurItem, MFT_BREAK)) ||
    00481                     (((cxItem + pCurItem->cxItem + gcxMenuFontChar) >
    00482                     pMenu->cxMenu) && (cItem != 0))) {
    00483                 cyItem += cMaxHeight;
    00484
    00485                 cxItem = xMenuLeft;
    00486                 cMaxHeight = pCurItem->cyItem;
    00487                 pMenu->fFlags |= MFMULTIROW;
    00488             }
    00489
    00490             pCurItem->yItem = cyItem;
    00491
    00492             pCurItem->xItem = cxItem;
    00493             cxItem += pCurItem->cxItem;
    00494         }
    00495
    00496         if (cMaxWidth < (int)(pCurItem->cxItem))
    00497             cMaxWidth = pCurItem->cxItem;
    00498
    00499         if (cMaxHeight != pCurItem->cyItem) {
    00500             if (cMaxHeight < pCurItem->cyItem)
    00501                 cMaxHeight = pCurItem->cyItem;
    00502
    00503             if (!fPopupMenu)
    00504                 menuHeight = cMaxHeight;
    00505         }
    00506
    00507         if (!fPopupMenu)
    00508             cyItemKeep = cyItem + cMaxHeight;
    00509
    00510         pCurItem++;
    00511
    00512     } /* of for loop */
    00513     /*
    00514      * Determine where the strings should be drawn so they are aligned
    00515      * The alignment is only for popup (vertical) menus (see xxxRealDrawMenuItem)
    00516      * The actual space depends on the MNS_NOCHECK and MNS_CHECKORBMP styles
    00517      * Multicolumn menus don't get aligment (now that we have scrollbars, multicolum is out)
    00518      */
    00519     if (!fStringAndBitmapItems || (cItemBegCol != 0)) {
    00520         pMenu->cxTextAlign = 0;
    00521     } else if (TestMF(pMenu, MNS_NOCHECK)) {
    00522         pMenu->cxTextAlign += MNXSPACE;
    00523     } else if (TestMF(pMenu, MNS_CHECKORBMP)) {
    00524         pMenu->cxTextAlign = max(pMenu->cxTextAlign, (UINT)gpsi->oembmi[OBI_MENUCHECK].cx);
    00525         pMenu->cxTextAlign += MNXSPACE;
    00526     } else {
    00527         pMenu->cxTextAlign += gpsi->oembmi[OBI_MENUCHECK].cx + MNXSPACE;
    00528     }
    00529     /*
    00530      * Add the left margin
    00531      */
    00532     if (pMenu->cxTextAlign != 0) {
    00533         pMenu->cxTextAlign += MNLEFTMARGIN;
    00534     }
    00535
    00536
    00537     if (cItemBegCol && pMenu->cItems &&
    00538         TestMFT(((PITEM)&pMenu->rgItems[0]), MFT_RIGHTJUSTIFY)) {
    00539         //
    00540         // multi-column, if we are in RtoL mode, reverse the columns
    00541         //
    00542         pCurItem = (PITEM)&pMenu->rgItems[0];
    00543
    00544         for (cItem = 0; cItem < pMenu->cItems; cItem++) {
    00545             pCurItem->xItem = pMenu->cxMenu -
    00546                               (pCurItem->xItem + pCurItem->cxItem);
    00547             pCurItem++;
    00548         }
    00549     }
    00550
    00551     GreSelectFont(hdc, hOldFont);
    00552     _ReleaseDC(hdc);
    00553
    00554     pMenu->cyMenu = cyItemKeep - yMenuTop;
    00555     ret = pMenu->cyMenu;
    00556
    00557     if (lpdwMenuHeight != NULL)
    00558         *lpdwMenuHeight = menuHeight;
    00559
    00560     return ret;
    00561 }

BOOL xxxMNGetBitmapSize | ( | LPITEM | pItem,
|  | PWND | pwndNotify
| ) |

Definition at line 27 of file mncomput.c.

References BOOL, tagITEM::cxBmp, tagITEM::cyBmp, tagITEM::dwItemData, FALSE, gpsi, LPITEM, MNIS_MEASUREBMP, TRUE, UINT, tagITEM::wID, and xxxSendMessage().

Referenced by xxxMNItemSize().

    00028 {
    00029     MEASUREITEMSTRUCT mis;
    00030
    00031     if (pItem->cxBmp != MNIS_MEASUREBMP) {
    00032         return FALSE;
    00033     }
    00034
    00035     // Send a measure item message to the owner
    00036     mis.CtlType = ODT_MENU;
    00037     mis.CtlID = 0;
    00038     mis.itemID  = pItem->wID;
    00039     mis.itemWidth = 0;
    00040 // After scrollable menus
    00041 //    mis32.itemHeight= gcyMenuFontChar;
    00042     mis.itemHeight= (UINT)gpsi->cySysFontChar;
    00043     mis.itemData = pItem->dwItemData;
    00044
    00045     xxxSendMessage(pwndNotify, WM_MEASUREITEM, 0, (LPARAM)&mis);
    00046
    00047     pItem->cxBmp = mis.itemWidth;
    00048     pItem->cyBmp = mis.itemHeight;
    00049
    00050     return TRUE;
    00051 }

BOOL xxxMNItemSize | ( | PMENU | pMenu,
|  | PWND | pwndNotify,
|  | HDC | hdc,
|  | PITEM | pItem,
|  | BOOL | fPopup,
|  | LPPOINT | lppt
| ) |

Definition at line 62 of file mncomput.c.

References BOOL, CheckLock, tagITEM::cxBmp, tagMENU::cxTextAlign, tagITEM::cyBmp, DWORD, FindCharPosition(), gcxMenuFontChar, gcyMenuFontChar, gcyMenuFontExternLeading, ghMenuFontDef, gpsi, tagITEM::hbmp, tagITEM::lpstr, max, MFISPOPUP, MNIS_MEASUREBMP, MNLEFTMARGIN, MNXSPACE, NULL, OBI_MENUCHECK, SYSMET, TestMF, TestMFS, TestMFT, TextPointer, xxxMNGetBitmapSize(), and xxxPSMGetTextExtent().

Referenced by xxxMNCompute().

    00069 {
    00070     BITMAP bmp;
    00071     int width = 0;
    00072     int height = 0;
    00073     DWORD xRightJustify;
    00074     LPWSTR lpMenuString;
    00075     HFONT               hfnOld;
    00076     int                 tcExtra;
    00077
    00078     UNREFERENCED_PARAMETER(pMenu);
    00079
    00080     CheckLock(pMenu);
    00081     CheckLock(pwndNotify);
    00082
    00083     if (!fPopup) {
    00084
    00085         /*
    00086          * Save off the height of the top menu bar since we will used this often
    00087          * if the pItem is not in a popup.  (ie.  it is in the top level menu bar)
    00088          */
    00089         height = SYSMET(CYMENUSIZE);
    00090     }
    00091
    00092     hfnOld = NULL;
    00093     if (TestMFS(pItem, MFS_DEFAULT)) {
    00094         if (ghMenuFontDef)
    00095             hfnOld = GreSelectFont(hdc, ghMenuFontDef);
    00096         else {
    00097             tcExtra = GreGetTextCharacterExtra(hdc);
    00098             GreSetTextCharacterExtra(hdc, tcExtra + 1 + (gcxMenuFontChar / gpsi->cxSysFontChar));
    00099         }
    00100     }
    00101
    00102     /*
    00103      * Compute bitmap dimensions if needed
    00104      */
    00105     if (pItem->hbmp != NULL)  {
    00106         if (pItem->hbmp == HBMMENU_CALLBACK) {
    00107             xxxMNGetBitmapSize(pItem, pwndNotify);
    00108         } else if (pItem->cxBmp == MNIS_MEASUREBMP) {
    00109             if (TestMFS(pItem, MFS_CACHEDBMP)) {
    00110                 pItem->cxBmp = SYSMET(CXMENUSIZE);
    00111                 pItem->cyBmp = SYSMET(CYMENUSIZE);
    00112                 if (pItem->hbmp == HBMMENU_SYSTEM) {
    00113                     pItem->cxBmp += SYSMET(CXEDGE);
    00114                     /*
    00115                      * Chicago/Memphis only stretch the width,
    00116                      * not the height.  NT Bug 124779.  FritzS
    00117                      */
    00118                  //  pItem->cyBmp += SYSMET(CXEDGE);
    00119                 }
    00120             } else {
    00121                 if (GreExtGetObjectW(pItem->hbmp, sizeof(BITMAP), (LPSTR)&bmp)) {
    00122                     pItem->cxBmp = bmp.bmWidth;
    00123                     pItem->cyBmp = bmp.bmHeight;
    00124                 } else {
    00125                     /*
    00126                      * If the bitmap is not useable, this is as good a default
    00127                      * as any.
    00128                      */
    00129                     pItem->cxBmp = SYSMET(CXMENUSIZE);
    00130                     pItem->cyBmp = SYSMET(CYMENUSIZE);
    00131                 }
    00132             }
    00133         }
    00134         width = pItem->cxBmp;
    00135         /*
    00136          * Remember the max bitmap width to align the text in all items.
    00137          */
    00138         pMenu->cxTextAlign = max(pMenu->cxTextAlign, (DWORD)width);
    00139         /*
    00140          * In menu bars, we force the item to be at least CYMNSIZE.
    00141          * Fixes many, many problems w/ apps that fake own MDI.
    00142          */
    00143         if (fPopup) {
    00144             height = pItem->cyBmp;
    00145         } else {
    00146             height = max((int)pItem->cyBmp, height);
    00147         }
    00148     } else if (TestMFT(pItem, MFT_OWNERDRAW)) {
    00149         // This is an ownerdraw item -- the width and height are stored in
    00150         // cxBmp and cyBmp
    00151         xxxMNGetBitmapSize(pItem, pwndNotify);
    00152         width = pItem->cxBmp;
    00153         //
    00154         // Ignore height with menu bar now--that's set by user.
    00155         //
    00156         if (fPopup) {
    00157             height = pItem->cyBmp;
    00158             // If this item has a popup (hierarchical) menu associated with it, then
    00159             // reserve room for the bitmap that tells the user that a hierarchical
    00160             // menu exists here.
    00161             // B#2966, t-arthb
    00162
    00163             UserAssert(fPopup == (TestMF(pMenu, MFISPOPUP) != 0));
    00164
    00165             width = width + (gcxMenuFontChar << 1);
    00166         }
    00167     }
    00168
    00169     if ((pItem->lpstr != NULL) && (!TestMFT(pItem, MFT_OWNERDRAW)) ) {
    00170         SIZE size;
    00171
    00172         /*
    00173          * This menu item contains a string
    00174          */
    00175
    00176         /*
    00177          * We want to keep the menu bar height if this isn't a popup.
    00178          */
    00179         if (fPopup) {
    00180             /* The thickness of mnemonic underscore is CYBORDER and the gap
    00181              * between the characters and the underscore is another CYBORDER
    00182              */
    00183             height = max(height, gcyMenuFontChar + gcyMenuFontExternLeading + SYSMET(CYEDGE));
    00184         }
    00185
    00186         lpMenuString = TextPointer(pItem->lpstr);
    00187         xRightJustify = FindCharPosition(lpMenuString, TEXT('\t'));
    00188
    00189         xxxPSMGetTextExtent(hdc, lpMenuString, xRightJustify, &size);
    00190
    00191         if (width) {
    00192             width += MNXSPACE + size.cx;
    00193         } else {
    00194             width =  size.cx;
    00195         }
    00196     }
    00197
    00198     if (fPopup && !TestMFT(pItem, MFT_OWNERDRAW)) {
    00199         /*
    00200          *  Add on space for checkmark, then horz spacing for default & disabled
    00201          *   plus some left margin.
    00202          */
    00203         if (TestMF(pMenu, MNS_CHECKORBMP) || !TestMF(pMenu, MNS_NOCHECK)) {
    00204             width += gpsi->oembmi[OBI_MENUCHECK].cx;
    00205         }
    00206         width += MNXSPACE + MNLEFTMARGIN + 2;
    00207         height += 2;
    00208     }
    00209
    00210     if (TestMFS(pItem, MFS_DEFAULT)) {
    00211         if (hfnOld)
    00212             GreSelectFont(hdc, hfnOld);
    00213         else
    00214             GreSetTextCharacterExtra(hdc, tcExtra);
    00215     }
    00216
    00217     /*
    00218      * Loword contains width, high word contains height of item.
    00219      */
    00220     lppt->x = width;
    00221     lppt->y = height;
    00222
    00223     return(TestMFT(pItem, MFT_OWNERDRAW));
    00224 }

void xxxMNRecomputeBarIfNeeded | ( | PWND | pwndNotify,
|  | PMENU | pMenu
| ) |

Definition at line 758 of file mncomput.c.

References CheckLock, tagMENU::cxMenu, tagMENU::cyMenu, FALSE, GetCaptionHeight(), GetWindowBorders(), MFISPOPUP, MFSYSMENU, tagWND::rcWindow, tagMENU::spwndNotify, SYSMET, TestMF, TRUE, and xxxMenuBarCompute().

Referenced by xxxGetMenuItemRect(), xxxHiliteMenuItem(), xxxHotTrackMenu(), xxxMenuItemFromPoint(), and xxxMNStartMenu().

    00761 {
    00762     int cxFrame;
    00763     int cyFrame;
    00764
    00765     UserAssert(!TestMF(pMenu, MFISPOPUP));
    00766
    00767     CheckLock(pwndNotify);
    00768     CheckLock(pMenu);
    00769
    00770     if (!TestMF(pMenu, MFSYSMENU)
    00771         && ((pMenu->spwndNotify != pwndNotify) || !pMenu->cxMenu || !pMenu->cyMenu)) {
    00772         int cBorders;
    00773
    00774         cBorders = GetWindowBorders(pwndNotify->style, pwndNotify->ExStyle, TRUE, FALSE);
    00775         cxFrame = cBorders * SYSMET(CXBORDER);
    00776         cyFrame = cBorders * SYSMET(CYBORDER);
    00777
    00778         cyFrame += GetCaptionHeight(pwndNotify);
    00779
    00780         // The width passed in this call was larger by cxFrame;
    00781         // Fix for Bug #11466 - Fixed by SANKAR - 01/06/92 --
    00782         xxxMenuBarCompute(pMenu, pwndNotify, cyFrame, cxFrame,
    00783                 (pwndNotify->rcWindow.right - pwndNotify->rcWindow.left) - cxFrame * 2);
    00784     }
    00785 }