00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <assert.h>
00025 #include <ctype.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <os2win.h>
00029 #include <heapstring.h>
00030 #include "controls.h"
00031 #include "menu.h"
00032
00033 #ifdef __WIN32OS2__
00034 #include <objhandle.h>
00035 #include "pmwindow.h"
00036 #include "win32wmisc.h"
00037 #include "oslibmsg.h"
00038 #include "oslibwin.h"
00039 #include "syscolor.h"
00040
00041 #define DBG_LOCALLOG DBG_menu
00042 #include "dbglocal.h"
00043 #endif
00044
00045
00046
00047
00048
00049
00050
00051 #define MM_SETMENUHANDLE (WM_USER + 0)
00052 #define MM_GETMENUHANDLE (WM_USER + 1)
00053
00054
00055 typedef struct {
00056
00057 UINT fType;
00058 UINT fState;
00059 UINT wID;
00060 HMENU hSubMenu;
00061 HBITMAP hCheckBit;
00062 HBITMAP hUnCheckBit;
00063 LPSTR text;
00064 DWORD dwItemData;
00065 DWORD dwTypeData;
00066 HBITMAP hbmpItem;
00067
00068 RECT rect;
00069 UINT xTab;
00070 } MENUITEM;
00071
00072
00073 typedef struct {
00074 WORD wFlags;
00075 WORD wMagic;
00076 HQUEUE hTaskQ;
00077 WORD Width;
00078 WORD Height;
00079 WORD nItems;
00080 HWND hWnd;
00081 MENUITEM *items;
00082 UINT FocusedItem;
00083 HWND hwndOwner;
00084 BOOL bTimeToHide;
00085
00086 DWORD dwStyle;
00087 UINT cyMax;
00088 HBRUSH hbrBack;
00089 DWORD dwContextHelpID;
00090 DWORD dwMenuData;
00091 HMENU hSysMenuOwner;
00092 } POPUPMENU, *LPPOPUPMENU;
00093
00094
00095
00096 #define TF_ENDMENU 0x0001
00097 #define TF_SUSPENDPOPUP 0x0002
00098 #define TF_SKIPREMOVE 0x0004
00099
00100 typedef struct
00101 {
00102 UINT trackFlags;
00103 HMENU hCurrentMenu;
00104 HMENU hTopMenu;
00105 HWND hOwnerWnd;
00106 POINT pt;
00107 } MTRACKER;
00108
00109 #define MENU_MAGIC 0x554d
00110
00111 #define IS_A_MENU(pmenu) ((pmenu) && (pmenu)->wMagic == MENU_MAGIC)
00112
00113 #define ITEM_PREV -1
00114 #define ITEM_NEXT 1
00115
00116
00117 #define TPM_INTERNAL 0xF0000000
00118 #define TPM_ENTERIDLEEX 0x80000000
00119 #define TPM_BUTTONDOWN 0x40000000
00120 #define TPM_POPUPMENU 0x20000000
00121 #define TPM_CAPTIONSYSMENU 0x10000000
00122
00123
00124 #define POPUP_XSHADE 4
00125 #define POPUP_YSHADE 4
00126
00127
00128 #define MENU_BAR_ITEMS_SPACE 12
00129
00130
00131 #define MENU_TAB_SPACE 8
00132
00133
00134 #define SEPARATOR_HEIGHT 5
00135
00136
00137 #define NO_SELECTED_ITEM 0xffff
00138
00139 #define MENU_ITEM_TYPE(flags) \
00140 ((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
00141
00142 #define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
00143 #define IS_SEPARATOR_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_SEPARATOR)
00144 #define IS_BITMAP_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_BITMAP)
00145
00146 #define IS_SYSTEM_MENU(menu) \
00147 (!((menu)->wFlags & MF_POPUP) && (menu)->wFlags & MF_SYSMENU)
00148
00149 #define IS_SYSTEM_POPUP(menu) \
00150 ((menu)->wFlags & MF_POPUP && (menu)->wFlags & MF_SYSMENU)
00151
00152 #define TYPE_MASK (MFT_STRING | MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR | \
00153 MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
00154 MFT_RIGHTORDER | MFT_RIGHTJUSTIFY | \
00155 MF_POPUP | MF_SYSMENU | MF_HELP)
00156 #define STATE_MASK (~TYPE_MASK)
00157
00158
00159 static WORD check_bitmap_width = 0, check_bitmap_height = 0;
00160 static WORD arrow_bitmap_width = 0, arrow_bitmap_height = 0;
00161
00162 static HBITMAP hStdRadioCheck = 0;
00163 static HBITMAP hStdCheck = 0;
00164 static HBITMAP hStdMnArrow = 0;
00165
00166
00167 static HBITMAP hBmpMinimize = 0;
00168 static HBITMAP hBmpMinimizeD = 0;
00169 static HBITMAP hBmpMaximize = 0;
00170 static HBITMAP hBmpMaximizeD = 0;
00171 static HBITMAP hBmpClose = 0;
00172 static HBITMAP hBmpCloseD = 0;
00173
00174
00175 static HBRUSH hShadeBrush = 0;
00176 static HFONT hMenuFont = 0;
00177 static HFONT hMenuFontBold = 0;
00178
00179 static HMENU MENU_DefSysPopup = 0;
00180
00181
00182
00183
00184 static HWND pTopPopupWnd = 0;
00185 static UINT uSubPWndLevel = 0;
00186
00187
00188 static BOOL fEndMenu = FALSE;
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 #define SUBMENU_POPUP_TIMERID 100
00199 #define POPUP_MENU_DELAY 500
00200 static UINT mouseOverMenuID = -1;
00201 static BOOL isTimerSet = FALSE;
00202
00203 #ifdef __WIN32OS2__
00204 static BOOL fDisableOdinSysMenuItems = FALSE;
00205 #endif
00206
00207
00208
00209
00210
00211
00212
00213 #define debug_print_menuitem(pre, mp, post) \
00214 if(!TRACE_ON(menu)) ; else do_debug_print_menuitem(pre, mp, post)
00215
00216 #define MENUOUT(text) \
00217 DPRINTF("%s%s", (count++ ? "," : ""), (text))
00218
00219 #define MENUFLAG(bit,text) \
00220 do { \
00221 if (flags & (bit)) { flags &= ~(bit); MENUOUT ((text)); } \
00222 } while (0)
00223
00224 #if 0
00225 static void do_debug_print_menuitem(const char *prefix, MENUITEM * mp,
00226 const char *postfix)
00227 {
00228 TRACE("%s ", prefix);
00229 if (mp) {
00230 UINT flags = mp->fType;
00231 int typ = MENU_ITEM_TYPE(flags);
00232 DPRINTF( "{ ID=0x%x", mp->wID);
00233 if (flags & MF_POPUP)
00234 DPRINTF( ", Sub=0x%x", mp->hSubMenu);
00235 if (flags) {
00236 int count = 0;
00237 DPRINTF( ", Typ=");
00238 if (typ == MFT_STRING)
00239 ;
00240 else if (typ == MFT_SEPARATOR)
00241 MENUOUT("sep");
00242 else if (typ == MFT_OWNERDRAW)
00243 MENUOUT("own");
00244 else if (typ == MFT_BITMAP)
00245 MENUOUT("bit");
00246 else
00247 MENUOUT("???");
00248 flags -= typ;
00249
00250 MENUFLAG(MF_POPUP, "pop");
00251 MENUFLAG(MFT_MENUBARBREAK, "barbrk");
00252 MENUFLAG(MFT_MENUBREAK, "brk");
00253 MENUFLAG(MFT_RADIOCHECK, "radio");
00254 MENUFLAG(MFT_RIGHTORDER, "rorder");
00255 MENUFLAG(MF_SYSMENU, "sys");
00256 MENUFLAG(MFT_RIGHTJUSTIFY, "right");
00257
00258 if (flags)
00259 DPRINTF( "+0x%x", flags);
00260 }
00261 flags = mp->fState;
00262 if (flags) {
00263 int count = 0;
00264 DPRINTF( ", State=");
00265 MENUFLAG(MFS_GRAYED, "grey");
00266 MENUFLAG(MFS_DEFAULT, "default");
00267 MENUFLAG(MFS_DISABLED, "dis");
00268 MENUFLAG(MFS_CHECKED, "check");
00269 MENUFLAG(MFS_HILITE, "hi");
00270 MENUFLAG(MF_USECHECKBITMAPS, "usebit");
00271 MENUFLAG(MF_MOUSESELECT, "mouse");
00272 if (flags)
00273 DPRINTF( "+0x%x", flags);
00274 }
00275 if (mp->hCheckBit)
00276 DPRINTF( ", Chk=0x%x", mp->hCheckBit);
00277 if (mp->hUnCheckBit)
00278 DPRINTF( ", Unc=0x%x", mp->hUnCheckBit);
00279
00280 if (typ == MFT_STRING) {
00281 if (mp->text)
00282 DPRINTF( ", Text=\"%s\"", mp->text);
00283 else
00284 DPRINTF( ", Text=Null");
00285 } else if (mp->text == NULL)
00286 ;
00287 else
00288 DPRINTF( ", Text=%p", mp->text);
00289 if (mp->dwItemData)
00290 DPRINTF( ", ItemData=0x%08lx", mp->dwItemData);
00291 DPRINTF( " }");
00292 } else {
00293 DPRINTF( "NULL");
00294 }
00295
00296 DPRINTF(" %s\n", postfix);
00297 }
00298 #endif
00299
00300 #undef MENUOUT
00301 #undef MENUFLAG
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 POPUPMENU *MENU_GetMenu(HMENU hMenu)
00313 {
00314 #ifdef __WIN32OS2__
00315 if(ObjGetHandleType(hMenu) == USEROBJ_MENU) {
00316 POPUPMENU *menu;
00317
00318 menu = (POPUPMENU *)ObjGetHandleData(hMenu, USEROBJ_MENU);
00319 return menu;
00320 }
00321 return NULL;
00322 #else
00323 POPUPMENU *menu;
00324 menu = (POPUPMENU*)hMenu;
00325 if (!IS_A_MENU(menu))
00326 {
00327
00328 menu = NULL;
00329 }
00330 return menu;
00331 #endif
00332 }
00333
00334
00335
00336
00337
00338
00339 static HMENU MENU_CopySysPopup(void)
00340 {
00341 HMENU hMenu = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU");
00342
00343 if( hMenu ) {
00344 #ifdef __WIN32OS2__
00345 POPUPMENU* menu = MENU_GetMenu(hMenu);
00346 #else
00347 POPUPMENU* menu = (POPUPMENU*)hMenu;
00348 #endif
00349 menu->wFlags |= MF_SYSMENU | MF_POPUP;
00350 SetMenuDefaultItem(hMenu, SC_CLOSE, FALSE);
00351 #ifdef __WIN32OS2__
00352 if(fDisableOdinSysMenuItems) {
00353 RemoveMenu(hMenu, 9, MF_BYPOSITION);
00354 RemoveMenu(hMenu, 9, MF_BYPOSITION);
00355 RemoveMenu(hMenu, 9, MF_BYPOSITION);
00356 RemoveMenu(hMenu, 9, MF_BYPOSITION);
00357 RemoveMenu(hMenu, 9, MF_BYPOSITION);
00358 }
00359 #ifndef DEBUG
00360 else {
00361 RemoveMenu(hMenu, SC_PUTMARK, MF_BYCOMMAND);
00362 RemoveMenu(hMenu, SC_DEBUGINT3, MF_BYCOMMAND);
00363 RemoveMenu(hMenu, 11, MF_BYPOSITION);
00364 }
00365 #endif
00366 #endif
00367 }
00368 else {
00369 hMenu = 0;
00370
00371 }
00372
00373
00374
00375 return hMenu;
00376 }
00377
00378
00379
00380
00381
00382
00383 static HWND MENU_GetTopPopupWnd()
00384 {
00385 return pTopPopupWnd;
00386 }
00387
00388
00389
00390
00391
00392 static void MENU_ReleaseTopPopupWnd()
00393 {
00394 }
00395
00396
00397
00398
00399
00400 static void MENU_DestroyTopPopupWnd()
00401 {
00402 pTopPopupWnd = NULL;
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu )
00417 {
00418 HMENU hMenu;
00419
00420 hMenu = CreateMenu();
00421 if (hMenu)
00422 {
00423 #ifdef __WIN32OS2__
00424 POPUPMENU *menu = MENU_GetMenu(hMenu);
00425 #else
00426 POPUPMENU *menu = (POPUPMENU*)hMenu;
00427 #endif
00428 menu->wFlags = MF_SYSMENU;
00429 menu->hWnd = hWnd;
00430
00431 if (hPopupMenu == (HMENU)(-1))
00432 hPopupMenu = MENU_CopySysPopup();
00433 else if( !hPopupMenu ) hPopupMenu = MENU_DefSysPopup;
00434
00435 if (hPopupMenu)
00436 {
00437 InsertMenuA( hMenu, -1, MF_SYSMENU | MF_POPUP | MF_BYPOSITION, hPopupMenu, NULL );
00438
00439 menu->items[0].fType = MF_SYSMENU | MF_POPUP;
00440 menu->items[0].fState = 0;
00441 #ifdef __WIN32OS2__
00442 menu = MENU_GetMenu(hPopupMenu);
00443 #else
00444 menu = (POPUPMENU*)hPopupMenu;
00445 #endif
00446 menu->wFlags |= MF_SYSMENU;
00447
00448
00449 return hMenu;
00450 }
00451 DestroyMenu( hMenu );
00452 }
00453
00454 return 0;
00455 }
00456
00457
00458
00459
00460
00461
00462
00463 BOOL MENU_Init()
00464 {
00465 HBITMAP hBitmap;
00466 NONCLIENTMETRICSA ncm;
00467
00468 static unsigned char shade_bits[16] = { 0x55, 0, 0xAA, 0,
00469 0x55, 0, 0xAA, 0,
00470 0x55, 0, 0xAA, 0,
00471 0x55, 0, 0xAA, 0 };
00472
00473
00474 hStdCheck = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_CHECK));
00475 hStdRadioCheck = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_RADIOCHECK));
00476 hStdMnArrow = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_MNARROW));
00477
00478 hBmpMinimize = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_REDUCE));
00479 hBmpMinimizeD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_REDUCED));
00480 hBmpMaximize = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_RESTORE));
00481 hBmpMaximizeD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_RESTORED));
00482 hBmpClose = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_CLOSE));
00483 hBmpCloseD = LoadBitmapA(0,MAKEINTRESOURCEA(OBM_CLOSED));
00484
00485 if (hStdCheck)
00486 {
00487 BITMAP bm;
00488 GetObjectA( hStdCheck, sizeof(bm), &bm );
00489 check_bitmap_width = bm.bmWidth;
00490 check_bitmap_height = bm.bmHeight;
00491 } else
00492 return FALSE;
00493
00494
00495 if (!hStdRadioCheck)
00496 return FALSE;
00497
00498 if (hStdMnArrow)
00499 {
00500 BITMAP bm;
00501 GetObjectA( hStdMnArrow, sizeof(bm), &bm );
00502 arrow_bitmap_width = bm.bmWidth;
00503 arrow_bitmap_height = bm.bmHeight;
00504 } else
00505 return FALSE;
00506
00507 if (! (hBitmap = CreateBitmap( 8, 8, 1, 1, shade_bits)))
00508 return FALSE;
00509
00510 if(!(hShadeBrush = CreatePatternBrush( hBitmap )))
00511 return FALSE;
00512
00513 DeleteObject( hBitmap );
00514 if (!(MENU_DefSysPopup = MENU_CopySysPopup()))
00515 return FALSE;
00516
00517 ncm.cbSize = sizeof (NONCLIENTMETRICSA);
00518 if (!(SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &ncm, 0)))
00519 return FALSE;
00520
00521 if (!(hMenuFont = CreateFontIndirectA( &ncm.lfMenuFont )))
00522 return FALSE;
00523
00524 ncm.lfMenuFont.lfWeight += 300;
00525 if ( ncm.lfMenuFont.lfWeight > 1000)
00526 ncm.lfMenuFont.lfWeight = 1000;
00527
00528 if (!(hMenuFontBold = CreateFontIndirectA( &ncm.lfMenuFont )))
00529 return FALSE;
00530
00531 return TRUE;
00532 }
00533
00534
00535
00536
00537
00538
00539 static void MENU_InitSysMenuPopup( HMENU hmenu, DWORD style, DWORD clsStyle )
00540 {
00541 BOOL gray;
00542
00543 gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
00544 EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
00545 gray = ((style & WS_MAXIMIZE) != 0);
00546 EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
00547 gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
00548 EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
00549 gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
00550 EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
00551 gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
00552 EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
00553 gray = (clsStyle & CS_NOCLOSE) != 0;
00554
00555
00556 if(gray)
00557 EnableMenuItem( hmenu, SC_CLOSE, MF_GRAYED);
00558 }
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 static UINT MENU_GetStartOfNextColumn(
00569 HMENU hMenu )
00570 {
00571 #ifdef __WIN32OS2__
00572 POPUPMENU *menu = MENU_GetMenu(hMenu);
00573 #else
00574 POPUPMENU *menu = (POPUPMENU*)hMenu;
00575 #endif
00576 UINT i = menu->FocusedItem + 1;
00577
00578 if(!menu)
00579 return NO_SELECTED_ITEM;
00580
00581 if( i == NO_SELECTED_ITEM )
00582 return i;
00583
00584 for( ; i < menu->nItems; ++i ) {
00585 if (menu->items[i].fType & MF_MENUBARBREAK)
00586 return i;
00587 }
00588
00589 return NO_SELECTED_ITEM;
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 static UINT MENU_GetStartOfPrevColumn(
00601 HMENU hMenu )
00602 {
00603 #ifdef __WIN32OS2__
00604 POPUPMENU const *menu = MENU_GetMenu(hMenu);
00605 #else
00606 POPUPMENU const *menu = (POPUPMENU*)hMenu;
00607 #endif
00608 UINT i;
00609
00610 if( !menu )
00611 return NO_SELECTED_ITEM;
00612
00613 if( menu->FocusedItem == 0 || menu->FocusedItem == NO_SELECTED_ITEM )
00614 return NO_SELECTED_ITEM;
00615
00616
00617
00618 for(i = menu->FocusedItem; i != 0 &&
00619 !(menu->items[i].fType & MF_MENUBARBREAK);
00620 --i);
00621
00622 if(i == 0)
00623 return NO_SELECTED_ITEM;
00624
00625 for(--i; i != 0; --i) {
00626 if (menu->items[i].fType & MF_MENUBARBREAK)
00627 break;
00628 }
00629
00630
00631
00632 return i;
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 static MENUITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
00644 {
00645 POPUPMENU *menu;
00646 UINT i;
00647
00648 if (((*hmenu)==0xffff) || (!(menu = MENU_GetMenu(*hmenu)))) return NULL;
00649 if (!menu) return NULL;
00650 if (wFlags & MF_BYPOSITION)
00651 {
00652 if (*nPos >= menu->nItems) return NULL;
00653 return &menu->items[*nPos];
00654 }
00655 else
00656 {
00657 MENUITEM *item = menu->items;
00658
00659 for (i = 0; i < menu->nItems; i++, item++)
00660 {
00661 if (item->wID == *nPos)
00662 {
00663 *nPos = i;
00664 return item;
00665 }
00666 else if (item->fType & MF_POPUP)
00667 {
00668 HMENU hsubmenu = item->hSubMenu;
00669 MENUITEM *subitem = MENU_FindItem( &hsubmenu, nPos, wFlags );
00670 #ifdef __WIN32OS2__
00671 if (subitem && subitem!=item)
00672 #else
00673 if (subitem)
00674 #endif
00675 {
00676 *hmenu = hsubmenu;
00677 return subitem;
00678 }
00679 }
00680 }
00681 }
00682 return NULL;
00683 }
00684
00685
00686
00687
00688
00689
00690
00691
00692 UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget )
00693 {
00694 POPUPMENU *menu;
00695 UINT i;
00696 MENUITEM *item;
00697 if (((*hmenu)==0xffff) ||
00698 (!(menu = MENU_GetMenu(*hmenu))))
00699 return NO_SELECTED_ITEM;
00700 item = menu->items;
00701 for (i = 0; i < menu->nItems; i++, item++) {
00702 if(!(item->fType & MF_POPUP)) continue;
00703 if (item->hSubMenu == hSubTarget) {
00704 return i;
00705 }
00706 else {
00707 HMENU hsubmenu = item->hSubMenu;
00708 UINT pos = MENU_FindSubMenu( &hsubmenu, hSubTarget );
00709 if (pos != NO_SELECTED_ITEM) {
00710 *hmenu = hsubmenu;
00711 return pos;
00712 }
00713 }
00714 }
00715 return NO_SELECTED_ITEM;
00716 }
00717
00718
00719
00720
00721 static void MENU_FreeItemData( MENUITEM* item )
00722 {
00723
00724 if (IS_STRING_ITEM(item->fType) && item->text)
00725 HeapFree(GetProcessHeap(), 0, item->text );
00726 }
00727
00728
00729
00730
00731
00732
00733
00734
00735 static MENUITEM *MENU_FindItemByCoords( POPUPMENU *menu,
00736 POINT pt, UINT *pos )
00737 {
00738 MENUITEM *item;
00739 UINT i;
00740 RECT wrect;
00741
00742 if (!GetWindowRect(menu->hWnd,&wrect)) return NULL;
00743 pt.x -= wrect.left;pt.y -= wrect.top;
00744 item = menu->items;
00745 for (i = 0; i < menu->nItems; i++, item++)
00746 {
00747 if ((pt.x >= item->rect.left) && (pt.x < item->rect.right) &&
00748 (pt.y >= item->rect.top) && (pt.y < item->rect.bottom))
00749 {
00750 if (pos) *pos = i;
00751 return item;
00752 }
00753 }
00754 return NULL;
00755 }
00756
00757
00758
00759
00760
00761
00762
00763
00764 static UINT MENU_FindItemByKey( HWND hwndOwner, HMENU hmenu,
00765 UINT key, BOOL forceMenuChar )
00766 {
00767
00768
00769 if (!IsMenu( hmenu ))
00770 {
00771 hmenu = GetSubMenu(getSysMenu(hwndOwner), 0);
00772 }
00773
00774 if (hmenu)
00775 {
00776 POPUPMENU *menu = MENU_GetMenu(hmenu);
00777 MENUITEM *item = menu->items;
00778 LONG menuchar;
00779
00780 if( !forceMenuChar )
00781 {
00782 UINT i;
00783
00784 key = toupper(key);
00785 for (i = 0; i < menu->nItems; i++, item++)
00786 {
00787 if (item->text && (IS_STRING_ITEM(item->fType)))
00788 {
00789 char *p = item->text - 2;
00790 do
00791 {
00792 p = strchr (p + 2, '&');
00793 }
00794 while (p != NULL && p [1] == '&');
00795 if (p && (toupper(p[1]) == key)) return i;
00796 }
00797 }
00798 }
00799 menuchar = SendMessageA( hwndOwner, WM_MENUCHAR,
00800 MAKEWPARAM( key, menu->wFlags ), hmenu );
00801 if (HIWORD(menuchar) == 2) return LOWORD(menuchar);
00802 if (HIWORD(menuchar) == 1) return (UINT)(-2);
00803 }
00804 return (UINT)(-1);
00805 }
00806
00807
00808
00809
00810
00811
00812 static HBITMAP MENU_LoadMagicItem(UINT id, BOOL hilite, DWORD dwItemData)
00813 {
00814
00815
00816
00817
00818
00819
00820
00821
00822 switch(id & 0xffff)
00823 { case HBMMENU_SYSTEM:
00824 return (dwItemData) ?
00825 (HBITMAP)dwItemData :
00826 (hilite ? hBmpMinimizeD : hBmpMinimize);
00827 case HBMMENU_MBAR_RESTORE:
00828 return (hilite ? hBmpMaximizeD: hBmpMaximize);
00829 case HBMMENU_MBAR_MINIMIZE:
00830 return (hilite ? hBmpMinimizeD : hBmpMinimize);
00831 case HBMMENU_MBAR_CLOSE:
00832 return (hilite ? hBmpCloseD : hBmpClose);
00833 case HBMMENU_CALLBACK:
00834 case HBMMENU_MBAR_CLOSE_D:
00835 case HBMMENU_MBAR_MINIMIZE_D:
00836 case HBMMENU_POPUP_CLOSE:
00837 case HBMMENU_POPUP_RESTORE:
00838 case HBMMENU_POPUP_MAXIMIZE:
00839 case HBMMENU_POPUP_MINIMIZE:
00840 default:
00841
00842 return 0;
00843 }
00844
00845 }
00846
00847
00848
00849
00850
00851
00852 static void MENU_CalcItemSize( HDC hdc, MENUITEM *lpitem, HWND hwndOwner,
00853 INT orgX, INT orgY, BOOL menuBar )
00854 {
00855 char *p;
00856
00857
00858
00859
00860
00861 SetRect( &lpitem->rect, orgX, orgY, orgX, orgY );
00862
00863 if (lpitem->fType & MF_OWNERDRAW)
00864 {
00865 MEASUREITEMSTRUCT mis;
00866 mis.CtlType = ODT_MENU;
00867 mis.CtlID = 0;
00868 mis.itemID = lpitem->wID;
00869 mis.itemData = (DWORD)lpitem->dwItemData;
00870 mis.itemHeight = 0;
00871 mis.itemWidth = 0;
00872 SendMessageA( hwndOwner, WM_MEASUREITEM, 0, (LPARAM)&mis );
00873 lpitem->rect.bottom += mis.itemHeight;
00874 lpitem->rect.right += mis.itemWidth;
00875
00876
00877 if(menuBar)
00878 {
00879 lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
00880 }
00881
00882
00883
00884 return;
00885 }
00886
00887 if (lpitem->fType & MF_SEPARATOR)
00888 {
00889 lpitem->rect.bottom += SEPARATOR_HEIGHT;
00890 return;
00891 }
00892
00893 if (!menuBar)
00894 {
00895 lpitem->rect.right += 2 * check_bitmap_width;
00896 if (lpitem->fType & MF_POPUP)
00897 lpitem->rect.right += arrow_bitmap_width;
00898 }
00899
00900 if (IS_BITMAP_ITEM(lpitem->fType))
00901 {
00902 BITMAP bm;
00903 HBITMAP resBmp = 0;
00904
00905
00906 if((LOWORD((int)lpitem->text))<12)
00907 {
00908 resBmp = MENU_LoadMagicItem((int)lpitem->text, (lpitem->fType & MF_HILITE),
00909 lpitem->dwItemData);
00910 }
00911 else
00912 resBmp = (HBITMAP)lpitem->text;
00913
00914 if (GetObjectA(resBmp, sizeof(bm), &bm ))
00915 {
00916 lpitem->rect.right += bm.bmWidth;
00917 lpitem->rect.bottom += bm.bmHeight;
00918
00919 }
00920 }
00921
00922
00923
00924 if (!(lpitem->fType & MF_SYSMENU) && IS_STRING_ITEM( lpitem->fType ))
00925 { SIZE size;
00926
00927 GetTextExtentPoint32A(hdc, lpitem->text, strlen(lpitem->text), &size);
00928
00929 lpitem->rect.right += size.cx;
00930 lpitem->rect.bottom += MAX (size.cy, GetSystemMetrics(SM_CYMENU)-1);
00931 lpitem->xTab = 0;
00932
00933 if (menuBar)
00934 {
00935 lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
00936 }
00937 else if ((p = strchr( lpitem->text, '\t' )) != NULL)
00938 {
00939
00940 GetTextExtentPoint32A(hdc, lpitem->text, (int)(p - lpitem->text) , &size);
00941 lpitem->xTab = check_bitmap_width + MENU_TAB_SPACE + size.cx;
00942 lpitem->rect.right += MENU_TAB_SPACE;
00943 }
00944 else
00945 {
00946 if (strchr( lpitem->text, '\b' ))
00947 lpitem->rect.right += MENU_TAB_SPACE;
00948 lpitem->xTab = lpitem->rect.right - check_bitmap_width
00949 - arrow_bitmap_width;
00950 }
00951 }
00952
00953
00954 }
00955
00956
00957
00958
00959
00960
00961
00962 static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner )
00963 {
00964 MENUITEM *lpitem;
00965 HDC hdc;
00966 int start, i;
00967 int orgX, orgY, maxX, maxTab, maxTabWidth;
00968
00969 lppop->Width = lppop->Height = 0;
00970 if (lppop->nItems == 0) return;
00971 #ifdef __WIN32OS2__
00972 hdc = CreateCompatibleDC( 0 );
00973 #else
00974 hdc = GetDC( 0 );
00975 #endif
00976
00977 SelectObject( hdc, hMenuFont);
00978
00979 start = 0;
00980 maxX = 2 ;
00981
00982 while (start < lppop->nItems)
00983 {
00984 lpitem = &lppop->items[start];
00985 orgX = maxX;
00986 orgY = 2;
00987
00988 maxTab = maxTabWidth = 0;
00989
00990
00991 for (i = start; i < lppop->nItems; i++, lpitem++)
00992 {
00993 if ((i != start) &&
00994 (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
00995
00996 MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, FALSE );
00997
00998 if (lpitem->fType & MF_MENUBARBREAK) orgX++;
00999 maxX = MAX( maxX, lpitem->rect.right );
01000 orgY = lpitem->rect.bottom;
01001 if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
01002 {
01003 maxTab = MAX( maxTab, lpitem->xTab );
01004 maxTabWidth = MAX(maxTabWidth,lpitem->rect.right-lpitem->xTab);
01005 }
01006 }
01007
01008
01009 maxX = MAX( maxX, maxTab + maxTabWidth );
01010 for (lpitem = &lppop->items[start]; start < i; start++, lpitem++)
01011 {
01012 lpitem->rect.right = maxX;
01013 if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
01014 lpitem->xTab = maxTab;
01015
01016 }
01017 lppop->Height = MAX( lppop->Height, orgY );
01018 }
01019
01020 lppop->Width = maxX;
01021
01022
01023 lppop->Height += 2;
01024 lppop->Width += 2;
01025
01026 #ifdef __WIN32OS2__
01027 DeleteDC(hdc);
01028 #else
01029 ReleaseDC( 0, hdc );
01030 #endif
01031 }
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043 static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
01044 LPPOPUPMENU lppop, HWND hwndOwner )
01045 {
01046 MENUITEM *lpitem;
01047 int start, i, orgX, orgY, maxY, helpPos;
01048
01049 if ((lprect == NULL) || (lppop == NULL)) return;
01050 if (lppop->nItems == 0) return;
01051
01052
01053 lppop->Width = lprect->right - lprect->left;
01054 lppop->Height = 0;
01055 maxY = lprect->top;
01056 start = 0;
01057 helpPos = -1;
01058 while (start < lppop->nItems)
01059 {
01060 lpitem = &lppop->items[start];
01061 orgX = lprect->left;
01062 orgY = maxY;
01063
01064
01065 for (i = start; i < lppop->nItems; i++, lpitem++)
01066 {
01067 if ((helpPos == -1) && (lpitem->fType & MF_HELP)) helpPos = i;
01068 if ((i != start) &&
01069 (lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
01070
01071
01072
01073
01074 MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, TRUE );
01075
01076 if (lpitem->rect.right > lprect->right)
01077 {
01078 if (i != start) break;
01079 else lpitem->rect.right = lprect->right;
01080 }
01081 maxY = MAX( maxY, lpitem->rect.bottom );
01082 orgX = lpitem->rect.right;
01083 }
01084
01085
01086 while (start < i) lppop->items[start++].rect.bottom = maxY;
01087 }
01088
01089 lprect->bottom = maxY;
01090 lppop->Height = lprect->bottom - lprect->top;
01091
01092
01093
01094 lpitem = &lppop->items[lppop->nItems-1];
01095 orgY = lpitem->rect.top;
01096 orgX = lprect->right;
01097 for (i = lppop->nItems - 1; i >= helpPos; i--, lpitem--)
01098 {
01099 if ( !IS_BITMAP_ITEM(lpitem->fType) && ((helpPos ==-1) ? TRUE : (helpPos>i) ))
01100 break;
01101 if (lpitem->rect.top != orgY) break;
01102 if (lpitem->rect.right >= orgX) break;
01103 lpitem->rect.left += orgX - lpitem->rect.right;
01104 lpitem->rect.right = orgX;
01105 orgX = lpitem->rect.left;
01106 }
01107 }
01108
01109
01110
01111
01112
01113
01114 static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, MENUITEM *lpitem,
01115 UINT height, BOOL menuBar, UINT odaction )
01116 {
01117 RECT rect;
01118
01119
01120
01121 if (lpitem->fType & MF_SYSMENU) return;
01122
01123 if (lpitem->fType & MF_OWNERDRAW)
01124 {
01125 DRAWITEMSTRUCT dis;
01126
01127 dis.CtlType = ODT_MENU;
01128 dis.CtlID = 0;
01129 dis.itemID = lpitem->wID;
01130 dis.itemData = (DWORD)lpitem->dwItemData;
01131 dis.itemState = 0;
01132 if (lpitem->fState & MF_CHECKED) dis.itemState |= ODS_CHECKED;
01133 if (lpitem->fState & MF_GRAYED) dis.itemState |= ODS_GRAYED;
01134 if (lpitem->fState & MF_HILITE) dis.itemState |= ODS_SELECTED;
01135 dis.itemAction = odaction;
01136 dis.hwndItem = hmenu;
01137 dis.hDC = hdc;
01138 dis.rcItem = lpitem->rect;
01139
01140
01141
01142
01143
01144 SendMessageA( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&dis );
01145 return;
01146 }
01147
01148
01149
01150
01151 if (menuBar && (lpitem->fType & MF_SEPARATOR)) return;
01152
01153 rect = lpitem->rect;
01154
01155
01156
01157 if ((lpitem->fState & MF_HILITE) && !(IS_BITMAP_ITEM(lpitem->fType)))
01158 #ifdef __WIN32OS2__
01159 if(fOS2Look)
01160 FillRect( hdc, &rect, GetOS2ColorBrush(PMSYSCLR_MENUHILITEBGND) );
01161 else FillRect( hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT) );
01162 #else
01163 FillRect( hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT) );
01164 #endif
01165 else {
01166
01167
01168 RECT dummy = rect;
01169
01170 FillRect( hdc, &dummy, GetSysColorBrush(COLOR_HIGHLIGHT) );
01171 FillRect( hdc, &rect, GetSysColorBrush(COLOR_MENU) );
01172 }
01173
01174 SetBkMode( hdc, TRANSPARENT );
01175
01176
01177 if (!menuBar && (lpitem->fType & MF_MENUBARBREAK))
01178 {
01179 RECT rc = rect;
01180 rc.top = 3;
01181 rc.bottom = height - 3;
01182 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT);
01183 }
01184
01185
01186 if (lpitem->fType & MF_SEPARATOR)
01187 {
01188 RECT rc = rect;
01189 rc.left++;
01190 rc.right--;
01191 rc.top += SEPARATOR_HEIGHT / 2;
01192 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP);
01193 return;
01194 }
01195
01196
01197
01198 if ((lpitem->fState & MF_HILITE) && !(IS_BITMAP_ITEM(lpitem->fType)) )
01199 {
01200 if (lpitem->fState & MF_GRAYED)
01201 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
01202 #if 1 //CB: WINE's Win98 menubar -> to check
01203
01204 else
01205 SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
01206 #else
01207 else
01208 {
01209 if (menuBar)
01210 SetTextColor(hdc,GetSysColor(COLOR_MENUTEXT));
01211 else
01212 SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
01213 }
01214 #endif
01215 SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
01216 }
01217 else
01218 {
01219 if (lpitem->fState & MF_GRAYED)
01220 SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
01221 else
01222 SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) );
01223 SetBkColor( hdc, GetSysColor( COLOR_MENU ) );
01224 }
01225
01226
01227
01228
01229
01230
01231
01232
01233 if (!menuBar)
01234 {
01235 INT y = rect.top + rect.bottom;
01236
01237
01238
01239
01240
01241
01242
01243 if (lpitem->fState & MF_CHECKED)
01244 {
01245 HBITMAP bm = lpitem->hCheckBit ? lpitem->hCheckBit :
01246 ((lpitem->fType & MFT_RADIOCHECK) ? hStdRadioCheck : hStdCheck);
01247 HDC hdcMem = CreateCompatibleDC( hdc );
01248
01249 SelectObject( hdcMem, bm );
01250 BitBlt( hdc, rect.left, (y - check_bitmap_height) / 2,
01251 check_bitmap_width, check_bitmap_height,
01252 hdcMem, 0, 0, (lpitem->fState & MF_HILITE) ? MERGEPAINT : SRCAND );
01253 DeleteDC( hdcMem );
01254 }
01255 else if (lpitem->hUnCheckBit)
01256 {
01257 HDC hdcMem = CreateCompatibleDC( hdc );
01258
01259 SelectObject( hdcMem, lpitem->hUnCheckBit );
01260 BitBlt( hdc, rect.left, (y - check_bitmap_height) / 2,
01261 check_bitmap_width, check_bitmap_height,
01262 hdcMem, 0, 0, (lpitem->fState & MF_HILITE) ? MERGEPAINT : SRCAND );
01263 DeleteDC( hdcMem );
01264 }
01265
01266
01267 if (lpitem->fType & MF_POPUP)
01268 {
01269 HDC hdcMem = CreateCompatibleDC( hdc );
01270
01271 SelectObject( hdcMem, hStdMnArrow );
01272 BitBlt( hdc, rect.right - arrow_bitmap_width - 1,
01273 (y - arrow_bitmap_height) / 2,
01274 arrow_bitmap_width, arrow_bitmap_height,
01275 hdcMem, 0, 0, (lpitem->fState & MF_HILITE) ? MERGEPAINT : SRCAND );
01276 DeleteDC( hdcMem );
01277 }
01278
01279 rect.left += check_bitmap_width;
01280 rect.right -= arrow_bitmap_width;
01281 }
01282
01283
01284 if (IS_BITMAP_ITEM(lpitem->fType))
01285 { int top;
01286
01287 HBITMAP resBmp = 0;
01288
01289 HDC hdcMem = CreateCompatibleDC( hdc );
01290
01291
01292
01293
01294
01295 if((LOWORD((int)lpitem->text)) < 12)
01296 {
01297 resBmp = MENU_LoadMagicItem((int)lpitem->text, (lpitem->fState & MF_HILITE),
01298 lpitem->dwItemData);
01299 }
01300 else
01301 resBmp = (HBITMAP)lpitem->text;
01302
01303 if (resBmp)
01304 {
01305 BITMAP bm;
01306 GetObjectA( resBmp, sizeof(bm), &bm );
01307
01308 SelectObject(hdcMem,resBmp );
01309
01310
01311 top = ((rect.bottom-rect.top)>bm.bmHeight) ?
01312 rect.top+(rect.bottom-rect.top-bm.bmHeight)/2 : rect.top;
01313
01314 BitBlt( hdc, rect.left, top, rect.right - rect.left,
01315 rect.bottom - rect.top, hdcMem, 0, 0, SRCCOPY );
01316 }
01317 DeleteDC( hdcMem );
01318
01319 return;
01320
01321 }
01322
01323 else if (IS_STRING_ITEM(lpitem->fType))
01324 {
01325 register int i;
01326 HFONT hfontOld = 0;
01327
01328 UINT uFormat = (menuBar) ?
01329 DT_CENTER | DT_VCENTER | DT_SINGLELINE :
01330 DT_LEFT | DT_VCENTER | DT_SINGLELINE;
01331
01332 if ( lpitem->fState & MFS_DEFAULT )
01333 {
01334 hfontOld = SelectObject( hdc, hMenuFontBold);
01335 }
01336
01337 if (menuBar)
01338 {
01339 rect.left += MENU_BAR_ITEMS_SPACE / 2;
01340 rect.right -= MENU_BAR_ITEMS_SPACE / 2;
01341 i = strlen( lpitem->text );
01342 }
01343 else
01344 {
01345 for (i = 0; lpitem->text[i]; i++)
01346 if ((lpitem->text[i] == '\t') || (lpitem->text[i] == '\b'))
01347 break;
01348 }
01349
01350 if(lpitem->fState & MF_GRAYED)
01351 {
01352 if (!(lpitem->fState & MF_HILITE) )
01353 {
01354 ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
01355 SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
01356 DrawTextA( hdc, lpitem->text, i, &rect, uFormat );
01357 --rect.left; --rect.top; --rect.right; --rect.bottom;
01358 }
01359 SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
01360 }
01361
01362 DrawTextA( hdc, lpitem->text, i, &rect, uFormat);
01363
01364
01365 if (lpitem->text[i])
01366 {
01367 if (lpitem->text[i] == '\t')
01368 {
01369 rect.left = lpitem->xTab;
01370 uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
01371 }
01372 else
01373 {
01374 uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
01375 }
01376
01377 if(lpitem->fState & MF_GRAYED)
01378 {
01379 if (!(lpitem->fState & MF_HILITE) )
01380 {
01381 ++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
01382 SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
01383 DrawTextA( hdc, lpitem->text + i + 1, -1, &rect, uFormat );
01384 --rect.left; --rect.top; --rect.right; --rect.bottom;
01385 }
01386 SetTextColor(hdc, RGB(0x80, 0x80, 0x80));
01387 }
01388 DrawTextA( hdc, lpitem->text + i + 1, -1, &rect, uFormat );
01389 }
01390
01391 if (hfontOld)
01392 SelectObject (hdc, hfontOld);
01393 }
01394 }
01395
01396
01397
01398
01399
01400
01401
01402 static void MENU_DrawPopupMenu( HWND hwnd, HDC hdc, HMENU hmenu )
01403 {
01404 HBRUSH hPrevBrush = 0;
01405 RECT rect;
01406
01407
01408
01409 GetClientRect( hwnd, &rect );
01410
01411 if((hPrevBrush = SelectObject( hdc, GetSysColorBrush(COLOR_MENU) ))
01412 && (SelectObject( hdc, hMenuFont)))
01413 {
01414 HPEN hPrevPen;
01415
01416 Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom );
01417
01418 hPrevPen = SelectObject( hdc, GetStockObject( NULL_PEN ) );
01419 if( hPrevPen )
01420 {
01421 INT ropPrev, i;
01422 POPUPMENU *menu;
01423
01424
01425 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
01426
01427
01428
01429 menu = MENU_GetMenu(hmenu);
01430 if (menu && menu->nItems)
01431 {
01432 MENUITEM *item;
01433 UINT u;
01434
01435 for (u = menu->nItems, item = menu->items; u > 0; u--, item++)
01436 MENU_DrawMenuItem( hwnd, hmenu, menu->hwndOwner, hdc, item,
01437 menu->Height, FALSE, ODA_DRAWENTIRE );
01438
01439 }
01440 } else
01441 {
01442 SelectObject( hdc, hPrevBrush );
01443 }
01444 }
01445 }
01446
01447
01448
01449
01450
01451
01452
01453 UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
01454 BOOL suppress_draw)
01455 {
01456 LPPOPUPMENU lppop;
01457 UINT i,retvalue;
01458 HFONT hfontOld = 0;
01459
01460 lppop = MENU_GetMenu(GetMenu(hwnd));
01461 if (lppop == NULL || lprect == NULL)
01462 {
01463 retvalue = GetSystemMetrics(SM_CYMENU);
01464 goto END;
01465 }
01466
01467
01468
01469 hfontOld = SelectObject( hDC, hMenuFont);
01470
01471 if (lppop->Height == 0)
01472 MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
01473
01474 lprect->bottom = lprect->top + lppop->Height;
01475
01476 if (suppress_draw)
01477 {
01478 retvalue = lppop->Height;
01479 goto END;
01480 }
01481
01482 HDC memDC;
01483 HBITMAP memBmp,oldBmp;
01484 RECT r;
01485 HFONT oldMemFont;
01486
01487 memDC = CreateCompatibleDC(hDC);
01488 r = *lprect;
01489 r.right -= r.left;
01490 r.bottom -= r.top;
01491 r.left = r.top = 0;
01492 memBmp = CreateCompatibleBitmap(hDC,r.right,r.bottom+1);
01493 oldBmp = SelectObject(memDC,memBmp);
01494 oldMemFont = SelectObject(memDC,hMenuFont);
01495
01496 FillRect(memDC,&r,GetSysColorBrush(COLOR_MENU));
01497
01498 SelectObject(memDC,GetSysColorPen(COLOR_3DFACE));
01499 MoveToEx(memDC,r.left,r.bottom,NULL);
01500 LineTo(memDC,r.right,r.bottom);
01501
01502 if (lppop->nItems == 0)
01503 {
01504 retvalue = GetSystemMetrics(SM_CYMENU);
01505 } else
01506 {
01507 for (i = 0; i < lppop->nItems; i++)
01508 {
01509 OffsetRect(&lppop->items[i].rect,-lprect->left,-lprect->top);
01510 MENU_DrawMenuItem( hwnd,GetMenu(hwnd), GetWindow(hwnd,GW_OWNER),
01511 memDC, &lppop->items[i], lppop->Height, TRUE, ODA_DRAWENTIRE );
01512 OffsetRect(&lppop->items[i].rect,lprect->left,lprect->top);
01513 }
01514 retvalue = lppop->Height;
01515 }
01516
01517 BitBlt(hDC,lprect->left,lprect->top,lprect->right-lprect->left,lprect->bottom-lprect->top+1,memDC,0,0,SRCCOPY);
01518 SelectObject(memDC,oldBmp);
01519 if (oldMemFont) SelectObject(memDC,oldMemFont);
01520 DeleteObject(memBmp);
01521 DeleteDC(memDC);
01522
01523 END:
01524 if (hfontOld)
01525 SelectObject (hDC, hfontOld);
01526
01527 return retvalue;
01528 }
01529
01530
01531
01532
01533 BOOL MENU_PatchResidentPopup( HQUEUE checkQueue, HWND checkWnd )
01534 {
01535 HWND pTPWnd = MENU_GetTopPopupWnd();
01536 #if 0 //CB: todo
01537 if( pTPWnd )
01538 {
01539 HTASK hTask = 0;
01540
01541
01542
01543
01544
01545 switch( checkQueue )
01546 {
01547 case 0:
01548 if( checkWnd )
01549 {
01550 pTPWnd->owner = checkWnd;
01551 if( pTPWnd->hmemTaskQ != checkWnd->hmemTaskQ )
01552 hTask = QUEUE_GetQueueTask( checkWnd->hmemTaskQ );
01553 }
01554 break;
01555
01556 case 0xFFFF:
01557 if( pTPWnd->owner == checkWnd )
01558 pTPWnd->owner = NULL;
01559 MENU_ReleaseTopPopupWnd();
01560 return TRUE;
01561
01562 default:
01563 if( pTPWnd->hmemTaskQ == checkQueue )
01564 {
01565 hTask = QUEUE_GetQueueTask( pTPWnd->hmemTaskQ );
01566 hTask = TASK_GetNextTask( hTask );
01567 }
01568 break;
01569 }
01570
01571 if( hTask )
01572 {
01573 TDB* task = (TDB*)GlobalLock( hTask );
01574 if( task )
01575 {
01576 pTPWnd->hInstance = task->hInstance;
01577 pTPWnd->hmemTaskQ = task->hQueue;
01578 MENU_ReleaseTopPopupWnd();
01579 return TRUE;
01580 }
01581
01582 }
01583 }
01584 #endif
01585 MENU_ReleaseTopPopupWnd();
01586 return FALSE;
01587 }
01588
01589
01590
01591
01592
01593
01594 static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id,
01595 INT x, INT y, INT xanchor, INT yanchor )
01596 {
01597 POPUPMENU *menu;
01598
01599
01600
01601
01602 if (!(menu = MENU_GetMenu(hmenu))) return FALSE;
01603 if (menu->FocusedItem != NO_SELECTED_ITEM)
01604 {
01605 menu->items[menu->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
01606 menu->FocusedItem = NO_SELECTED_ITEM;
01607 }
01608
01609
01610 menu->hwndOwner = hwndOwner;
01611
01612 if(IsWindow(hwndOwner))
01613 {
01614 UINT width, height;
01615
01616 MENU_PopupMenuCalcSize( menu, hwndOwner );
01617
01618
01619
01620 width = menu->Width + GetSystemMetrics(SM_CXBORDER);
01621 height = menu->Height + GetSystemMetrics(SM_CYBORDER);
01622
01623 if( x + width > GetSystemMetrics(SM_CXSCREEN ))
01624 {
01625 if( xanchor )
01626 x -= width - xanchor;
01627 if( x + width > GetSystemMetrics(SM_CXSCREEN))
01628 x = GetSystemMetrics(SM_CXSCREEN) - width;
01629 }
01630 if( x < 0 ) x = 0;
01631
01632 if( y + height > GetSystemMetrics(SM_CYSCREEN ))
01633 {
01634 if( yanchor )
01635 y -= height + yanchor;
01636 if( y + height > GetSystemMetrics(SM_CYSCREEN ))
01637 y = GetSystemMetrics(SM_CYSCREEN) - height;
01638 }
01639 if( y < 0 ) y = 0;
01640
01641
01642 if (!pTopPopupWnd)
01643 {
01644 assert( uSubPWndLevel == 0 );
01645
01646 pTopPopupWnd = CreateWindowA( POPUPMENUCLASSNAME, NULL,
01647 WS_POPUP, x, y, width, height,
01648 hwndOwner, 0, GetWindowLongA(hwndOwner,GWL_HINSTANCE),
01649 (LPVOID)hmenu );
01650 if (!pTopPopupWnd)
01651 {
01652 DebugInt3();
01653 return FALSE;
01654 }
01655 menu->hWnd = pTopPopupWnd;
01656 MENU_ReleaseTopPopupWnd();
01657 }
01658 else
01659 if( uSubPWndLevel )
01660 {
01661
01662
01663 menu->hWnd = CreateWindowA( POPUPMENUCLASSNAME, NULL,
01664 WS_POPUP, x, y, width, height,
01665 hwndOwner, 0, GetWindowLongA(hwndOwner,GWL_HINSTANCE),
01666 (LPVOID)hmenu );
01667 if( !menu->hWnd )
01668 {
01669 DebugInt3();
01670 return FALSE;
01671 }
01672 }
01673 else
01674 {
01675 HWND pTPWnd = MENU_GetTopPopupWnd();
01676 menu->hWnd = pTPWnd;
01677
01678 MENU_PatchResidentPopup( 0, hwndOwner );
01679 SendMessageA( pTPWnd, MM_SETMENUHANDLE, (WPARAM)hmenu, 0L);
01680
01681
01682
01683 SetWindowPos( menu->hWnd, 0, x, y, width, height,
01684 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW);
01685 MENU_ReleaseTopPopupWnd();
01686 }
01687
01688 uSubPWndLevel++;
01689
01690
01691
01692 SetWindowPos( menu->hWnd, HWND_TOP, 0, 0, 0, 0,
01693 SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
01694 EnableWindow(menu->hWnd,TRUE);
01695 UpdateWindow( menu->hWnd );
01696 return TRUE;
01697 }
01698 return FALSE;
01699 }
01700
01701
01702
01703
01704
01705 static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex,
01706 BOOL sendMenuSelect, HMENU topmenu )
01707 {
01708 LPPOPUPMENU lppop;
01709 HDC hdc;
01710
01711
01712
01713 lppop = MENU_GetMenu(hmenu);
01714 if ((!lppop) || (!lppop->nItems)) return;
01715
01716 if (lppop->FocusedItem == wIndex) return;
01717 if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
01718 else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
01719
01720 SelectObject( hdc, hMenuFont);
01721
01722
01723 if (lppop->FocusedItem != NO_SELECTED_ITEM)
01724 {
01725 lppop->items[lppop->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
01726 MENU_DrawMenuItem(lppop->hWnd, hmenu, hwndOwner, hdc,&lppop->items[lppop->FocusedItem],
01727 lppop->Height, !(lppop->wFlags & MF_POPUP),
01728 ODA_SELECT );
01729 }
01730
01731
01732 lppop->FocusedItem = wIndex;
01733 if (lppop->FocusedItem != NO_SELECTED_ITEM)
01734 {
01735 if(!(lppop->items[wIndex].fType & MF_SEPARATOR)) {
01736 lppop->items[wIndex].fState |= MF_HILITE;
01737 MENU_DrawMenuItem( lppop->hWnd, hmenu, hwndOwner, hdc,
01738 &lppop->items[wIndex], lppop->Height,
01739 !(lppop->wFlags & MF_POPUP), ODA_SELECT );
01740 }
01741 if (sendMenuSelect)
01742 {
01743 MENUITEM *ip = &lppop->items[lppop->FocusedItem];
01744 SendMessageA( hwndOwner, WM_MENUSELECT,
01745 MAKELONG(ip->fType & MF_POPUP ? wIndex: ip->wID,
01746 ip->fType | ip->fState | MF_MOUSESELECT |
01747 (lppop->wFlags & MF_SYSMENU)), hmenu);
01748 }
01749 }
01750 else if (sendMenuSelect) {
01751 if(topmenu){
01752 int pos;
01753 if((pos=MENU_FindSubMenu(&topmenu, hmenu))!=NO_SELECTED_ITEM){
01754 #ifdef __WIN32OS2__
01755 POPUPMENU *ptm = MENU_GetMenu(topmenu);
01756 #else
01757 POPUPMENU *ptm = (POPUPMENU*)topmenu;
01758 #endif
01759 MENUITEM *ip = &ptm->items[pos];
01760 SendMessageA( hwndOwner, WM_MENUSELECT, MAKELONG(pos,
01761 ip->fType | ip->fState | MF_MOUSESELECT |
01762 (ptm->wFlags & MF_SYSMENU)), topmenu);
01763 }
01764 }
01765 }
01766 ReleaseDC( lppop->hWnd, hdc );
01767 }
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777 static void MENU_MoveSelection( HWND hwndOwner, HMENU hmenu, INT offset )
01778 {
01779 INT i;
01780 POPUPMENU *menu;
01781
01782
01783
01784 menu = MENU_GetMenu(hmenu);
01785 if ((!menu) || (!menu->items)) return;
01786
01787 if ( menu->FocusedItem != NO_SELECTED_ITEM )
01788 {
01789 if( menu->nItems == 1 ) return; else
01790 for (i = menu->FocusedItem + offset ; i >= 0 && i < menu->nItems
01791 ; i += offset)
01792 if (!(menu->items[i].fType & MF_SEPARATOR))
01793 {
01794 MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 );
01795 return;
01796 }
01797 }
01798
01799 for ( i = (offset > 0) ? 0 : menu->nItems - 1;
01800 i >= 0 && i < menu->nItems ; i += offset)
01801 if (!(menu->items[i].fType & MF_SEPARATOR))
01802 {
01803 MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 );
01804 return;
01805 }
01806 }
01807
01808
01809
01810
01811
01812
01813
01814
01815 static BOOL MENU_SetItemData( MENUITEM *item, UINT flags, UINT id,
01816 LPCSTR str )
01817 {
01818 LPSTR prevText = IS_STRING_ITEM(item->fType) ? item->text : NULL;
01819
01820
01821
01822
01823 if (IS_STRING_ITEM(flags))
01824 {
01825 if (!str || !*str)
01826 {
01827 flags |= MF_SEPARATOR;
01828 item->text = NULL;
01829 }
01830 else
01831 {
01832 LPSTR text;
01833
01834 if (*str == '\b')
01835 {
01836 flags |= MF_HELP;
01837 str++;
01838 }
01839 if (!(text = HEAP_strdupA(GetProcessHeap(), 0, str ))) return FALSE;
01840 item->text = text;
01841 }
01842 }
01843 else if (IS_BITMAP_ITEM(flags))
01844 #ifdef __WIN32OS2__
01845
01846 item->text = (LPSTR)str;
01847 #else
01848 item->text = (LPSTR)(HBITMAP)LOWORD(str);
01849 #endif
01850 else item->text = NULL;
01851
01852 if (flags & MF_OWNERDRAW)
01853 item->dwItemData = (DWORD)str;
01854 else
01855 item->dwItemData = 0;
01856
01857 if ((item->fType & MF_POPUP) && (flags & MF_POPUP) && (item->hSubMenu != id) )
01858 DestroyMenu( item->hSubMenu );
01859
01860 if (flags & MF_POPUP)
01861 {
01862 POPUPMENU *menu = MENU_GetMenu((UINT)id);
01863 if (IS_A_MENU(menu)) menu->wFlags |= MF_POPUP;
01864 else
01865 {
01866 item->wID = 0;
01867 item->hSubMenu = 0;
01868 item->fType = 0;
01869 item->fState = 0;
01870 return FALSE;
01871 }
01872 }
01873
01874 item->wID = id;
01875 if (flags & MF_POPUP)
01876 item->hSubMenu = id;
01877
01878 if ((item->fType & MF_POPUP) && !(flags & MF_POPUP) )
01879 flags |= MF_POPUP;
01880
01881 item->fType = flags & TYPE_MASK;
01882 item->fState = (flags & STATE_MASK) &
01883 ~(MF_HILITE | MF_MOUSESELECT | MF_BYPOSITION);
01884
01885
01886
01887
01888
01889 if (prevText) HeapFree(GetProcessHeap(), 0, prevText );
01890
01891
01892 return TRUE;
01893 }
01894
01895
01896
01897
01898
01899
01900
01901 static MENUITEM *MENU_InsertItem( HMENU hMenu, UINT pos, UINT flags )
01902 {
01903 MENUITEM *newItems;
01904 POPUPMENU *menu;
01905
01906 if (!(menu = MENU_GetMenu(hMenu)))
01907 return NULL;
01908
01909
01910 if (flags & MF_BYPOSITION) {
01911 if (pos > menu->nItems)
01912 pos = menu->nItems;
01913 } else {
01914 if (!MENU_FindItem( &hMenu, &pos, flags ))
01915 pos = menu->nItems;
01916 else {
01917 if (!(menu = MENU_GetMenu( hMenu )))
01918 return NULL;
01919 }
01920 }
01921
01922
01923 newItems = (MENUITEM*)HeapAlloc(GetProcessHeap(), 0, sizeof(MENUITEM) * (menu->nItems+1) );
01924 if (!newItems)
01925 {
01926
01927 return NULL;
01928 }
01929 if (menu->nItems > 0)
01930 {
01931
01932 if (pos > 0) memcpy( newItems, menu->items, pos * sizeof(MENUITEM) );
01933 if (pos < menu->nItems) memcpy( &newItems[pos+1], &menu->items[pos],
01934 (menu->nItems-pos)*sizeof(MENUITEM) );
01935 HeapFree(GetProcessHeap(), 0, menu->items );
01936 }
01937 menu->items = newItems;
01938 menu->nItems++;
01939 memset( &newItems[pos], 0, sizeof(*newItems) );
01940 menu->Height = 0;
01941 return &newItems[pos];
01942 }
01943
01944
01945
01946
01947
01948
01949
01950
01951 static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
01952 {
01953 WORD flags, id = 0;
01954 LPCSTR str;
01955
01956 do
01957 {
01958 flags = GET_WORD(res);
01959 res += sizeof(WORD);
01960 if (!(flags & MF_POPUP))
01961 {
01962 id = GET_WORD(res);
01963 res += sizeof(WORD);
01964 }
01965
01966
01967 str = res;
01968 if (!unicode) res += strlen(str) + 1;
01969 else res += (lstrlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
01970 if (flags & MF_POPUP)
01971 {
01972 HMENU hSubMenu = CreatePopupMenu();
01973 if (!hSubMenu) return NULL;
01974 if (!(res = MENU_ParseResource( res, hSubMenu, unicode )))
01975 return NULL;
01976 if (!unicode) AppendMenuA( hMenu, flags, (UINT)hSubMenu, str );
01977 else AppendMenuW( hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str );
01978 }
01979 else
01980 {
01981 if (!unicode) AppendMenuA( hMenu, flags, id, *str ? str : NULL );
01982 else AppendMenuW( hMenu, flags, id,
01983 *(LPCWSTR)str ? (LPCWSTR)str : NULL );
01984 }
01985 } while (!(flags & MF_END));
01986 return res;
01987 }
01988
01989
01990
01991
01992
01993
01994
01995
01996 static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU hMenu)
01997 {
01998 WORD resinfo;
01999 do {
02000 MENUITEMINFOW mii;
02001
02002 mii.cbSize = sizeof(mii);
02003 mii.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE;
02004 mii.fType = GET_DWORD(res);
02005 res += sizeof(DWORD);
02006 mii.fState = GET_DWORD(res);
02007 res += sizeof(DWORD);
02008 mii.wID = GET_DWORD(res);
02009 res += sizeof(DWORD);
02010 resinfo = GET_WORD(res);
02011 res += sizeof(WORD);
02012
02013 res += (~((int)res - 1)) & 1;
02014 mii.dwTypeData = (LPWSTR) res;
02015 res += (1 + lstrlenW(mii.dwTypeData)) * sizeof(WCHAR);
02016
02017 res += (~((int)res - 1)) & 3;
02018
02019
02020 {
02021 LPSTR newstr = HEAP_strdupWtoA(GetProcessHeap(),
02022 0, mii.dwTypeData);
02023
02024
02025 HeapFree( GetProcessHeap(), 0, newstr );
02026 }
02027
02028 if (resinfo & 1) {
02029
02030 res += sizeof(DWORD);
02031 mii.hSubMenu = CreatePopupMenu();
02032 if (!mii.hSubMenu)
02033 return NULL;
02034 if (!(res = MENUEX_ParseResource(res, mii.hSubMenu))) {
02035 DestroyMenu(mii.hSubMenu);
02036 return NULL;
02037 }
02038 mii.fMask |= MIIM_SUBMENU;
02039 mii.fType |= MF_POPUP;
02040 }
02041 InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii);
02042 } while (!(resinfo & MF_END));
02043 return res;
02044 }
02045
02046
02047
02048
02049
02050
02051
02052 static HMENU MENU_GetSubPopup( HMENU hmenu )
02053 {
02054 POPUPMENU *menu;
02055 MENUITEM *item;
02056
02057 menu = MENU_GetMenu(hmenu);
02058
02059 if ((!menu) || (menu->FocusedItem == NO_SELECTED_ITEM)) return 0;
02060
02061 item = &menu->items[menu->FocusedItem];
02062 if ((item->fType & MF_POPUP) && (item->fState & MF_MOUSESELECT))
02063 return item->hSubMenu;
02064 return 0;
02065 }
02066
02067
02068
02069
02070
02071
02072
02073 static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu,
02074 BOOL sendMenuSelect )
02075 {
02076 POPUPMENU *menu = MENU_GetMenu(hmenu);
02077
02078
02079
02080 if (menu && uSubPWndLevel)
02081 {
02082 HMENU hsubmenu;
02083 POPUPMENU *submenu;
02084 MENUITEM *item;
02085
02086 if (menu->FocusedItem != NO_SELECTED_ITEM)
02087 {
02088 item = &menu->items[menu->FocusedItem];
02089 if (!(item->fType & MF_POPUP) ||
02090 !(item->fState & MF_MOUSESELECT)) return;
02091 item->fState &= ~MF_MOUSESELECT;
02092 hsubmenu = item->hSubMenu;
02093 } else return;
02094
02095 submenu = MENU_GetMenu(hsubmenu);
02096 MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE );
02097 MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 );
02098
02099 if (submenu->hWnd == MENU_GetTopPopupWnd() )
02100 {
02101 DestroyWindow( submenu->hWnd );
02102 submenu->hWnd = 0;
02103
02104 uSubPWndLevel = 0;
02105 }
02106 else
02107 {
02108 DestroyWindow( submenu->hWnd );
02109 submenu->hWnd = 0;
02110 }
02111 MENU_ReleaseTopPopupWnd();
02112 }
02113 }
02114
02115
02116
02117
02118
02119
02120
02121
02122 static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu,
02123 BOOL selectFirst, UINT wFlags,POINT *pt)
02124 {
02125 RECT rect;
02126 POPUPMENU *menu;
02127 MENUITEM *item;
02128 HDC hdc;
02129
02130
02131
02132 if (!(menu = MENU_GetMenu(hmenu))) return hmenu;
02133
02134 if (menu->FocusedItem == NO_SELECTED_ITEM)
02135 {
02136 return hmenu;
02137 }
02138
02139 item = &menu->items[menu->FocusedItem];
02140 if (!(item->fType & MF_POPUP) ||
02141 (item->fState & (MF_GRAYED | MF_DISABLED)))
02142 {
02143 return hmenu;
02144 }
02145
02146
02147
02148
02149
02150 if (!(wFlags & TPM_NONOTIFY))
02151 SendMessageA( hwndOwner, WM_INITMENUPOPUP, item->hSubMenu,
02152 MAKELONG( menu->FocusedItem, IS_SYSTEM_MENU(menu) ));
02153
02154 item = &menu->items[menu->FocusedItem];
02155 rect = item->rect;
02156
02157
02158 if (!(item->fState & MF_HILITE))
02159 {
02160 if (menu->wFlags & MF_POPUP) hdc = GetDC( menu->hWnd );
02161 else hdc = GetDCEx( menu->hWnd, 0, DCX_CACHE | DCX_WINDOW);
02162
02163 SelectObject( hdc, hMenuFont);
02164
02165 item->fState |= MF_HILITE;
02166 MENU_DrawMenuItem( menu->hWnd, hmenu, hwndOwner, hdc, item, menu->Height, !(menu->wFlags & MF_POPUP), ODA_DRAWENTIRE );
02167 ReleaseDC( menu->hWnd, hdc );
02168 }
02169 if (!item->rect.top && !item->rect.left && !item->rect.bottom && !item->rect.right)
02170 item->rect = rect;
02171
02172 item->fState |= MF_MOUSESELECT;
02173
02174 if (IS_SYSTEM_MENU(menu))
02175 {
02176 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(menu->hWnd);
02177
02178 MENU_InitSysMenuPopup(item->hSubMenu,GetWindowLongA(menu->hWnd,GWL_STYLE), GetClassLongA(menu->hWnd, GCL_STYLE));
02179
02180 if ((wFlags & TPM_CAPTIONSYSMENU) && pt)
02181 {
02182 rect.top = pt->y;
02183 rect.left = pt->x;
02184 rect.bottom = rect.right = 0;
02185 } else
02186 {
02187 if (win32wnd) win32wnd->GetSysPopupPos(&rect);
02188 rect.top = rect.bottom;
02189 rect.right = GetSystemMetrics(SM_CXSIZE);
02190 rect.bottom = GetSystemMetrics(SM_CYSIZE);
02191 }
02192 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
02193 }
02194 else
02195 {
02196 if (menu->wFlags & MF_POPUP)
02197 {
02198 RECT rectWindow;
02199
02200 GetWindowRect(menu->hWnd,&rectWindow);
02201 rect.left = rectWindow.left + item->rect.right;
02202 rect.top = rectWindow.top + item->rect.top;
02203 rect.right = item->rect.left - item->rect.right;
02204 rect.bottom = item->rect.top - item->rect.bottom;
02205 }
02206 else
02207 {
02208 RECT rectWindow;
02209
02210 GetWindowRect(menu->hWnd,&rectWindow);
02211 rect.left = rectWindow.left + item->rect.left;
02212 rect.top = rectWindow.top + item->rect.bottom;
02213 rect.right = item->rect.right - item->rect.left;
02214 rect.bottom = item->rect.bottom - item->rect.top;
02215 }
02216 }
02217
02218 MENU_ShowPopup( hwndOwner, item->hSubMenu, menu->FocusedItem,
02219 rect.left, rect.top, rect.right, rect.bottom );
02220 if (selectFirst)
02221 MENU_MoveSelection( hwndOwner, item->hSubMenu, ITEM_NEXT );
02222 return item->hSubMenu;
02223 }
02224
02225
02226
02227
02228
02229
02230 static HMENU MENU_PtMenu(HMENU hMenu,POINT pt,BOOL inMenuBar)
02231 {
02232 POPUPMENU *menu = MENU_GetMenu(hMenu);
02233 register UINT ht = menu->FocusedItem;
02234
02235
02236 ht = (ht != NO_SELECTED_ITEM &&
02237 (menu->items[ht].fType & MF_POPUP) &&
02238 (menu->items[ht].fState & MF_MOUSESELECT))
02239 ? (UINT) MENU_PtMenu(menu->items[ht].hSubMenu,pt,inMenuBar) : 0;
02240
02241 if( !ht )
02242 {
02243 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(menu->hWnd);
02244 if(win32wnd==NULL) {
02245
02246
02247 return (HMENU)0;
02248 }
02249
02250 ht = win32wnd->HandleNCHitTest(pt);
02251 RELEASE_WNDOBJ(win32wnd);
02252 if( menu->wFlags & MF_POPUP )
02253 ht = (ht != (UINT)HTNOWHERE &&
02254 ht != (UINT)HTERROR) ? (UINT)hMenu : 0;
02255 else
02256 {
02257 ht = ((ht == HTSYSMENU) && !inMenuBar) ? (UINT)(getSysMenu(menu->hWnd))
02258 : ((ht == HTMENU) && inMenuBar) ? (UINT)(GetMenu(menu->hWnd)) : 0;
02259 }
02260 }
02261 return (HMENU)ht;
02262 }
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274 static INT MENU_ExecFocusedItem( MTRACKER* pmt, HMENU hMenu, UINT wFlags )
02275 {
02276 MENUITEM *item;
02277 POPUPMENU *menu = MENU_GetMenu(hMenu);
02278
02279
02280
02281 if (!menu || !menu->nItems ||
02282 (menu->FocusedItem == NO_SELECTED_ITEM)) return -1;
02283
02284 item = &menu->items[menu->FocusedItem];
02285
02286
02287
02288
02289 if (!(item->fType & MF_POPUP))
02290 {
02291 if (!(item->fState & (MF_GRAYED | MF_DISABLED)))
02292 {
02293
02294
02295 if(!(wFlags & TPM_RETURNCMD))
02296 {
02297 if( menu->wFlags & MF_SYSMENU )
02298 PostMessageA( pmt->hOwnerWnd, WM_SYSCOMMAND, item->wID,
02299 MAKELPARAM(pmt->pt.x, pmt->pt.y) );
02300 else
02301 PostMessageA( pmt->hOwnerWnd, WM_COMMAND, item->wID, 0 );
02302 }
02303 return item->wID;
02304 }
02305 }
02306 else
02307 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hMenu, TRUE, wFlags,&pmt->pt);
02308
02309 return -1;
02310 }
02311
02312
02313
02314
02315
02316
02317 static void MENU_SwitchTracking( MTRACKER* pmt, HMENU hPtMenu, UINT id )
02318 {
02319 POPUPMENU *ptmenu = MENU_GetMenu(hPtMenu);
02320 POPUPMENU *topmenu = MENU_GetMenu(pmt->hTopMenu);
02321
02322
02323
02324 if( pmt->hTopMenu != hPtMenu &&
02325 !((ptmenu->wFlags | topmenu->wFlags) & MF_POPUP) )
02326 {
02327
02328 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
02329 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE, 0 );
02330 pmt->hTopMenu = hPtMenu;
02331 }
02332 else MENU_HideSubPopups( pmt->hOwnerWnd, hPtMenu, FALSE );
02333 MENU_SelectItem( pmt->hOwnerWnd, hPtMenu, id, TRUE, 0 );
02334 }
02335
02336
02337
02338
02339
02340
02341
02342 static BOOL MENU_ButtonDown( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
02343 {
02344
02345
02346 if (hPtMenu)
02347 {
02348 UINT id = 0;
02349 POPUPMENU *ptmenu = MENU_GetMenu(hPtMenu);
02350 MENUITEM *item;
02351
02352 if( IS_SYSTEM_MENU(ptmenu) )
02353 item = ptmenu->items;
02354 else
02355 item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
02356
02357 if( item )
02358 {
02359 if( ptmenu->FocusedItem != id )
02360 MENU_SwitchTracking( pmt, hPtMenu, id );
02361
02362
02363 if(!(item->fState & MF_MOUSESELECT ))
02364 {
02365 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd,hPtMenu,FALSE,wFlags,&pmt->pt);
02366
02367 #ifdef __WIN32OS2__
02368 if(fOS2Look)
02369 ptmenu->bTimeToHide = FALSE;
02370 #else
02371
02372 if(TWEAK_WineLook == WIN31_LOOK)
02373 ptmenu->bTimeToHide = FALSE;
02374 #endif
02375 }
02376
02377 return TRUE;
02378 }
02379
02380 }
02381 return FALSE;
02382 }
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392 static INT MENU_ButtonUp( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags)
02393 {
02394
02395
02396 if (hPtMenu)
02397 {
02398 UINT id = 0;
02399 POPUPMENU *ptmenu = MENU_GetMenu(hPtMenu);
02400 MENUITEM *item;
02401
02402 if( IS_SYSTEM_MENU(ptmenu) )
02403 item = ptmenu->items;
02404 else
02405 item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
02406
02407 if( item && (ptmenu->FocusedItem == id ))
02408 {
02409 if( !(item->fType & MF_POPUP) )
02410 return MENU_ExecFocusedItem( pmt, hPtMenu, wFlags);
02411
02412
02413
02414
02415 if((pmt->hTopMenu == hPtMenu) && (ptmenu->bTimeToHide == TRUE))
02416 return 0;
02417 }
02418 ptmenu->bTimeToHide = TRUE;
02419 }
02420 return -1;
02421 }
02422
02423
02424
02425
02426
02427
02428
02429 static BOOL MENU_MouseMove( MTRACKER* pmt, HMENU hPtMenu, UINT wFlags )
02430 {
02431 UINT id = NO_SELECTED_ITEM;
02432 POPUPMENU *ptmenu = NULL;
02433
02434 if( hPtMenu )
02435 {
02436 ptmenu = MENU_GetMenu(hPtMenu);
02437 if( IS_SYSTEM_MENU(ptmenu) )
02438 id = 0;
02439 else
02440 MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
02441 }
02442
02443 if( id == NO_SELECTED_ITEM )
02444 {
02445 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
02446 NO_SELECTED_ITEM, TRUE, pmt->hTopMenu);
02447
02448 }
02449 else if( ptmenu->FocusedItem != id )
02450 {
02451 POPUPMENU *menu;
02452 MENUITEM *item;
02453
02454 MENU_SwitchTracking( pmt, hPtMenu, id );
02455
02456
02457
02458
02459
02460
02461
02462 if (!(menu = (POPUPMENU *)MENU_GetMenu( hPtMenu )))
02463 {
02464 pmt->hCurrentMenu = hPtMenu;
02465 return TRUE;
02466 }
02467
02468 if (!IsWindow( menu->hWnd ) ||
02469 (menu->FocusedItem == NO_SELECTED_ITEM))
02470 {
02471 pmt->hCurrentMenu = hPtMenu;
02472 return TRUE;
02473 }
02474
02475 item = &menu->items[menu->FocusedItem];
02476 if (!(item->fType & MF_POPUP) ||
02477 (item->fState & (MF_GRAYED | MF_DISABLED)))
02478 {
02479 pmt->hCurrentMenu = hPtMenu;
02480 return TRUE;
02481 }
02482
02483
02484
02485
02486 if (uSubPWndLevel)
02487 {
02488
02489
02490
02491
02492
02493
02494
02495 KillTimer (pmt->hOwnerWnd, SUBMENU_POPUP_TIMERID);
02496 if ( (SetTimer (pmt->hOwnerWnd, SUBMENU_POPUP_TIMERID, POPUP_MENU_DELAY, NULL)) != SUBMENU_POPUP_TIMERID)
02497 {
02498
02499
02500
02501
02502 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd,hPtMenu,FALSE,wFlags,&pmt->pt);
02503 return TRUE;
02504 }
02505 } else
02506 {
02507
02508
02509 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hPtMenu, FALSE, wFlags,&pmt->pt);
02510 return TRUE;
02511 }
02512
02513 mouseOverMenuID = id;
02514 isTimerSet = TRUE;
02515 }
02516 return TRUE;
02517 }
02518
02519
02520
02521
02522
02523
02524
02525 static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk )
02526 {
02527 POPUPMENU *menu = MENU_GetMenu(pmt->hTopMenu);
02528
02529 if( (vk == VK_LEFT && menu->FocusedItem == 0 ) ||
02530 (vk == VK_RIGHT && menu->FocusedItem == menu->nItems - 1))
02531 {
02532 MDINEXTMENU next_menu;
02533 HMENU hNewMenu;
02534 HWND hNewWnd;
02535 UINT id = 0;
02536
02537 next_menu.hmenuIn = (IS_SYSTEM_MENU(menu)) ? GetSubMenu(pmt->hTopMenu,0) : pmt->hTopMenu;
02538 next_menu.hmenuNext = 0;
02539 next_menu.hwndNext = 0;
02540
02541 SendMessageW( pmt->hOwnerWnd, WM_NEXTMENU, vk, (LPARAM)&next_menu );
02542
02543 dprintf(("%04x [%04x] -> %04x [%04x]\n",
02544 pmt->hCurrentMenu, pmt->hOwnerWnd, next_menu.hmenuNext, next_menu.hwndNext ));
02545
02546 if (!next_menu.hmenuNext || !next_menu.hwndNext)
02547 {
02548 hNewWnd = pmt->hOwnerWnd;
02549 if( IS_SYSTEM_MENU(menu) )
02550 {
02551
02552
02553 if( (GetWindowLongA(pmt->hOwnerWnd,GWL_STYLE) & WS_CHILD) || !GetMenu(pmt->hOwnerWnd) )
02554 {
02555 return FALSE;
02556 }
02557
02558 hNewMenu = GetMenu(pmt->hOwnerWnd);
02559 if( vk == VK_LEFT )
02560 {
02561 menu = MENU_GetMenu(hNewMenu);
02562 id = menu->nItems - 1;
02563 }
02564 }
02565 else if( GetWindowLongA(pmt->hOwnerWnd,GWL_STYLE) & WS_SYSMENU )
02566 {
02567
02568 hNewMenu = getSysMenu(pmt->hOwnerWnd);
02569 }
02570 else
02571 {
02572 return FALSE;
02573 }
02574 }
02575 else
02576 {
02577 hNewMenu = next_menu.hmenuNext;
02578 hNewWnd = next_menu.hwndNext;
02579
02580 if( IsMenu(hNewMenu) && IsWindow(hNewWnd) )
02581 {
02582 if( (GetWindowLongA(hNewWnd,GWL_STYLE) & WS_SYSMENU) &&
02583 GetSubMenu(getSysMenu(hNewWnd), 0) == hNewMenu )
02584 {
02585
02586 hNewMenu = getSysMenu(hNewWnd);
02587 }
02588 else if( (GetWindowLongA(hNewWnd,GWL_STYLE) & WS_CHILD) || (GetMenu(hNewWnd) != hNewMenu) )
02589 {
02590
02591
02592
02593
02594 return FALSE;
02595 }
02596 }
02597 else return FALSE;
02598 }
02599
02600 if( hNewMenu != pmt->hTopMenu )
02601 {
02602 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM,
02603 FALSE, 0 );
02604 if( pmt->hCurrentMenu != pmt->hTopMenu )
02605 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
02606 }
02607
02608 if( hNewWnd != pmt->hOwnerWnd )
02609 {
02610 ReleaseCapture();
02611 pmt->hOwnerWnd = hNewWnd;
02612 SetCapture(pmt->hOwnerWnd);
02613
02614 }
02615
02616 pmt->hTopMenu = pmt->hCurrentMenu = hNewMenu;
02617 MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, id, TRUE, 0 );
02618
02619 return TRUE;
02620 }
02621 return FALSE;
02622 }
02623
02624
02625
02626
02627
02628
02629
02630 static BOOL MENU_SuspendPopup( MTRACKER* pmt, UINT uMsg )
02631 {
02632 MSG msg;
02633
02634 msg.hwnd = pmt->hOwnerWnd;
02635
02636 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
02637 pmt->trackFlags |= TF_SKIPREMOVE;
02638
02639 switch( uMsg )
02640 {
02641 case WM_KEYDOWN:
02642 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
02643 if( msg.message == WM_KEYUP || msg.message == WM_PAINT )
02644 {
02645 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
02646 PeekMessageA( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
02647 if( msg.message == WM_KEYDOWN &&
02648 (msg.wParam == VK_LEFT || msg.wParam == VK_RIGHT))
02649 {
02650 pmt->trackFlags |= TF_SUSPENDPOPUP;
02651 return TRUE;
02652 }
02653 }
02654 break;
02655 }
02656
02657
02658 pmt->trackFlags &= ~TF_SUSPENDPOPUP;
02659 return FALSE;
02660 }
02661
02662
02663
02664
02665
02666
02667 static void MENU_KeyLeft( MTRACKER* pmt, UINT wFlags )
02668 {
02669 POPUPMENU *menu;
02670 HMENU hmenutmp, hmenuprev;
02671 UINT prevcol;
02672
02673 hmenuprev = hmenutmp = pmt->hTopMenu;
02674 menu = MENU_GetMenu(hmenutmp);
02675
02676
02677 if( (prevcol = MENU_GetStartOfPrevColumn( pmt->hCurrentMenu )) !=
02678 NO_SELECTED_ITEM ) {
02679
02680 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
02681 prevcol, TRUE, 0 );
02682 return;
02683 }
02684
02685
02686 while (hmenutmp != pmt->hCurrentMenu)
02687 {
02688 hmenuprev = hmenutmp;
02689 hmenutmp = MENU_GetSubPopup( hmenuprev );
02690 }
02691
02692 MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE );
02693 pmt->hCurrentMenu = hmenuprev;
02694
02695 if ( (hmenuprev == pmt->hTopMenu) && !(menu->wFlags & MF_POPUP) )
02696 {
02697
02698
02699 if( !MENU_DoNextMenu( pmt, VK_LEFT) )
02700 MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_PREV );
02701
02702 if ( hmenuprev != hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP )
02703 {
02704
02705
02706
02707 if( !MENU_SuspendPopup( pmt, WM_KEYDOWN ) )
02708 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd,
02709 pmt->hTopMenu, TRUE, wFlags,&pmt->pt);
02710 }
02711 }
02712 }
02713
02714
02715
02716
02717
02718
02719
02720 static void MENU_KeyRight( MTRACKER* pmt, UINT wFlags )
02721 {
02722 HMENU hmenutmp;
02723 POPUPMENU *menu = MENU_GetMenu(pmt->hTopMenu);
02724 UINT nextcol;
02725
02726
02727
02728
02729
02730
02731
02732 if ( (menu->wFlags & MF_POPUP) || (pmt->hCurrentMenu != pmt->hTopMenu))
02733 {
02734
02735
02736 hmenutmp = pmt->hCurrentMenu;
02737 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hmenutmp, TRUE, wFlags,&pmt->pt);
02738
02739
02740 if (hmenutmp != pmt->hCurrentMenu) return;
02741 }
02742
02743
02744 if( (nextcol = MENU_GetStartOfNextColumn( pmt->hCurrentMenu )) !=
02745 NO_SELECTED_ITEM ) {
02746
02747 MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu,
02748 nextcol, TRUE, 0 );
02749 return;
02750 }
02751
02752 if (!(menu->wFlags & MF_POPUP))
02753 {
02754 if( pmt->hCurrentMenu != pmt->hTopMenu )
02755 {
02756 MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE );
02757 hmenutmp = pmt->hCurrentMenu = pmt->hTopMenu;
02758 } else hmenutmp = 0;
02759
02760
02761 if( !MENU_DoNextMenu( pmt, VK_RIGHT) )
02762 MENU_MoveSelection( pmt->hOwnerWnd, pmt->hTopMenu, ITEM_NEXT );
02763
02764 if( hmenutmp || pmt->trackFlags & TF_SUSPENDPOPUP )
02765 if( !MENU_SuspendPopup(pmt, WM_KEYDOWN) )
02766 pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd,
02767 pmt->hTopMenu, TRUE, wFlags,&pmt->pt);
02768 }
02769 }
02770
02771 VOID MENU_DispatchMouseMsg(MSG *msg)
02772 {
02773 LONG hittest;
02774
02775 hittest = SendMessageA(msg->hwnd,WM_NCHITTEST,0,MAKELONG(msg->pt.x,msg->pt.y));
02776 if (hittest != HTCLIENT)
02777 SendMessageA(msg->hwnd,msg->message+WM_NCMOUSEMOVE-WM_MOUSEMOVE,hittest,MAKELONG(msg->pt.x,msg->pt.y));
02778 else
02779 DispatchMessageA(msg);
02780 }
02781
02782
02783
02784
02785
02786
02787 static INT MENU_TrackMenu(HMENU hmenu,UINT wFlags,INT x,INT y,HWND hwnd,BOOL inMenuBar,const RECT *lprect)
02788 {
02789 MSG msg;
02790 POPUPMENU *menu;
02791 BOOL fRemove;
02792 INT executedMenuId = -1;
02793 MTRACKER mt;
02794 BOOL enterIdleSent = FALSE;
02795 BOOL bSysMenu;
02796
02797 mt.trackFlags = 0;
02798 mt.hCurrentMenu = hmenu;
02799 mt.hTopMenu = hmenu;
02800 mt.hOwnerWnd = hwnd;
02801 mt.pt.x = x;
02802 mt.pt.y = y;
02803
02804
02805
02806
02807
02808 fEndMenu = FALSE;
02809 if (!(menu = MENU_GetMenu(hmenu))) return FALSE;
02810
02811 bSysMenu = IS_SYSTEM_MENU(menu);
02812
02813 if (wFlags & TPM_BUTTONDOWN)
02814 {
02815
02816 fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
02817 fEndMenu = !fRemove;
02818 }
02819
02820 #ifdef __WIN32OS2__
02821
02822 SetCapture(mt.hOwnerWnd);
02823
02824
02825 SetMenuDoubleClick(TRUE);
02826 #else
02827 EVENT_Capture( mt.hOwnerWnd, HTMENU );
02828 #endif
02829
02830 while (!fEndMenu)
02831 {
02832 menu = MENU_GetMenu(mt.hCurrentMenu);
02833 msg.hwnd = (wFlags & TPM_ENTERIDLEEX && menu->wFlags & MF_POPUP) ? menu->hWnd : 0;
02834
02835
02836
02837 #ifdef __WIN32OS2__
02838
02839 if (!GetMessageA(&msg,0,0,0)) break;
02840 #else
02841 if (!GetMessageA(&msg,msg.hwnd,0,0)) break;
02842 #endif
02843 TranslateMessage( &msg );
02844 mt.pt = msg.pt;
02845
02846 if ( (msg.hwnd==menu->hWnd) || (msg.message!=WM_TIMER) )
02847 enterIdleSent=FALSE;
02848
02849 fRemove = FALSE;
02850 if((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
02851 {
02852
02853 POINT pt = msg.pt;
02854
02855 hmenu = MENU_PtMenu(mt.hTopMenu,pt,inMenuBar);
02856
02857
02858
02859 switch(msg.message)
02860 {
02861
02862
02863 case WM_RBUTTONDBLCLK:
02864 case WM_RBUTTONDOWN:
02865 if (!(wFlags & TPM_RIGHTBUTTON)) break;
02866 goto buttondown;
02867 case WM_LBUTTONDBLCLK:
02868 if (bSysMenu && (hmenu == mt.hTopMenu))
02869 {
02870 #ifdef __WIN32OS2__
02871
02872 PostMessageA(hwnd, WM_SYSCOMMAND,SC_CLOSE, msg.lParam);
02873 #endif
02874 fEndMenu = TRUE;
02875 break;
02876 }
02877
02878 case WM_LBUTTONDOWN:
02879
02880
02881
02882 buttondown:
02883
02884 mouseOverMenuID = -1;
02885 fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
02886 fEndMenu = !fRemove;
02887 break;
02888
02889 case WM_RBUTTONUP:
02890 if (!(wFlags & TPM_RIGHTBUTTON)) break;
02891
02892 case WM_LBUTTONUP:
02893
02894 if (hmenu)
02895 {
02896
02897 mouseOverMenuID = -1;
02898 executedMenuId = MENU_ButtonUp( &mt, hmenu, wFlags);
02899
02900
02901
02902 fEndMenu = fRemove = (executedMenuId != -1);
02903 }
02904
02905
02906
02907 else
02908 fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE);
02909
02910 break;
02911
02912 case WM_MOUSEMOVE:
02913
02914
02915 #ifdef __WIN32OS2__
02916 if ( !fOS2Look ||
02917 ( (msg.wParam & MK_LBUTTON) ||
02918 ((wFlags & TPM_RIGHTBUTTON) && (msg.wParam & MK_RBUTTON))) )
02919 fEndMenu |= !MENU_MouseMove( &mt, hmenu, wFlags );
02920 #else
02921 if ( (TWEAK_WineLook > WIN31_LOOK) ||
02922 ( (msg.wParam & MK_LBUTTON) ||
02923 ((wFlags & TPM_RIGHTBUTTON) && (msg.wParam & MK_RBUTTON))) )
02924 fEndMenu |= !MENU_MouseMove( &mt, hmenu, wFlags );
02925 #endif
02926
02927 }
02928 }
02929 else if (msg.message == WM_TIMER)
02930 {
02931 UINT id = -1;
02932 POPUPMENU *ptmenu = NULL;
02933
02934 if (isTimerSet)
02935 {
02936
02937
02938
02939
02940
02941
02942 if( hmenu )
02943 {
02944 ptmenu = (POPUPMENU *)MENU_GetMenu( hmenu );
02945 if( IS_SYSTEM_MENU(ptmenu) )
02946 id = 0;
02947 else
02948 MENU_FindItemByCoords( ptmenu, mt.pt, &id );
02949
02950
02951 if (mouseOverMenuID != -1 && mouseOverMenuID == id)
02952 {
02953
02954 mt.hCurrentMenu = MENU_ShowSubPopup(mt.hOwnerWnd, hmenu, FALSE, wFlags,&mt.pt);
02955 }
02956 }
02957
02958
02959
02960 KillTimer(mt.hOwnerWnd,SUBMENU_POPUP_TIMERID);
02961 isTimerSet = FALSE;
02962 }
02963 }
02964 else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
02965 {
02966 fRemove = TRUE;
02967 switch(msg.message)
02968 {
02969 case WM_KEYDOWN:
02970 switch(msg.wParam)
02971 {
02972 case VK_HOME:
02973 case VK_END:
02974 MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu,
02975 NO_SELECTED_ITEM, FALSE, 0 );
02976
02977 case VK_UP:
02978 MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu,
02979 (msg.wParam == VK_HOME)? ITEM_NEXT : ITEM_PREV );
02980 break;
02981
02982 case VK_DOWN:
02983
02984 menu = MENU_GetMenu(mt.hCurrentMenu);
02985 if (!(menu->wFlags & MF_POPUP))
02986 mt.hCurrentMenu = MENU_ShowSubPopup(mt.hOwnerWnd, mt.hTopMenu, TRUE, wFlags,&mt.pt);
02987 else
02988 MENU_MoveSelection( mt.hOwnerWnd, mt.hCurrentMenu, ITEM_NEXT );
02989 break;
02990
02991 case VK_LEFT:
02992 MENU_KeyLeft( &mt, wFlags );
02993 break;
02994
02995 case VK_RIGHT:
02996 MENU_KeyRight( &mt, wFlags );
02997 break;
02998
02999 case VK_ESCAPE:
03000 fEndMenu = TRUE;
03001 break;
03002
03003 case VK_F1:
03004 {
03005 HELPINFO hi;
03006 hi.cbSize = sizeof(HELPINFO);
03007 hi.iContextType = HELPINFO_MENUITEM;
03008 if (menu->FocusedItem == NO_SELECTED_ITEM)
03009 hi.iCtrlId = 0;
03010 else
03011 hi.iCtrlId = menu->items[menu->FocusedItem].wID;
03012 hi.hItemHandle = hmenu;
03013 hi.dwContextId = menu->dwContextHelpID;
03014 hi.MousePos = msg.pt;
03015
03016 SendMessageA(hwnd, WM_HELP, 0, (LPARAM)&hi);
03017 break;
03018 }
03019
03020 default:
03021 break;
03022 }
03023 break;
03024
03025 case WM_SYSKEYDOWN:
03026 switch(msg.wParam)
03027 {
03028 case VK_MENU:
03029 fEndMenu = TRUE;
03030 break;
03031
03032 }
03033 break;
03034
03035 case WM_CHAR:
03036 {
03037 UINT pos;
03038
03039 if (msg.wParam == '\r' || msg.wParam == ' ')
03040 {
03041 executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu, wFlags);
03042 fEndMenu = (executedMenuId != -1);
03043
03044 break;
03045 }
03046
03047
03048
03049 if ((msg.wParam <= 32) || (msg.wParam >= 127)) break;
03050
03051 pos = MENU_FindItemByKey( mt.hOwnerWnd, mt.hCurrentMenu,
03052 LOWORD(msg.wParam), FALSE );
03053 if (pos == (UINT)-2) fEndMenu = TRUE;
03054 else if (pos == (UINT)-1) MessageBeep(0);
03055 else
03056 {
03057 MENU_SelectItem( mt.hOwnerWnd, mt.hCurrentMenu, pos,
03058 TRUE, 0 );
03059 executedMenuId = MENU_ExecFocusedItem(&mt,mt.hCurrentMenu, wFlags);
03060 fEndMenu = (executedMenuId != -1);
03061 }
03062 }
03063 break;
03064 }
03065 }
03066 else if (msg.message == WM_SYSCOMMAND)
03067 {
03068
03069 fEndMenu = TRUE;
03070 break;
03071 }
03072 else
03073 {
03074 DispatchMessageA( &msg );
03075 }
03076
03077 if (!fEndMenu) fRemove = TRUE;
03078
03079
03080
03081 if (fRemove && !(mt.trackFlags & TF_SKIPREMOVE) )
03082 PeekMessageA( &msg, 0, msg.message, msg.message, PM_REMOVE );
03083 else mt.trackFlags &= ~TF_SKIPREMOVE;
03084 }
03085 #ifdef __WIN32OS2__
03086 SetMenuDoubleClick(FALSE);
03087 ReleaseCapture();
03088 #endif
03089
03090 menu = MENU_GetMenu(mt.hTopMenu);
03091
03092 if( IsWindow( mt.hOwnerWnd ) )
03093 {
03094 MENU_HideSubPopups( mt.hOwnerWnd, mt.hTopMenu, FALSE );
03095
03096 MENU_SelectItem( mt.hOwnerWnd, mt.hTopMenu, NO_SELECTED_ITEM, FALSE, 0 );
03097 #ifdef __WIN32OS2__
03098 if (menu && menu->wFlags & MF_POPUP)
03099 {
03100 DestroyWindow( menu->hWnd );
03101 menu->hWnd = 0;
03102
03103 uSubPWndLevel = 0;
03104 }
03105 #endif
03106 SendMessageA( mt.hOwnerWnd, WM_MENUSELECT, MAKELONG(0,0xffff), 0 );
03107 }
03108
03109
03110 menu->bTimeToHide = FALSE;
03111
03112
03113 return ((executedMenuId != -1) ? executedMenuId : 0);
03114 }
03115
03116
03117
03118
03119 static BOOL MENU_InitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT wFlags)
03120 {
03121
03122
03123 HideCaret(0);
03124
03125
03126 if (!(wFlags & TPM_NONOTIFY))
03127 SendMessageA( hWnd, WM_ENTERMENULOOP, bPopup, 0 );
03128
03129 SendMessageA( hWnd, WM_SETCURSOR, hWnd, HTCAPTION );
03130
03131 if (!(wFlags & TPM_NONOTIFY))
03132 SendMessageA( hWnd, WM_INITMENU, hMenu, 0 );
03133
03134 return TRUE;
03135 }
03136
03137
03138
03139 static BOOL MENU_ExitTracking(HWND hWnd)
03140 {
03141
03142
03143 SendMessageA( hWnd, WM_EXITMENULOOP, 0, 0 );
03144 ShowCaret(0);
03145 return TRUE;
03146 }
03147
03148
03149
03150
03151
03152
03153 void MENU_TrackMouseMenuBar( HWND hWnd, INT ht, POINT pt )
03154 {
03155 HMENU hMenu = (ht == 0) ? GetMenu(hWnd):getSysMenu(hWnd);
03156 UINT wFlags = TPM_ENTERIDLEEX | TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
03157
03158
03159
03160 if (IsMenu(hMenu))
03161 {
03162 if (ht == HTCAPTION) wFlags |= TPM_CAPTIONSYSMENU | TPM_RIGHTBUTTON;
03163 if (IsIconic(hWnd)) wFlags |= TPM_BOTTOMALIGN;
03164
03165 MENU_InitTracking( hWnd, hMenu, FALSE, wFlags );
03166 MENU_TrackMenu( hMenu, wFlags, pt.x, pt.y, hWnd,ht == 0, NULL );
03167 MENU_ExitTracking(hWnd);
03168 }
03169 }
03170
03171 MENUITEM *MENU_HighlightedItem=NULL;
03172 UINT MENU_HighlightedItemID=NO_SELECTED_ITEM;
03173 POPUPMENU *MENU_HighlightedMenu=NULL;
03174
03175 void MENU_TrackMouseMenuBar_MouseMove(HWND hwnd,POINT pt,BOOL OnMenu)
03176 {
03177 HMENU hMenu = GetMenu(hwnd);
03178 MENUITEM *item = NULL;
03179 RECT rect;
03180 HDC hdc;
03181 BOOL UnHighlight = (OnMenu==TRUE)?FALSE:TRUE;
03182 POPUPMENU *ptmenu = NULL;
03183 UINT id = NO_SELECTED_ITEM;
03184
03185 if (OnMenu == TRUE && IsMenu(hMenu)) {
03186
03187 ptmenu=(POPUPMENU *)MENU_GetMenu( hMenu );
03188
03189 item=MENU_FindItemByCoords( ptmenu, pt, &id );
03190
03191 if(!item) {
03192
03193 UnHighlight = TRUE;
03194
03195 item=NULL;
03196 } else if(id == MENU_HighlightedItemID) {
03197
03198 return;
03199 } else if(item->fState & MF_MOUSESELECT) {
03200
03201 return;
03202 } else if(item->fType & MF_BITMAP) {
03203 UnHighlight = TRUE;
03204
03205 item=NULL;
03206 } else {
03207 hdc = GetDCEx( ptmenu->hWnd, 0, DCX_CACHE | DCX_WINDOW);
03208 rect = item->rect;
03209 DrawEdge(hdc, &rect, BDR_RAISEDINNER, BF_RECT);
03210 ReleaseDC( ptmenu->hWnd, hdc );
03211
03212 UnHighlight = TRUE;
03213 }
03214 }
03215
03216 if(UnHighlight == TRUE) {
03217 if(MENU_HighlightedItem) {
03218 if(!(MENU_HighlightedItem->fState & MF_MOUSESELECT)) {
03219 hdc = GetDCEx( MENU_HighlightedMenu->hWnd, 0, DCX_CACHE | DCX_WINDOW);
03220 rect = MENU_HighlightedItem->rect;
03221
03222 FrameRect(hdc, &rect, GetSysColorBrush(COLOR_MENU));
03223 ReleaseDC( MENU_HighlightedMenu->hWnd, hdc );
03224 }
03225 }
03226
03227
03228
03229 MENU_HighlightedItem = item;
03230 MENU_HighlightedItemID = id;
03231 MENU_HighlightedMenu= ptmenu;
03232 }
03233 }
03234
03235
03236
03237
03238
03239
03240 void MENU_TrackKbdMenuBar( HWND hWnd, UINT wParam, INT vkey)
03241 {
03242 UINT uItem = NO_SELECTED_ITEM;
03243 HMENU hTrackMenu;
03244 UINT wFlags = TPM_ENTERIDLEEX | TPM_LEFTALIGN | TPM_LEFTBUTTON;
03245
03246
03247
03248 while(GetWindowLongA(hWnd,GWL_STYLE) & WS_CHILD)
03249 if( !(hWnd = GetParent(hWnd)) ) return;
03250
03251
03252
03253 if( (GetWindowLongA(hWnd,GWL_STYLE) & (WS_CHILD | WS_MINIMIZE)) ||
03254 !GetMenu(hWnd) || vkey == VK_SPACE )
03255 {
03256 if( !(GetWindowLongA(hWnd,GWL_STYLE) & WS_SYSMENU) ) return;
03257 hTrackMenu = getSysMenu(hWnd);
03258 uItem = 0;
03259 wParam |= HTSYSMENU;
03260 }
03261 else
03262 hTrackMenu = GetMenu(hWnd);
03263
03264 if (IsMenu( hTrackMenu ))
03265 {
03266 MENU_InitTracking( hWnd, hTrackMenu, FALSE, wFlags );
03267
03268 if( vkey && vkey != VK_SPACE )
03269 {
03270 uItem = MENU_FindItemByKey( hWnd, hTrackMenu,
03271 vkey, (wParam & HTSYSMENU) );
03272 if( uItem >= (UINT)(-2) )
03273 {
03274 if( uItem == (UINT)(-1) ) MessageBeep(0);
03275 hTrackMenu = 0;
03276 }
03277 }
03278
03279 if( hTrackMenu )
03280 {
03281 MENU_SelectItem( hWnd, hTrackMenu, uItem, TRUE, 0 );
03282
03283 if( uItem == NO_SELECTED_ITEM )
03284 MENU_MoveSelection( hWnd, hTrackMenu, ITEM_NEXT );
03285 else if( vkey )
03286 PostMessageA( hWnd, WM_KEYDOWN, VK_DOWN, 0L );
03287
03288 MENU_TrackMenu( hTrackMenu, wFlags, 0, 0, hWnd,TRUE, NULL );
03289 }
03290
03291 MENU_ExitTracking (hWnd);
03292 }
03293 }
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303 BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y,
03304 INT nReserved, HWND hWnd, const RECT *lpRect )
03305 {
03306 BOOL ret = FALSE;
03307
03308 if(lpRect) {
03309 dprintf(("USER32: TrackPopupMenu %x %x (%d,%d) %x %x (%d,%d)(%d,%d)", hMenu, wFlags, x, y, nReserved, hWnd, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom));
03310 }
03311 else dprintf(("USER32: TrackPopupMenu %x %x (%d,%d) %x %x lpRect=NULL", hMenu, wFlags, x, y, nReserved, hWnd));
03312
03313 MENU_InitTracking(hWnd, hMenu, TRUE, wFlags);
03314
03315
03316 if (!(wFlags & TPM_NONOTIFY))
03317 SendMessageA( hWnd, WM_INITMENUPOPUP, hMenu, 0);
03318
03319 if (MENU_ShowPopup( hWnd, hMenu, 0, x, y, 0, 0 ))
03320 ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd,FALSE, lpRect );
03321 MENU_ExitTracking(hWnd);
03322
03323 if( (!(wFlags & TPM_RETURNCMD)) && (ret != FALSE) )
03324 ret = 1;
03325
03326 return ret;
03327 }
03328
03329
03330
03331
03332 BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y,
03333 HWND hWnd, LPTPMPARAMS lpTpm )
03334 {
03335 dprintf(("USER32: TrackPopupMenuEx"));
03336
03337 return TrackPopupMenu( hMenu, wFlags, x, y, 0, hWnd,
03338 lpTpm ? &lpTpm->rcExclude : NULL );
03339 }
03340
03341
03342
03343
03344
03345
03346 LRESULT WINAPI PopupMenuWndProc( HWND hwnd, UINT message, WPARAM wParam,
03347 LPARAM lParam )
03348 {
03349 LRESULT retvalue;
03350
03351
03352
03353
03354 switch(message)
03355 {
03356 case WM_CREATE:
03357 {
03358 CREATESTRUCTA *cs = (CREATESTRUCTA*)lParam;
03359 SetWindowLongA( hwnd, 0, (LONG)cs->lpCreateParams );
03360 retvalue = 0;
03361 goto END;
03362 }
03363
03364 case WM_MOUSEACTIVATE:
03365 retvalue = MA_NOACTIVATE;
03366 goto END;
03367
03368 case WM_PAINT:
03369 {
03370 PAINTSTRUCT ps;
03371 BeginPaint( hwnd, &ps );
03372 MENU_DrawPopupMenu( hwnd, ps.hdc,
03373 (HMENU)GetWindowLongA( hwnd, 0 ) );
03374 EndPaint( hwnd, &ps );
03375 retvalue = 0;
03376 goto END;
03377 }
03378 case WM_ERASEBKGND:
03379 retvalue = 1;
03380 goto END;
03381
03382 case WM_DESTROY:
03383
03384
03385
03386
03387 if(MENU_GetTopPopupWnd() )
03388 {
03389 if( hwnd == pTopPopupWnd )
03390 {
03391
03392
03393 MENU_DestroyTopPopupWnd();
03394 uSubPWndLevel = 0;
03395 }
03396 else
03397 uSubPWndLevel--;
03398 MENU_ReleaseTopPopupWnd();
03399 }
03400 break;
03401
03402 case WM_SHOWWINDOW:
03403
03404 if( wParam )
03405 {
03406
03407
03408 }
03409 else
03410 SetWindowLongA(hwnd,0,0);
03411 break;
03412
03413 case MM_SETMENUHANDLE:
03414
03415 SetWindowLongA(hwnd,0,wParam);
03416 break;
03417
03418 case MM_GETMENUHANDLE:
03419
03420 retvalue = GetWindowLongA(hwnd,0);
03421 goto END;
03422
03423 default:
03424 retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
03425 goto END;
03426 }
03427 retvalue = 0;
03428 END:
03429 return retvalue;
03430 }
03431
03432
03433
03434
03435
03436
03437
03438 UINT MENU_GetMenuBarHeight(HWND hwnd,UINT menubarWidth,INT orgX,INT orgY)
03439 {
03440 HDC hdc;
03441 RECT rectBar;
03442 LPPOPUPMENU lppop;
03443 UINT retvalue;
03444
03445
03446
03447
03448 if (!(lppop = MENU_GetMenu(GetMenu(hwnd))))
03449 {
03450 return 0;
03451 }
03452
03453 hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
03454 SelectObject( hdc, hMenuFont);
03455 SetRect(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+GetSystemMetrics(SM_CYMENU));
03456 MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
03457 ReleaseDC( hwnd, hdc );
03458 retvalue = lppop->Height;
03459 return retvalue;
03460 }
03461
03462
03463
03464
03465
03466 BOOL WINAPI ChangeMenuA( HMENU hMenu, UINT pos, LPCSTR data,
03467 UINT id, UINT flags )
03468 {
03469 dprintf(("USER32: ChangeMenuA"));
03470
03471
03472
03473 if (flags & MF_APPEND) return AppendMenuA( hMenu, flags & ~MF_APPEND,
03474 id, data );
03475 if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
03476 if (flags & MF_CHANGE) return ModifyMenuA(hMenu, pos, flags & ~MF_CHANGE,
03477 id, data );
03478 if (flags & MF_REMOVE) return RemoveMenu( hMenu,
03479 flags & MF_BYPOSITION ? pos : id,
03480 flags & ~MF_REMOVE );
03481
03482 return InsertMenuA( hMenu, pos, flags, id, data );
03483 }
03484
03485
03486
03487
03488
03489 BOOL WINAPI ChangeMenuW( HMENU hMenu, UINT pos, LPCWSTR data,
03490 UINT id, UINT flags )
03491 {
03492 dprintf(("USER32: ChangeMenuW"));
03493
03494
03495
03496 if (flags & MF_APPEND) return AppendMenuW( hMenu, flags & ~MF_APPEND,
03497 id, data );
03498 if (flags & MF_DELETE) return DeleteMenu(hMenu, pos, flags & ~MF_DELETE);
03499 if (flags & MF_CHANGE) return ModifyMenuW(hMenu, pos, flags & ~MF_CHANGE,
03500 id, data );
03501 if (flags & MF_REMOVE) return RemoveMenu( hMenu,
03502 flags & MF_BYPOSITION ? pos : id,
03503 flags & ~MF_REMOVE );
03504
03505 return InsertMenuW( hMenu, pos, flags, id, data );
03506 }
03507
03508
03509
03510
03511
03512 DWORD WINAPI CheckMenuItem( HMENU hMenu, UINT id, UINT flags )
03513 {
03514 MENUITEM *item;
03515 DWORD ret;
03516
03517 dprintf(("USER32: CheckMenuItem %x %x %x", hMenu, id, flags));
03518
03519
03520 if (!(item = MENU_FindItem( &hMenu, &id, flags ))) return -1;
03521 ret = item->fState & MF_CHECKED;
03522 if (flags & MF_CHECKED) item->fState |= MF_CHECKED;
03523 else item->fState &= ~MF_CHECKED;
03524 return ret;
03525 }
03526
03527
03528
03529
03530
03531 UINT WINAPI EnableMenuItem( HMENU hMenu, UINT wItemID, UINT wFlags )
03532 {
03533 UINT oldflags;
03534 MENUITEM *item;
03535 POPUPMENU *menu;
03536
03537 dprintf(("USER32: EnableMenuItem %x %x %x", hMenu, wItemID, wFlags));
03538
03539
03540
03541
03542
03543 if (!(menu = MENU_GetMenu(hMenu)))
03544 return (UINT)-1;
03545
03546 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags )))
03547 return (UINT)-1;
03548
03549 oldflags = item->fState & (MF_GRAYED | MF_DISABLED);
03550 item->fState ^= (oldflags ^ wFlags) & (MF_GRAYED | MF_DISABLED);
03551
03552
03553 if((item->wID == SC_CLOSE) && (oldflags != wFlags))
03554 {
03555 if (menu->hSysMenuOwner != 0)
03556 {
03557 POPUPMENU* parentMenu;
03558
03559
03560 if (!(parentMenu = MENU_GetMenu(menu->hSysMenuOwner)))
03561 return (UINT)-1;
03562
03563
03564 SetWindowPos(parentMenu->hWnd, 0, 0, 0, 0, 0,
03565 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
03566 }
03567 }
03568
03569 return oldflags;
03570 }
03571
03572
03573
03574
03575
03576 INT WINAPI GetMenuStringA(
03577 HMENU hMenu,
03578 UINT wItemID,
03579 LPSTR str,
03580 INT nMaxSiz,
03581 UINT wFlags
03582 ) {
03583 MENUITEM *item;
03584
03585 dprintf(("USER32: GetMenuStringA %x %d %d %x", hMenu, wItemID, nMaxSiz, wFlags));
03586
03587
03588
03589
03590 item = MENU_FindItem( &hMenu, &wItemID, wFlags );
03591
03592 if (!str || !nMaxSiz)
03593 {
03594 if (item && IS_STRING_ITEM(item->fType))
03595 return strlen(item->text);
03596 else
03597 return 0;
03598 }
03599
03600 str[0] = '\0';
03601
03602 if (item)
03603 {
03604 if (!IS_STRING_ITEM(item->fType)) return 0;
03605 lstrcpynA( str, item->text, nMaxSiz );
03606 }
03607
03608 return strlen(str);
03609 }
03610
03611
03612
03613
03614
03615 INT WINAPI GetMenuStringW( HMENU hMenu, UINT wItemID,
03616 LPWSTR str, INT nMaxSiz, UINT wFlags )
03617 {
03618 MENUITEM *item;
03619
03620 dprintf(("USER32: GetMenuStringW %x %d %x %d %d", hMenu, wItemID, str, nMaxSiz, wFlags));
03621
03622
03623
03624
03625 item = MENU_FindItem( &hMenu, &wItemID, wFlags );
03626
03627 if (!str || !nMaxSiz)
03628 {
03629 if (item && IS_STRING_ITEM(item->fType))
03630 return strlen(item->text);
03631 else
03632 return 0;
03633 }
03634
03635 str[0] = '\0';
03636
03637 if (item)
03638 {
03639 if (!IS_STRING_ITEM(item->fType)) return 0;
03640 lstrcpynAtoW( str, item->text, nMaxSiz );
03641 }
03642
03643 return lstrlenW(str);
03644 }
03645
03646
03647
03648
03649
03650 BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
03651 UINT wHilite )
03652 {
03653 LPPOPUPMENU menu;
03654
03655 dprintf(("USER32: HiliteMenuItem"));
03656
03657
03658
03659 if (!MENU_FindItem( &hMenu, &wItemID, wHilite )) return FALSE;
03660 if (!(menu = MENU_GetMenu(hMenu))) return FALSE;
03661 if (menu->FocusedItem == wItemID) return TRUE;
03662 MENU_HideSubPopups( hWnd, hMenu, FALSE );
03663 MENU_SelectItem( hWnd, hMenu, wItemID, TRUE, 0 );
03664 return TRUE;
03665 }
03666
03667
03668
03669
03670
03671 UINT WINAPI GetMenuState( HMENU hMenu, UINT wItemID, UINT wFlags )
03672 {
03673 MENUITEM *item;
03674
03675 dprintf(("USER32: GetMenuState %d %d",wItemID,wFlags));
03676
03677
03678
03679
03680 if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return -1;
03681
03682
03683 if (item->fType & MF_POPUP)
03684 {
03685 POPUPMENU *menu = MENU_GetMenu(item->hSubMenu);
03686 if (!menu) return -1;
03687 else return (menu->nItems << 8) | ((item->fState|item->fType) & 0xff);
03688 }
03689 else
03690 {
03691
03692
03693
03694 return (item->fType | item->fState);
03695 }
03696 }
03697
03698
03699
03700
03701
03702 INT WINAPI GetMenuItemCount( HMENU hMenu )
03703 {
03704 LPPOPUPMENU menu = MENU_GetMenu(hMenu);
03705
03706 dprintf(("USER32: GetMenuItemCount %x", hMenu));
03707
03708 if (!IS_A_MENU(menu)) return -1;
03709
03710
03711 return menu->nItems;
03712 }
03713
03714
03715
03716
03717 UINT WINAPI GetMenuItemID( HMENU hMenu, INT nPos )
03718 {
03719 MENUITEM * lpmi;
03720
03721 dprintf(("USER32: GetMenuItemID %x %d", hMenu, nPos));
03722
03723 if (!(lpmi = MENU_FindItem(&hMenu,(UINT*)&nPos,MF_BYPOSITION))) return 0xFFFFFFFF;
03724 if (lpmi->fType & MF_POPUP) return 0xFFFFFFFF;
03725 return lpmi->wID;
03726
03727 }
03728
03729
03730
03731
03732 BOOL WINAPI InsertMenuA( HMENU hMenu, UINT pos, UINT flags,
03733 UINT id, LPCSTR str )
03734 {
03735 MENUITEM *item;
03736
03737 if (IS_STRING_ITEM(flags) && str)
03738 dprintf(("USER32: InsertMenuA %x %d %x %x %s", hMenu, pos, flags, id, str));
03739
03740
03741
03742 else
03743 dprintf(("USER32: InsertMenuA %x %d %x %d %x", hMenu, pos, flags, id, str));
03744
03745
03746
03747 if (!(item = MENU_InsertItem( hMenu, pos, flags ))) return FALSE;
03748
03749 if (!(MENU_SetItemData( item, flags, id, str )))
03750 {
03751 RemoveMenu( hMenu, pos, flags );
03752 return FALSE;
03753 }
03754
03755 if (flags & MF_POPUP)
03756 (MENU_GetMenu((HMENU)id))->wFlags |= MF_POPUP;
03757
03758 item->hCheckBit = item->hUnCheckBit = 0;
03759 return TRUE;
03760 }
03761
03762
03763
03764
03765
03766 BOOL WINAPI InsertMenuW( HMENU hMenu, UINT pos, UINT flags,
03767 UINT id, LPCWSTR str )
03768 {
03769 BOOL ret;
03770
03771 if (IS_STRING_ITEM(flags) && str)
03772 {
03773 LPSTR newstr = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
03774 ret = InsertMenuA( hMenu, pos, flags, id, newstr );
03775 HeapFree( GetProcessHeap(), 0, newstr );
03776 return ret;
03777 }
03778 else return InsertMenuA( hMenu, pos, flags, id, (LPCSTR)str );
03779 }
03780
03781
03782
03783
03784
03785 BOOL WINAPI AppendMenuA( HMENU hMenu, UINT flags,
03786 UINT id, LPCSTR data )
03787 {
03788 dprintf(("USER32: AppendMenuA %x %x %x %x", hMenu, flags, id, data));
03789
03790 return InsertMenuA( hMenu, -1, flags | MF_BYPOSITION, id, data );
03791 }
03792
03793
03794
03795
03796
03797 BOOL WINAPI AppendMenuW( HMENU hMenu, UINT flags,
03798 UINT id, LPCWSTR data )
03799 {
03800 dprintf(("USER32: AppendMenuW %x %x %x %x", hMenu, flags, id, data));
03801
03802 return InsertMenuW( hMenu, -1, flags | MF_BYPOSITION, id, data );
03803 }
03804
03805
03806
03807
03808
03809 BOOL WINAPI RemoveMenu( HMENU hMenu, UINT nPos, UINT wFlags )
03810 {
03811 LPPOPUPMENU menu;
03812 MENUITEM *item;
03813
03814 dprintf(("USER32: RemoveMenu %x %d %x", hMenu, nPos, wFlags));
03815
03816
03817 if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
03818 if (!(menu = MENU_GetMenu(hMenu))) return FALSE;
03819
03820
03821
03822 MENU_FreeItemData( item );
03823
03824 if (--menu->nItems == 0)
03825 {
03826 HeapFree(GetProcessHeap(), 0, menu->items );
03827 menu->items = NULL;
03828 }
03829 else
03830 {
03831 while(nPos < menu->nItems)
03832 {
03833 *item = *(item+1);
03834 item++;
03835 nPos++;
03836 }
03837 menu->items = (MENUITEM*)HeapReAlloc(GetProcessHeap(), 0, menu->items,
03838 menu->nItems * sizeof(MENUITEM) );
03839 }
03840 return TRUE;
03841 }
03842
03843
03844
03845
03846
03847 BOOL WINAPI DeleteMenu( HMENU hMenu, UINT nPos, UINT wFlags )
03848 {
03849 MENUITEM *item = MENU_FindItem( &hMenu, &nPos, wFlags );
03850
03851 dprintf(("USER32: DeleteMenu %x %d %x", hMenu, nPos, wFlags));
03852
03853 if (!item) return FALSE;
03854 if (item->fType & MF_POPUP) DestroyMenu( item->hSubMenu );
03855
03856 RemoveMenu( hMenu, nPos, wFlags | MF_BYPOSITION );
03857 return TRUE;
03858 }
03859
03860
03861
03862
03863
03864 BOOL WINAPI ModifyMenuA( HMENU hMenu, UINT pos, UINT flags,
03865 UINT id, LPCSTR str )
03866 {
03867 MENUITEM *item;
03868
03869
03870 if (IS_STRING_ITEM(flags))
03871 {
03872 dprintf(("USER32: ModifyMenuA, %x %d %x %d %s", hMenu, pos, flags, id, str));
03873
03874
03875 if (!str) return FALSE;
03876 }
03877 else
03878 {
03879 dprintf(("USER32: ModifyMenuA, %x %d %x %d %x", hMenu, pos, flags, id, str));
03880
03881
03882 }
03883
03884 if (!(item = MENU_FindItem( &hMenu, &pos, flags ))) return FALSE;
03885 return MENU_SetItemData( item, flags, id, str );
03886 }
03887
03888
03889
03890
03891
03892 BOOL WINAPI ModifyMenuW( HMENU hMenu, UINT pos, UINT flags,
03893 UINT id, LPCWSTR str )
03894 {
03895 BOOL ret;
03896
03897 if (IS_STRING_ITEM(flags) && str)
03898 {
03899 LPSTR newstr = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
03900 ret = ModifyMenuA( hMenu, pos, flags, id, newstr );
03901 HeapFree( GetProcessHeap(), 0, newstr );
03902 return ret;
03903 }
03904 else return ModifyMenuA( hMenu, pos, flags, id, (LPCSTR)str );
03905 }
03906
03907
03908
03909
03910
03911 HMENU WINAPI CreatePopupMenu(void)
03912 {
03913 HMENU hmenu;
03914 POPUPMENU *menu;
03915
03916 dprintf(("USER32: CreatePopupMenu"));
03917
03918 if (!(hmenu = CreateMenu())) return 0;
03919 menu = MENU_GetMenu(hmenu);
03920 menu->wFlags |= MF_POPUP;
03921 menu->bTimeToHide = FALSE;
03922 return hmenu;
03923 }
03924
03925
03926
03927
03928
03929 DWORD WINAPI GetMenuCheckMarkDimensions(void)
03930 {
03931 dprintf(("USER32: GetMenuCheckMarkDimensions"));
03932
03933 return MAKELONG( check_bitmap_width, check_bitmap_height );
03934 }
03935
03936
03937
03938
03939
03940 BOOL WINAPI SetMenuItemBitmaps(HMENU hMenu, UINT nPos, UINT wFlags,
03941 HBITMAP hNewUnCheck, HBITMAP hNewCheck)
03942 {
03943 MENUITEM *item;
03944
03945 dprintf(("USER32: SetMenuItemBitmaps %x %d %x %x %x", hMenu, nPos, wFlags, hNewCheck, hNewUnCheck));
03946
03947
03948
03949 if (!(item = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
03950
03951 if (!hNewCheck && !hNewUnCheck)
03952 {
03953 item->fState &= ~MF_USECHECKBITMAPS;
03954 }
03955 else
03956 {
03957 item->hCheckBit = hNewCheck;
03958 item->hUnCheckBit = hNewUnCheck;
03959 item->fState |= MF_USECHECKBITMAPS;
03960 }
03961 return TRUE;
03962 }
03963
03964
03965
03966
03967
03968 HMENU WINAPI CreateMenu(void)
03969 {
03970 HMENU hMenu;
03971 LPPOPUPMENU menu;
03972
03973 dprintf(("USER32: CreateMenu"));
03974
03975 #ifdef __WIN32OS2__
03976 if (!(menu = (LPPOPUPMENU)HeapAlloc(GetProcessHeap(),0,sizeof(POPUPMENU)))) return 0;
03977 if(ObjAllocateHandle(&hMenu, (DWORD)menu, USEROBJ_MENU) == FALSE) return 0;
03978 #else
03979 if (!(hMenu = (HMENU)HeapAlloc(GetProcessHeap(),0,sizeof(POPUPMENU)))) return 0;
03980 menu = (LPPOPUPMENU)hMenu;
03981 #endif
03982
03983 ZeroMemory(menu, sizeof(POPUPMENU));
03984 menu->wMagic = MENU_MAGIC;
03985 menu->FocusedItem = NO_SELECTED_ITEM;
03986 menu->bTimeToHide = FALSE;
03987
03988
03989
03990 return hMenu;
03991 }
03992
03993
03994
03995
03996
03997 BOOL WINAPI DestroyMenu( HMENU hMenu )
03998 {
03999
04000
04001 dprintf(("USER32: DestroyMenu %x", hMenu));
04002
04003
04004
04005 if (hMenu && hMenu != MENU_DefSysPopup)
04006 {
04007 LPPOPUPMENU lppop = MENU_GetMenu(hMenu);
04008 HWND pTPWnd = MENU_GetTopPopupWnd();
04009
04010 if( pTPWnd && (hMenu == GetWindowLongA(pTPWnd,0)) )
04011 SetWindowLongA(pTPWnd,0,0);
04012
04013 if (IS_A_MENU(lppop))
04014 {
04015 lppop->wMagic = 0;
04016
04017 if ((lppop->wFlags & MF_POPUP) && lppop->hWnd &&
04018 (!pTPWnd || (lppop->hWnd != pTPWnd)))
04019 DestroyWindow( lppop->hWnd );
04020
04021 if (lppop->items)
04022 {
04023 int i;
04024 MENUITEM *item = lppop->items;
04025 for (i = lppop->nItems; i > 0; i--, item++)
04026 {
04027 if (item->fType & MF_POPUP) DestroyMenu(item->hSubMenu);
04028 MENU_FreeItemData( item );
04029 }
04030 HeapFree(GetProcessHeap(), 0, lppop->items );
04031 }
04032 #ifdef __WIN32OS2__
04033 HeapFree(GetProcessHeap(),0,(LPVOID)lppop);
04034 ObjFreeHandle(hMenu);
04035 #else
04036 HeapFree(GetProcessHeap(),0,(LPVOID)hMenu);
04037 #endif
04038 MENU_ReleaseTopPopupWnd();
04039 }
04040 else
04041 {
04042 MENU_ReleaseTopPopupWnd();
04043 return FALSE;
04044 }
04045 }
04046 return (hMenu != MENU_DefSysPopup);
04047 }
04048
04049
04050
04051
04052 HMENU WINAPI GetSystemMenu( HWND hWnd, BOOL bRevert )
04053 {
04054 HMENU retvalue = 0;
04055
04056 dprintf(("USER32: GetSystemMenu %x %d", hWnd, bRevert));
04057
04058 if (IsWindow(hWnd))
04059 {
04060 HMENU hSysMenu = getSysMenu(hWnd);
04061 if(hSysMenu)
04062 {
04063 if( bRevert )
04064 {
04065 DestroyMenu(hSysMenu);
04066 hSysMenu = 0;
04067 setSysMenu(hWnd,hSysMenu);
04068 }
04069 else
04070 {
04071 POPUPMENU *menu = MENU_GetMenu(hSysMenu);
04072 if(menu)
04073 {
04074 if( menu->nItems > 0 && menu->items[0].hSubMenu == MENU_DefSysPopup )
04075 menu->items[0].hSubMenu = MENU_CopySysPopup();
04076 }
04077 else
04078 {
04079
04080
04081 hSysMenu = 0;
04082 setSysMenu(hWnd,hSysMenu);
04083 }
04084 }
04085 }
04086
04087 if(!hSysMenu && (GetWindowLongA(hWnd,GWL_STYLE) & WS_SYSMENU) )
04088 {
04089 hSysMenu = MENU_GetSysMenu( hWnd, (HMENU)(-1) );
04090 setSysMenu(hWnd,hSysMenu);
04091 }
04092
04093 if( hSysMenu )
04094 {
04095 POPUPMENU *menu;
04096 retvalue = GetSubMenu(hSysMenu, 0);
04097
04098
04099
04100 menu = MENU_GetMenu(retvalue);
04101 if (menu)
04102 menu->hSysMenuOwner = hSysMenu;
04103 }
04104 }
04105 return retvalue;
04106 }
04107
04108
04109
04110
04111
04112 BOOL WINAPI SetSystemMenu( HWND hwnd, HMENU hMenu )
04113 {
04114 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
04115
04116 dprintf(("USER32: SetSystemMenu"));
04117
04118 if (win32wnd)
04119 {
04120 if (win32wnd->GetSysMenu()) DestroyMenu(win32wnd->GetSysMenu());
04121 win32wnd->SetSysMenu(MENU_GetSysMenu( hwnd, hMenu ));
04122 RELEASE_WNDOBJ(win32wnd);
04123 return TRUE;
04124 }
04125 return FALSE;
04126 }
04127
04128
04129
04130
04131 HMENU WINAPI GetMenu( HWND hWnd )
04132 {
04133 HMENU retvalue;
04134
04135 dprintf(("USER32: GetMenu %x %x", hWnd, GetWindowLongA( hWnd, GWL_ID )));
04136
04137 if (GetWindowLongA(hWnd,GWL_STYLE) & WS_CHILD) {
04138 dprintf(("WARNING: window is child; no menu"));
04139 return 0;
04140 }
04141 retvalue = (HMENU)GetWindowLongA( hWnd, GWL_ID );
04142 #ifdef __WIN32OS2__
04143 if(MENU_GetMenu(retvalue) != NULL) {
04144 return retvalue;
04145 }
04146 return 0;
04147 #else
04148 return retvalue;
04149 #endif
04150 }
04151
04152
04153
04154
04155 BOOL WINAPI SetMenu( HWND hWnd, HMENU hMenu )
04156 {
04157
04158
04159 dprintf(("USER32: SetMenu %x %x", hWnd, hMenu));
04160
04161 if (hMenu && !IsMenu(hMenu))
04162 {
04163
04164 return FALSE;
04165 }
04166
04167
04168 if (!(GetWindowLongA(hWnd,GWL_STYLE) & WS_CHILD))
04169 {
04170 if (GetCapture() == hWnd) ReleaseCapture();
04171
04172 if (hMenu != 0)
04173 {
04174 LPPOPUPMENU lpmenu;
04175
04176 if (!(lpmenu = MENU_GetMenu(hMenu)))
04177 {
04178 return FALSE;
04179 }
04180 lpmenu->hWnd = hWnd;
04181 lpmenu->wFlags &= ~MF_POPUP;
04182 lpmenu->Height = 0;
04183 }
04184 SetWindowLongA( hWnd, GWL_ID, hMenu );
04185
04186 #ifdef __WIN32OS2__
04187
04188
04189
04190 #endif
04191 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
04192 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
04193 return TRUE;
04194 }
04195 return FALSE;
04196 }
04197
04198
04199
04200
04201
04202 HMENU WINAPI GetSubMenu( HMENU hMenu, INT nPos )
04203 {
04204 MENUITEM * lpmi;
04205
04206 dprintf(("USER32: GetSubMenu %x %d", hMenu, nPos));
04207
04208 #ifdef __WIN32OS2__
04209 if (!(lpmi = MENU_FindItem(&hMenu,(UINT*)&nPos,MF_BYPOSITION))) {
04210 SetLastError(ERROR_INVALID_HANDLE);
04211 return 0;
04212 }
04213 #else
04214 if (!(lpmi = MENU_FindItem(&hMenu,(UINT*)&nPos,MF_BYPOSITION))) return 0;
04215 #endif
04216
04217 if (!(lpmi->fType & MF_POPUP)) return 0;
04218 return lpmi->hSubMenu;
04219 }
04220
04221
04222
04223
04224
04225 BOOL WINAPI DrawMenuBar( HWND hWnd )
04226 {
04227 LPPOPUPMENU lppop;
04228
04229 dprintf(("USER32: DrawMenuBar %x", hWnd));
04230
04231 if (!(GetWindowLongA(hWnd,GWL_STYLE) & WS_CHILD) && GetMenu(hWnd))
04232 {
04233 lppop = MENU_GetMenu(GetMenu(hWnd));
04234 if (lppop == NULL)
04235 {
04236 return FALSE;
04237 }
04238
04239 lppop->Height = 0;
04240 lppop->hwndOwner = hWnd;
04241 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
04242 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
04243 return TRUE;
04244 }
04245 return FALSE;
04246 }
04247
04248
04249
04250
04251
04252 void WINAPI EndMenu(void)
04253 {
04254 dprintf(("USER32: EndMenu not implemented!"));
04255
04256
04257
04258
04259 fEndMenu = TRUE;
04260 }
04261
04262
04263
04264
04265
04266 HMENU WINAPI LoadMenuA( HINSTANCE instance, LPCSTR name )
04267 {
04268 HRSRC hrsrc = FindResourceA( instance, name, RT_MENUA );
04269
04270 dprintf(("USER32: LoadMenuA %x %x", instance, name));
04271
04272 if (!hrsrc) return 0;
04273 return LoadMenuIndirectA( (MENUITEMTEMPLATEHEADER*)LoadResource( instance, hrsrc ));
04274 }
04275
04276
04277
04278
04279
04280 HMENU WINAPI LoadMenuW( HINSTANCE instance, LPCWSTR name )
04281 {
04282 HRSRC hrsrc = FindResourceW( instance, name, RT_MENUW );
04283
04284 dprintf(("USER32: LoadMenuW %x %x", instance, name));
04285
04286 if (!hrsrc) return 0;
04287 return LoadMenuIndirectW( (MENUITEMTEMPLATEHEADER*)LoadResource( instance, hrsrc ));
04288 }
04289
04290
04291
04292
04293
04294 HMENU WINAPI LoadMenuIndirectA(CONST MENUITEMTEMPLATEHEADER *lpMenuTemplate)
04295 {
04296 HMENU hMenu;
04297 WORD version, offset;
04298 LPCSTR p = (LPCSTR)lpMenuTemplate;
04299
04300 dprintf(("USER32: LoadMenuIndirectA"));
04301
04302
04303 version = GET_WORD(p);
04304 p += sizeof(WORD);
04305 switch (version)
04306 {
04307 case 0:
04308 offset = GET_WORD(p);
04309 p += sizeof(WORD) + offset;
04310 if (!(hMenu = CreateMenu())) return 0;
04311 if (!MENU_ParseResource( p, hMenu, TRUE ))
04312 {
04313 DestroyMenu( hMenu );
04314 return 0;
04315 }
04316 return hMenu;
04317 case 1:
04318 offset = GET_WORD(p);
04319 p += sizeof(WORD) + offset;
04320 if (!(hMenu = CreateMenu())) return 0;
04321 if (!MENUEX_ParseResource( p, hMenu))
04322 {
04323 DestroyMenu( hMenu );
04324 return 0;
04325 }
04326 return hMenu;
04327 default:
04328
04329 return 0;
04330 }
04331 }
04332
04333
04334
04335
04336
04337 HMENU WINAPI LoadMenuIndirectW(CONST MENUITEMTEMPLATEHEADER *lpMenuTemplate )
04338 {
04339 dprintf(("USER32: LoadMenuIndirectW"));
04340
04341
04342 return LoadMenuIndirectA(lpMenuTemplate);
04343 }
04344
04345
04346
04347
04348
04349 BOOL WINAPI IsMenu(HMENU hmenu)
04350 {
04351 LPPOPUPMENU menu = MENU_GetMenu(hmenu);
04352
04353 dprintf(("USER32: IsMenu %x", hmenu));
04354
04355 return IS_A_MENU(menu);
04356 }
04357
04358
04359
04360
04361
04362 static BOOL GetMenuItemInfo_common ( HMENU hmenu, UINT item, BOOL bypos,
04363 LPMENUITEMINFOA lpmii, BOOL unicode)
04364 {
04365 MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos? MF_BYPOSITION : 0);
04366
04367
04368
04369 if (!menu)
04370 return FALSE;
04371
04372 if (lpmii->fMask & MIIM_TYPE) {
04373 lpmii->fType = menu->fType;
04374 switch (MENU_ITEM_TYPE(menu->fType)) {
04375 case MF_STRING:
04376 if (menu->text) {
04377 if (unicode) {
04378 if(lpmii->dwTypeData && lpmii->cch)
04379 lstrcpynAtoW((LPWSTR) lpmii->dwTypeData, menu->text, lpmii->cch);
04380 lpmii->cch = lstrlenA(menu->text);
04381 } else {
04382 if(lpmii->dwTypeData && lpmii->cch)
04383 lstrcpynA(lpmii->dwTypeData, menu->text, lpmii->cch);
04384 lpmii->cch = lstrlenA(menu->text);
04385 }
04386 }
04387 break;
04388 case MF_OWNERDRAW:
04389 case MF_BITMAP:
04390 lpmii->dwTypeData = menu->text;
04391
04392 default:
04393 lpmii->cch = 0;
04394 }
04395 }
04396
04397 if (lpmii->fMask & MIIM_STRING) {
04398 if (unicode) {
04399 lstrcpynAtoW((LPWSTR) lpmii->dwTypeData, menu->text, lpmii->cch);
04400 lpmii->cch = lstrlenW((LPWSTR)menu->text);
04401 } else {
04402 lstrcpynA(lpmii->dwTypeData, menu->text, lpmii->cch);
04403 lpmii->cch = lstrlenA(menu->text);
04404 }
04405 }
04406
04407 if (lpmii->fMask & MIIM_FTYPE)
04408 lpmii->fType = menu->fType;
04409
04410 if (lpmii->fMask & MIIM_BITMAP)
04411 lpmii->hbmpItem = menu->hbmpItem;
04412
04413 if (lpmii->fMask & MIIM_STATE)
04414 lpmii->fState = menu->fState;
04415
04416 if (lpmii->fMask & MIIM_ID)
04417 lpmii->wID = menu->wID;
04418
04419 if (lpmii->fMask & MIIM_SUBMENU)
04420 lpmii->hSubMenu = menu->hSubMenu;
04421
04422 if (lpmii->fMask & MIIM_CHECKMARKS) {
04423 lpmii->hbmpChecked = menu->hCheckBit;
04424 lpmii->hbmpUnchecked = menu->hUnCheckBit;
04425 }
04426 if (lpmii->fMask & MIIM_DATA)
04427 lpmii->dwItemData = menu->dwItemData;
04428
04429 return TRUE;
04430 }
04431
04432
04433
04434
04435 BOOL WINAPI GetMenuItemInfoA( HMENU hmenu, UINT item, BOOL bypos,
04436 LPMENUITEMINFOA lpmii)
04437 {
04438 dprintf(("USER32: GetMenuItemInfoA %x %d %d %x", hmenu, item, bypos, lpmii));
04439
04440 return GetMenuItemInfo_common (hmenu, item, bypos, lpmii, FALSE);
04441 }
04442
04443
04444
04445
04446 BOOL WINAPI GetMenuItemInfoW( HMENU hmenu, UINT item, BOOL bypos,
04447 LPMENUITEMINFOW lpmii)
04448 {
04449 dprintf(("USER32: GetMenuItemInfoW %x %d %d %x", hmenu, item, bypos, lpmii));
04450
04451 return GetMenuItemInfo_common (hmenu, item, bypos,
04452 (LPMENUITEMINFOA)lpmii, TRUE);
04453 }
04454
04455
04456
04457
04458
04459 static BOOL SetMenuItemInfo_common(MENUITEM * menu,
04460 const MENUITEMINFOA *lpmii,
04461 BOOL unicode)
04462 {
04463 if (!menu) return FALSE;
04464
04465 if (lpmii->fMask & MIIM_TYPE ) {
04466
04467 if ( IS_STRING_ITEM(menu->fType) && menu->text) {
04468 HeapFree(GetProcessHeap(), 0, menu->text);
04469 menu->text = NULL;
04470 }
04471
04472
04473 menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
04474 menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
04475
04476 menu->text = lpmii->dwTypeData;
04477
04478 if (IS_STRING_ITEM(menu->fType) && menu->text) {
04479 if (unicode)
04480 menu->text = HEAP_strdupWtoA(GetProcessHeap(), 0, (LPWSTR) lpmii->dwTypeData);
04481 else
04482 menu->text = HEAP_strdupA(GetProcessHeap(), 0, lpmii->dwTypeData);
04483 }
04484 }
04485
04486 if (lpmii->fMask & MIIM_FTYPE ) {
04487
04488 if ( (!IS_STRING_ITEM(lpmii->fType)) && IS_STRING_ITEM(menu->fType) && menu->text) {
04489 HeapFree(GetProcessHeap(), 0, menu->text);
04490 menu->text = NULL;
04491 }
04492 menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
04493 menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
04494 }
04495
04496 if (lpmii->fMask & MIIM_STRING ) {
04497
04498 if ( IS_STRING_ITEM(menu->fType) && menu->text) {
04499 HeapFree(GetProcessHeap(), 0, menu->text);
04500 if (unicode)
04501 menu->text = HEAP_strdupWtoA(GetProcessHeap(), 0, (LPWSTR) lpmii->dwTypeData);
04502 else
04503 menu->text = HEAP_strdupA(GetProcessHeap(), 0, lpmii->dwTypeData);
04504 }
04505 }
04506
04507 if (lpmii->fMask & MIIM_STATE)
04508 {
04509
04510 menu->fState = lpmii->fState;
04511 }
04512
04513 if (lpmii->fMask & MIIM_ID)
04514 menu->wID = lpmii->wID;
04515
04516 if (lpmii->fMask & MIIM_SUBMENU) {
04517 menu->hSubMenu = lpmii->hSubMenu;
04518 if (menu->hSubMenu) {
04519 POPUPMENU *subMenu = MENU_GetMenu((UINT)menu->hSubMenu);
04520 if (IS_A_MENU(subMenu)) {
04521 subMenu->wFlags |= MF_POPUP;
04522 menu->fType |= MF_POPUP;
04523 }
04524 else
04525
04526 menu->fType &= ~MF_POPUP;
04527 }
04528 else
04529 menu->fType &= ~MF_POPUP;
04530 }
04531
04532 if (lpmii->fMask & MIIM_CHECKMARKS)
04533 {
04534 menu->hCheckBit = lpmii->hbmpChecked;
04535 menu->hUnCheckBit = lpmii->hbmpUnchecked;
04536 }
04537 if (lpmii->fMask & MIIM_DATA)
04538 menu->dwItemData = lpmii->dwItemData;
04539
04540
04541 return TRUE;
04542 }
04543
04544
04545
04546
04547 BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos,
04548 const MENUITEMINFOA *lpmii)
04549 {
04550 dprintf(("USER32: SetMenuItemInfoA %x %d %d %x", hmenu, item, bypos, lpmii));
04551
04552 return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
04553 lpmii, FALSE);
04554 }
04555
04556
04557
04558
04559 BOOL WINAPI SetMenuItemInfoW(HMENU hmenu, UINT item, BOOL bypos,
04560 const MENUITEMINFOW *lpmii)
04561 {
04562 dprintf(("USER32: SetMenuItemInfoW"));
04563
04564 return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
04565 (const MENUITEMINFOA*)lpmii, TRUE);
04566 }
04567
04568
04569
04570
04571
04572 BOOL WINAPI SetMenuDefaultItem(HMENU hmenu, UINT uItem, UINT bypos)
04573 {
04574 UINT i;
04575 POPUPMENU *menu;
04576 MENUITEM *item;
04577
04578
04579 dprintf(("USER32: SetMenuDefaultItem"));
04580
04581
04582 if (!(menu = MENU_GetMenu(hmenu))) return FALSE;
04583
04584
04585 item = menu->items;
04586 for (i = 0; i < menu->nItems; i++, item++)
04587 {
04588 item->fState &= ~MFS_DEFAULT;
04589 }
04590
04591
04592 if ( -1 == uItem)
04593 {
04594 return TRUE;
04595 }
04596
04597 item = menu->items;
04598 if ( bypos )
04599 {
04600 if ( uItem >= menu->nItems ) return FALSE;
04601 item[uItem].fState |= MFS_DEFAULT;
04602 return TRUE;
04603 }
04604 else
04605 {
04606 for (i = 0; i < menu->nItems; i++, item++)
04607 {
04608 if (item->wID == uItem)
04609 {
04610 item->fState |= MFS_DEFAULT;
04611 return TRUE;
04612 }
04613 }
04614
04615 }
04616 return FALSE;
04617 }
04618
04619
04620
04621
04622 UINT WINAPI GetMenuDefaultItem(HMENU hmenu, UINT bypos, UINT flags)
04623 {
04624 POPUPMENU *menu;
04625 MENUITEM * item;
04626 UINT i = 0;
04627
04628 dprintf(("USER32: GetMenuDefaultItem"));
04629
04630
04631 if (!(menu = MENU_GetMenu(hmenu))) return -1;
04632
04633
04634 item = menu->items;
04635
04636
04637 if (! item) return -1;
04638
04639 while ( !( item->fState & MFS_DEFAULT ) )
04640 {
04641 i++; item++;
04642 if (i >= menu->nItems ) return -1;
04643 }
04644
04645
04646 if ( (!(GMDI_USEDISABLED & flags)) && (item->fState & MFS_DISABLED )) return -1;
04647
04648
04649 if ( (item->fType & MF_POPUP) && (flags & GMDI_GOINTOPOPUPS) )
04650 {
04651 UINT ret;
04652 ret = GetMenuDefaultItem( item->hSubMenu, bypos, flags );
04653 if ( -1 != ret ) return ret;
04654
04655
04656 }
04657 return ( bypos ) ? i : item->wID;
04658
04659 }
04660
04661
04662
04663
04664 BOOL WINAPI InsertMenuItemA(HMENU hMenu, UINT uItem, BOOL bypos,
04665 const MENUITEMINFOA *lpmii)
04666 {
04667 MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
04668
04669 dprintf(("USER32: InsertMenuItemA %x %d %d %x", hMenu, uItem, bypos, lpmii->wID));
04670
04671 return SetMenuItemInfo_common(item, lpmii, FALSE);
04672 }
04673
04674
04675
04676
04677
04678 BOOL WINAPI InsertMenuItemW(HMENU hMenu, UINT uItem, BOOL bypos,
04679 const MENUITEMINFOW *lpmii)
04680 {
04681 MENUITEM *item = MENU_InsertItem(hMenu, uItem, bypos ? MF_BYPOSITION : 0 );
04682
04683 dprintf(("USER32: InsertMenuItemW"));
04684
04685 return SetMenuItemInfo_common(item, (const MENUITEMINFOA*)lpmii, TRUE);
04686 }
04687
04688
04689
04690
04691
04692 BOOL WINAPI CheckMenuRadioItem(HMENU hMenu,
04693 UINT first, UINT last, UINT check,
04694 UINT bypos)
04695 {
04696 MENUITEM *mifirst, *milast, *micheck;
04697 HMENU mfirst = hMenu, mlast = hMenu, mcheck = hMenu;
04698
04699 dprintf(("USER32: CheckMenuRadioItem"));
04700
04701
04702
04703 mifirst = MENU_FindItem (&mfirst, &first, bypos);
04704 milast = MENU_FindItem (&mlast, &last, bypos);
04705 micheck = MENU_FindItem (&mcheck, &check, bypos);
04706
04707 if (mifirst == NULL || milast == NULL || micheck == NULL ||
04708 mifirst > milast || mfirst != mlast || mfirst != mcheck ||
04709 micheck > milast || micheck < mifirst)
04710 return FALSE;
04711
04712 while (mifirst <= milast)
04713 {
04714 if (mifirst == micheck)
04715 {
04716 mifirst->fType |= MFT_RADIOCHECK;
04717 mifirst->fState |= MFS_CHECKED;
04718 } else {
04719 mifirst->fType &= ~MFT_RADIOCHECK;
04720 mifirst->fState &= ~MFS_CHECKED;
04721 }
04722 mifirst++;
04723 }
04724
04725 return TRUE;
04726 }
04727
04728
04729
04730
04731
04732
04733
04734
04735
04736 BOOL WINAPI GetMenuItemRect (HWND hwnd, HMENU hMenu, UINT uItem,
04737 LPRECT rect)
04738 {
04739 POPUPMENU *itemMenu;
04740 MENUITEM *item;
04741 HWND referenceHwnd;
04742
04743
04744
04745 item = MENU_FindItem (&hMenu, &uItem, MF_BYPOSITION);
04746 referenceHwnd = hwnd;
04747
04748 if(!hwnd)
04749 {
04750 itemMenu = MENU_GetMenu(hMenu);
04751 if (itemMenu == NULL) {
04752 SetLastError(ERROR_INVALID_PARAMETER);
04753 return FALSE;
04754 }
04755
04756 if(itemMenu->hWnd == 0)
04757 return FALSE;
04758 referenceHwnd = itemMenu->hWnd;
04759 }
04760
04761 if ((rect == NULL) || (item == NULL)) {
04762 SetLastError(ERROR_INVALID_PARAMETER);
04763 return FALSE;
04764 }
04765 *rect = item->rect;
04766
04767 MapWindowPoints(referenceHwnd, 0, (LPPOINT)rect, 2);
04768 dprintf(("USER32: GetMenuItemRect %x %x %d (%d,%d)(%d,%d)", hwnd, hMenu, uItem, rect->left, rect->top, rect->right, rect->bottom));
04769
04770 return TRUE;
04771 }
04772
04773
04774
04775
04776
04777
04778
04779
04780 BOOL WINAPI SetMenuInfo (HMENU hMenu, LPCMENUINFO lpmi)
04781 {
04782 POPUPMENU *menu;
04783
04784 dprintf(("USER32: SetMenuInfo"));
04785
04786
04787 if (lpmi && (lpmi->cbSize==sizeof(MENUINFO)) && (menu=MENU_GetMenu(hMenu)))
04788 {
04789
04790 if (lpmi->fMask & MIM_BACKGROUND)
04791 menu->hbrBack = lpmi->hbrBack;
04792
04793 if (lpmi->fMask & MIM_HELPID)
04794 menu->dwContextHelpID = lpmi->dwContextHelpID;
04795
04796 if (lpmi->fMask & MIM_MAXHEIGHT)
04797 menu->cyMax = lpmi->cyMax;
04798
04799 if (lpmi->fMask & MIM_MENUDATA)
04800 menu->dwMenuData = lpmi->dwMenuData;
04801
04802 if (lpmi->fMask & MIM_STYLE)
04803 menu->dwStyle = lpmi->dwStyle;
04804
04805 return TRUE;
04806 }
04807 return FALSE;
04808 }
04809
04810
04811
04812
04813
04814
04815
04816
04817 BOOL WINAPI GetMenuInfo (HMENU hMenu, LPMENUINFO lpmi)
04818 { POPUPMENU *menu;
04819
04820 dprintf(("USER32: GetMenuInfo"));
04821
04822
04823 if (lpmi && (menu = MENU_GetMenu(hMenu)))
04824 {
04825
04826 if (lpmi->fMask & MIM_BACKGROUND)
04827 lpmi->hbrBack = menu->hbrBack;
04828
04829 if (lpmi->fMask & MIM_HELPID)
04830 lpmi->dwContextHelpID = menu->dwContextHelpID;
04831
04832 if (lpmi->fMask & MIM_MAXHEIGHT)
04833 lpmi->cyMax = menu->cyMax;
04834
04835 if (lpmi->fMask & MIM_MENUDATA)
04836 lpmi->dwMenuData = menu->dwMenuData;
04837
04838 if (lpmi->fMask & MIM_STYLE)
04839 lpmi->dwStyle = menu->dwStyle;
04840
04841 return TRUE;
04842 }
04843 return FALSE;
04844 }
04845
04846
04847
04848
04849 BOOL WINAPI SetMenuContextHelpId( HMENU hMenu, DWORD dwContextHelpID)
04850 {
04851 LPPOPUPMENU menu;
04852
04853 dprintf(("USER32: SetMenuContextHelpId"));
04854
04855
04856 menu = MENU_GetMenu(hMenu);
04857 if (menu)
04858 {
04859 menu->dwContextHelpID = dwContextHelpID;
04860 return TRUE;
04861 }
04862 return FALSE;
04863 }
04864
04865
04866
04867
04868 DWORD WINAPI GetMenuContextHelpId( HMENU hMenu )
04869 {
04870 LPPOPUPMENU menu;
04871
04872 dprintf(("USER32: GetMenuContextHelpId"));
04873
04874 menu = MENU_GetMenu(hMenu);
04875 if (menu)
04876 {
04877 return menu->dwContextHelpID;
04878 }
04879 return 0;
04880 }
04881
04882
04883
04884
04885 UINT WINAPI MenuItemFromPoint(HWND hWnd, HMENU hMenu, POINT ptScreen)
04886 {
04887 dprintf(("USER32: MenuItemFromPoint not implemented!"));
04888
04889 return 0;
04890 }
04891
04892
04893
04894
04895 BOOL IsMenuActive(void)
04896 {
04897 return pTopPopupWnd && (GetWindowLongA(pTopPopupWnd,GWL_STYLE) & WS_VISIBLE);
04898 }
04899
04900 BOOL POPUPMENU_Register()
04901 {
04902 WNDCLASSA wndClass;
04903 BOOL rc;
04904
04905
04906
04907
04908 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
04909 wndClass.style = CS_GLOBALCLASS | CS_SAVEBITS;
04910 wndClass.lpfnWndProc = (WNDPROC)PopupMenuWndProc;
04911 wndClass.cbClsExtra = 0;
04912 wndClass.cbWndExtra = sizeof(HMENU);
04913 wndClass.hCursor = LoadCursorA(0,IDC_ARROWA);
04914 wndClass.hbrBackground = NULL_BRUSH;
04915 wndClass.lpszClassName = POPUPMENUCLASSNAME;
04916
04917 rc = RegisterClassA(&wndClass);
04918 MENU_Init();
04919
04920 return rc;
04921 }
04922
04923
04924 BOOL POPUPMENU_Unregister()
04925 {
04926 if (GlobalFindAtomA(POPUPMENUCLASSNAME))
04927 return UnregisterClassA(POPUPMENUCLASSNAME,(HINSTANCE)NULL);
04928 else return FALSE;
04929 }
04930
04931
04932 #ifdef __WIN32OS2__
04933 void DisableOdinSysMenuItems()
04934 {
04935 fDisableOdinSysMenuItems = TRUE;
04936 }
04937
04938
04939 #endif