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 }


Generated on Sat May 15 19:44:47 2004 for test by doxygen 1.3.7