Implemented SHCreateShellFolderViewEx.
[wine.git] / dlls / shell32 / shlmenu.c
blob861ec4503590d85db5d0eaf93f9b5c5eab784ce0
1 /*
2 * see www.geocities.com/SiliconValley/4942/filemenu.html
3 */
4 #include <assert.h>
5 #include <string.h>
7 #include "wine/obj_base.h"
8 #include "wine/obj_enumidlist.h"
9 #include "wine/obj_shellfolder.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
22 { BOOL bInitialized;
23 BOOL bIsMagic;
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 assert ((menudata != 0) && (MenuInfo.cbSize == sizeof(MENUINFO)));
65 return menudata;
68 /*************************************************************************
69 * FM_SetMenuParameter [internal]
72 static LPFMINFO FM_SetMenuParameter(
73 HMENU hmenu,
74 UINT uID,
75 LPCITEMIDLIST pidl,
76 UINT uFlags,
77 UINT uEnumFlags,
78 LPFNFMCALLBACK lpfnCallback)
80 LPFMINFO menudata;
82 TRACE("\n");
84 menudata = FM_GetMenuInfo(hmenu);
86 if ( menudata->pidl)
87 { SHFree(menudata->pidl);
90 menudata->uID = uID;
91 menudata->pidl = ILClone(pidl);
92 menudata->uFlags = uFlags;
93 menudata->uEnumFlags = uEnumFlags;
94 menudata->lpfnCallback = lpfnCallback;
96 return menudata;
99 /*************************************************************************
100 * FM_InitMenuPopup [internal]
103 static int FM_InitMenuPopup(HMENU hmenu, LPITEMIDLIST pAlternatePidl)
104 { IShellFolder *lpsf, *lpsf2;
105 ULONG ulItemAttr;
106 UINT uID, uFlags, uEnumFlags;
107 LPFNFMCALLBACK lpfnCallback;
108 LPITEMIDLIST pidl;
109 char sTemp[MAX_PATH];
110 int NumberOfItems = 0, iIcon;
111 MENUINFO MenuInfo;
112 LPFMINFO menudata;
114 TRACE("\n");
116 MenuInfo.cbSize = sizeof(MENUINFO);
117 MenuInfo.fMask = MIM_MENUDATA;
119 if (! GetMenuInfo(hmenu, &MenuInfo))
120 return FALSE;
122 menudata = (LPFMINFO)MenuInfo.dwMenuData;
124 assert ((menudata != 0) && (MenuInfo.cbSize == sizeof(MENUINFO)));
126 if (menudata->bInitialized)
127 return 0;
129 uID = menudata->uID;
130 pidl = ((pAlternatePidl) ? pAlternatePidl : menudata->pidl);
131 uFlags = menudata->uFlags;
132 uEnumFlags = menudata->uEnumFlags;
133 lpfnCallback = menudata->lpfnCallback;
135 menudata->bInitialized = FALSE;
136 SetMenuInfo(hmenu, &MenuInfo);
138 if (SUCCEEDED (SHGetDesktopFolder(&lpsf)))
140 if (SUCCEEDED(IShellFolder_BindToObject(lpsf, pidl,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2)))
142 IEnumIDList *lpe = NULL;
144 if (SUCCEEDED (IShellFolder_EnumObjects(lpsf2, 0, uEnumFlags, &lpe )))
147 LPITEMIDLIST pidlTemp = NULL;
148 ULONG ulFetched;
150 while ((!bAbortInit) && (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched)))
152 if (SUCCEEDED (IShellFolder_GetAttributesOf(lpsf, 1, &pidlTemp, &ulItemAttr)))
154 ILGetDisplayName( pidlTemp, sTemp);
155 if (! (PidlToSicIndex(lpsf, pidlTemp, FALSE, &iIcon)))
156 iIcon = FM_BLANK_ICON;
157 if ( SFGAO_FOLDER & ulItemAttr)
159 LPFMINFO lpFmMi;
160 MENUINFO MenuInfo;
161 HMENU hMenuPopup = CreatePopupMenu();
163 lpFmMi = (LPFMINFO) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO));
165 lpFmMi->pidl = ILCombine(pidl, pidlTemp);
166 lpFmMi->uEnumFlags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
168 MenuInfo.cbSize = sizeof(MENUINFO);
169 MenuInfo.fMask = MIM_MENUDATA;
170 MenuInfo.dwMenuData = (DWORD) lpFmMi;
171 SetMenuInfo (hMenuPopup, &MenuInfo);
173 FileMenu_AppendItemA (hmenu, sTemp, uID, iIcon, hMenuPopup, FM_DEFAULT_HEIGHT);
175 else
177 ((LPSTR)PathFindExtensionA(sTemp))[0] = 0x00;
178 FileMenu_AppendItemA (hmenu, sTemp, uID, iIcon, 0, FM_DEFAULT_HEIGHT);
182 if (lpfnCallback)
184 TRACE("enter callback\n");
185 lpfnCallback ( pidl, pidlTemp);
186 TRACE("leave callback\n");
189 NumberOfItems++;
191 IEnumIDList_Release (lpe);
193 IShellFolder_Release(lpsf2);
195 IShellFolder_Release(lpsf);
198 if ( GetMenuItemCount (hmenu) == 0 )
199 { FileMenu_AppendItemA (hmenu, "(empty)", uID, FM_BLANK_ICON, 0, FM_DEFAULT_HEIGHT);
200 NumberOfItems++;
203 menudata->bInitialized = TRUE;
204 SetMenuInfo(hmenu, &MenuInfo);
206 return NumberOfItems;
208 /*************************************************************************
209 * FileMenu_Create [SHELL32.114]
212 HMENU WINAPI FileMenu_Create (
213 COLORREF crBorderColor,
214 int nBorderWidth,
215 HBITMAP hBorderBmp,
216 int nSelHeight,
217 UINT uFlags)
219 MENUINFO MenuInfo;
220 LPFMINFO menudata;
222 HMENU hMenu = CreatePopupMenu();
224 TRACE("0x%08lx 0x%08x 0x%08x 0x%08x 0x%08x hMenu=0x%08x\n",
225 crBorderColor, nBorderWidth, hBorderBmp, nSelHeight, uFlags, hMenu);
227 menudata = (LPFMINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO));
228 menudata->bIsMagic = TRUE;
229 menudata->crBorderColor = crBorderColor;
230 menudata->nBorderWidth = nBorderWidth;
231 menudata->hBorderBmp = hBorderBmp;
233 MenuInfo.cbSize = sizeof(MENUINFO);
234 MenuInfo.fMask = MIM_MENUDATA;
235 MenuInfo.dwMenuData = (DWORD) menudata;
236 SetMenuInfo (hMenu, &MenuInfo);
238 return hMenu;
241 /*************************************************************************
242 * FileMenu_Destroy [SHELL32.118]
244 * NOTES
245 * exported by name
247 void WINAPI FileMenu_Destroy (HMENU hmenu)
249 LPFMINFO menudata;
251 TRACE("0x%08x\n", hmenu);
253 FileMenu_DeleteAllItems (hmenu);
255 menudata = FM_GetMenuInfo(hmenu);
257 if ( menudata->pidl)
258 { SHFree( menudata->pidl);
260 HeapFree(GetProcessHeap(), 0, menudata);
262 DestroyMenu (hmenu);
265 /*************************************************************************
266 * FileMenu_AppendItemAW [SHELL32.115]
269 BOOL WINAPI FileMenu_AppendItemA(
270 HMENU hMenu,
271 LPCSTR lpText,
272 UINT uID,
273 int icon,
274 HMENU hMenuPopup,
275 int nItemHeight)
277 LPSTR lpszText = (LPSTR)lpText;
278 MENUITEMINFOA mii;
279 LPFMITEM myItem;
281 TRACE("0x%08x %s 0x%08x 0x%08x 0x%08x 0x%08x\n",
282 hMenu, (lpszText!=FM_SEPARATOR) ? lpText: NULL,
283 uID, icon, hMenuPopup, nItemHeight);
285 ZeroMemory (&mii, sizeof(MENUITEMINFOA));
287 mii.cbSize = sizeof(MENUITEMINFOA);
289 if (lpText != FM_SEPARATOR)
290 { int len = strlen (lpText);
291 myItem = (LPFMITEM) SHAlloc( sizeof(FMITEM) + len);
292 strcpy (myItem->szItemText, lpText);
293 myItem->cchItemText = len;
294 myItem->iIconIndex = icon;
295 myItem->hMenu = hMenu;
296 mii.fMask = MIIM_DATA;
297 mii.dwItemData = (DWORD) myItem;
300 if ( hMenuPopup )
301 { /* sub menu */
302 mii.fMask |= MIIM_TYPE | MIIM_SUBMENU;
303 mii.fType = MFT_OWNERDRAW;
304 mii.hSubMenu = hMenuPopup;
306 else if (lpText == FM_SEPARATOR )
307 { mii.fMask |= MIIM_ID | MIIM_TYPE;
308 mii.fType = MFT_SEPARATOR;
310 else
311 { /* normal item */
312 mii.fMask |= MIIM_ID | MIIM_TYPE | MIIM_STATE;
313 mii.fState = MFS_ENABLED | MFS_DEFAULT;
314 mii.fType = MFT_OWNERDRAW;
316 mii.wID = uID;
318 InsertMenuItemA (hMenu, (UINT)-1, TRUE, &mii);
320 return TRUE;
323 BOOL WINAPI FileMenu_AppendItemAW(
324 HMENU hMenu,
325 LPCVOID lpText,
326 UINT uID,
327 int icon,
328 HMENU hMenuPopup,
329 int nItemHeight)
331 BOOL ret;
332 LPSTR lpszText=NULL;
334 if (VERSION_OsIsUnicode() && (lpText!=FM_SEPARATOR))
335 lpszText = HEAP_strdupWtoA ( GetProcessHeap(),0, lpText);
337 ret = FileMenu_AppendItemA(hMenu, (lpszText) ? lpszText : lpText, uID, icon, hMenuPopup, nItemHeight);
339 if (lpszText)
340 HeapFree( GetProcessHeap(), 0, lpszText );
342 return ret;
344 /*************************************************************************
345 * FileMenu_InsertUsingPidl [SHELL32.110]
347 * NOTES
348 * uEnumFlags any SHCONTF flag
350 int WINAPI FileMenu_InsertUsingPidl (
351 HMENU hmenu,
352 UINT uID,
353 LPCITEMIDLIST pidl,
354 UINT uFlags,
355 UINT uEnumFlags,
356 LPFNFMCALLBACK lpfnCallback)
358 TRACE("0x%08x 0x%08x %p 0x%08x 0x%08x %p\n",
359 hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
361 pdump (pidl);
363 bAbortInit = FALSE;
365 FM_SetMenuParameter(hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
367 return FM_InitMenuPopup(hmenu, NULL);
370 /*************************************************************************
371 * FileMenu_ReplaceUsingPidl [SHELL32.113]
374 int WINAPI FileMenu_ReplaceUsingPidl(
375 HMENU hmenu,
376 UINT uID,
377 LPCITEMIDLIST pidl,
378 UINT uEnumFlags,
379 LPFNFMCALLBACK lpfnCallback)
381 TRACE("0x%08x 0x%08x %p 0x%08x %p\n",
382 hmenu, uID, pidl, uEnumFlags, lpfnCallback);
384 FileMenu_DeleteAllItems (hmenu);
386 FM_SetMenuParameter(hmenu, uID, pidl, 0, uEnumFlags, lpfnCallback);
388 return FM_InitMenuPopup(hmenu, NULL);
391 /*************************************************************************
392 * FileMenu_Invalidate [SHELL32.111]
394 void WINAPI FileMenu_Invalidate (HMENU hMenu)
396 FIXME("0x%08x\n",hMenu);
399 /*************************************************************************
400 * FileMenu_FindSubMenuByPidl [SHELL32.106]
402 HMENU WINAPI FileMenu_FindSubMenuByPidl(
403 HMENU hMenu,
404 LPCITEMIDLIST pidl)
406 FIXME("0x%08x %p\n",hMenu, pidl);
407 return 0;
410 /*************************************************************************
411 * FileMenu_AppendFilesForPidl [SHELL32.124]
413 HMENU WINAPI FileMenu_AppendFilesForPidl(
414 HMENU hmenu,
415 LPCITEMIDLIST pidl,
416 BOOL bAddSeperator)
418 LPFMINFO menudata;
420 menudata = FM_GetMenuInfo(hmenu);
422 menudata->bInitialized = FALSE;
424 FM_InitMenuPopup(hmenu, pidl);
426 if (bAddSeperator)
427 FileMenu_AppendItemA (hmenu, FM_SEPARATOR, 0, 0, 0, FM_DEFAULT_HEIGHT);
429 TRACE("0x%08x %p 0x%08x\n",hmenu, pidl,bAddSeperator);
431 return 0;
433 /*************************************************************************
434 * FileMenu_AddFilesForPidl [SHELL32.125]
436 * NOTES
437 * uEnumFlags any SHCONTF flag
439 int WINAPI FileMenu_AddFilesForPidl (
440 HMENU hmenu,
441 UINT uReserved,
442 UINT uID,
443 LPCITEMIDLIST pidl,
444 UINT uFlags,
445 UINT uEnumFlags,
446 LPFNFMCALLBACK lpfnCallback)
448 TRACE("0x%08x 0x%08x 0x%08x %p 0x%08x 0x%08x %p\n",
449 hmenu, uReserved, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
451 return FileMenu_InsertUsingPidl ( hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
456 /*************************************************************************
457 * FileMenu_TrackPopupMenuEx [SHELL32.116]
459 HRESULT WINAPI FileMenu_TrackPopupMenuEx (
460 HMENU hMenu,
461 UINT uFlags,
462 int x,
463 int y,
464 HWND hWnd,
465 LPTPMPARAMS lptpm)
467 TRACE("0x%08x 0x%08x 0x%x 0x%x 0x%08x %p\n",
468 hMenu, uFlags, x, y, hWnd, lptpm);
469 return TrackPopupMenuEx(hMenu, uFlags, x, y, hWnd, lptpm);
472 /*************************************************************************
473 * FileMenu_GetLastSelectedItemPidls [SHELL32.107]
475 BOOL WINAPI FileMenu_GetLastSelectedItemPidls(
476 UINT uReserved,
477 LPCITEMIDLIST *ppidlFolder,
478 LPCITEMIDLIST *ppidlItem)
480 FIXME("0x%08x %p %p\n",uReserved, ppidlFolder, ppidlItem);
481 return 0;
484 #define FM_ICON_SIZE 16
485 #define FM_Y_SPACE 4
486 #define FM_SPACE1 4
487 #define FM_SPACE2 2
488 #define FM_LEFTBORDER 2
489 #define FM_RIGHTBORDER 8
490 /*************************************************************************
491 * FileMenu_MeasureItem [SHELL32.112]
493 LRESULT WINAPI FileMenu_MeasureItem(
494 HWND hWnd,
495 LPMEASUREITEMSTRUCT lpmis)
497 LPFMITEM pMyItem = (LPFMITEM)(lpmis->itemData);
498 HDC hdc = GetDC(hWnd);
499 SIZE size;
500 LPFMINFO menuinfo;
502 TRACE("0x%08x %p %s\n", hWnd, lpmis, pMyItem->szItemText);
504 GetTextExtentPoint32A(hdc, pMyItem->szItemText, pMyItem->cchItemText, &size);
506 lpmis->itemWidth = size.cx + FM_LEFTBORDER + FM_ICON_SIZE + FM_SPACE1 + FM_SPACE2 + FM_RIGHTBORDER;
507 lpmis->itemHeight = (size.cy > (FM_ICON_SIZE + FM_Y_SPACE)) ? size.cy : (FM_ICON_SIZE + FM_Y_SPACE);
509 /* add the menubitmap */
510 menuinfo = FM_GetMenuInfo(pMyItem->hMenu);
511 if (menuinfo->bIsMagic)
512 lpmis->itemWidth += menuinfo->nBorderWidth;
514 TRACE("-- 0x%04x 0x%04x\n", lpmis->itemWidth, lpmis->itemHeight);
515 ReleaseDC (hWnd, hdc);
516 return 0;
518 /*************************************************************************
519 * FileMenu_DrawItem [SHELL32.105]
521 LRESULT WINAPI FileMenu_DrawItem(
522 HWND hWnd,
523 LPDRAWITEMSTRUCT lpdis)
525 LPFMITEM pMyItem = (LPFMITEM)(lpdis->itemData);
526 COLORREF clrPrevText, clrPrevBkgnd;
527 int xi,yi,xt,yt;
528 HIMAGELIST hImageList;
529 RECT TextRect, BorderRect;
530 LPFMINFO menuinfo;
532 TRACE("0x%08x %p %s\n", hWnd, lpdis, pMyItem->szItemText);
534 if (lpdis->itemState & ODS_SELECTED)
536 clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHTTEXT));
537 clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHT));
539 else
541 clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_MENUTEXT));
542 clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_MENU));
545 CopyRect(&TextRect, &(lpdis->rcItem));
547 /* add the menubitmap */
548 menuinfo = FM_GetMenuInfo(pMyItem->hMenu);
549 if (menuinfo->bIsMagic)
550 TextRect.left += menuinfo->nBorderWidth;
552 BorderRect.right = menuinfo->nBorderWidth;
553 /* FillRect(lpdis->hDC, &BorderRect, CreateSolidBrush( menuinfo->crBorderColor));
555 TextRect.left += FM_LEFTBORDER;
556 xi = TextRect.left + FM_SPACE1;
557 yi = TextRect.top + FM_Y_SPACE/2;
558 TextRect.bottom -= FM_Y_SPACE/2;
560 xt = xi + FM_ICON_SIZE + FM_SPACE2;
561 yt = yi;
563 ExtTextOutA (lpdis->hDC, xt , yt, ETO_OPAQUE, &TextRect, pMyItem->szItemText, pMyItem->cchItemText, NULL);
565 Shell_GetImageList(0, &hImageList);
566 pImageList_Draw(hImageList, pMyItem->iIconIndex, lpdis->hDC, xi, yi, ILD_NORMAL);
568 TRACE("-- 0x%04x 0x%04x 0x%04x 0x%04x\n", TextRect.left, TextRect.top, TextRect.right, TextRect.bottom);
570 SetTextColor(lpdis->hDC, clrPrevText);
571 SetBkColor(lpdis->hDC, clrPrevBkgnd);
573 return TRUE;
576 /*************************************************************************
577 * FileMenu_InitMenuPopup [SHELL32.109]
579 * NOTES
580 * The filemenu is a ownerdrawn menu. Call this function responding to
581 * WM_INITPOPUPMENU
584 BOOL WINAPI FileMenu_InitMenuPopup (HMENU hmenu)
586 FM_InitMenuPopup(hmenu, NULL);
587 return TRUE;
590 /*************************************************************************
591 * FileMenu_HandleMenuChar [SHELL32.108]
593 LRESULT WINAPI FileMenu_HandleMenuChar(
594 HMENU hMenu,
595 WPARAM wParam)
597 FIXME("0x%08x 0x%08x\n",hMenu,wParam);
598 return 0;
601 /*************************************************************************
602 * FileMenu_DeleteAllItems [SHELL32.104]
604 * NOTES
605 * exported by name
607 BOOL WINAPI FileMenu_DeleteAllItems (HMENU hmenu)
609 MENUITEMINFOA mii;
610 LPFMINFO menudata;
612 int i;
614 TRACE("0x%08x\n", hmenu);
616 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
617 mii.cbSize = sizeof(MENUITEMINFOA);
618 mii.fMask = MIIM_SUBMENU|MIIM_DATA;
620 for (i = 0; i < GetMenuItemCount( hmenu ); i++)
621 { GetMenuItemInfoA(hmenu, i, TRUE, &mii );
623 if (mii.dwItemData)
624 SHFree((LPFMINFO)mii.dwItemData);
626 if (mii.hSubMenu)
627 FileMenu_Destroy(mii.hSubMenu);
630 while (DeleteMenu (hmenu, 0, MF_BYPOSITION)){};
632 menudata = FM_GetMenuInfo(hmenu);
634 menudata->bInitialized = FALSE;
636 return TRUE;
639 /*************************************************************************
640 * FileMenu_DeleteItemByCmd [SHELL32.]
643 BOOL WINAPI FileMenu_DeleteItemByCmd (HMENU hMenu, UINT uID)
645 MENUITEMINFOA mii;
647 TRACE("0x%08x 0x%08x\n", hMenu, uID);
649 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
650 mii.cbSize = sizeof(MENUITEMINFOA);
651 mii.fMask = MIIM_SUBMENU;
653 GetMenuItemInfoA(hMenu, uID, FALSE, &mii );
654 if ( mii.hSubMenu );
656 DeleteMenu(hMenu, MF_BYCOMMAND, uID);
657 return TRUE;
660 /*************************************************************************
661 * FileMenu_DeleteItemByIndex [SHELL32.140]
663 BOOL WINAPI FileMenu_DeleteItemByIndex ( HMENU hMenu, UINT uPos)
665 MENUITEMINFOA mii;
667 TRACE("0x%08x 0x%08x\n", hMenu, uPos);
669 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
670 mii.cbSize = sizeof(MENUITEMINFOA);
671 mii.fMask = MIIM_SUBMENU;
673 GetMenuItemInfoA(hMenu, uPos, TRUE, &mii );
674 if ( mii.hSubMenu );
676 DeleteMenu(hMenu, MF_BYPOSITION, uPos);
677 return TRUE;
680 /*************************************************************************
681 * FileMenu_DeleteItemByFirstID [SHELL32.141]
683 BOOL WINAPI FileMenu_DeleteItemByFirstID(
684 HMENU hMenu,
685 UINT uID)
687 TRACE("0x%08x 0x%08x\n", hMenu, uID);
688 return 0;
691 /*************************************************************************
692 * FileMenu_DeleteSeparator [SHELL32.142]
694 BOOL WINAPI FileMenu_DeleteSeparator(HMENU hMenu)
696 TRACE("0x%08x\n", hMenu);
697 return 0;
700 /*************************************************************************
701 * FileMenu_EnableItemByCmd [SHELL32.143]
703 BOOL WINAPI FileMenu_EnableItemByCmd(
704 HMENU hMenu,
705 UINT uID,
706 BOOL bEnable)
708 TRACE("0x%08x 0x%08x 0x%08x\n", hMenu, uID,bEnable);
709 return 0;
712 /*************************************************************************
713 * FileMenu_GetItemExtent [SHELL32.144]
715 * NOTES
716 * if the menu is to big, entrys are getting cut away!!
718 DWORD WINAPI FileMenu_GetItemExtent (HMENU hMenu, UINT uPos)
719 { RECT rect;
721 FIXME("0x%08x 0x%08x\n", hMenu, uPos);
723 if (GetMenuItemRect(0, hMenu, uPos, &rect))
724 { FIXME("0x%04x 0x%04x 0x%04x 0x%04x\n",
725 rect.right, rect.left, rect.top, rect.bottom);
726 return ((rect.right-rect.left)<<16) + (rect.top-rect.bottom);
728 return 0x00100010; /*fixme*/
731 /*************************************************************************
732 * FileMenu_AbortInitMenu [SHELL32.120]
735 void WINAPI FileMenu_AbortInitMenu (void)
736 { TRACE("\n");
737 bAbortInit = TRUE;
740 /*************************************************************************
741 * SHFind_InitMenuPopup [SHELL32.149]
744 * PARAMETERS
745 * hMenu [in] handel of menu previously created
746 * hWndParent [in] parent window
747 * w [in] no pointer
748 * x [in] no pointer
750 HRESULT WINAPI SHFind_InitMenuPopup (HMENU hMenu, HWND hWndParent, DWORD w, DWORD x)
751 { FIXME("hmenu=0x%08x hwnd=0x%08x 0x%08lx 0x%08lx stub\n",
752 hMenu,hWndParent,w,x);
753 return TRUE;
756 /*************************************************************************
757 * Shell_MergeMenus [SHELL32.67]
760 BOOL _SHIsMenuSeparator(HMENU hm, int i)
762 MENUITEMINFOA mii;
764 mii.cbSize = sizeof(MENUITEMINFOA);
765 mii.fMask = MIIM_TYPE;
766 mii.cch = 0; /* WARNING: We MUST initialize it to 0*/
767 if (!GetMenuItemInfoA(hm, i, TRUE, &mii))
768 { return(FALSE);
771 if (mii.fType & MFT_SEPARATOR)
772 { return(TRUE);
775 return(FALSE);
777 #define MM_ADDSEPARATOR 0x00000001L
778 #define MM_SUBMENUSHAVEIDS 0x00000002L
779 HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags)
780 { int nItem;
781 HMENU hmSubMenu;
782 BOOL bAlreadySeparated;
783 MENUITEMINFOA miiSrc;
784 char szName[256];
785 UINT uTemp, uIDMax = uIDAdjust;
787 FIXME("hmenu1=0x%04x hmenu2=0x%04x 0x%04x 0x%04x 0x%04x 0x%04lx stub\n",
788 hmDst, hmSrc, uInsert, uIDAdjust, uIDAdjustMax, uFlags);
790 if (!hmDst || !hmSrc)
791 { return uIDMax;
794 nItem = GetMenuItemCount(hmDst);
795 if (uInsert >= (UINT)nItem)
796 { uInsert = (UINT)nItem;
797 bAlreadySeparated = TRUE;
799 else
800 { bAlreadySeparated = _SHIsMenuSeparator(hmDst, uInsert);;
802 if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
803 { /* Add a separator between the menus */
804 InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
805 bAlreadySeparated = TRUE;
809 /* Go through the menu items and clone them*/
810 for (nItem = GetMenuItemCount(hmSrc) - 1; nItem >= 0; nItem--)
811 { miiSrc.cbSize = sizeof(MENUITEMINFOA);
812 miiSrc.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA;
813 /* We need to reset this every time through the loop in case
814 menus DON'T have IDs*/
815 miiSrc.fType = MFT_STRING;
816 miiSrc.dwTypeData = szName;
817 miiSrc.dwItemData = 0;
818 miiSrc.cch = sizeof(szName);
820 if (!GetMenuItemInfoA(hmSrc, nItem, TRUE, &miiSrc))
821 { continue;
823 if (miiSrc.fType & MFT_SEPARATOR)
824 { /* This is a separator; don't put two of them in a row*/
825 if (bAlreadySeparated)
826 { continue;
828 bAlreadySeparated = TRUE;
830 else if (miiSrc.hSubMenu)
831 { if (uFlags & MM_SUBMENUSHAVEIDS)
832 { /* Adjust the ID and check it*/
833 miiSrc.wID += uIDAdjust;
834 if (miiSrc.wID > uIDAdjustMax)
835 { continue;
837 if (uIDMax <= miiSrc.wID)
838 { uIDMax = miiSrc.wID + 1;
841 else
842 { /* Don't set IDs for submenus that didn't have them already */
843 miiSrc.fMask &= ~MIIM_ID;
845 hmSubMenu = miiSrc.hSubMenu;
846 miiSrc.hSubMenu = CreatePopupMenu();
847 if (!miiSrc.hSubMenu)
848 { return(uIDMax);
850 uTemp = Shell_MergeMenus(miiSrc.hSubMenu, hmSubMenu, 0, uIDAdjust, uIDAdjustMax, uFlags&MM_SUBMENUSHAVEIDS);
851 if (uIDMax <= uTemp)
852 { uIDMax = uTemp;
854 bAlreadySeparated = FALSE;
856 else
857 { /* Adjust the ID and check it*/
858 miiSrc.wID += uIDAdjust;
859 if (miiSrc.wID > uIDAdjustMax)
860 { continue;
862 if (uIDMax <= miiSrc.wID)
863 { uIDMax = miiSrc.wID + 1;
865 bAlreadySeparated = FALSE;
867 if (!InsertMenuItemA(hmDst, uInsert, TRUE, &miiSrc))
868 { return(uIDMax);
872 /* Ensure the correct number of separators at the beginning of the
873 inserted menu items*/
874 if (uInsert == 0)
875 { if (bAlreadySeparated)
876 { DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
879 else
880 { if (_SHIsMenuSeparator(hmDst, uInsert-1))
881 { if (bAlreadySeparated)
882 { DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
885 else
886 { if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
887 { /* Add a separator between the menus*/
888 InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
892 return(uIDMax);