source: trunk/src/shell32/shlmenu.c@ 6650

Last change on this file since 6650 was 6650, checked in by bird, 24 years ago

Added $Id:$ keyword.

File size: 25.3 KB
Line 
1/* $Id: shlmenu.c,v 1.3 2001-09-05 13:46:59 bird Exp $ */
2/*
3 * see www.geocities.com/SiliconValley/4942/filemenu.html
4 */
5#include <string.h>
6
7#include "shlobj.h"
8#include "wine/obj_base.h"
9#include "wine/obj_enumidlist.h"
10#include "wine/obj_shellfolder.h"
11#include "wine/undocshell.h"
12#include "shlwapi.h"
13#include "heap.h"
14#include "debugtools.h"
15#include "shell32_main.h"
16#include "shlguid.h"
17
18#include "pidl.h"
19
20BOOL WINAPI FileMenu_DeleteAllItems (HMENU hMenu);
21BOOL WINAPI FileMenu_AppendItemA(HMENU hMenu, LPCSTR lpText, UINT uID, int icon, HMENU hMenuPopup, int nItemHeight);
22
23typedef struct
24{
25 BOOL bInitialized;
26 BOOL bFixedItems;
27 /* create */
28 COLORREF crBorderColor;
29 int nBorderWidth;
30 HBITMAP hBorderBmp;
31
32 /* insert using pidl */
33 LPITEMIDLIST pidl;
34 UINT uID;
35 UINT uFlags;
36 UINT uEnumFlags;
37 LPFNFMCALLBACK lpfnCallback;
38} FMINFO, *LPFMINFO;
39
40typedef struct
41{ int cchItemText;
42 int iIconIndex;
43 HMENU hMenu;
44 char szItemText[1];
45} FMITEM, * LPFMITEM;
46
47static BOOL bAbortInit;
48
49#define CCH_MAXITEMTEXT 256
50
51DEFAULT_DEBUG_CHANNEL(shell);
52
53LPFMINFO FM_GetMenuInfo(HMENU hmenu)
54{ MENUINFO MenuInfo;
55 LPFMINFO menudata;
56
57 MenuInfo.cbSize = sizeof(MENUINFO);
58 MenuInfo.fMask = MIM_MENUDATA;
59
60 if (! GetMenuInfo(hmenu, &MenuInfo))
61 return NULL;
62
63 menudata = (LPFMINFO)MenuInfo.dwMenuData;
64
65 if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO)))
66 {
67 ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize);
68 return 0;
69 }
70
71 return menudata;
72
73}
74/*************************************************************************
75 * FM_SetMenuParameter [internal]
76 *
77 */
78static LPFMINFO FM_SetMenuParameter(
79 HMENU hmenu,
80 UINT uID,
81 LPCITEMIDLIST pidl,
82 UINT uFlags,
83 UINT uEnumFlags,
84 LPFNFMCALLBACK lpfnCallback)
85{
86 LPFMINFO menudata;
87
88 TRACE("\n");
89
90 menudata = FM_GetMenuInfo(hmenu);
91
92 if ( menudata->pidl)
93 { SHFree(menudata->pidl);
94 }
95
96 menudata->uID = uID;
97 menudata->pidl = ILClone(pidl);
98 menudata->uFlags = uFlags;
99 menudata->uEnumFlags = uEnumFlags;
100 menudata->lpfnCallback = lpfnCallback;
101
102 return menudata;
103}
104
105/*************************************************************************
106 * FM_InitMenuPopup [internal]
107 *
108 */
109static int FM_InitMenuPopup(HMENU hmenu, LPITEMIDLIST pAlternatePidl)
110{ IShellFolder *lpsf, *lpsf2;
111 ULONG ulItemAttr = SFGAO_FOLDER;
112 UINT uID, uFlags, uEnumFlags;
113 LPFNFMCALLBACK lpfnCallback;
114 LPITEMIDLIST pidl;
115 char sTemp[MAX_PATH];
116 int NumberOfItems = 0, iIcon;
117 MENUINFO MenuInfo;
118 LPFMINFO menudata;
119
120 TRACE("0x%04x %p\n", hmenu, pAlternatePidl);
121
122 MenuInfo.cbSize = sizeof(MENUINFO);
123 MenuInfo.fMask = MIM_MENUDATA;
124
125 if (! GetMenuInfo(hmenu, &MenuInfo))
126 return FALSE;
127
128 menudata = (LPFMINFO)MenuInfo.dwMenuData;
129
130 if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO)))
131 {
132 ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize);
133 return 0;
134 }
135
136 if (menudata->bInitialized)
137 return 0;
138
139 pidl = ((pAlternatePidl) ? pAlternatePidl : menudata->pidl);
140 if (!pidl)
141 return 0;
142
143 uID = menudata->uID;
144 uFlags = menudata->uFlags;
145 uEnumFlags = menudata->uEnumFlags;
146 lpfnCallback = menudata->lpfnCallback;
147 menudata->bInitialized = FALSE;
148
149 SetMenuInfo(hmenu, &MenuInfo);
150
151 if (SUCCEEDED (SHGetDesktopFolder(&lpsf)))
152 {
153 if (SUCCEEDED(IShellFolder_BindToObject(lpsf, pidl,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2)))
154 {
155 IEnumIDList *lpe = NULL;
156
157 if (SUCCEEDED (IShellFolder_EnumObjects(lpsf2, 0, uEnumFlags, &lpe )))
158 {
159
160 LPITEMIDLIST pidlTemp = NULL;
161 ULONG ulFetched;
162
163 while ((!bAbortInit) && (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched)))
164 {
165 if (SUCCEEDED (IShellFolder_GetAttributesOf(lpsf, 1, &pidlTemp, &ulItemAttr)))
166 {
167 ILGetDisplayName( pidlTemp, sTemp);
168 if (! (PidlToSicIndex(lpsf, pidlTemp, FALSE, 0, &iIcon)))
169 iIcon = FM_BLANK_ICON;
170 if ( SFGAO_FOLDER & ulItemAttr)
171 {
172 LPFMINFO lpFmMi;
173 MENUINFO MenuInfo;
174 HMENU hMenuPopup = CreatePopupMenu();
175
176 lpFmMi = (LPFMINFO) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO));
177
178 lpFmMi->pidl = ILCombine(pidl, pidlTemp);
179 lpFmMi->uEnumFlags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
180
181 MenuInfo.cbSize = sizeof(MENUINFO);
182 MenuInfo.fMask = MIM_MENUDATA;
183 MenuInfo.dwMenuData = (DWORD) lpFmMi;
184 SetMenuInfo (hMenuPopup, &MenuInfo);
185
186 FileMenu_AppendItemA (hmenu, sTemp, uID, iIcon, hMenuPopup, FM_DEFAULT_HEIGHT);
187 }
188 else
189 {
190 ((LPSTR)PathFindExtensionA(sTemp))[0] = 0x00;
191 FileMenu_AppendItemA (hmenu, sTemp, uID, iIcon, 0, FM_DEFAULT_HEIGHT);
192 }
193 }
194
195 if (lpfnCallback)
196 {
197 TRACE("enter callback\n");
198 lpfnCallback ( pidl, pidlTemp);
199 TRACE("leave callback\n");
200 }
201
202 NumberOfItems++;
203 }
204 IEnumIDList_Release (lpe);
205 }
206 IShellFolder_Release(lpsf2);
207 }
208 IShellFolder_Release(lpsf);
209 }
210
211 if ( GetMenuItemCount (hmenu) == 0 )
212 { FileMenu_AppendItemA (hmenu, "(empty)", uID, FM_BLANK_ICON, 0, FM_DEFAULT_HEIGHT);
213 NumberOfItems++;
214 }
215
216 menudata->bInitialized = TRUE;
217 SetMenuInfo(hmenu, &MenuInfo);
218
219 return NumberOfItems;
220}
221/*************************************************************************
222 * FileMenu_Create [SHELL32.114]
223 *
224 * NOTES
225 * for non-root menus values are
226 * (ffffffff,00000000,00000000,00000000,00000000)
227 */
228HMENU WINAPI FileMenu_Create (
229 COLORREF crBorderColor,
230 int nBorderWidth,
231 HBITMAP hBorderBmp,
232 int nSelHeight,
233 UINT uFlags)
234{
235 MENUINFO MenuInfo;
236 LPFMINFO menudata;
237
238 HMENU hMenu = CreatePopupMenu();
239
240 TRACE("0x%08lx 0x%08x 0x%08x 0x%08x 0x%08x hMenu=0x%08x\n",
241 crBorderColor, nBorderWidth, hBorderBmp, nSelHeight, uFlags, hMenu);
242
243 menudata = (LPFMINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO));
244 menudata->crBorderColor = crBorderColor;
245 menudata->nBorderWidth = nBorderWidth;
246 menudata->hBorderBmp = hBorderBmp;
247
248 MenuInfo.cbSize = sizeof(MENUINFO);
249 MenuInfo.fMask = MIM_MENUDATA;
250 MenuInfo.dwMenuData = (DWORD) menudata;
251 SetMenuInfo (hMenu, &MenuInfo);
252
253 return hMenu;
254}
255
256/*************************************************************************
257 * FileMenu_Destroy [SHELL32.118]
258 *
259 * NOTES
260 * exported by name
261 */
262void WINAPI FileMenu_Destroy (HMENU hmenu)
263{
264 LPFMINFO menudata;
265
266 TRACE("0x%08x\n", hmenu);
267
268 FileMenu_DeleteAllItems (hmenu);
269
270 menudata = FM_GetMenuInfo(hmenu);
271
272 if ( menudata->pidl)
273 { SHFree( menudata->pidl);
274 }
275 HeapFree(GetProcessHeap(), 0, menudata);
276
277 DestroyMenu (hmenu);
278}
279
280/*************************************************************************
281 * FileMenu_AppendItemAW [SHELL32.115]
282 *
283 */
284BOOL WINAPI FileMenu_AppendItemA(
285 HMENU hMenu,
286 LPCSTR lpText,
287 UINT uID,
288 int icon,
289 HMENU hMenuPopup,
290 int nItemHeight)
291{
292 LPSTR lpszText = (LPSTR)lpText;
293 MENUITEMINFOA mii;
294 LPFMITEM myItem;
295 LPFMINFO menudata;
296 MENUINFO MenuInfo;
297
298
299 TRACE("0x%08x %s 0x%08x 0x%08x 0x%08x 0x%08x\n",
300 hMenu, (lpszText!=FM_SEPARATOR) ? lpText: NULL,
301 uID, icon, hMenuPopup, nItemHeight);
302
303 ZeroMemory (&mii, sizeof(MENUITEMINFOA));
304
305 mii.cbSize = sizeof(MENUITEMINFOA);
306
307 if (lpText != FM_SEPARATOR)
308 { int len = strlen (lpText);
309 myItem = (LPFMITEM) SHAlloc( sizeof(FMITEM) + len);
310 strcpy (myItem->szItemText, lpText);
311 myItem->cchItemText = len;
312 myItem->iIconIndex = icon;
313 myItem->hMenu = hMenu;
314 mii.fMask = MIIM_DATA;
315 mii.dwItemData = (DWORD) myItem;
316 }
317
318 if ( hMenuPopup )
319 { /* sub menu */
320 mii.fMask |= MIIM_TYPE | MIIM_SUBMENU;
321 mii.fType = MFT_OWNERDRAW;
322 mii.hSubMenu = hMenuPopup;
323 }
324 else if (lpText == FM_SEPARATOR )
325 { mii.fMask |= MIIM_ID | MIIM_TYPE;
326 mii.fType = MFT_SEPARATOR;
327 }
328 else
329 { /* normal item */
330 mii.fMask |= MIIM_ID | MIIM_TYPE | MIIM_STATE;
331 mii.fState = MFS_ENABLED | MFS_DEFAULT;
332 mii.fType = MFT_OWNERDRAW;
333 }
334 mii.wID = uID;
335
336 InsertMenuItemA (hMenu, (UINT)-1, TRUE, &mii);
337
338 /* set bFixedItems to true */
339 MenuInfo.cbSize = sizeof(MENUINFO);
340 MenuInfo.fMask = MIM_MENUDATA;
341
342 if (! GetMenuInfo(hMenu, &MenuInfo))
343 return FALSE;
344
345 menudata = (LPFMINFO)MenuInfo.dwMenuData;
346 if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO)))
347 {
348 ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize);
349 return 0;
350 }
351
352 menudata->bFixedItems = TRUE;
353 SetMenuInfo(hMenu, &MenuInfo);
354
355 return TRUE;
356
357}
358
359/**********************************************************************/
360
361BOOL WINAPI FileMenu_AppendItemAW(
362 HMENU hMenu,
363 LPCVOID lpText,
364 UINT uID,
365 int icon,
366 HMENU hMenuPopup,
367 int nItemHeight)
368{
369 BOOL ret;
370 LPSTR lpszText=NULL;
371
372 if (SHELL_OsIsUnicode() && (lpText!=FM_SEPARATOR))
373 lpszText = HEAP_strdupWtoA ( GetProcessHeap(),0, lpText);
374
375 ret = FileMenu_AppendItemA(hMenu, (lpszText) ? lpszText : lpText, uID, icon, hMenuPopup, nItemHeight);
376
377 if (lpszText)
378 HeapFree( GetProcessHeap(), 0, lpszText );
379
380 return ret;
381}
382/*************************************************************************
383 * FileMenu_InsertUsingPidl [SHELL32.110]
384 *
385 * NOTES
386 * uEnumFlags any SHCONTF flag
387 */
388int WINAPI FileMenu_InsertUsingPidl (
389 HMENU hmenu,
390 UINT uID,
391 LPCITEMIDLIST pidl,
392 UINT uFlags,
393 UINT uEnumFlags,
394 LPFNFMCALLBACK lpfnCallback)
395{
396 TRACE("0x%08x 0x%08x %p 0x%08x 0x%08x %p\n",
397 hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
398
399 pdump (pidl);
400
401 bAbortInit = FALSE;
402
403 FM_SetMenuParameter(hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
404
405 return FM_InitMenuPopup(hmenu, NULL);
406}
407
408/*************************************************************************
409 * FileMenu_ReplaceUsingPidl [SHELL32.113]
410 *
411 * FIXME: the static items are deleted but wont be refreshed
412 */
413int WINAPI FileMenu_ReplaceUsingPidl(
414 HMENU hmenu,
415 UINT uID,
416 LPCITEMIDLIST pidl,
417 UINT uEnumFlags,
418 LPFNFMCALLBACK lpfnCallback)
419{
420 TRACE("0x%08x 0x%08x %p 0x%08x %p\n",
421 hmenu, uID, pidl, uEnumFlags, lpfnCallback);
422
423 FileMenu_DeleteAllItems (hmenu);
424
425 FM_SetMenuParameter(hmenu, uID, pidl, 0, uEnumFlags, lpfnCallback);
426
427 return FM_InitMenuPopup(hmenu, NULL);
428}
429
430/*************************************************************************
431 * FileMenu_Invalidate [SHELL32.111]
432 */
433void WINAPI FileMenu_Invalidate (HMENU hMenu)
434{
435 FIXME("0x%08x\n",hMenu);
436}
437
438/*************************************************************************
439 * FileMenu_FindSubMenuByPidl [SHELL32.106]
440 */
441HMENU WINAPI FileMenu_FindSubMenuByPidl(
442 HMENU hMenu,
443 LPCITEMIDLIST pidl)
444{
445 FIXME("0x%08x %p\n",hMenu, pidl);
446 return 0;
447}
448
449/*************************************************************************
450 * FileMenu_AppendFilesForPidl [SHELL32.124]
451 */
452int WINAPI FileMenu_AppendFilesForPidl(
453 HMENU hmenu,
454 LPCITEMIDLIST pidl,
455 BOOL bAddSeperator)
456{
457 LPFMINFO menudata;
458
459 menudata = FM_GetMenuInfo(hmenu);
460
461 menudata->bInitialized = FALSE;
462
463 FM_InitMenuPopup(hmenu, pidl);
464
465 if (bAddSeperator)
466 FileMenu_AppendItemA (hmenu, FM_SEPARATOR, 0, 0, 0, FM_DEFAULT_HEIGHT);
467
468 TRACE("0x%08x %p 0x%08x\n",hmenu, pidl,bAddSeperator);
469
470 return 0;
471}
472/*************************************************************************
473 * FileMenu_AddFilesForPidl [SHELL32.125]
474 *
475 * NOTES
476 * uEnumFlags any SHCONTF flag
477 */
478int WINAPI FileMenu_AddFilesForPidl (
479 HMENU hmenu,
480 UINT uReserved,
481 UINT uID,
482 LPCITEMIDLIST pidl,
483 UINT uFlags,
484 UINT uEnumFlags,
485 LPFNFMCALLBACK lpfnCallback)
486{
487 TRACE("0x%08x 0x%08x 0x%08x %p 0x%08x 0x%08x %p\n",
488 hmenu, uReserved, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
489
490 return FileMenu_InsertUsingPidl ( hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
491
492}
493
494
495/*************************************************************************
496 * FileMenu_TrackPopupMenuEx [SHELL32.116]
497 */
498BOOL WINAPI FileMenu_TrackPopupMenuEx (
499 HMENU hMenu,
500 UINT uFlags,
501 int x,
502 int y,
503 HWND hWnd,
504 LPTPMPARAMS lptpm)
505{
506 TRACE("0x%08x 0x%08x 0x%x 0x%x 0x%08x %p\n",
507 hMenu, uFlags, x, y, hWnd, lptpm);
508 return TrackPopupMenuEx(hMenu, uFlags, x, y, hWnd, lptpm);
509}
510
511/*************************************************************************
512 * FileMenu_GetLastSelectedItemPidls [SHELL32.107]
513 */
514BOOL WINAPI FileMenu_GetLastSelectedItemPidls(
515 UINT uReserved,
516 LPCITEMIDLIST *ppidlFolder,
517 LPCITEMIDLIST *ppidlItem)
518{
519 FIXME("0x%08x %p %p\n",uReserved, ppidlFolder, ppidlItem);
520 return 0;
521}
522
523#define FM_ICON_SIZE 16
524#define FM_Y_SPACE 4
525#define FM_SPACE1 4
526#define FM_SPACE2 2
527#define FM_LEFTBORDER 2
528#define FM_RIGHTBORDER 8
529/*************************************************************************
530 * FileMenu_MeasureItem [SHELL32.112]
531 */
532LRESULT WINAPI FileMenu_MeasureItem(
533 HWND hWnd,
534 LPMEASUREITEMSTRUCT lpmis)
535{
536 LPFMITEM pMyItem = (LPFMITEM)(lpmis->itemData);
537 HDC hdc = GetDC(hWnd);
538 SIZE size;
539 LPFMINFO menuinfo;
540
541 TRACE("0x%08x %p %s\n", hWnd, lpmis, pMyItem->szItemText);
542
543 GetTextExtentPoint32A(hdc, pMyItem->szItemText, pMyItem->cchItemText, &size);
544
545 lpmis->itemWidth = size.cx + FM_LEFTBORDER + FM_ICON_SIZE + FM_SPACE1 + FM_SPACE2 + FM_RIGHTBORDER;
546 lpmis->itemHeight = (size.cy > (FM_ICON_SIZE + FM_Y_SPACE)) ? size.cy : (FM_ICON_SIZE + FM_Y_SPACE);
547
548 /* add the menubitmap */
549 menuinfo = FM_GetMenuInfo(pMyItem->hMenu);
550 if (menuinfo->nBorderWidth)
551 lpmis->itemWidth += menuinfo->nBorderWidth;
552
553 TRACE("-- 0x%04x 0x%04x\n", lpmis->itemWidth, lpmis->itemHeight);
554 ReleaseDC (hWnd, hdc);
555 return 0;
556}
557/*************************************************************************
558 * FileMenu_DrawItem [SHELL32.105]
559 */
560LRESULT WINAPI FileMenu_DrawItem(
561 HWND hWnd,
562 LPDRAWITEMSTRUCT lpdis)
563{
564 LPFMITEM pMyItem = (LPFMITEM)(lpdis->itemData);
565 COLORREF clrPrevText, clrPrevBkgnd;
566 int xi,yi,xt,yt;
567 HIMAGELIST hImageList;
568 RECT TextRect, BorderRect;
569 LPFMINFO menuinfo;
570
571 TRACE("0x%08x %p %s\n", hWnd, lpdis, pMyItem->szItemText);
572
573 if (lpdis->itemState & ODS_SELECTED)
574 {
575 clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHTTEXT));
576 clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHT));
577 }
578 else
579 {
580 clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_MENUTEXT));
581 clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_MENU));
582 }
583
584 CopyRect(&TextRect, &(lpdis->rcItem));
585
586 /* add the menubitmap */
587 menuinfo = FM_GetMenuInfo(pMyItem->hMenu);
588 if (menuinfo->nBorderWidth)
589 TextRect.left += menuinfo->nBorderWidth;
590
591 BorderRect.right = menuinfo->nBorderWidth;
592/* FillRect(lpdis->hDC, &BorderRect, CreateSolidBrush( menuinfo->crBorderColor));
593*/
594 TextRect.left += FM_LEFTBORDER;
595 xi = TextRect.left + FM_SPACE1;
596 yi = TextRect.top + FM_Y_SPACE/2;
597 TextRect.bottom -= FM_Y_SPACE/2;
598
599 xt = xi + FM_ICON_SIZE + FM_SPACE2;
600 yt = yi;
601
602 ExtTextOutA (lpdis->hDC, xt , yt, ETO_OPAQUE, &TextRect, pMyItem->szItemText, pMyItem->cchItemText, NULL);
603
604 Shell_GetImageList(0, &hImageList);
605 ImageList_Draw(hImageList, pMyItem->iIconIndex, lpdis->hDC, xi, yi, ILD_NORMAL);
606
607 TRACE("-- 0x%04x 0x%04x 0x%04x 0x%04x\n", TextRect.left, TextRect.top, TextRect.right, TextRect.bottom);
608
609 SetTextColor(lpdis->hDC, clrPrevText);
610 SetBkColor(lpdis->hDC, clrPrevBkgnd);
611
612 return TRUE;
613}
614
615/*************************************************************************
616 * FileMenu_InitMenuPopup [SHELL32.109]
617 *
618 * NOTES
619 * The filemenu is a ownerdrawn menu. Call this function responding to
620 * WM_INITPOPUPMENU
621 *
622 */
623BOOL WINAPI FileMenu_InitMenuPopup (HMENU hmenu)
624{
625 FM_InitMenuPopup(hmenu, NULL);
626 return TRUE;
627}
628
629/*************************************************************************
630 * FileMenu_HandleMenuChar [SHELL32.108]
631 */
632LRESULT WINAPI FileMenu_HandleMenuChar(
633 HMENU hMenu,
634 WPARAM wParam)
635{
636 FIXME("0x%08x 0x%08x\n",hMenu,wParam);
637 return 0;
638}
639
640/*************************************************************************
641 * FileMenu_DeleteAllItems [SHELL32.104]
642 *
643 * NOTES
644 * exported by name
645 */
646BOOL WINAPI FileMenu_DeleteAllItems (HMENU hmenu)
647{
648 MENUITEMINFOA mii;
649 LPFMINFO menudata;
650
651 int i;
652
653 TRACE("0x%08x\n", hmenu);
654
655 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
656 mii.cbSize = sizeof(MENUITEMINFOA);
657 mii.fMask = MIIM_SUBMENU|MIIM_DATA;
658
659 for (i = 0; i < GetMenuItemCount( hmenu ); i++)
660 { GetMenuItemInfoA(hmenu, i, TRUE, &mii );
661
662 if (mii.dwItemData)
663 SHFree((LPFMINFO)mii.dwItemData);
664
665 if (mii.hSubMenu)
666 FileMenu_Destroy(mii.hSubMenu);
667 }
668
669 while (DeleteMenu (hmenu, 0, MF_BYPOSITION)){};
670
671 menudata = FM_GetMenuInfo(hmenu);
672
673 menudata->bInitialized = FALSE;
674
675 return TRUE;
676}
677
678/*************************************************************************
679 * FileMenu_DeleteItemByCmd [SHELL32.]
680 *
681 */
682BOOL WINAPI FileMenu_DeleteItemByCmd (HMENU hMenu, UINT uID)
683{
684 MENUITEMINFOA mii;
685
686 TRACE("0x%08x 0x%08x\n", hMenu, uID);
687
688 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
689 mii.cbSize = sizeof(MENUITEMINFOA);
690 mii.fMask = MIIM_SUBMENU;
691
692 GetMenuItemInfoA(hMenu, uID, FALSE, &mii );
693 if ( mii.hSubMenu )
694 {
695 /* FIXME: Do what? */
696 }
697
698 DeleteMenu(hMenu, MF_BYCOMMAND, uID);
699 return TRUE;
700}
701
702/*************************************************************************
703 * FileMenu_DeleteItemByIndex [SHELL32.140]
704 */
705BOOL WINAPI FileMenu_DeleteItemByIndex ( HMENU hMenu, UINT uPos)
706{
707 MENUITEMINFOA mii;
708
709 TRACE("0x%08x 0x%08x\n", hMenu, uPos);
710
711 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
712 mii.cbSize = sizeof(MENUITEMINFOA);
713 mii.fMask = MIIM_SUBMENU;
714
715 GetMenuItemInfoA(hMenu, uPos, TRUE, &mii );
716 if ( mii.hSubMenu )
717 {
718 /* FIXME: Do what? */
719 }
720
721 DeleteMenu(hMenu, MF_BYPOSITION, uPos);
722 return TRUE;
723}
724
725/*************************************************************************
726 * FileMenu_DeleteItemByFirstID [SHELL32.141]
727 */
728BOOL WINAPI FileMenu_DeleteItemByFirstID(
729 HMENU hMenu,
730 UINT uID)
731{
732 TRACE("0x%08x 0x%08x\n", hMenu, uID);
733 return 0;
734}
735
736/*************************************************************************
737 * FileMenu_DeleteSeparator [SHELL32.142]
738 */
739BOOL WINAPI FileMenu_DeleteSeparator(HMENU hMenu)
740{
741 TRACE("0x%08x\n", hMenu);
742 return 0;
743}
744
745/*************************************************************************
746 * FileMenu_EnableItemByCmd [SHELL32.143]
747 */
748BOOL WINAPI FileMenu_EnableItemByCmd(
749 HMENU hMenu,
750 UINT uID,
751 BOOL bEnable)
752{
753 TRACE("0x%08x 0x%08x 0x%08x\n", hMenu, uID,bEnable);
754 return 0;
755}
756
757/*************************************************************************
758 * FileMenu_GetItemExtent [SHELL32.144]
759 *
760 * NOTES
761 * if the menu is to big, entrys are getting cut away!!
762 */
763DWORD WINAPI FileMenu_GetItemExtent (HMENU hMenu, UINT uPos)
764{ RECT rect;
765
766 FIXME("0x%08x 0x%08x\n", hMenu, uPos);
767
768 if (GetMenuItemRect(0, hMenu, uPos, &rect))
769 { FIXME("0x%04x 0x%04x 0x%04x 0x%04x\n",
770 rect.right, rect.left, rect.top, rect.bottom);
771 return ((rect.right-rect.left)<<16) + (rect.top-rect.bottom);
772 }
773 return 0x00100010; /*fixme*/
774}
775
776/*************************************************************************
777 * FileMenu_AbortInitMenu [SHELL32.120]
778 *
779 */
780void WINAPI FileMenu_AbortInitMenu (void)
781{ TRACE("\n");
782 bAbortInit = TRUE;
783}
784
785/*************************************************************************
786 * SHFind_InitMenuPopup [SHELL32.149]
787 *
788 *
789 * PARAMETERS
790 * hMenu [in] handle of menu previously created
791 * hWndParent [in] parent window
792 * w [in] no pointer (0x209 over here) perhaps menu IDs ???
793 * x [in] no pointer (0x226 over here)
794 *
795 * RETURNS
796 * LPXXXXX pointer to struct containing a func addr at offset 8
797 * or NULL at failure.
798 */
799LPVOID WINAPI SHFind_InitMenuPopup (HMENU hMenu, HWND hWndParent, DWORD w, DWORD x)
800{ FIXME("hmenu=0x%08x hwnd=0x%08x 0x%08lx 0x%08lx stub\n",
801 hMenu,hWndParent,w,x);
802 return NULL; /* this is supposed to be a pointer */
803}
804
805/*************************************************************************
806 * Shell_MergeMenus [SHELL32.67]
807 *
808 */
809BOOL _SHIsMenuSeparator(HMENU hm, int i)
810{
811 MENUITEMINFOA mii;
812
813 mii.cbSize = sizeof(MENUITEMINFOA);
814 mii.fMask = MIIM_TYPE;
815 mii.cch = 0; /* WARNING: We MUST initialize it to 0*/
816 if (!GetMenuItemInfoA(hm, i, TRUE, &mii))
817 {
818 return(FALSE);
819 }
820
821 if (mii.fType & MFT_SEPARATOR)
822 {
823 return(TRUE);
824 }
825
826 return(FALSE);
827}
828
829/**********************************************************************/
830
831HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags)
832{ int nItem;
833 HMENU hmSubMenu;
834 BOOL bAlreadySeparated;
835 MENUITEMINFOA miiSrc;
836 char szName[256];
837 UINT uTemp, uIDMax = uIDAdjust;
838
839 TRACE("hmenu1=0x%04x hmenu2=0x%04x 0x%04x 0x%04x 0x%04x 0x%04lx\n",
840 hmDst, hmSrc, uInsert, uIDAdjust, uIDAdjustMax, uFlags);
841
842 if (!hmDst || !hmSrc)
843 { return uIDMax;
844 }
845
846 nItem = GetMenuItemCount(hmDst);
847
848 if (uInsert >= (UINT)nItem) /* insert position inside menu? */
849 {
850 uInsert = (UINT)nItem; /* append on the end */
851 bAlreadySeparated = TRUE;
852 }
853 else
854 {
855 bAlreadySeparated = _SHIsMenuSeparator(hmDst, uInsert);;
856 }
857
858 if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
859 {
860 /* Add a separator between the menus */
861 InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
862 bAlreadySeparated = TRUE;
863 }
864
865
866 /* Go through the menu items and clone them*/
867 for (nItem = GetMenuItemCount(hmSrc) - 1; nItem >= 0; nItem--)
868 {
869 miiSrc.cbSize = sizeof(MENUITEMINFOA);
870 miiSrc.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA;
871
872 /* We need to reset this every time through the loop in case menus DON'T have IDs*/
873 miiSrc.fType = MFT_STRING;
874 miiSrc.dwTypeData = szName;
875 miiSrc.dwItemData = 0;
876 miiSrc.cch = sizeof(szName);
877
878 if (!GetMenuItemInfoA(hmSrc, nItem, TRUE, &miiSrc))
879 {
880 continue;
881 }
882
883/* 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);
884*/
885 if (miiSrc.fType & MFT_SEPARATOR)
886 {
887 /* This is a separator; don't put two of them in a row */
888 if (bAlreadySeparated)
889 continue;
890
891 bAlreadySeparated = TRUE;
892 }
893 else if (miiSrc.hSubMenu)
894 {
895 if (uFlags & MM_SUBMENUSHAVEIDS)
896 {
897 miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */
898
899 if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */
900 continue;
901
902 if (uIDMax <= miiSrc.wID) /* remember the highest ID */
903 uIDMax = miiSrc.wID + 1;
904 }
905 else
906 {
907 miiSrc.fMask &= ~MIIM_ID; /* Don't set IDs for submenus that didn't have them already */
908 }
909 hmSubMenu = miiSrc.hSubMenu;
910
911 miiSrc.hSubMenu = CreatePopupMenu();
912
913 if (!miiSrc.hSubMenu) return(uIDMax);
914
915 uTemp = Shell_MergeMenus(miiSrc.hSubMenu, hmSubMenu, 0, uIDAdjust, uIDAdjustMax, uFlags & MM_SUBMENUSHAVEIDS);
916
917 if (uIDMax <= uTemp)
918 uIDMax = uTemp;
919
920 bAlreadySeparated = FALSE;
921 }
922 else /* normal menu item */
923 {
924 miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */
925
926 if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */
927 continue;
928
929 if (uIDMax <= miiSrc.wID) /* remember the highest ID */
930 uIDMax = miiSrc.wID + 1;
931
932 bAlreadySeparated = FALSE;
933 }
934
935/* 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);
936*/
937 if (!InsertMenuItemA(hmDst, uInsert, TRUE, &miiSrc))
938 {
939 return(uIDMax);
940 }
941 }
942
943 /* Ensure the correct number of separators at the beginning of the
944 inserted menu items*/
945 if (uInsert == 0)
946 {
947 if (bAlreadySeparated)
948 {
949 DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
950 }
951 }
952 else
953 {
954 if (_SHIsMenuSeparator(hmDst, uInsert-1))
955 {
956 if (bAlreadySeparated)
957 {
958 DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
959 }
960 }
961 else
962 {
963 if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
964 {
965 /* Add a separator between the menus*/
966 InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
967 }
968 }
969 }
970 return(uIDMax);
971}
972
Note: See TracBrowser for help on using the repository browser.