Fixes crash when calling Treeview_EndEditLabelNow and no node is
[wine.git] / dlls / shell32 / shlmenu.c
blob5b41ccc33dba94be5b0edfb7a5768356e459dfdd
1 /*
2 * see www.geocities.com/SiliconValley/4942/filemenu.html
3 */
4 #include <string.h>
6 #include "wine/obj_base.h"
7 #include "wine/obj_enumidlist.h"
8 #include "wine/obj_shellfolder.h"
9 #include "wine/undocshell.h"
11 #include "heap.h"
12 #include "debugtools.h"
13 #include "winversion.h"
14 #include "shell32_main.h"
16 #include "pidl.h"
18 BOOL WINAPI FileMenu_DeleteAllItems (HMENU hMenu);
19 BOOL WINAPI FileMenu_AppendItemA(HMENU hMenu, LPCSTR lpText, UINT uID, int icon, HMENU hMenuPopup, int nItemHeight);
21 typedef struct
23 BOOL bInitialized;
24 BOOL bFixedItems;
25 /* create */
26 COLORREF crBorderColor;
27 int nBorderWidth;
28 HBITMAP hBorderBmp;
30 /* insert using pidl */
31 LPITEMIDLIST pidl;
32 UINT uID;
33 UINT uFlags;
34 UINT uEnumFlags;
35 LPFNFMCALLBACK lpfnCallback;
36 } FMINFO, *LPFMINFO;
38 typedef struct
39 { int cchItemText;
40 int iIconIndex;
41 HMENU hMenu;
42 char szItemText[1];
43 } FMITEM, * LPFMITEM;
45 static BOOL bAbortInit;
47 #define CCH_MAXITEMTEXT 256
49 DEFAULT_DEBUG_CHANNEL(shell)
51 LPFMINFO FM_GetMenuInfo(HMENU hmenu)
52 { MENUINFO MenuInfo;
53 LPFMINFO menudata;
55 MenuInfo.cbSize = sizeof(MENUINFO);
56 MenuInfo.fMask = MIM_MENUDATA;
58 if (! GetMenuInfo(hmenu, &MenuInfo))
59 return NULL;
61 menudata = (LPFMINFO)MenuInfo.dwMenuData;
63 if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO)))
65 ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize);
66 return 0;
69 return menudata;
72 /*************************************************************************
73 * FM_SetMenuParameter [internal]
76 static LPFMINFO FM_SetMenuParameter(
77 HMENU hmenu,
78 UINT uID,
79 LPCITEMIDLIST pidl,
80 UINT uFlags,
81 UINT uEnumFlags,
82 LPFNFMCALLBACK lpfnCallback)
84 LPFMINFO menudata;
86 TRACE("\n");
88 menudata = FM_GetMenuInfo(hmenu);
90 if ( menudata->pidl)
91 { SHFree(menudata->pidl);
94 menudata->uID = uID;
95 menudata->pidl = ILClone(pidl);
96 menudata->uFlags = uFlags;
97 menudata->uEnumFlags = uEnumFlags;
98 menudata->lpfnCallback = lpfnCallback;
100 return menudata;
103 /*************************************************************************
104 * FM_InitMenuPopup [internal]
107 static int FM_InitMenuPopup(HMENU hmenu, LPITEMIDLIST pAlternatePidl)
108 { IShellFolder *lpsf, *lpsf2;
109 ULONG ulItemAttr;
110 UINT uID, uFlags, uEnumFlags;
111 LPFNFMCALLBACK lpfnCallback;
112 LPITEMIDLIST pidl;
113 char sTemp[MAX_PATH];
114 int NumberOfItems = 0, iIcon;
115 MENUINFO MenuInfo;
116 LPFMINFO menudata;
118 TRACE("0x%04x %p\n", hmenu, pAlternatePidl);
120 MenuInfo.cbSize = sizeof(MENUINFO);
121 MenuInfo.fMask = MIM_MENUDATA;
123 if (! GetMenuInfo(hmenu, &MenuInfo))
124 return FALSE;
126 menudata = (LPFMINFO)MenuInfo.dwMenuData;
128 if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO)))
130 ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize);
131 return 0;
134 if (menudata->bInitialized)
135 return 0;
137 pidl = ((pAlternatePidl) ? pAlternatePidl : menudata->pidl);
138 if (!pidl)
139 return 0;
141 uID = menudata->uID;
142 uFlags = menudata->uFlags;
143 uEnumFlags = menudata->uEnumFlags;
144 lpfnCallback = menudata->lpfnCallback;
145 menudata->bInitialized = FALSE;
147 SetMenuInfo(hmenu, &MenuInfo);
149 if (SUCCEEDED (SHGetDesktopFolder(&lpsf)))
151 if (SUCCEEDED(IShellFolder_BindToObject(lpsf, pidl,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2)))
153 IEnumIDList *lpe = NULL;
155 if (SUCCEEDED (IShellFolder_EnumObjects(lpsf2, 0, uEnumFlags, &lpe )))
158 LPITEMIDLIST pidlTemp = NULL;
159 ULONG ulFetched;
161 while ((!bAbortInit) && (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched)))
163 if (SUCCEEDED (IShellFolder_GetAttributesOf(lpsf, 1, &pidlTemp, &ulItemAttr)))
165 ILGetDisplayName( pidlTemp, sTemp);
166 if (! (PidlToSicIndex(lpsf, pidlTemp, FALSE, 0, &iIcon)))
167 iIcon = FM_BLANK_ICON;
168 if ( SFGAO_FOLDER & ulItemAttr)
170 LPFMINFO lpFmMi;
171 MENUINFO MenuInfo;
172 HMENU hMenuPopup = CreatePopupMenu();
174 lpFmMi = (LPFMINFO) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO));
176 lpFmMi->pidl = ILCombine(pidl, pidlTemp);
177 lpFmMi->uEnumFlags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
179 MenuInfo.cbSize = sizeof(MENUINFO);
180 MenuInfo.fMask = MIM_MENUDATA;
181 MenuInfo.dwMenuData = (DWORD) lpFmMi;
182 SetMenuInfo (hMenuPopup, &MenuInfo);
184 FileMenu_AppendItemA (hmenu, sTemp, uID, iIcon, hMenuPopup, FM_DEFAULT_HEIGHT);
186 else
188 ((LPSTR)PathFindExtensionA(sTemp))[0] = 0x00;
189 FileMenu_AppendItemA (hmenu, sTemp, uID, iIcon, 0, FM_DEFAULT_HEIGHT);
193 if (lpfnCallback)
195 TRACE("enter callback\n");
196 lpfnCallback ( pidl, pidlTemp);
197 TRACE("leave callback\n");
200 NumberOfItems++;
202 IEnumIDList_Release (lpe);
204 IShellFolder_Release(lpsf2);
206 IShellFolder_Release(lpsf);
209 if ( GetMenuItemCount (hmenu) == 0 )
210 { FileMenu_AppendItemA (hmenu, "(empty)", uID, FM_BLANK_ICON, 0, FM_DEFAULT_HEIGHT);
211 NumberOfItems++;
214 menudata->bInitialized = TRUE;
215 SetMenuInfo(hmenu, &MenuInfo);
217 return NumberOfItems;
219 /*************************************************************************
220 * FileMenu_Create [SHELL32.114]
222 * NOTES
223 * for non-root menus values are
224 * (ffffffff,00000000,00000000,00000000,00000000)
226 HMENU WINAPI FileMenu_Create (
227 COLORREF crBorderColor,
228 int nBorderWidth,
229 HBITMAP hBorderBmp,
230 int nSelHeight,
231 UINT uFlags)
233 MENUINFO MenuInfo;
234 LPFMINFO menudata;
236 HMENU hMenu = CreatePopupMenu();
238 TRACE("0x%08lx 0x%08x 0x%08x 0x%08x 0x%08x hMenu=0x%08x\n",
239 crBorderColor, nBorderWidth, hBorderBmp, nSelHeight, uFlags, hMenu);
241 menudata = (LPFMINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO));
242 menudata->crBorderColor = crBorderColor;
243 menudata->nBorderWidth = nBorderWidth;
244 menudata->hBorderBmp = hBorderBmp;
246 MenuInfo.cbSize = sizeof(MENUINFO);
247 MenuInfo.fMask = MIM_MENUDATA;
248 MenuInfo.dwMenuData = (DWORD) menudata;
249 SetMenuInfo (hMenu, &MenuInfo);
251 return hMenu;
254 /*************************************************************************
255 * FileMenu_Destroy [SHELL32.118]
257 * NOTES
258 * exported by name
260 void WINAPI FileMenu_Destroy (HMENU hmenu)
262 LPFMINFO menudata;
264 TRACE("0x%08x\n", hmenu);
266 FileMenu_DeleteAllItems (hmenu);
268 menudata = FM_GetMenuInfo(hmenu);
270 if ( menudata->pidl)
271 { SHFree( menudata->pidl);
273 HeapFree(GetProcessHeap(), 0, menudata);
275 DestroyMenu (hmenu);
278 /*************************************************************************
279 * FileMenu_AppendItemAW [SHELL32.115]
282 BOOL WINAPI FileMenu_AppendItemA(
283 HMENU hMenu,
284 LPCSTR lpText,
285 UINT uID,
286 int icon,
287 HMENU hMenuPopup,
288 int nItemHeight)
290 LPSTR lpszText = (LPSTR)lpText;
291 MENUITEMINFOA mii;
292 LPFMITEM myItem;
293 LPFMINFO menudata;
294 MENUINFO MenuInfo;
297 TRACE("0x%08x %s 0x%08x 0x%08x 0x%08x 0x%08x\n",
298 hMenu, (lpszText!=FM_SEPARATOR) ? lpText: NULL,
299 uID, icon, hMenuPopup, nItemHeight);
301 ZeroMemory (&mii, sizeof(MENUITEMINFOA));
303 mii.cbSize = sizeof(MENUITEMINFOA);
305 if (lpText != FM_SEPARATOR)
306 { int len = strlen (lpText);
307 myItem = (LPFMITEM) SHAlloc( sizeof(FMITEM) + len);
308 strcpy (myItem->szItemText, lpText);
309 myItem->cchItemText = len;
310 myItem->iIconIndex = icon;
311 myItem->hMenu = hMenu;
312 mii.fMask = MIIM_DATA;
313 mii.dwItemData = (DWORD) myItem;
316 if ( hMenuPopup )
317 { /* sub menu */
318 mii.fMask |= MIIM_TYPE | MIIM_SUBMENU;
319 mii.fType = MFT_OWNERDRAW;
320 mii.hSubMenu = hMenuPopup;
322 else if (lpText == FM_SEPARATOR )
323 { mii.fMask |= MIIM_ID | MIIM_TYPE;
324 mii.fType = MFT_SEPARATOR;
326 else
327 { /* normal item */
328 mii.fMask |= MIIM_ID | MIIM_TYPE | MIIM_STATE;
329 mii.fState = MFS_ENABLED | MFS_DEFAULT;
330 mii.fType = MFT_OWNERDRAW;
332 mii.wID = uID;
334 InsertMenuItemA (hMenu, (UINT)-1, TRUE, &mii);
336 /* set bFixedItems to true */
337 MenuInfo.cbSize = sizeof(MENUINFO);
338 MenuInfo.fMask = MIM_MENUDATA;
340 if (! GetMenuInfo(hMenu, &MenuInfo))
341 return FALSE;
343 menudata = (LPFMINFO)MenuInfo.dwMenuData;
344 if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO)))
346 ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize);
347 return 0;
350 menudata->bFixedItems = TRUE;
351 SetMenuInfo(hMenu, &MenuInfo);
353 return TRUE;
356 BOOL WINAPI FileMenu_AppendItemAW(
357 HMENU hMenu,
358 LPCVOID lpText,
359 UINT uID,
360 int icon,
361 HMENU hMenuPopup,
362 int nItemHeight)
364 BOOL ret;
365 LPSTR lpszText=NULL;
367 if (VERSION_OsIsUnicode() && (lpText!=FM_SEPARATOR))
368 lpszText = HEAP_strdupWtoA ( GetProcessHeap(),0, lpText);
370 ret = FileMenu_AppendItemA(hMenu, (lpszText) ? lpszText : lpText, uID, icon, hMenuPopup, nItemHeight);
372 if (lpszText)
373 HeapFree( GetProcessHeap(), 0, lpszText );
375 return ret;
377 /*************************************************************************
378 * FileMenu_InsertUsingPidl [SHELL32.110]
380 * NOTES
381 * uEnumFlags any SHCONTF flag
383 int WINAPI FileMenu_InsertUsingPidl (
384 HMENU hmenu,
385 UINT uID,
386 LPCITEMIDLIST pidl,
387 UINT uFlags,
388 UINT uEnumFlags,
389 LPFNFMCALLBACK lpfnCallback)
391 TRACE("0x%08x 0x%08x %p 0x%08x 0x%08x %p\n",
392 hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
394 pdump (pidl);
396 bAbortInit = FALSE;
398 FM_SetMenuParameter(hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
400 return FM_InitMenuPopup(hmenu, NULL);
403 /*************************************************************************
404 * FileMenu_ReplaceUsingPidl [SHELL32.113]
406 * FIXME: the static items are deleted but wont be refreshed
408 int WINAPI FileMenu_ReplaceUsingPidl(
409 HMENU hmenu,
410 UINT uID,
411 LPCITEMIDLIST pidl,
412 UINT uEnumFlags,
413 LPFNFMCALLBACK lpfnCallback)
415 TRACE("0x%08x 0x%08x %p 0x%08x %p\n",
416 hmenu, uID, pidl, uEnumFlags, lpfnCallback);
418 FileMenu_DeleteAllItems (hmenu);
420 FM_SetMenuParameter(hmenu, uID, pidl, 0, uEnumFlags, lpfnCallback);
422 return FM_InitMenuPopup(hmenu, NULL);
425 /*************************************************************************
426 * FileMenu_Invalidate [SHELL32.111]
428 void WINAPI FileMenu_Invalidate (HMENU hMenu)
430 FIXME("0x%08x\n",hMenu);
433 /*************************************************************************
434 * FileMenu_FindSubMenuByPidl [SHELL32.106]
436 HMENU WINAPI FileMenu_FindSubMenuByPidl(
437 HMENU hMenu,
438 LPCITEMIDLIST pidl)
440 FIXME("0x%08x %p\n",hMenu, pidl);
441 return 0;
444 /*************************************************************************
445 * FileMenu_AppendFilesForPidl [SHELL32.124]
447 int WINAPI FileMenu_AppendFilesForPidl(
448 HMENU hmenu,
449 LPCITEMIDLIST pidl,
450 BOOL bAddSeperator)
452 LPFMINFO menudata;
454 menudata = FM_GetMenuInfo(hmenu);
456 menudata->bInitialized = FALSE;
458 FM_InitMenuPopup(hmenu, pidl);
460 if (bAddSeperator)
461 FileMenu_AppendItemA (hmenu, FM_SEPARATOR, 0, 0, 0, FM_DEFAULT_HEIGHT);
463 TRACE("0x%08x %p 0x%08x\n",hmenu, pidl,bAddSeperator);
465 return 0;
467 /*************************************************************************
468 * FileMenu_AddFilesForPidl [SHELL32.125]
470 * NOTES
471 * uEnumFlags any SHCONTF flag
473 int WINAPI FileMenu_AddFilesForPidl (
474 HMENU hmenu,
475 UINT uReserved,
476 UINT uID,
477 LPCITEMIDLIST pidl,
478 UINT uFlags,
479 UINT uEnumFlags,
480 LPFNFMCALLBACK lpfnCallback)
482 TRACE("0x%08x 0x%08x 0x%08x %p 0x%08x 0x%08x %p\n",
483 hmenu, uReserved, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
485 return FileMenu_InsertUsingPidl ( hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
490 /*************************************************************************
491 * FileMenu_TrackPopupMenuEx [SHELL32.116]
493 BOOL WINAPI FileMenu_TrackPopupMenuEx (
494 HMENU hMenu,
495 UINT uFlags,
496 int x,
497 int y,
498 HWND hWnd,
499 LPTPMPARAMS lptpm)
501 TRACE("0x%08x 0x%08x 0x%x 0x%x 0x%08x %p\n",
502 hMenu, uFlags, x, y, hWnd, lptpm);
503 return TrackPopupMenuEx(hMenu, uFlags, x, y, hWnd, lptpm);
506 /*************************************************************************
507 * FileMenu_GetLastSelectedItemPidls [SHELL32.107]
509 BOOL WINAPI FileMenu_GetLastSelectedItemPidls(
510 UINT uReserved,
511 LPCITEMIDLIST *ppidlFolder,
512 LPCITEMIDLIST *ppidlItem)
514 FIXME("0x%08x %p %p\n",uReserved, ppidlFolder, ppidlItem);
515 return 0;
518 #define FM_ICON_SIZE 16
519 #define FM_Y_SPACE 4
520 #define FM_SPACE1 4
521 #define FM_SPACE2 2
522 #define FM_LEFTBORDER 2
523 #define FM_RIGHTBORDER 8
524 /*************************************************************************
525 * FileMenu_MeasureItem [SHELL32.112]
527 LRESULT WINAPI FileMenu_MeasureItem(
528 HWND hWnd,
529 LPMEASUREITEMSTRUCT lpmis)
531 LPFMITEM pMyItem = (LPFMITEM)(lpmis->itemData);
532 HDC hdc = GetDC(hWnd);
533 SIZE size;
534 LPFMINFO menuinfo;
536 TRACE("0x%08x %p %s\n", hWnd, lpmis, pMyItem->szItemText);
538 GetTextExtentPoint32A(hdc, pMyItem->szItemText, pMyItem->cchItemText, &size);
540 lpmis->itemWidth = size.cx + FM_LEFTBORDER + FM_ICON_SIZE + FM_SPACE1 + FM_SPACE2 + FM_RIGHTBORDER;
541 lpmis->itemHeight = (size.cy > (FM_ICON_SIZE + FM_Y_SPACE)) ? size.cy : (FM_ICON_SIZE + FM_Y_SPACE);
543 /* add the menubitmap */
544 menuinfo = FM_GetMenuInfo(pMyItem->hMenu);
545 if (menuinfo->nBorderWidth)
546 lpmis->itemWidth += menuinfo->nBorderWidth;
548 TRACE("-- 0x%04x 0x%04x\n", lpmis->itemWidth, lpmis->itemHeight);
549 ReleaseDC (hWnd, hdc);
550 return 0;
552 /*************************************************************************
553 * FileMenu_DrawItem [SHELL32.105]
555 LRESULT WINAPI FileMenu_DrawItem(
556 HWND hWnd,
557 LPDRAWITEMSTRUCT lpdis)
559 LPFMITEM pMyItem = (LPFMITEM)(lpdis->itemData);
560 COLORREF clrPrevText, clrPrevBkgnd;
561 int xi,yi,xt,yt;
562 HIMAGELIST hImageList;
563 RECT TextRect, BorderRect;
564 LPFMINFO menuinfo;
566 TRACE("0x%08x %p %s\n", hWnd, lpdis, pMyItem->szItemText);
568 if (lpdis->itemState & ODS_SELECTED)
570 clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHTTEXT));
571 clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHT));
573 else
575 clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_MENUTEXT));
576 clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_MENU));
579 CopyRect(&TextRect, &(lpdis->rcItem));
581 /* add the menubitmap */
582 menuinfo = FM_GetMenuInfo(pMyItem->hMenu);
583 if (menuinfo->nBorderWidth)
584 TextRect.left += menuinfo->nBorderWidth;
586 BorderRect.right = menuinfo->nBorderWidth;
587 /* FillRect(lpdis->hDC, &BorderRect, CreateSolidBrush( menuinfo->crBorderColor));
589 TextRect.left += FM_LEFTBORDER;
590 xi = TextRect.left + FM_SPACE1;
591 yi = TextRect.top + FM_Y_SPACE/2;
592 TextRect.bottom -= FM_Y_SPACE/2;
594 xt = xi + FM_ICON_SIZE + FM_SPACE2;
595 yt = yi;
597 ExtTextOutA (lpdis->hDC, xt , yt, ETO_OPAQUE, &TextRect, pMyItem->szItemText, pMyItem->cchItemText, NULL);
599 Shell_GetImageList(0, &hImageList);
600 pImageList_Draw(hImageList, pMyItem->iIconIndex, lpdis->hDC, xi, yi, ILD_NORMAL);
602 TRACE("-- 0x%04x 0x%04x 0x%04x 0x%04x\n", TextRect.left, TextRect.top, TextRect.right, TextRect.bottom);
604 SetTextColor(lpdis->hDC, clrPrevText);
605 SetBkColor(lpdis->hDC, clrPrevBkgnd);
607 return TRUE;
610 /*************************************************************************
611 * FileMenu_InitMenuPopup [SHELL32.109]
613 * NOTES
614 * The filemenu is a ownerdrawn menu. Call this function responding to
615 * WM_INITPOPUPMENU
618 BOOL WINAPI FileMenu_InitMenuPopup (HMENU hmenu)
620 FM_InitMenuPopup(hmenu, NULL);
621 return TRUE;
624 /*************************************************************************
625 * FileMenu_HandleMenuChar [SHELL32.108]
627 LRESULT WINAPI FileMenu_HandleMenuChar(
628 HMENU hMenu,
629 WPARAM wParam)
631 FIXME("0x%08x 0x%08x\n",hMenu,wParam);
632 return 0;
635 /*************************************************************************
636 * FileMenu_DeleteAllItems [SHELL32.104]
638 * NOTES
639 * exported by name
641 BOOL WINAPI FileMenu_DeleteAllItems (HMENU hmenu)
643 MENUITEMINFOA mii;
644 LPFMINFO menudata;
646 int i;
648 TRACE("0x%08x\n", hmenu);
650 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
651 mii.cbSize = sizeof(MENUITEMINFOA);
652 mii.fMask = MIIM_SUBMENU|MIIM_DATA;
654 for (i = 0; i < GetMenuItemCount( hmenu ); i++)
655 { GetMenuItemInfoA(hmenu, i, TRUE, &mii );
657 if (mii.dwItemData)
658 SHFree((LPFMINFO)mii.dwItemData);
660 if (mii.hSubMenu)
661 FileMenu_Destroy(mii.hSubMenu);
664 while (DeleteMenu (hmenu, 0, MF_BYPOSITION)){};
666 menudata = FM_GetMenuInfo(hmenu);
668 menudata->bInitialized = FALSE;
670 return TRUE;
673 /*************************************************************************
674 * FileMenu_DeleteItemByCmd [SHELL32.]
677 BOOL WINAPI FileMenu_DeleteItemByCmd (HMENU hMenu, UINT uID)
679 MENUITEMINFOA mii;
681 TRACE("0x%08x 0x%08x\n", hMenu, uID);
683 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
684 mii.cbSize = sizeof(MENUITEMINFOA);
685 mii.fMask = MIIM_SUBMENU;
687 GetMenuItemInfoA(hMenu, uID, FALSE, &mii );
688 if ( mii.hSubMenu );
690 DeleteMenu(hMenu, MF_BYCOMMAND, uID);
691 return TRUE;
694 /*************************************************************************
695 * FileMenu_DeleteItemByIndex [SHELL32.140]
697 BOOL WINAPI FileMenu_DeleteItemByIndex ( HMENU hMenu, UINT uPos)
699 MENUITEMINFOA mii;
701 TRACE("0x%08x 0x%08x\n", hMenu, uPos);
703 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
704 mii.cbSize = sizeof(MENUITEMINFOA);
705 mii.fMask = MIIM_SUBMENU;
707 GetMenuItemInfoA(hMenu, uPos, TRUE, &mii );
708 if ( mii.hSubMenu );
710 DeleteMenu(hMenu, MF_BYPOSITION, uPos);
711 return TRUE;
714 /*************************************************************************
715 * FileMenu_DeleteItemByFirstID [SHELL32.141]
717 BOOL WINAPI FileMenu_DeleteItemByFirstID(
718 HMENU hMenu,
719 UINT uID)
721 TRACE("0x%08x 0x%08x\n", hMenu, uID);
722 return 0;
725 /*************************************************************************
726 * FileMenu_DeleteSeparator [SHELL32.142]
728 BOOL WINAPI FileMenu_DeleteSeparator(HMENU hMenu)
730 TRACE("0x%08x\n", hMenu);
731 return 0;
734 /*************************************************************************
735 * FileMenu_EnableItemByCmd [SHELL32.143]
737 BOOL WINAPI FileMenu_EnableItemByCmd(
738 HMENU hMenu,
739 UINT uID,
740 BOOL bEnable)
742 TRACE("0x%08x 0x%08x 0x%08x\n", hMenu, uID,bEnable);
743 return 0;
746 /*************************************************************************
747 * FileMenu_GetItemExtent [SHELL32.144]
749 * NOTES
750 * if the menu is to big, entrys are getting cut away!!
752 DWORD WINAPI FileMenu_GetItemExtent (HMENU hMenu, UINT uPos)
753 { RECT rect;
755 FIXME("0x%08x 0x%08x\n", hMenu, uPos);
757 if (GetMenuItemRect(0, hMenu, uPos, &rect))
758 { FIXME("0x%04x 0x%04x 0x%04x 0x%04x\n",
759 rect.right, rect.left, rect.top, rect.bottom);
760 return ((rect.right-rect.left)<<16) + (rect.top-rect.bottom);
762 return 0x00100010; /*fixme*/
765 /*************************************************************************
766 * FileMenu_AbortInitMenu [SHELL32.120]
769 void WINAPI FileMenu_AbortInitMenu (void)
770 { TRACE("\n");
771 bAbortInit = TRUE;
774 /*************************************************************************
775 * SHFind_InitMenuPopup [SHELL32.149]
778 * PARAMETERS
779 * hMenu [in] handle of menu previously created
780 * hWndParent [in] parent window
781 * w [in] no pointer (0x209 over here) perhaps menu IDs ???
782 * x [in] no pointer (0x226 over here)
784 * RETURNS
785 * LPXXXXX pointer to struct containing a func addr at offset 8
786 * or NULL at failure.
788 LPVOID WINAPI SHFind_InitMenuPopup (HMENU hMenu, HWND hWndParent, DWORD w, DWORD x)
789 { FIXME("hmenu=0x%08x hwnd=0x%08x 0x%08lx 0x%08lx stub\n",
790 hMenu,hWndParent,w,x);
791 return NULL; /* this is supposed to be a pointer */
794 /*************************************************************************
795 * Shell_MergeMenus [SHELL32.67]
798 BOOL _SHIsMenuSeparator(HMENU hm, int i)
800 MENUITEMINFOA mii;
802 mii.cbSize = sizeof(MENUITEMINFOA);
803 mii.fMask = MIIM_TYPE;
804 mii.cch = 0; /* WARNING: We MUST initialize it to 0*/
805 if (!GetMenuItemInfoA(hm, i, TRUE, &mii))
807 return(FALSE);
810 if (mii.fType & MFT_SEPARATOR)
812 return(TRUE);
815 return(FALSE);
818 HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags)
819 { int nItem;
820 HMENU hmSubMenu;
821 BOOL bAlreadySeparated;
822 MENUITEMINFOA miiSrc;
823 char szName[256];
824 UINT uTemp, uIDMax = uIDAdjust;
826 TRACE("hmenu1=0x%04x hmenu2=0x%04x 0x%04x 0x%04x 0x%04x 0x%04lx\n",
827 hmDst, hmSrc, uInsert, uIDAdjust, uIDAdjustMax, uFlags);
829 if (!hmDst || !hmSrc)
830 { return uIDMax;
833 nItem = GetMenuItemCount(hmDst);
835 if (uInsert >= (UINT)nItem) /* insert position inside menu? */
837 uInsert = (UINT)nItem; /* append on the end */
838 bAlreadySeparated = TRUE;
840 else
842 bAlreadySeparated = _SHIsMenuSeparator(hmDst, uInsert);;
845 if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
847 /* Add a separator between the menus */
848 InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
849 bAlreadySeparated = TRUE;
853 /* Go through the menu items and clone them*/
854 for (nItem = GetMenuItemCount(hmSrc) - 1; nItem >= 0; nItem--)
856 miiSrc.cbSize = sizeof(MENUITEMINFOA);
857 miiSrc.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA;
859 /* We need to reset this every time through the loop in case menus DON'T have IDs*/
860 miiSrc.fType = MFT_STRING;
861 miiSrc.dwTypeData = szName;
862 miiSrc.dwItemData = 0;
863 miiSrc.cch = sizeof(szName);
865 if (!GetMenuItemInfoA(hmSrc, nItem, TRUE, &miiSrc))
867 continue;
870 /* TRACE("found menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmSrc, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask, miiSrc.hSubMenu);
872 if (miiSrc.fType & MFT_SEPARATOR)
874 /* This is a separator; don't put two of them in a row */
875 if (bAlreadySeparated)
876 continue;
878 bAlreadySeparated = TRUE;
880 else if (miiSrc.hSubMenu)
882 if (uFlags & MM_SUBMENUSHAVEIDS)
884 miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */
886 if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */
887 continue;
889 if (uIDMax <= miiSrc.wID) /* remember the highest ID */
890 uIDMax = miiSrc.wID + 1;
892 else
894 miiSrc.fMask &= ~MIIM_ID; /* Don't set IDs for submenus that didn't have them already */
896 hmSubMenu = miiSrc.hSubMenu;
898 miiSrc.hSubMenu = CreatePopupMenu();
900 if (!miiSrc.hSubMenu) return(uIDMax);
902 uTemp = Shell_MergeMenus(miiSrc.hSubMenu, hmSubMenu, 0, uIDAdjust, uIDAdjustMax, uFlags & MM_SUBMENUSHAVEIDS);
904 if (uIDMax <= uTemp)
905 uIDMax = uTemp;
907 bAlreadySeparated = FALSE;
909 else /* normal menu item */
911 miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */
913 if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */
914 continue;
916 if (uIDMax <= miiSrc.wID) /* remember the highest ID */
917 uIDMax = miiSrc.wID + 1;
919 bAlreadySeparated = FALSE;
922 /* TRACE("inserting menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmDst, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask, miiSrc.hSubMenu);
924 if (!InsertMenuItemA(hmDst, uInsert, TRUE, &miiSrc))
926 return(uIDMax);
930 /* Ensure the correct number of separators at the beginning of the
931 inserted menu items*/
932 if (uInsert == 0)
934 if (bAlreadySeparated)
936 DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
939 else
941 if (_SHIsMenuSeparator(hmDst, uInsert-1))
943 if (bAlreadySeparated)
945 DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
948 else
950 if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
952 /* Add a separator between the menus*/
953 InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
957 return(uIDMax);